merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-07-18 17:07:59 +02:00
Родитель c1adcb3fe5 a3d12cc23a
Коммит ca457776f8
152 изменённых файлов: 5079 добавлений и 2466 удалений

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

@ -102,6 +102,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "SelfSupportBackend",
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
"resource:///modules/sessionstore/SessionStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUsageTelemetry",
"resource:///modules/BrowserUsageTelemetry.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
"resource:///modules/BrowserUITelemetry.jsm");
@ -781,6 +784,7 @@ BrowserGlue.prototype = {
NewTabMessages.init();
SessionStore.init();
BrowserUsageTelemetry.init();
BrowserUITelemetry.init();
ContentSearch.init();
FormValidationHandler.init();
@ -1174,6 +1178,7 @@ BrowserGlue.prototype = {
Cu.reportError("Could not end startup crash tracking in quit-application-granted: " + e);
}
BrowserUsageTelemetry.uninit();
SelfSupportBackend.uninit();
NewTabMessages.uninit();

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

@ -0,0 +1,175 @@
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["BrowserUsageTelemetry"];
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
// Observed topic names.
const WINDOWS_RESTORED_TOPIC = "sessionstore-windows-restored";
const TELEMETRY_SUBSESSIONSPLIT_TOPIC = "internal-telemetry-after-subsession-split";
const DOMWINDOW_OPENED_TOPIC = "domwindowopened";
const DOMWINDOW_CLOSED_TOPIC = "domwindowclosed";
// Probe names.
const MAX_TAB_COUNT_SCALAR_NAME = "browser.engagement.max_concurrent_tab_count";
const MAX_WINDOW_COUNT_SCALAR_NAME = "browser.engagement.max_concurrent_window_count";
const TAB_OPEN_EVENT_COUNT_SCALAR_NAME = "browser.engagement.tab_open_event_count";
const WINDOW_OPEN_EVENT_COUNT_SCALAR_NAME = "browser.engagement.window_open_event_count";
function getOpenTabsAndWinsCounts() {
let tabCount = 0;
let winCount = 0;
let browserEnum = Services.wm.getEnumerator("navigator:browser");
while (browserEnum.hasMoreElements()) {
let win = browserEnum.getNext();
winCount++;
tabCount += win.gBrowser.tabs.length;
}
return { tabCount, winCount };
}
let BrowserUsageTelemetry = {
init() {
Services.obs.addObserver(this, WINDOWS_RESTORED_TOPIC, false);
},
/**
* Handle subsession splits in the parent process.
*/
afterSubsessionSplit() {
// Scalars just got cleared due to a subsession split. We need to set the maximum
// concurrent tab and window counts so that they reflect the correct value for the
// new subsession.
const counts = getOpenTabsAndWinsCounts();
Services.telemetry.scalarSetMaximum(MAX_TAB_COUNT_SCALAR_NAME, counts.tabCount);
Services.telemetry.scalarSetMaximum(MAX_WINDOW_COUNT_SCALAR_NAME, counts.winCount);
},
uninit() {
Services.obs.removeObserver(this, DOMWINDOW_OPENED_TOPIC, false);
Services.obs.removeObserver(this, DOMWINDOW_CLOSED_TOPIC, false);
Services.obs.removeObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC, false);
Services.obs.removeObserver(this, WINDOWS_RESTORED_TOPIC, false);
},
observe(subject, topic, data) {
switch(topic) {
case WINDOWS_RESTORED_TOPIC:
this._setupAfterRestore();
break;
case DOMWINDOW_OPENED_TOPIC:
this._onWindowOpen(subject);
break;
case DOMWINDOW_CLOSED_TOPIC:
this._unregisterWindow(subject);
break;
case TELEMETRY_SUBSESSIONSPLIT_TOPIC:
this.afterSubsessionSplit();
break;
}
},
handleEvent(event) {
switch(event.type) {
case "TabOpen":
this._onTabOpen();
break;
}
},
/**
* This gets called shortly after the SessionStore has finished restoring
* windows and tabs. It counts the open tabs and adds listeners to all the
* windows.
*/
_setupAfterRestore() {
// Make sure to catch new chrome windows and subsession splits.
Services.obs.addObserver(this, DOMWINDOW_OPENED_TOPIC, false);
Services.obs.addObserver(this, DOMWINDOW_CLOSED_TOPIC, false);
Services.obs.addObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC, false);
// Attach the tabopen handlers to the existing Windows.
let browserEnum = Services.wm.getEnumerator("navigator:browser");
while (browserEnum.hasMoreElements()) {
this._registerWindow(browserEnum.getNext());
}
// Get the initial tab and windows max counts.
const counts = getOpenTabsAndWinsCounts();
Services.telemetry.scalarSetMaximum(MAX_TAB_COUNT_SCALAR_NAME, counts.tabCount);
Services.telemetry.scalarSetMaximum(MAX_WINDOW_COUNT_SCALAR_NAME, counts.winCount);
},
/**
* Adds listeners to a single chrome window.
*/
_registerWindow(win) {
win.addEventListener("TabOpen", this, true);
},
/**
* Removes listeners from a single chrome window.
*/
_unregisterWindow(win) {
// Ignore non-browser windows.
if (!(win instanceof Ci.nsIDOMWindow) ||
win.document.documentElement.getAttribute("windowtype") != "navigator:browser") {
return;
}
win.removeEventListener("TabOpen", this, true);
},
/**
* Updates the tab counts.
* @param {Number} [newTabCount=0] The count of the opened tabs across all windows. This
* is computed manually if not provided.
*/
_onTabOpen(tabCount = 0) {
// Use the provided tab count if available. Otherwise, go on and compute it.
tabCount = tabCount || getOpenTabsAndWinsCounts().tabCount;
// Update the "tab opened" count and its maximum.
Services.telemetry.scalarAdd(TAB_OPEN_EVENT_COUNT_SCALAR_NAME, 1);
Services.telemetry.scalarSetMaximum(MAX_TAB_COUNT_SCALAR_NAME, tabCount);
},
/**
* Tracks the window count and registers the listeners for the tab count.
* @param{Object} win The window object.
*/
_onWindowOpen(win) {
// Make sure to have a |nsIDOMWindow|.
if (!(win instanceof Ci.nsIDOMWindow)) {
return;
}
let onLoad = () => {
win.removeEventListener("load", onLoad, false);
// Ignore non browser windows.
if (win.document.documentElement.getAttribute("windowtype") != "navigator:browser") {
return;
}
this._registerWindow(win);
// Track the window open event and check the maximum.
const counts = getOpenTabsAndWinsCounts();
Services.telemetry.scalarAdd(WINDOW_OPEN_EVENT_COUNT_SCALAR_NAME, 1);
Services.telemetry.scalarSetMaximum(MAX_WINDOW_COUNT_SCALAR_NAME, counts.winCount);
// We won't receive the "TabOpen" event for the first tab within a new window.
// Account for that.
this._onTabOpen(counts.tabCount);
};
win.addEventListener("load", onLoad, false);
},
};

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

@ -14,6 +14,7 @@ EXTRA_JS_MODULES += [
'AboutHome.jsm',
'AboutNewTab.jsm',
'BrowserUITelemetry.jsm',
'BrowserUsageTelemetry.jsm',
'CaptivePortalWatcher.jsm',
'CastingApps.jsm',
'Chat.jsm',

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

@ -23,3 +23,4 @@ support-files =
../../components/uitour/UITour-lib.js
[browser_taskbar_preview.js]
skip-if = os != "win"
[browser_UsageTelemetry.js]

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

@ -20,6 +20,12 @@ const TEST_WAIT_RETRIES = 60;
const TEST_PAGE_URL = getRootDirectory(gTestPath) + "uitour.html";
const TEST_PAGE_URL_HTTPS = TEST_PAGE_URL.replace("chrome://mochitests/content/", "https://example.com/");
function sendSessionRestoredNotification() {
let selfSupportBackendImpl =
Cu.import("resource:///modules/SelfSupportBackend.jsm", {}).SelfSupportBackendInternal;
selfSupportBackendImpl.observe(null, "sessionstore-windows-restored", null);
}
/**
* Find a browser, with an IFRAME as parent, who has aURL as the source attribute.
*
@ -128,7 +134,7 @@ add_task(function* test_selfSupport() {
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
info("Sending sessionstore-windows-restored");
Services.obs.notifyObservers(null, "sessionstore-windows-restored", null);
sendSessionRestoredNotification();
// Wait for the SelfSupport page to load.
info("Waiting for the SelfSupport local page to load.");
@ -196,7 +202,7 @@ add_task(function* test_selfSupport_noHTTPS() {
// SelfSupportBackend waits for "sessionstore-windows-restored" to start loading. Send it.
info("Sending sessionstore-windows-restored");
Services.obs.notifyObservers(null, "sessionstore-windows-restored", null);
sendSessionRestoredNotification();
// Find the SelfSupport browser. We don't expect to find it since we are not using https.
let selfSupportBrowser = findSelfSupportBrowser(TEST_PAGE_URL);

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

@ -0,0 +1,143 @@
"use strict";
const MAX_CONCURRENT_TABS = "browser.engagement.max_concurrent_tab_count";
const TAB_EVENT_COUNT = "browser.engagement.tab_open_event_count";
const MAX_CONCURRENT_WINDOWS = "browser.engagement.max_concurrent_window_count";
const WINDOW_OPEN_COUNT = "browser.engagement.window_open_event_count";
const TELEMETRY_SUBSESSION_TOPIC = "internal-telemetry-after-subsession-split";
/**
* An helper that checks the value of a scalar if it's expected to be > 0,
* otherwise makes sure that the scalar it's not reported.
*/
let checkScalar = (scalars, scalarName, value, msg) => {
if (value > 0) {
is(scalars[scalarName], value, msg);
return;
}
ok(!(scalarName in scalars), scalarName + " must not be reported.");
};
/**
* Get a snapshot of the scalars and check them against the provided values.
*/
let checkScalars = (maxTabs, tabOpenCount, maxWindows, windowsOpenCount) => {
const scalars =
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
// Check the expected values. Scalars that are never set must not be reported.
checkScalar(scalars, MAX_CONCURRENT_TABS, maxTabs,
"The maximum tab count must match the expected value.");
checkScalar(scalars, TAB_EVENT_COUNT, tabOpenCount,
"The number of open tab event count must match the expected value.");
checkScalar(scalars, MAX_CONCURRENT_WINDOWS, maxWindows,
"The maximum window count must match the expected value.");
checkScalar(scalars, WINDOW_OPEN_COUNT, windowsOpenCount,
"The number of window open event count must match the expected value.");
};
add_task(function* test_tabsAndWindows() {
// Let's reset the counts.
Services.telemetry.clearScalars();
let openedTabs = [];
let expectedTabOpenCount = 0;
let expectedWinOpenCount = 0;
let expectedMaxTabs = 0;
let expectedMaxWins = 0;
// Add a new tab and check that the count is right.
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
expectedTabOpenCount = 1;
expectedMaxTabs = 2;
checkScalars(expectedMaxTabs, expectedTabOpenCount, expectedMaxWins, expectedWinOpenCount);
// Add two new tabs in the same window.
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
expectedTabOpenCount += 2;
expectedMaxTabs += 2;
checkScalars(expectedMaxTabs, expectedTabOpenCount, expectedMaxWins, expectedWinOpenCount);
// Add a new window and then some tabs in it. An empty new windows counts as a tab.
let win = yield BrowserTestUtils.openNewBrowserWindow();
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
// The new window started with a new tab, so account for it.
expectedTabOpenCount += 4;
expectedWinOpenCount += 1;
expectedMaxWins = 2;
expectedMaxTabs += 4;
// Remove a tab from the first window, the max shouldn't change.
yield BrowserTestUtils.removeTab(openedTabs.pop());
checkScalars(expectedMaxTabs, expectedTabOpenCount, expectedMaxWins, expectedWinOpenCount);
// Remove all the extra windows and tabs.
for (let tab of openedTabs) {
yield BrowserTestUtils.removeTab(tab);
}
yield BrowserTestUtils.closeWindow(win);
// Make sure all the scalars still have the expected values.
checkScalars(expectedMaxTabs, expectedTabOpenCount, expectedMaxWins, expectedWinOpenCount);
});
add_task(function* test_subsessionSplit() {
// Let's reset the counts.
Services.telemetry.clearScalars();
// Add a new window (that will have 4 tabs).
let win = yield BrowserTestUtils.openNewBrowserWindow();
let openedTabs = [];
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
openedTabs.push(yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:blank"));
// Check that the scalars have the right values.
checkScalars(5 /*maxTabs*/, 4 /*tabOpen*/, 2 /*maxWins*/, 1 /*winOpen*/);
// Remove a tab.
yield BrowserTestUtils.removeTab(openedTabs.pop());
// Simulate a subsession split by clearing the scalars (via |snapshotScalars|) and
// notifying the subsession split topic.
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN,
true /* clearScalars*/);
Services.obs.notifyObservers(null, TELEMETRY_SUBSESSION_TOPIC, "");
// After a subsession split, only the MAX_CONCURRENT_* scalars must be available
// and have the correct value. No tabs or windows were opened so other scalars
// must not be reported.
checkScalars(4 /*maxTabs*/, 0 /*tabOpen*/, 2 /*maxWins*/, 0 /*winOpen*/);
// Remove all the extra windows and tabs.
for (let tab of openedTabs) {
yield BrowserTestUtils.removeTab(tab);
}
yield BrowserTestUtils.closeWindow(win);
});
add_task(function* test_privateMode() {
// Let's reset the counts.
Services.telemetry.clearScalars();
// Open a private window and load a website in it.
let privateWin = yield BrowserTestUtils.openNewBrowserWindow({private: true});
yield BrowserTestUtils.loadURI(privateWin.gBrowser.selectedBrowser, "http://example.com/");
yield BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser);
// Check that tab and window count is recorded.
const scalars =
Services.telemetry.snapshotScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
is(scalars[TAB_EVENT_COUNT], 1, "The number of open tab event count must match the expected value.");
is(scalars[MAX_CONCURRENT_TABS], 2, "The maximum tab count must match the expected value.");
is(scalars[WINDOW_OPEN_COUNT], 1, "The number of window open event count must match the expected value.");
is(scalars[MAX_CONCURRENT_WINDOWS], 2, "The maximum window count must match the expected value.");
// Clean up.
yield BrowserTestUtils.closeWindow(privateWin);
});

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

@ -72,6 +72,7 @@ support-files =
[browser_styleeditor_init.js]
[browser_styleeditor_inline_friendly_names.js]
[browser_styleeditor_loading.js]
[browser_styleeditor_loading_with_containers.js]
[browser_styleeditor_media_sidebar.js]
[browser_styleeditor_media_sidebar_links.js]
skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s

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

@ -0,0 +1,63 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the stylesheets can be loaded correctly with containers
// (bug 1282660).
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
const EXPECTED_SHEETS = [
{
sheetIndex: 0,
name: /^simple.css$/,
rules: 1,
active: true
}, {
sheetIndex: 1,
name: /^<.*>$/,
rules: 3,
active: false
}
];
add_task(function* () {
// Using the personal container.
let userContextId = 1;
let { tab } = yield* openTabInUserContext(TESTCASE_URI, userContextId);
let { ui } = yield openStyleEditor(tab);
is(ui.editors.length, 2, "The UI contains two style sheets.");
checkSheet(ui.editors[0], EXPECTED_SHEETS[0]);
checkSheet(ui.editors[1], EXPECTED_SHEETS[1]);
});
function* openTabInUserContext(uri, userContextId) {
// Open the tab in the correct userContextId.
let tab = gBrowser.addTab(uri, {userContextId});
// Select tab and make sure its browser is focused.
gBrowser.selectedTab = tab;
tab.ownerDocument.defaultView.focus();
let browser = gBrowser.getBrowserForTab(tab);
yield BrowserTestUtils.browserLoaded(browser);
return {tab, browser};
}
function checkSheet(editor, expected) {
is(editor.styleSheet.styleSheetIndex, expected.sheetIndex,
"Style sheet has correct index.");
let summary = editor.summary;
let name = summary.querySelector(".stylesheet-name > label")
.getAttribute("value");
ok(expected.name.test(name), "The name '" + name + "' is correct.");
let ruleCount = summary.querySelector(".stylesheet-rule-count").textContent;
is(parseInt(ruleCount, 10), expected.rules, "the rule count is correct");
is(summary.classList.contains("splitview-active"), expected.active,
"The active status for this sheet is correct.");
}

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

@ -452,10 +452,19 @@ var StyleSheetActor = protocol.ActorClassWithSpec(styleSheetSpec, {
let options = {
loadFromCache: true,
policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
window: this.window,
charset: this._getCSSCharset()
};
// Bug 1282660 - We use the system principal to load the default internal
// stylesheets instead of the content principal since such stylesheets
// require system principal to load. At meanwhile, we strip the loadGroup
// for preventing the assertion of the userContextId mismatching.
// The default internal stylesheets load from the 'resource:' URL.
if (!/^resource:\/\//.test(this.href)) {
options.window = this.window;
options.principal = this.document.nodePrincipal;
}
return fetch(this.href, options).then(({ content }) => {
this.text = content;
return content;

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

@ -14236,7 +14236,10 @@ nsDocShell::SetOriginAttributesBeforeLoading(JS::Handle<JS::Value> aOriginAttrib
}
AutoJSAPI jsapi;
jsapi.Init(&aOriginAttributes.toObject());
if (!jsapi.Init(&aOriginAttributes.toObject())) {
return NS_ERROR_UNEXPECTED;
}
JSContext* cx = jsapi.cx();
if (NS_WARN_IF(!cx)) {
return NS_ERROR_FAILURE;

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

@ -225,11 +225,11 @@ public:
// If aGlobalObject represents a web-visible global, errors reported by this
// AutoJSAPI as it comes off the stack will fire the relevant error events and
// show up in the corresponding web console.
bool Init(nsIGlobalObject* aGlobalObject);
MOZ_MUST_USE bool Init(nsIGlobalObject* aGlobalObject);
// This is a helper that grabs the native global associated with aObject and
// invokes the above Init() with that.
bool Init(JSObject* aObject);
MOZ_MUST_USE bool Init(JSObject* aObject);
// Unsurprisingly, this uses aCx and enters the compartment of aGlobalObject.
// If aGlobalObject or its associated JS global are null then it returns
@ -239,15 +239,15 @@ public:
// If aGlobalObject represents a web-visible global, errors reported by this
// AutoJSAPI as it comes off the stack will fire the relevant error events and
// show up in the corresponding web console.
bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx);
MOZ_MUST_USE bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx);
// Convenience functions to take an nsPIDOMWindow* or nsGlobalWindow*,
// when it is more easily available than an nsIGlobalObject.
bool Init(nsPIDOMWindowInner* aWindow);
bool Init(nsPIDOMWindowInner* aWindow, JSContext* aCx);
MOZ_MUST_USE bool Init(nsPIDOMWindowInner* aWindow);
MOZ_MUST_USE bool Init(nsPIDOMWindowInner* aWindow, JSContext* aCx);
bool Init(nsGlobalWindow* aWindow);
bool Init(nsGlobalWindow* aWindow, JSContext* aCx);
MOZ_MUST_USE bool Init(nsGlobalWindow* aWindow);
MOZ_MUST_USE bool Init(nsGlobalWindow* aWindow, JSContext* aCx);
JSContext* cx() const {
MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
@ -273,7 +273,7 @@ public:
//
// Note that this fails if and only if we OOM while wrapping the exception
// into the current compartment.
bool StealException(JS::MutableHandle<JS::Value> aVal);
MOZ_MUST_USE bool StealException(JS::MutableHandle<JS::Value> aVal);
// Peek the current exception from the JS engine, without stealing it.
// Callers must ensure that HasException() is true, and that cx() is in a
@ -281,7 +281,7 @@ public:
//
// Note that this fails if and only if we OOM while wrapping the exception
// into the current compartment.
bool PeekException(JS::MutableHandle<JS::Value> aVal);
MOZ_MUST_USE bool PeekException(JS::MutableHandle<JS::Value> aVal);
void ClearException() {
MOZ_ASSERT(IsStackTop());

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

@ -327,7 +327,9 @@ nsresult
nsDOMClassInfo::DefineStaticJSVals()
{
AutoJSAPI jsapi;
jsapi.Init(xpc::UnprivilegedJunkScope());
if (!jsapi.Init(xpc::UnprivilegedJunkScope())) {
return NS_ERROR_UNEXPECTED;
}
JSContext* cx = jsapi.cx();
#define SET_JSID_TO_STRING(_id, _cx, _str) \

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

@ -7,8 +7,11 @@
#include "nsHostObjectProtocolHandler.h"
#include "DOMMediaStream.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/Exceptions.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/dom/MediaSource.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/ModuleUtils.h"
@ -38,9 +41,79 @@ struct DataInfo
static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable;
static DataInfo*
GetDataInfo(const nsACString& aUri)
{
if (!gDataTable) {
return nullptr;
}
DataInfo* res;
// Let's remove any fragment and query from this URI.
int32_t hasFragmentPos = aUri.FindChar('#');
int32_t hasQueryPos = aUri.FindChar('?');
int32_t pos = -1;
if (hasFragmentPos >= 0 && hasQueryPos >= 0) {
pos = std::min(hasFragmentPos, hasQueryPos);
} else if (hasFragmentPos >= 0) {
pos = hasFragmentPos;
} else {
pos = hasQueryPos;
}
if (pos < 0) {
gDataTable->Get(aUri, &res);
} else {
gDataTable->Get(StringHead(aUri, pos), &res);
}
return res;
}
// Memory reporting for the hash table.
namespace mozilla {
void
BroadcastBlobURLRegistration(const nsACString& aURI,
BlobImpl* aBlobImpl,
nsIPrincipal* aPrincipal)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBlobImpl);
if (XRE_IsParentProcess()) {
ContentParent::BroadcastBlobURLRegistration(aURI, aBlobImpl,
aPrincipal);
return;
}
ContentChild* cc = ContentChild::GetSingleton();
BlobChild* actor = cc->GetOrCreateActorForBlobImpl(aBlobImpl);
if (NS_WARN_IF(!actor)) {
return;
}
NS_WARN_IF(!cc->SendStoreAndBroadcastBlobURLRegistration(nsCString(aURI), actor,
IPC::Principal(aPrincipal)));
}
void
BroadcastBlobURLUnregistration(const nsACString& aURI, DataInfo* aInfo)
{
MOZ_ASSERT(aInfo);
MOZ_ASSERT(NS_IsMainThread());
if (XRE_IsParentProcess()) {
ContentParent::BroadcastBlobURLUnregistration(aURI);
return;
}
ContentChild* cc = ContentChild::GetSingleton();
NS_WARN_IF(!cc->SendUnstoreAndBroadcastBlobURLUnregistration(nsCString(aURI)));
}
class HostObjectURLsReporter final : public nsIMemoryReporter
{
~HostObjectURLsReporter() {}
@ -321,12 +394,14 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
nsACString& aUri)
{
#ifdef DEBUG
nsCOMPtr<BlobImpl> blobImpl(do_QueryInterface(aObject));
nsCOMPtr<MediaSource> mediaSource(do_QueryInterface(aObject));
nsCOMPtr<DOMMediaStream> mediaStream(do_QueryInterface(aObject));
{
nsCOMPtr<BlobImpl> blobImpl(do_QueryInterface(aObject));
nsCOMPtr<MediaSource> mediaSource(do_QueryInterface(aObject));
nsCOMPtr<DOMMediaStream> mediaStream(do_QueryInterface(aObject));
// We support only these types.
MOZ_ASSERT(blobImpl || mediaSource || mediaStream);
// We support only these types.
MOZ_ASSERT(blobImpl || mediaSource || mediaStream);
}
#endif
Init();
@ -334,6 +409,22 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
nsresult rv = GenerateURIString(aScheme, aPrincipal, aUri);
NS_ENSURE_SUCCESS(rv, rv);
rv = AddDataEntry(aUri, aObject, aPrincipal);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(aObject);
if (blobImpl) {
BroadcastBlobURLRegistration(aUri, blobImpl, aPrincipal);
}
return NS_OK;
}
/* static */ nsresult
nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aURI,
nsISupports* aObject,
nsIPrincipal* aPrincipal)
{
if (!gDataTable) {
gDataTable = new nsClassHashtable<nsCStringHashKey, DataInfo>;
}
@ -344,17 +435,62 @@ nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
info->mPrincipal = aPrincipal;
mozilla::BlobURLsReporter::GetJSStackForBlob(info);
gDataTable->Put(aUri, info);
gDataTable->Put(aURI, info);
return NS_OK;
}
/* static */ bool
nsHostObjectProtocolHandler::GetAllBlobURLEntries(nsTArray<BlobURLRegistrationData>& aRegistrations,
ContentParent* aCP)
{
MOZ_ASSERT(aCP);
if (!gDataTable) {
return true;
}
for (auto iter = gDataTable->ConstIter(); !iter.Done(); iter.Next()) {
DataInfo* info = iter.UserData();
MOZ_ASSERT(info);
nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(info->mObject);
if (!blobImpl) {
continue;
}
PBlobParent* blobParent = aCP->GetOrCreateActorForBlobImpl(blobImpl);
if (!blobParent) {
return false;
}
aRegistrations.AppendElement(
BlobURLRegistrationData(nsCString(iter.Key()), blobParent, nullptr,
IPC::Principal(info->mPrincipal)));
}
return true;
}
void
nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri)
nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri,
bool aBroadcastToOtherProcesses)
{
if (!gDataTable) {
return;
}
DataInfo* info = GetDataInfo(aUri);
if (!info) {
return;
}
if (aBroadcastToOtherProcesses) {
nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(info->mObject);
if (blobImpl) {
BroadcastBlobURLUnregistration(aUri, info);
}
}
gDataTable->Remove(aUri);
if (gDataTable->Count() == 0) {
delete gDataTable;
@ -362,6 +498,20 @@ nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri)
}
}
void
nsHostObjectProtocolHandler::RemoveDataEntries()
{
MOZ_ASSERT(XRE_IsContentProcess());
if (!gDataTable) {
return;
}
gDataTable->Clear();
delete gDataTable;
gDataTable = nullptr;
}
nsresult
nsHostObjectProtocolHandler::GenerateURIString(const nsACString &aScheme,
nsIPrincipal* aPrincipal,
@ -398,37 +548,6 @@ nsHostObjectProtocolHandler::GenerateURIString(const nsACString &aScheme,
return NS_OK;
}
static DataInfo*
GetDataInfo(const nsACString& aUri)
{
if (!gDataTable) {
return nullptr;
}
DataInfo* res;
// Let's remove any fragment and query from this URI.
int32_t hasFragmentPos = aUri.FindChar('#');
int32_t hasQueryPos = aUri.FindChar('?');
int32_t pos = -1;
if (hasFragmentPos >= 0 && hasQueryPos >= 0) {
pos = std::min(hasFragmentPos, hasQueryPos);
} else if (hasFragmentPos >= 0) {
pos = hasFragmentPos;
} else {
pos = hasQueryPos;
}
if (pos < 0) {
gDataTable->Get(aUri, &res);
} else {
gDataTable->Get(StringHead(aUri, pos), &res);
}
return res;
}
nsIPrincipal*
nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri)
{
@ -509,8 +628,13 @@ nsHostObjectProtocolHandler::NewURI(const nsACString& aSpec,
DataInfo* info = GetDataInfo(aSpec);
RefPtr<nsHostObjectURI> uri =
new nsHostObjectURI(info ? info->mPrincipal.get() : nullptr);
RefPtr<nsHostObjectURI> uri;
if (info) {
nsCOMPtr<BlobImpl> blob = do_QueryInterface(info->mObject);
uri = new nsHostObjectURI(info->mPrincipal, blob);
} else {
uri = new nsHostObjectURI(nullptr, nullptr);
}
rv = uri->SetSpec(aSpec);
NS_ENSURE_SUCCESS(rv, rv);
@ -528,22 +652,26 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri,
{
*result = nullptr;
nsCOMPtr<nsIURIWithBlobImpl> uriBlobImpl = do_QueryInterface(uri);
if (!uriBlobImpl) {
return NS_ERROR_DOM_BAD_URI;
}
nsCOMPtr<nsISupports> tmp;
MOZ_ALWAYS_SUCCEEDS(uriBlobImpl->GetBlobImpl(getter_AddRefs(tmp)));
nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(tmp);
if (!blobImpl) {
return NS_ERROR_DOM_BAD_URI;
}
#ifdef DEBUG
nsCString spec;
uri->GetSpec(spec);
DataInfo* info = GetDataInfo(spec);
if (!info) {
return NS_ERROR_DOM_BAD_URI;
}
nsCOMPtr<BlobImpl> blob = do_QueryInterface(info->mObject);
if (!blob) {
return NS_ERROR_DOM_BAD_URI;
}
#ifdef DEBUG
{
// Info can be null, in case this blob URL has been revoked already.
if (info) {
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
@ -553,13 +681,13 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri,
ErrorResult rv;
nsCOMPtr<nsIInputStream> stream;
blob->GetInternalStream(getter_AddRefs(stream), rv);
blobImpl->GetInternalStream(getter_AddRefs(stream), rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
nsAutoString contentType;
blob->GetType(contentType);
blobImpl->GetType(contentType);
nsCOMPtr<nsIChannel> channel;
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
@ -572,13 +700,13 @@ nsHostObjectProtocolHandler::NewChannel2(nsIURI* uri,
return rv.StealNSResult();
}
if (blob->IsFile()) {
if (blobImpl->IsFile()) {
nsString filename;
blob->GetName(filename);
blobImpl->GetName(filename);
channel->SetContentDispositionFilename(filename);
}
uint64_t size = blob->GetSize(rv);
uint64_t size = blobImpl->GetSize(rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
@ -795,3 +923,4 @@ static const mozilla::Module kHostObjectProtocolHandlerModule = {
};
NSMODULE_DEFN(HostObjectProtocolHandler) = &kHostObjectProtocolHandlerModule;

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

@ -12,6 +12,7 @@
#include "nsIURI.h"
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
#include "nsTArray.h"
#define BLOBURI_SCHEME "blob"
#define MEDIASTREAMURI_SCHEME "mediastream"
@ -25,6 +26,8 @@ namespace mozilla {
class DOMMediaStream;
namespace dom {
class BlobImpl;
class BlobURLRegistrationData;
class ContentParent;
class MediaSource;
} // namespace dom
} // namespace mozilla
@ -55,10 +58,23 @@ public:
nsISupports* aObject,
nsIPrincipal* aPrincipal,
nsACString& aUri);
static void RemoveDataEntry(const nsACString& aUri);
static void RemoveDataEntry(const nsACString& aUri,
bool aBroadcastToOTherProcesses = true);
// This is for IPC only.
static void RemoveDataEntries();
static nsIPrincipal* GetDataEntryPrincipal(const nsACString& aUri);
static void Traverse(const nsACString& aUri, nsCycleCollectionTraversalCallback& aCallback);
// IPC or internal use only
static nsresult AddDataEntry(const nsACString& aURI,
nsISupports* aObject,
nsIPrincipal* aPrincipal);
static bool
GetAllBlobURLEntries(nsTArray<mozilla::dom::BlobURLRegistrationData>& aRegistrations,
mozilla::dom::ContentParent* aCP);
protected:
virtual ~nsHostObjectProtocolHandler() {}

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

@ -21,6 +21,7 @@ NS_IMPL_ADDREF_INHERITED(nsHostObjectURI, mozilla::net::nsSimpleURI)
NS_IMPL_RELEASE_INHERITED(nsHostObjectURI, mozilla::net::nsSimpleURI)
NS_INTERFACE_MAP_BEGIN(nsHostObjectURI)
NS_INTERFACE_MAP_ENTRY(nsIURIWithBlobImpl)
NS_INTERFACE_MAP_ENTRY(nsIURIWithPrincipal)
if (aIID.Equals(kHOSTOBJECTURICID))
foundInterface = static_cast<nsIURI*>(this);
@ -34,6 +35,16 @@ NS_INTERFACE_MAP_BEGIN(nsHostObjectURI)
else
NS_INTERFACE_MAP_END_INHERITING(mozilla::net::nsSimpleURI)
// nsIURIWithBlobImpl methods:
NS_IMETHODIMP
nsHostObjectURI::GetBlobImpl(nsISupports** aBlobImpl)
{
RefPtr<BlobImpl> blobImpl(mBlobImpl);
blobImpl.forget(aBlobImpl);
return NS_OK;
}
// nsIURIWithPrincipal methods:
NS_IMETHODIMP
@ -126,6 +137,10 @@ nsHostObjectURI::Deserialize(const mozilla::ipc::URIParams& aParams)
if (!mozilla::net::nsSimpleURI::Deserialize(hostParams.simpleParams())) {
return false;
}
// XXXbaku: when we will have shared blobURL maps, we can populate mBlobImpl
// here asll well.
if (hostParams.principal().type() == OptionalPrincipalInfo::Tvoid_t) {
return true;
}
@ -162,6 +177,7 @@ nsHostObjectURI::CloneInternal(mozilla::net::nsSimpleURI::RefHandlingEnum aRefHa
nsHostObjectURI* u = static_cast<nsHostObjectURI*>(simpleClone.get());
u->mPrincipal = mPrincipal;
u->mBlobImpl = mBlobImpl;
simpleClone.forget(aClone);
return NS_OK;
@ -190,7 +206,10 @@ nsHostObjectURI::EqualsInternal(nsIURI* aOther,
return NS_OK;
}
// Compare the piece of additional member data that we add to base class.
// Compare the piece of additional member data that we add to base class,
// but we cannot compare BlobImpl. This should not be a problem, because we
// don't support changing the underlying mBlobImpl.
if (mPrincipal && otherUri->mPrincipal) {
// Both of us have mPrincipals. Compare them.
return mPrincipal->Equals(otherUri->mPrincipal, aResult);

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

@ -8,10 +8,12 @@
#define nsHostObjectURI_h
#include "mozilla/Attributes.h"
#include "mozilla/dom/File.h"
#include "nsCOMPtr.h"
#include "nsIClassInfo.h"
#include "nsIPrincipal.h"
#include "nsISerializable.h"
#include "nsIURIWithBlobImpl.h"
#include "nsIURIWithPrincipal.h"
#include "nsSimpleURI.h"
#include "nsIIPCSerializableURI.h"
@ -21,18 +23,23 @@
* MediaStreams, with scheme "mediastream", and MediaSources, with scheme
* "mediasource".
*/
class nsHostObjectURI : public mozilla::net::nsSimpleURI,
public nsIURIWithPrincipal
class nsHostObjectURI : public mozilla::net::nsSimpleURI
, public nsIURIWithPrincipal
, public nsIURIWithBlobImpl
{
public:
explicit nsHostObjectURI(nsIPrincipal* aPrincipal) :
mozilla::net::nsSimpleURI(), mPrincipal(aPrincipal)
nsHostObjectURI(nsIPrincipal* aPrincipal,
mozilla::dom::BlobImpl* aBlobImpl)
: mozilla::net::nsSimpleURI()
, mPrincipal(aPrincipal)
, mBlobImpl(aBlobImpl)
{}
// For use only from deserialization
nsHostObjectURI() : mozilla::net::nsSimpleURI() {}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIURIWITHBLOBIMPL
NS_DECL_NSIURIWITHPRINCIPAL
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
@ -52,6 +59,7 @@ public:
{ return new nsHostObjectURI(); }
nsCOMPtr<nsIPrincipal> mPrincipal;
RefPtr<mozilla::dom::BlobImpl> mBlobImpl;
protected:
virtual ~nsHostObjectURI() {}

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

@ -191,7 +191,6 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
const bool isDstPremult = webgl->mPixelStore_PremultiplyAlpha;
const auto pi = dstDUI->ToPacking();
const auto dstFormat = FormatForPackingInfo(pi);
const auto dstBPP = webgl::BytesPerPixel(pi);
const auto dstWidthBytes = CheckedUint32(dstBPP) * mWidth;
@ -203,8 +202,9 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
//////
const auto dstTotalRows = CheckedUint32(mDepth - 1) * mImageHeight + mHeight;
const auto dstUsedSizeExceptLastRow = (dstTotalRows - 1) * dstStride;
const auto dstSize = skipBytes + (dstTotalRows - 1) * dstStride + dstWidthBytes;
const auto dstSize = skipBytes + dstUsedSizeExceptLastRow + dstWidthBytes;
if (!dstSize.isValid()) {
webgl->ErrorOutOfMemory("%s: Invalid dstSize calculation during conversion.",
funcName);
@ -213,32 +213,71 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
//////
bool needsConvert = (srcOrigin != dstOrigin ||
srcFormat != dstFormat ||
srcStride != dstStride.value());
const auto dstFormat = FormatForPackingInfo(pi);
if (UnpackFormatHasAlpha(dstDUI->unpackFormat)) {
needsConvert |= (mIsSrcPremult != isDstPremult);
bool premultMatches = (mIsSrcPremult == isDstPremult);
if (!UnpackFormatHasAlpha(dstDUI->unpackFormat)) {
premultMatches = true;
}
if (!needsConvert)
const bool needsPixelConversion = (srcFormat != dstFormat || !premultMatches);
const bool originsMatch = (srcOrigin == dstOrigin);
MOZ_ASSERT_IF(!needsPixelConversion, srcBPP == dstBPP);
if (!needsPixelConversion &&
originsMatch &&
srcStride == dstStride.value())
{
// No conversion needed!
return true;
////////////
// Ugh, ok, fine!
webgl->GenerateWarning("%s: Incurred CPU data conversion, which is slow.",
funcName);
}
//////
// We need some sort of conversion, so create the dest buffer.
*out_anchoredBuffer = calloc(1, dstSize.value());
if (!out_anchoredBuffer->get()) {
*out_bytes = out_anchoredBuffer->get();
if (!*out_bytes) {
webgl->ErrorOutOfMemory("%s: Unable to allocate buffer during conversion.",
funcName);
return false;
}
const auto dstBegin = (uint8_t*)out_anchoredBuffer->get() + skipBytes;
const auto dstBegin = (uint8_t*)(*out_bytes) + skipBytes;
//////
// Row conversion
if (!needsPixelConversion) {
webgl->GenerateWarning("%s: Incurred CPU row conversion, which is slow.",
funcName);
const uint8_t* srcRow = srcBegin;
uint8_t* dstRow = dstBegin;
const auto widthBytes = dstWidthBytes.value();
ptrdiff_t dstCopyStride = dstStride.value();
if (!originsMatch) {
dstRow += dstUsedSizeExceptLastRow.value();
dstCopyStride = -dstCopyStride;
}
for (uint32_t i = 0; i < dstTotalRows.value(); i++) {
memcpy(dstRow, srcRow, widthBytes);
srcRow += srcStride;
dstRow += dstCopyStride;
}
return true;
}
////////////
// Pixel conversion.
MOZ_ASSERT(srcFormat != WebGLTexelFormat::FormatNotSupportingAnyConversion);
MOZ_ASSERT(dstFormat != WebGLTexelFormat::FormatNotSupportingAnyConversion);
webgl->GenerateWarning("%s: Incurred CPU pixel conversion, which is very slow.",
funcName);
//////
@ -259,7 +298,6 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
funcName, dstDUI->unpackFormat, dstDUI->unpackType);
}
*out_bytes = out_anchoredBuffer->get();
return true;
}
@ -297,7 +335,6 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
WebGLContext* webgl = tex->mContext;
const auto pi = dui->ToPacking();
const auto format = FormatForPackingInfo(pi);
const auto bytesPerPixel = webgl::BytesPerPixel(pi);
const auto bytesPerRow = CheckedUint32(mRowLength) * bytesPerPixel;
@ -306,6 +343,8 @@ TexUnpackBytes::TexOrSubImage(bool isSubImage, bool needsRespec, const char* fun
MOZ_CRASH("Should be checked earlier.");
}
const auto format = FormatForPackingInfo(pi);
const void* uploadBytes;
UniqueBuffer tempBuffer;
if (!ConvertIfNeeded(webgl, funcName, mBytes, rowStride.value(), bytesPerPixel,

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

@ -55,7 +55,16 @@ public:
const dom::Nullable<dom::ArrayBuffer>& maybeData);
void GetBufferSubData(GLenum target, GLintptr offset,
const dom::SharedArrayBuffer& data);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
GLenum type, WebGLsizeiptr offset, ErrorResult& out_error);
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const dom::Nullable<dom::ArrayBufferView>& pixels,
ErrorResult& out_error)
{
WebGLContext::ReadPixels(x, y, width, height, format, type, pixels, out_error);
}
// -------------------------------------------------------------------------
// Framebuffer objects - WebGL2ContextFramebuffers.cpp
@ -142,111 +151,68 @@ public:
void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
// GL 3.0 & ES 3.0
void Uniform1ui(WebGLUniformLocation* location, GLuint v0);
void Uniform2ui(WebGLUniformLocation* location, GLuint v0, GLuint v1);
void Uniform3ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2);
void Uniform4ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
void Uniform1ui(WebGLUniformLocation* loc, GLuint v0);
void Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1);
void Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2);
void Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
GLuint v3);
private:
void Uniform1uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
void Uniform2uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
void Uniform3uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
void Uniform4uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data);
////////////////
protected:
typedef Arr<GLuint, dom::Uint32Array> UintArr;
void UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const UintArr& arr);
//////
public:
void Uniform1uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
Uniform1uiv_base(loc, arr.Length(), arr.Elements());
template<typename T>
void Uniform1uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform1uiv", 1, loc, UintArr(arr));
}
void Uniform2uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
Uniform2uiv_base(loc, arr.Length(), arr.Elements());
template<typename T>
void Uniform2uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform2uiv", 2, loc, UintArr(arr));
}
void Uniform3uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
Uniform3uiv_base(loc, arr.Length(), arr.Elements());
template<typename T>
void Uniform3uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform3uiv", 3, loc, UintArr(arr));
}
void Uniform4uiv(WebGLUniformLocation* loc, const dom::Sequence<GLuint>& arr) {
Uniform4uiv_base(loc, arr.Length(), arr.Elements());
}
void Uniform1uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
arr.ComputeLengthAndData();
Uniform1uiv_base(loc, arr.Length(), arr.Data());
}
void Uniform2uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
arr.ComputeLengthAndData();
Uniform2uiv_base(loc, arr.Length(), arr.Data());
}
void Uniform3uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
arr.ComputeLengthAndData();
Uniform3uiv_base(loc, arr.Length(), arr.Data());
}
void Uniform4uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) {
arr.ComputeLengthAndData();
Uniform4uiv_base(loc, arr.Length(), arr.Data());
template<typename T>
void Uniform4uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform4uiv", 4, loc, UintArr(arr));
}
private:
void UniformMatrix2x3fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data);
void UniformMatrix3x2fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data);
void UniformMatrix2x4fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data);
void UniformMatrix4x2fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data);
void UniformMatrix3x4fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data);
void UniformMatrix4x3fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data);
//////
public:
// GL 2.1 & ES 3.0
void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
UniformMatrix2x3fv_base(loc, transpose, value.Length(), value.Elements());
template<typename T>
void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix2x3fv", 2, 3, loc, transpose, FloatArr(arr));
}
void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
UniformMatrix2x4fv_base(loc, transpose, value.Length(), value.Elements());
template<typename T>
void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix2x4fv", 2, 4, loc, transpose, FloatArr(arr));
}
void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
UniformMatrix3x2fv_base(loc, transpose, value.Length(), value.Elements());
template<typename T>
void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix3x2fv", 3, 2, loc, transpose, FloatArr(arr));
}
void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
UniformMatrix3x4fv_base(loc, transpose, value.Length(), value.Elements());
template<typename T>
void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix3x4fv", 3, 4, loc, transpose, FloatArr(arr));
}
void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
UniformMatrix4x2fv_base(loc, transpose, value.Length(), value.Elements());
template<typename T>
void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix4x2fv", 4, 2, loc, transpose, FloatArr(arr));
}
void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence<GLfloat>& value){
UniformMatrix4x3fv_base(loc, transpose, value.Length(), value.Elements());
template<typename T>
void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix4x3fv", 4, 3, loc, transpose, FloatArr(arr));
}
void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
value.ComputeLengthAndData();
UniformMatrix2x3fv_base(loc, transpose, value.Length(), value.Data());
}
void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
value.ComputeLengthAndData();
UniformMatrix2x4fv_base(loc, transpose, value.Length(), value.Data());
}
void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
value.ComputeLengthAndData();
UniformMatrix3x2fv_base(loc, transpose, value.Length(), value.Data());
}
void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
value.ComputeLengthAndData();
UniformMatrix3x4fv_base(loc, transpose, value.Length(), value.Data());
}
void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
value.ComputeLengthAndData();
UniformMatrix4x2fv_base(loc, transpose, value.Length(), value.Data());
}
void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){
value.ComputeLengthAndData();
UniformMatrix4x3fv_base(loc, transpose, value.Length(), value.Data());
}
////////////////
private:
void VertexAttribI4iv(GLuint index, size_t length, const GLint* v);

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

@ -12,26 +12,26 @@
namespace mozilla {
bool
WebGL2Context::ValidateBufferTarget(GLenum target, const char* info)
WebGL2Context::ValidateBufferTarget(GLenum target, const char* funcName)
{
switch (target) {
case LOCAL_GL_ARRAY_BUFFER:
case LOCAL_GL_COPY_READ_BUFFER:
case LOCAL_GL_COPY_WRITE_BUFFER:
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
case LOCAL_GL_UNIFORM_BUFFER:
return true;
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
ErrorInvalidOperation("%s: PBOs are still under development, and are currently"
" disabled.",
info);
funcName);
return false;
default:
ErrorInvalidEnumInfo(info, target);
ErrorInvalidEnumInfo(funcName, target);
return false;
}
}
@ -80,11 +80,12 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
GLintptr readOffset, GLintptr writeOffset,
GLsizeiptr size)
{
const char funcName[] = "copyBufferSubData";
if (IsContextLost())
return;
if (!ValidateBufferTarget(readTarget, "copyBufferSubData") ||
!ValidateBufferTarget(writeTarget, "copyBufferSubData"))
if (!ValidateBufferTarget(readTarget, funcName) ||
!ValidateBufferTarget(writeTarget, funcName))
{
return;
}
@ -95,27 +96,25 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
return;
const WebGLBuffer* readBuffer = readBufferSlot.get();
if (!readBuffer)
return ErrorInvalidOperation("copyBufferSubData: No buffer bound to readTarget");
if (!readBuffer) {
ErrorInvalidOperation("%s: No buffer bound to readTarget.", funcName);
return;
}
WebGLBuffer* writeBuffer = writeBufferSlot.get();
if (!writeBuffer)
return ErrorInvalidOperation("copyBufferSubData: No buffer bound to writeTarget");
if (!ValidateDataOffsetSize(readOffset, size, readBuffer->ByteLength(),
"copyBufferSubData"))
{
if (!writeBuffer) {
ErrorInvalidOperation("%s: No buffer bound to writeTarget.", funcName);
return;
}
if (!ValidateDataOffsetSize(writeOffset, size, writeBuffer->ByteLength(),
"copyBufferSubData"))
{
if (!ValidateDataOffsetSize(readOffset, size, readBuffer->ByteLength(), funcName))
return;
if (!ValidateDataOffsetSize(writeOffset, size, writeBuffer->ByteLength(), funcName))
return;
}
if (readTarget == writeTarget &&
!ValidateDataRanges(readOffset, writeOffset, size, "copyBufferSubData"))
!ValidateDataRanges(readOffset, writeOffset, size, funcName))
{
return;
}
@ -127,9 +126,12 @@ WebGL2Context::CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
writeType != WebGLBuffer::Kind::Undefined &&
writeType != readType)
{
ErrorInvalidOperation("copyBufferSubData: Can't copy %s data to %s data",
(readType == WebGLBuffer::Kind::OtherData) ? "other" : "element",
(writeType == WebGLBuffer::Kind::OtherData) ? "other" : "element");
ErrorInvalidOperation("%s: Can't copy %s data to %s data.",
funcName,
(readType == WebGLBuffer::Kind::OtherData) ? "other"
: "element",
(writeType == WebGLBuffer::Kind::OtherData) ? "other"
: "element");
return;
}
@ -150,6 +152,7 @@ template<typename BufferT>
void
WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT& data)
{
const char funcName[] = "getBufferSubData";
if (IsContextLost())
return;
@ -159,18 +162,22 @@ WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT&
// If zero is bound to target, an INVALID_OPERATION error is
// generated.
if (!ValidateBufferTarget(target, "getBufferSubData"))
if (!ValidateBufferTarget(target, funcName))
return;
// If offset is less than zero, an INVALID_VALUE error is
// generated.
if (offset < 0)
return ErrorInvalidValue("getBufferSubData: negative offset");
if (offset < 0) {
ErrorInvalidValue("%s: Offset must be non-negative.", funcName);
return;
}
WebGLRefPtr<WebGLBuffer>& bufferSlot = GetBufferSlotByTarget(target);
WebGLBuffer* boundBuffer = bufferSlot.get();
if (!boundBuffer)
return ErrorInvalidOperation("getBufferSubData: no buffer bound");
if (!boundBuffer) {
ErrorInvalidOperation("%s: No buffer bound.", funcName);
return;
}
// If offset + returnedData.byteLength would extend beyond the end
// of the buffer an INVALID_VALUE error is generated.
@ -178,15 +185,15 @@ WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT&
CheckedInt<WebGLsizeiptr> neededByteLength = CheckedInt<WebGLsizeiptr>(offset) + data.LengthAllowShared();
if (!neededByteLength.isValid()) {
ErrorInvalidValue("getBufferSubData: Integer overflow computing the needed"
" byte length.");
ErrorInvalidValue("%s: Integer overflow computing the needed byte length.",
funcName);
return;
}
if (neededByteLength.value() > boundBuffer->ByteLength()) {
ErrorInvalidValue("getBufferSubData: Not enough data. Operation requires"
" %d bytes, but buffer only has %d bytes.",
neededByteLength.value(), boundBuffer->ByteLength());
ErrorInvalidValue("%s: Not enough data. Operation requires %d bytes, but buffer"
" only has %d bytes.",
funcName, neededByteLength.value(), boundBuffer->ByteLength());
return;
}
@ -195,9 +202,11 @@ WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT&
// is generated.
WebGLTransformFeedback* currentTF = mBoundTransformFeedback;
if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER && currentTF) {
if (currentTF->mIsActive)
return ErrorInvalidOperation("getBufferSubData: Currently bound transform"
" feedback is active");
if (currentTF->mIsActive) {
ErrorInvalidOperation("%s: Currently bound transform feedback is active.",
funcName);
return;
}
// https://github.com/NVIDIA/WebGL/commit/63aff5e58c1d79825a596f0f4aa46174b9a5f72c
// Performing reads and writes on a buffer that is currently
@ -218,30 +227,37 @@ WebGL2Context::GetBufferSubDataT(GLenum target, GLintptr offset, const BufferT&
* bound to a transform feedback binding point.
*/
void* ptr = gl->fMapBufferRange(target, offset, data.LengthAllowShared(), LOCAL_GL_MAP_READ_BIT);
void* ptr = gl->fMapBufferRange(target, offset, data.LengthAllowShared(),
LOCAL_GL_MAP_READ_BIT);
// Warning: Possibly shared memory. See bug 1225033.
memcpy(data.DataAllowShared(), ptr, data.LengthAllowShared());
gl->fUnmapBuffer(target);
////
if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER && currentTF) {
BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, currentTF);
}
}
void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::Nullable<dom::ArrayBuffer>& maybeData)
void
WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::Nullable<dom::ArrayBuffer>& maybeData)
{
// If returnedData is null then an INVALID_VALUE error is
// generated.
if (maybeData.IsNull())
return ErrorInvalidValue("getBufferSubData: returnedData is null");
if (maybeData.IsNull()) {
ErrorInvalidValue("getBufferSubData: returnedData is null");
return;
}
const dom::ArrayBuffer& data = maybeData.Value();
GetBufferSubDataT(target, offset, data);
}
void WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::SharedArrayBuffer& data)
void
WebGL2Context::GetBufferSubData(GLenum target, GLintptr offset,
const dom::SharedArrayBuffer& data)
{
GetBufferSubDataT(target, offset, data);
}

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

@ -11,6 +11,7 @@
#include "WebGLBuffer.h"
#include "WebGLContext.h"
#include "WebGLProgram.h"
#include "WebGLUniformLocation.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
@ -28,220 +29,42 @@ WebGL2Context::ValidateUniformMatrixTranspose(bool /*transpose*/, const char* /*
void
WebGL2Context::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
{
GLuint rawLoc;
if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui", &rawLoc))
if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui"))
return;
MakeContextCurrent();
gl->fUniform1ui(rawLoc, v0);
gl->fUniform1ui(loc->mLoc, v0);
}
void
WebGL2Context::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1)
{
GLuint rawLoc;
if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui", &rawLoc))
if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui"))
return;
MakeContextCurrent();
gl->fUniform2ui(rawLoc, v0, v1);
gl->fUniform2ui(loc->mLoc, v0, v1);
}
void
WebGL2Context::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2)
{
GLuint rawLoc;
if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui", &rawLoc))
if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui"))
return;
MakeContextCurrent();
gl->fUniform3ui(rawLoc, v0, v1, v2);
gl->fUniform3ui(loc->mLoc, v0, v1, v2);
}
void
WebGL2Context::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
WebGL2Context::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
GLuint v3)
{
GLuint rawLoc;
if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui", &rawLoc))
if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui"))
return;
MakeContextCurrent();
gl->fUniform4ui(rawLoc, v0, v1, v2, v3);
}
void
WebGL2Context::Uniform1uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLuint* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformArraySetter(loc, 1, LOCAL_GL_UNSIGNED_INT, arrayLength,
"uniform1uiv", &rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniform1uiv(rawLoc, numElementsToUpload, data);
}
void
WebGL2Context::Uniform2uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLuint* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformArraySetter(loc, 2, LOCAL_GL_UNSIGNED_INT, arrayLength,
"uniform2uiv", &rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniform2uiv(rawLoc, numElementsToUpload, data);
}
void
WebGL2Context::Uniform3uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLuint* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformArraySetter(loc, 3, LOCAL_GL_UNSIGNED_INT, arrayLength,
"uniform3uiv", &rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniform1uiv(rawLoc, numElementsToUpload, data);
}
void
WebGL2Context::Uniform4uiv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLuint* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformArraySetter(loc, 4, LOCAL_GL_UNSIGNED_INT, arrayLength,
"uniform4uiv", &rawLoc, &numElementsToUpload)) {
return;
}
MakeContextCurrent();
gl->fUniform4uiv(rawLoc, numElementsToUpload, data);
}
void
WebGL2Context::UniformMatrix2x3fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformMatrixArraySetter(loc, 2, 3, LOCAL_GL_FLOAT, arrayLength,
transpose, "uniformMatrix2x3fv",
&rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniformMatrix2x3fv(rawLoc, numElementsToUpload, transpose, data);
}
void
WebGL2Context::UniformMatrix2x4fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformMatrixArraySetter(loc, 2, 4, LOCAL_GL_FLOAT, arrayLength,
transpose, "uniformMatrix2x4fv",
&rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniformMatrix2x4fv(rawLoc, numElementsToUpload, transpose, data);
}
void
WebGL2Context::UniformMatrix3x2fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformMatrixArraySetter(loc, 3, 2, LOCAL_GL_FLOAT, arrayLength,
transpose, "uniformMatrix3x2fv",
&rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniformMatrix3x2fv(rawLoc, numElementsToUpload, transpose, data);
}
void
WebGL2Context::UniformMatrix3x4fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformMatrixArraySetter(loc, 3, 4, LOCAL_GL_FLOAT, arrayLength,
transpose, "uniformMatrix3x4fv",
&rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniformMatrix3x4fv(rawLoc, numElementsToUpload, transpose, data);
}
void
WebGL2Context::UniformMatrix4x2fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformMatrixArraySetter(loc, 4, 2, LOCAL_GL_FLOAT, arrayLength,
transpose, "uniformMatrix4x2fv",
&rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniformMatrix4x2fv(rawLoc, numElementsToUpload, transpose, data);
}
void
WebGL2Context::UniformMatrix4x3fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const GLfloat* data)
{
GLuint rawLoc;
GLsizei numElementsToUpload;
if (!ValidateUniformMatrixArraySetter(loc, 4, 3, LOCAL_GL_FLOAT, arrayLength,
transpose, "uniformMatrix4x3fv",
&rawLoc, &numElementsToUpload))
{
return;
}
MakeContextCurrent();
gl->fUniformMatrix4x3fv(rawLoc, numElementsToUpload, transpose, data);
gl->fUniform4ui(loc->mLoc, v0, v1, v2, v3);
}

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

@ -9,7 +9,7 @@
namespace mozilla {
uint8_t
static uint8_t
ElemSizeFromType(GLenum elemType)
{
switch (elemType) {
@ -76,6 +76,8 @@ ElemSizeFromType(GLenum elemType)
}
}
////////////////////
WebGLActiveInfo::WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType,
bool isArray, const nsACString& baseUserName,
const nsACString& baseMappedName)
@ -88,6 +90,32 @@ WebGLActiveInfo::WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum el
, mBaseMappedName(baseMappedName)
{ }
bool
WebGLActiveInfo::IsSampler() const
{
switch (mElemType) {
case LOCAL_GL_SAMPLER_2D:
case LOCAL_GL_SAMPLER_3D:
case LOCAL_GL_SAMPLER_CUBE:
case LOCAL_GL_SAMPLER_2D_SHADOW:
case LOCAL_GL_SAMPLER_2D_ARRAY:
case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW:
case LOCAL_GL_SAMPLER_CUBE_SHADOW:
case LOCAL_GL_INT_SAMPLER_2D:
case LOCAL_GL_INT_SAMPLER_3D:
case LOCAL_GL_INT_SAMPLER_CUBE:
case LOCAL_GL_INT_SAMPLER_2D_ARRAY:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
return true;
default:
return false;
}
}
////////////////////////////////////////////////////////////////////////////////
JSObject*

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

@ -30,11 +30,10 @@ public:
return mWebGL;
}
WebGLContext* const mWebGL;
// ActiveInfo state:
const GLint mElemCount; // `size`
const uint32_t mElemCount; // `size`
const GLenum mElemType; // `type`
const nsCString mBaseUserName; // `name`, but ASCII, and without any final "[0]".
@ -43,6 +42,8 @@ public:
const uint8_t mElemSize;
const nsCString mBaseMappedName; // Without any final "[0]".
bool IsSampler() const;
WebGLActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray,
const nsACString& baseUserName, const nsACString& baseMappedName);
@ -90,7 +91,7 @@ private:
//////////
uint8_t ElemSizeFromType(GLenum elemType);
bool IsElemTypeSampler(GLenum elemType);
} // namespace mozilla

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

@ -122,6 +122,7 @@ namespace webgl {
struct LinkedProgramInfo;
class ShaderValidator;
class TexUnpackBlob;
struct UniformInfo;
} // namespace webgl
WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
@ -539,9 +540,13 @@ public:
void PixelStorei(GLenum pname, GLint param);
void PolygonOffset(GLfloat factor, GLfloat units);
protected:
bool DoReadPixelsAndConvert(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum destFormat, GLenum destType, void* destBytes,
GLenum auxReadFormat, GLenum auxReadType);
bool ReadPixels_SharedPrecheck(ErrorResult* const out_error);
void ReadPixelsImpl(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
GLenum type, void* data, uint32_t dataLen);
bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat, GLint x, GLint y,
GLsizei width, GLsizei height, GLenum format,
GLenum destType, void* dest, uint32_t dataLen,
uint32_t rowStride);
public:
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
@ -565,160 +570,108 @@ public:
void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
GLenum dppass);
//////
void Uniform1i(WebGLUniformLocation* loc, GLint x);
void Uniform2i(WebGLUniformLocation* loc, GLint x, GLint y);
void Uniform3i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z);
void Uniform4i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z,
GLint w);
void Uniform4i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z, GLint w);
void Uniform1f(WebGLUniformLocation* loc, GLfloat x);
void Uniform2f(WebGLUniformLocation* loc, GLfloat x, GLfloat y);
void Uniform3f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z);
void Uniform4f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z,
GLfloat w);
void Uniform4f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
// Int array
void Uniform1iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform1iv_base(loc, arr.Length(), arr.Data());
}
void Uniform1iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& arr)
{
Uniform1iv_base(loc, arr.Length(), arr.Elements());
}
void Uniform1iv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLint* data);
//////////////////////////
void Uniform2iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform2iv_base(loc, arr.Length(), arr.Data());
}
void Uniform2iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& arr)
{
Uniform2iv_base(loc, arr.Length(), arr.Elements());
}
void Uniform2iv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLint* data);
protected:
template<typename elemT, typename arrT>
struct Arr {
size_t dataCount;
const elemT* data;
void Uniform3iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform3iv_base(loc, arr.Length(), arr.Data());
}
void Uniform3iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& arr)
{
Uniform3iv_base(loc, arr.Length(), arr.Elements());
}
void Uniform3iv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLint* data);
explicit Arr(const arrT& arr) {
arr.ComputeLengthAndData();
dataCount = arr.Length();
data = arr.Data();
}
void Uniform4iv(WebGLUniformLocation* loc, const dom::Int32Array& arr) {
arr.ComputeLengthAndData();
Uniform4iv_base(loc, arr.Length(), arr.Data());
}
void Uniform4iv(WebGLUniformLocation* loc,
const dom::Sequence<GLint>& arr)
{
Uniform4iv_base(loc, arr.Length(), arr.Elements());
}
void Uniform4iv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLint* data);
explicit Arr(const dom::Sequence<elemT>& arr) {
dataCount = arr.Length();
data = arr.Elements();
}
};
// Float array
void Uniform1fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform1fv_base(loc, arr.Length(), arr.Data());
}
void Uniform1fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& arr)
{
Uniform1fv_base(loc, arr.Length(), arr.Elements());
}
void Uniform1fv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLfloat* data);
typedef Arr<GLint, dom::Int32Array> IntArr;
typedef Arr<GLfloat, dom::Float32Array> FloatArr;
void Uniform2fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform2fv_base(loc, arr.Length(), arr.Data());
}
void Uniform2fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& arr)
{
Uniform2fv_base(loc, arr.Length(), arr.Elements());
}
void Uniform2fv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLfloat* data);
////////////////
void Uniform3fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform3fv_base(loc, arr.Length(), arr.Data());
}
void Uniform3fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& arr)
{
Uniform3fv_base(loc, arr.Length(), arr.Elements());
}
void Uniform3fv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLfloat* data);
void UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const IntArr& arr);
void Uniform4fv(WebGLUniformLocation* loc, const dom::Float32Array& arr) {
arr.ComputeLengthAndData();
Uniform4fv_base(loc, arr.Length(), arr.Data());
}
void Uniform4fv(WebGLUniformLocation* loc,
const dom::Sequence<GLfloat>& arr)
{
Uniform4fv_base(loc, arr.Length(), arr.Elements());
}
void Uniform4fv_base(WebGLUniformLocation* loc, size_t arrayLength,
const GLfloat* data);
void UniformNfv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const FloatArr& arr);
// Matrix
void UniformMatrix2fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Float32Array& value)
{
value.ComputeLengthAndData();
UniformMatrix2fv_base(loc, transpose, value.Length(), value.Data());
}
void UniformMatrix2fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Sequence<float>& value)
{
UniformMatrix2fv_base(loc, transpose, value.Length(),
value.Elements());
}
void UniformMatrix2fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const float* data);
void UniformMatrixAxBfv(const char* funcName, uint8_t A, uint8_t B,
WebGLUniformLocation* loc, bool transpose,
const FloatArr& arr);
void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Float32Array& value)
{
value.ComputeLengthAndData();
UniformMatrix3fv_base(loc, transpose, value.Length(), value.Data());
}
void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Sequence<float>& value)
{
UniformMatrix3fv_base(loc, transpose, value.Length(), value.Elements());
}
void UniformMatrix3fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const float* data);
////////////////
void UniformMatrix4fv(WebGLUniformLocation* loc, WebGLboolean transpose,
const dom::Float32Array& value)
{
value.ComputeLengthAndData();
UniformMatrix4fv_base(loc, transpose, value.Length(), value.Data());
public:
template<typename T>
void Uniform1iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform1iv", 1, loc, IntArr(arr));
}
void UniformMatrix4fv(WebGLUniformLocation* loc, bool transpose,
const dom::Sequence<float>& value)
{
UniformMatrix4fv_base(loc, transpose, value.Length(),
value.Elements());
template<typename T>
void Uniform2iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform2iv", 2, loc, IntArr(arr));
}
void UniformMatrix4fv_base(WebGLUniformLocation* loc, bool transpose,
size_t arrayLength, const float* data);
template<typename T>
void Uniform3iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform3iv", 3, loc, IntArr(arr));
}
template<typename T>
void Uniform4iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform4iv", 4, loc, IntArr(arr));
}
//////
template<typename T>
void Uniform1fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform1fv", 1, loc, FloatArr(arr));
}
template<typename T>
void Uniform2fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform2fv", 2, loc, FloatArr(arr));
}
template<typename T>
void Uniform3fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform3fv", 3, loc, FloatArr(arr));
}
template<typename T>
void Uniform4fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform4fv", 4, loc, FloatArr(arr));
}
//////
template<typename T>
void UniformMatrix2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix2fv", 2, 2, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix3fv", 3, 3, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix4fv", 4, 4, loc, transpose, FloatArr(arr));
}
////////////////////////////////////
void UseProgram(WebGLProgram* prog);
@ -726,22 +679,19 @@ public:
uint32_t arrayLength);
bool ValidateUniformLocation(WebGLUniformLocation* loc, const char* funcName);
bool ValidateUniformSetter(WebGLUniformLocation* loc, uint8_t setterSize,
GLenum setterType, const char* info,
GLuint* out_rawLoc);
GLenum setterType, const char* funcName);
bool ValidateUniformArraySetter(WebGLUniformLocation* loc,
uint8_t setterElemSize, GLenum setterType,
size_t setterArraySize, const char* info,
GLuint* out_rawLoc,
GLsizei* out_numElementsToUpload);
uint32_t setterArraySize, const char* funcName,
uint32_t* out_numElementsToUpload);
bool ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
uint8_t setterCols,
uint8_t setterRows,
GLenum setterType,
size_t setterArraySize,
uint32_t setterArraySize,
bool setterTranspose,
const char* info,
GLuint* out_rawLoc,
GLsizei* out_numElementsToUpload);
const char* funcName,
uint32_t* out_numElementsToUpload);
void ValidateProgram(WebGLProgram* prog);
bool ValidateUniformLocation(const char* info, WebGLUniformLocation* loc);
bool ValidateSamplerUniformSetter(const char* info,
@ -1603,6 +1553,9 @@ public:
virtual UniquePtr<webgl::FormatUsageAuthority>
CreateFormatUsage(gl::GLContext* gl) const = 0;
const decltype(mBound2DTextures)* TexListForElemType(GLenum elemType) const;
// Friend list
friend class ScopedCopyTexImageSource;
friend class ScopedResolveTexturesForDraw;
@ -1611,6 +1564,7 @@ public:
friend class webgl::TexUnpackBytes;
friend class webgl::TexUnpackImage;
friend class webgl::TexUnpackSurface;
friend struct webgl::UniformInfo;
friend class WebGLTexture;
friend class WebGLFBAttachPoint;
friend class WebGLFramebuffer;

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

@ -42,26 +42,95 @@ public:
~ScopedResolveTexturesForDraw();
};
bool
WebGLTexture::IsFeedback(WebGLContext* webgl, const char* funcName, uint32_t texUnit,
const std::vector<const WebGLFBAttachPoint*>& fbAttachments) const
{
auto itr = fbAttachments.cbegin();
for (; itr != fbAttachments.cend(); ++itr) {
const auto& attach = *itr;
if (attach->Texture() == this)
break;
}
if (itr == fbAttachments.cend())
return false;
////
const auto minLevel = mBaseMipmapLevel;
uint32_t maxLevel;
if (!MaxEffectiveMipmapLevel(texUnit, &maxLevel)) {
// No valid mips. Will need fake-black.
return false;
}
////
for (; itr != fbAttachments.cend(); ++itr) {
const auto& attach = *itr;
if (attach->Texture() != this)
continue;
const auto dstLevel = attach->MipLevel();
if (minLevel <= dstLevel && dstLevel <= maxLevel) {
webgl->ErrorInvalidOperation("%s: Feedback loop detected between tex target"
" 0x%04x, tex unit %u, levels %u-%u; and"
" framebuffer attachment 0x%04x, level %u.",
funcName, mTarget.get(), texUnit, minLevel,
maxLevel, attach->mAttachmentPoint, dstLevel);
return true;
}
}
return false;
}
ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
const char* funcName,
bool* const out_error)
: mWebGL(webgl)
{
MOZ_ASSERT(webgl->gl->IsCurrent());
MOZ_ASSERT(mWebGL->gl->IsCurrent());
typedef decltype(WebGLContext::mBound2DTextures) TexturesT;
if (!mWebGL->mActiveProgramLinkInfo) {
mWebGL->ErrorInvalidOperation("%s: The current program is not linked.", funcName);
*out_error = true;
return;
}
const auto fnResolveAll = [this, funcName](const TexturesT& textures)
{
const auto len = textures.Length();
for (uint32_t texUnit = 0; texUnit < len; ++texUnit) {
WebGLTexture* tex = textures[texUnit];
std::vector<const WebGLFBAttachPoint*> fbAttachments;
if (mWebGL->mBoundDrawFramebuffer) {
const auto& fb = mWebGL->mBoundDrawFramebuffer;
fb->GatherAttachments(&fbAttachments);
}
MOZ_ASSERT(mWebGL->mActiveProgramLinkInfo);
const auto& uniformSamplers = mWebGL->mActiveProgramLinkInfo->uniformSamplers;
for (const auto& uniform : uniformSamplers) {
const auto& texList = *(uniform->mSamplerTexList);
for (const auto& texUnit : uniform->mSamplerValues) {
if (texUnit >= texList.Length())
continue;
const auto& tex = texList[texUnit];
if (!tex)
continue;
if (tex->IsFeedback(mWebGL, funcName, texUnit, fbAttachments)) {
*out_error = true;
return;
}
FakeBlackType fakeBlack;
if (!tex->ResolveForDraw(funcName, texUnit, &fakeBlack))
return false;
if (!tex->ResolveForDraw(funcName, texUnit, &fakeBlack)) {
mWebGL->ErrorOutOfMemory("%s: Failed to resolve textures for draw.",
funcName);
*out_error = true;
return;
}
if (fakeBlack == FakeBlackType::None)
continue;
@ -69,21 +138,9 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
mWebGL->BindFakeBlack(texUnit, tex->Target(), fakeBlack);
mRebindRequests.push_back({texUnit, tex});
}
return true;
};
bool ok = true;
ok &= fnResolveAll(mWebGL->mBound2DTextures);
ok &= fnResolveAll(mWebGL->mBoundCubeMapTextures);
ok &= fnResolveAll(mWebGL->mBound3DTextures);
ok &= fnResolveAll(mWebGL->mBound2DArrayTextures);
if (!ok) {
mWebGL->ErrorOutOfMemory("%s: Failed to resolve textures for draw.", funcName);
}
*out_error = !ok;
*out_error = false;
}
ScopedResolveTexturesForDraw::~ScopedResolveTexturesForDraw()
@ -195,12 +252,6 @@ WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
return false;
}
// Any checks below this depend on a program being available.
if (!mCurrentProgram) {
ErrorInvalidOperation("%s: null CURRENT_PROGRAM", info);
return false;
}
if (!ValidateBufferFetching(info)) {
return false;
}
@ -360,14 +411,6 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type,
return false;
}
// Any checks below this depend on mActiveProgramLinkInfo being available.
if (!mActiveProgramLinkInfo) {
// Technically, this will only be null iff CURRENT_PROGRAM is null.
// But it's better to branch on what we actually care about.
ErrorInvalidOperation("%s: null CURRENT_PROGRAM", info);
return false;
}
if (!mBoundVertexArray->mElementArrayBuffer) {
ErrorInvalidOperation("%s: must have element array buffer binding", info);
return false;
@ -603,8 +646,8 @@ WebGLContext::ValidateBufferFetching(const char* info)
mBufferFetch_IsAttrib0Active = false;
for (const auto& pair : mActiveProgramLinkInfo->activeAttribLocs) {
const uint32_t attribLoc = pair.second;
for (const auto& attrib : mActiveProgramLinkInfo->attribs) {
const auto& attribLoc = attrib.mLoc;
if (attribLoc >= attribCount)
continue;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -437,7 +437,7 @@ WebGLContext::ValidateUniformLocation(WebGLUniformLocation* loc, const char* fun
return false;
}
return loc->ValidateForProgram(mCurrentProgram, this, funcName);
return loc->ValidateForProgram(mCurrentProgram, funcName);
}
bool
@ -459,7 +459,7 @@ WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t setterElemSiz
bool
WebGLContext::ValidateUniformSetter(WebGLUniformLocation* loc,
uint8_t setterElemSize, GLenum setterType,
const char* funcName, GLuint* out_rawLoc)
const char* funcName)
{
if (IsContextLost())
return false;
@ -467,10 +467,9 @@ WebGLContext::ValidateUniformSetter(WebGLUniformLocation* loc,
if (!ValidateUniformLocation(loc, funcName))
return false;
if (!loc->ValidateSizeAndType(setterElemSize, setterType, this, funcName))
if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
return false;
*out_rawLoc = loc->mLoc;
return true;
}
@ -478,10 +477,9 @@ bool
WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation* loc,
uint8_t setterElemSize,
GLenum setterType,
size_t setterArraySize,
uint32_t setterArraySize,
const char* funcName,
GLuint* const out_rawLoc,
GLsizei* const out_numElementsToUpload)
uint32_t* const out_numElementsToUpload)
{
if (IsContextLost())
return false;
@ -489,16 +487,18 @@ WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation* loc,
if (!ValidateUniformLocation(loc, funcName))
return false;
if (!loc->ValidateSizeAndType(setterElemSize, setterType, this, funcName))
if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
return false;
if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, this, funcName))
if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, funcName))
return false;
MOZ_ASSERT((size_t)loc->mActiveInfo->mElemCount > loc->mArrayIndex);
size_t uniformElemCount = loc->mActiveInfo->mElemCount - loc->mArrayIndex;
*out_rawLoc = loc->mLoc;
*out_numElementsToUpload = std::min(uniformElemCount, setterArraySize / setterElemSize);
const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount;
MOZ_ASSERT(elemCount > loc->mArrayIndex);
const uint32_t uniformElemCount = elemCount - loc->mArrayIndex;
*out_numElementsToUpload = std::min(uniformElemCount,
setterArraySize / setterElemSize);
return true;
}
@ -507,13 +507,12 @@ WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
uint8_t setterCols,
uint8_t setterRows,
GLenum setterType,
size_t setterArraySize,
uint32_t setterArraySize,
bool setterTranspose,
const char* funcName,
GLuint* const out_rawLoc,
GLsizei* const out_numElementsToUpload)
uint32_t* const out_numElementsToUpload)
{
uint8_t setterElemSize = setterCols * setterRows;
const uint8_t setterElemSize = setterCols * setterRows;
if (IsContextLost())
return false;
@ -521,20 +520,21 @@ WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
if (!ValidateUniformLocation(loc, funcName))
return false;
if (!loc->ValidateSizeAndType(setterElemSize, setterType, this, funcName))
if (!loc->ValidateSizeAndType(setterElemSize, setterType, funcName))
return false;
if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, this, funcName))
if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, funcName))
return false;
if (!ValidateUniformMatrixTranspose(setterTranspose, funcName))
return false;
MOZ_ASSERT((size_t)loc->mActiveInfo->mElemCount > loc->mArrayIndex);
size_t uniformElemCount = loc->mActiveInfo->mElemCount - loc->mArrayIndex;
*out_rawLoc = loc->mLoc;
*out_numElementsToUpload = std::min(uniformElemCount, setterArraySize / setterElemSize);
const auto& elemCount = loc->mInfo->mActiveInfo->mElemCount;
MOZ_ASSERT(elemCount > loc->mArrayIndex);
const uint32_t uniformElemCount = elemCount - loc->mArrayIndex;
*out_numElementsToUpload = std::min(uniformElemCount,
setterArraySize / setterElemSize);
return true;
}

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

@ -440,24 +440,28 @@ FormatInfo::GetCopyDecayFormat(UnsizedFormat uf) const
return FindOrNull(this->copyDecayFormats, uf);
}
uint8_t
BytesPerPixel(const PackingInfo& packing)
bool
GetBytesPerPixel(const PackingInfo& packing, uint8_t* const out_bytes)
{
uint8_t bytesPerChannel;
switch (packing.type) {
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
return 2;
*out_bytes = 2;
return true;
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
case LOCAL_GL_UNSIGNED_INT_24_8:
case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
return 4;
*out_bytes = 4;
return true;
case LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
return 8;
*out_bytes = 8;
return true;
// Alright, that's all the fixed-size unpackTypes.
@ -480,11 +484,20 @@ BytesPerPixel(const PackingInfo& packing)
break;
default:
MOZ_CRASH("GFX: invalid PackingInfo");
return false;
}
uint8_t channels;
switch (packing.format) {
case LOCAL_GL_RED:
case LOCAL_GL_RED_INTEGER:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_ALPHA:
case LOCAL_GL_DEPTH_COMPONENT:
channels = 1;
break;
case LOCAL_GL_RG:
case LOCAL_GL_RG_INTEGER:
case LOCAL_GL_LUMINANCE_ALPHA:
@ -493,23 +506,36 @@ BytesPerPixel(const PackingInfo& packing)
case LOCAL_GL_RGB:
case LOCAL_GL_RGB_INTEGER:
case LOCAL_GL_SRGB:
channels = 3;
break;
case LOCAL_GL_BGRA:
case LOCAL_GL_RGBA:
case LOCAL_GL_RGBA_INTEGER:
case LOCAL_GL_SRGB_ALPHA:
channels = 4;
break;
default:
channels = 1;
break;
return false;
}
return bytesPerChannel * channels;
*out_bytes = bytesPerChannel * channels;
return true;
}
uint8_t
BytesPerPixel(const PackingInfo& packing)
{
uint8_t ret;
if (MOZ_LIKELY(GetBytesPerPixel(packing, &ret)))
return ret;
gfxCriticalError() << "Bad `packing`: " << gfx::hexa(packing.format) << ", "
<< gfx::hexa(packing.type);
MOZ_CRASH("Bad `packing`.");
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

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

@ -254,6 +254,7 @@ struct DriverUnpackInfo
const FormatInfo* GetFormat(EffectiveFormat format);
uint8_t BytesPerPixel(const PackingInfo& packing);
bool GetBytesPerPixel(const PackingInfo& packing, uint8_t* const out_bytes);
/*
GLint ComponentSize(const FormatInfo* format, GLenum component);
GLenum ComponentType(const FormatInfo* format);

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

@ -1281,6 +1281,34 @@ WebGLFramebuffer::GetAttachmentParameter(const char* funcName, JSContext* cx,
out_error);
}
void
WebGLFramebuffer::GatherAttachments(std::vector<const WebGLFBAttachPoint*>* const out) const
{
auto itr = mDrawBuffers.cbegin();
if (itr != mDrawBuffers.cend() &&
*itr != LOCAL_GL_NONE)
{
out->push_back(&mColorAttachment0);
++itr;
}
size_t i = 0;
for (; itr != mDrawBuffers.cend(); ++itr) {
if (i >= mMoreColorAttachments.Size())
break;
if (*itr != LOCAL_GL_NONE) {
out->push_back(&mMoreColorAttachments[i]);
}
++i;
}
out->push_back(&mDepthAttachment);
out->push_back(&mStencilAttachment);
out->push_back(&mDepthStencilAttachment);
}
////////////////////////////////////////////////////////////////////////////////
// Goop.

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

@ -38,7 +38,7 @@ private:
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
TexImageTarget mTexImageTarget;
GLint mTexImageLayer;
GLint mTexImageLevel;
uint32_t mTexImageLevel;
// PlacementArray needs a default constructor.
template<typename T>
@ -89,7 +89,7 @@ public:
GLint Layer() const {
return mTexImageLayer;
}
GLint MipLevel() const {
uint32_t MipLevel() const {
return mTexImageLevel;
}
void AttachmentName(nsCString* out) const;
@ -259,6 +259,8 @@ public:
GLenum ReadBufferMode() const { return mReadBufferMode; }
void GatherAttachments(std::vector<const WebGLFBAttachPoint*>* const out) const;
protected:
WebGLFBAttachPoint* GetAttachPoint(GLenum attachment); // Fallible

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

@ -69,36 +69,60 @@ ParseName(const nsCString& name, nsCString* const out_baseName,
return true;
}
static WebGLActiveInfo*
AddActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArray,
const nsACString& baseUserName, const nsACString& baseMappedName,
std::vector<RefPtr<WebGLActiveInfo>>* activeInfoList,
std::map<nsCString, const WebGLActiveInfo*>* infoLocMap)
{
RefPtr<WebGLActiveInfo> info = new WebGLActiveInfo(webgl, elemCount, elemType,
isArray, baseUserName,
baseMappedName);
activeInfoList->push_back(info);
//////////
infoLocMap->insert(std::make_pair(info->mBaseUserName, info.get()));
return info.get();
/*static*/ const webgl::UniformInfo::TexListT*
webgl::UniformInfo::GetTexList(WebGLActiveInfo* activeInfo)
{
const auto& webgl = activeInfo->mWebGL;
switch (activeInfo->mElemType) {
case LOCAL_GL_SAMPLER_2D:
case LOCAL_GL_SAMPLER_2D_SHADOW:
case LOCAL_GL_INT_SAMPLER_2D:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D:
return &webgl->mBound2DTextures;
case LOCAL_GL_SAMPLER_CUBE:
case LOCAL_GL_SAMPLER_CUBE_SHADOW:
case LOCAL_GL_INT_SAMPLER_CUBE:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE:
return &webgl->mBoundCubeMapTextures;
case LOCAL_GL_SAMPLER_3D:
case LOCAL_GL_INT_SAMPLER_3D:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D:
return &webgl->mBound3DTextures;
case LOCAL_GL_SAMPLER_2D_ARRAY:
case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW:
case LOCAL_GL_INT_SAMPLER_2D_ARRAY:
case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
return &webgl->mBound2DArrayTextures;
default:
return nullptr;
}
}
static void
AddActiveBlockInfo(const nsACString& baseUserName,
const nsACString& baseMappedName,
std::vector<RefPtr<webgl::UniformBlockInfo>>* activeInfoList)
webgl::UniformInfo::UniformInfo(WebGLActiveInfo* activeInfo)
: mActiveInfo(activeInfo)
, mSamplerTexList(GetTexList(activeInfo))
{
RefPtr<webgl::UniformBlockInfo> info = new webgl::UniformBlockInfo(baseUserName, baseMappedName);
activeInfoList->push_back(info);
if (mSamplerTexList) {
mSamplerValues.assign(mActiveInfo->mElemCount, 0);
}
}
//////////
//#define DUMP_SHADERVAR_MAPPINGS
static already_AddRefed<const webgl::LinkedProgramInfo>
QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
{
WebGLContext* const webgl = prog->mContext;
RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog));
GLuint maxAttribLenWithNull = 0;
@ -154,33 +178,37 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
mappedName.SetLength(lengthWithoutNull);
// Collect ActiveInfos:
// Attribs can't be arrays, so we can skip some of the mess we have in the Uniform
// path.
nsDependentCString userName;
if (!prog->FindAttribUserNameByMappedName(mappedName, &userName))
userName.Rebind(mappedName, 0);
///////
const GLint loc = gl->fGetAttribLocation(prog->mGLName,
mappedName.BeginReading());
if (loc == -1) {
MOZ_ASSERT(mappedName == "gl_InstanceID",
"Active attrib should have a location.");
continue;
}
#ifdef DUMP_SHADERVAR_MAPPINGS
printf_stderr("[attrib %i] %s/%s\n", i, mappedName.BeginReading(),
printf_stderr("[attrib %i: %i] %s/%s\n", i, loc, mappedName.BeginReading(),
userName.BeginReading());
printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
#endif
const bool isArray = false;
const auto attrib = AddActiveInfo(prog->mContext, elemCount, elemType, isArray,
userName, mappedName, &info->activeAttribs,
&info->attribMap);
///////
// Collect active locations:
GLint loc = gl->fGetAttribLocation(prog->mGLName, mappedName.BeginReading());
if (loc == -1) {
if (mappedName != "gl_InstanceID")
MOZ_CRASH("GFX: Active attrib has no location.");
} else {
info->activeAttribLocs.insert({attrib, (GLuint)loc});
}
const bool isArray = false;
const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
elemType, isArray,
userName,
mappedName);
const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc)};
info->attribs.push_back(attrib);
}
// Uniforms
@ -203,6 +231,8 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
mappedName.SetLength(lengthWithoutNull);
///////
nsAutoCString baseMappedName;
bool isArray;
size_t arrayIndex;
@ -212,8 +242,11 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
// Note that for good drivers, `isArray` should already be correct.
// However, if FindUniform succeeds, it will be validator-guaranteed correct.
///////
nsAutoCString baseUserName;
if (!prog->FindUniformByMappedName(baseMappedName, &baseUserName, &isArray)) {
// Validator likely missing.
baseUserName = baseMappedName;
if (needsCheckForArrays && !isArray) {
@ -229,6 +262,8 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
}
}
///////
#ifdef DUMP_SHADERVAR_MAPPINGS
printf_stderr("[uniform %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
(int)isArray, baseMappedName.BeginReading(),
@ -237,11 +272,23 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
printf_stderr(" isArray: %d\n", (int)isArray);
#endif
AddActiveInfo(prog->mContext, elemCount, elemType, isArray, baseUserName,
baseMappedName, &info->activeUniforms, &info->uniformMap);
///////
const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
elemType, isArray,
baseUserName,
baseMappedName);
auto* uniform = new webgl::UniformInfo(activeInfo);
info->uniforms.push_back(uniform);
if (uniform->mSamplerTexList) {
info->uniformSamplers.push_back(uniform);
}
}
// Uniform Blocks
// (no sampler types allowed!)
if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
GLuint numActiveUniformBlocks = 0;
@ -281,14 +328,15 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
}
#ifdef DUMP_SHADERVAR_MAPPINGS
printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
(int)isArray, baseMappedName.BeginReading(),
baseUserName.BeginReading());
printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i,
mappedName.BeginReading(), (int)isArray,
baseMappedName.BeginReading(), baseUserName.BeginReading());
printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull);
printf_stderr(" isArray: %d\n", (int)isArray);
#endif
AddActiveBlockInfo(baseUserName, baseMappedName, &info->uniformBlocks);
const auto* block = new webgl::UniformBlockInfo(baseUserName, baseMappedName);
info->uniformBlocks.push_back(block);
}
}
@ -304,19 +352,23 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
mappedName.SetLength(maxTransformFeedbackVaryingLenWithNull - 1);
GLint lengthWithoutNull;
GLsizei size;
GLenum type;
gl->fGetTransformFeedbackVarying(prog->mGLName, i, maxTransformFeedbackVaryingLenWithNull,
&lengthWithoutNull, &size, &type,
GLsizei elemCount;
GLenum elemType;
gl->fGetTransformFeedbackVarying(prog->mGLName, i,
maxTransformFeedbackVaryingLenWithNull,
&lengthWithoutNull, &elemCount, &elemType,
mappedName.BeginWriting());
mappedName.SetLength(lengthWithoutNull);
////
nsAutoCString baseMappedName;
bool isArray;
size_t arrayIndex;
if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
nsAutoCString baseUserName;
if (!prog->FindVaryingByMappedName(mappedName, &baseUserName, &isArray)) {
baseUserName = baseMappedName;
@ -332,9 +384,15 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
}
}
AddActiveInfo(prog->mContext, size, type, isArray, baseUserName, mappedName,
&info->transformFeedbackVaryings,
&info->transformFeedbackVaryingsMap);
////
const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl,
elemCount,
elemType,
isArray,
baseUserName,
mappedName);
info->transformFeedbackVaryings.push_back(activeInfo);
}
}
@ -347,6 +405,16 @@ webgl::LinkedProgramInfo::LinkedProgramInfo(WebGLProgram* prog)
: prog(prog)
{ }
webgl::LinkedProgramInfo::~LinkedProgramInfo()
{
for (auto& cur : uniforms) {
delete cur;
}
for (auto& cur : uniformBlocks) {
delete cur;
}
}
////////////////////////////////////////////////////////////////////////////////
// WebGLProgram
@ -487,15 +555,15 @@ WebGLProgram::GetActiveAttrib(GLuint index) const
return ret.forget();
}
const auto& activeList = mMostRecentLinkInfo->activeAttribs;
const auto& attribs = mMostRecentLinkInfo->attribs;
if (index >= activeList.size()) {
if (index >= attribs.size()) {
mContext->ErrorInvalidValue("`index` (%i) must be less than %s (%i).",
index, "ACTIVE_ATTRIBS", activeList.size());
index, "ACTIVE_ATTRIBS", attribs.size());
return nullptr;
}
RefPtr<WebGLActiveInfo> ret = activeList[index];
RefPtr<WebGLActiveInfo> ret = attribs[index].mActiveInfo;
return ret.forget();
}
@ -508,15 +576,15 @@ WebGLProgram::GetActiveUniform(GLuint index) const
return ret.forget();
}
const auto& activeList = mMostRecentLinkInfo->activeUniforms;
const auto& uniforms = mMostRecentLinkInfo->uniforms;
if (index >= activeList.size()) {
if (index >= uniforms.size()) {
mContext->ErrorInvalidValue("`index` (%i) must be less than %s (%i).",
index, "ACTIVE_UNIFORMS", activeList.size());
index, "ACTIVE_UNIFORMS", uniforms.size());
return nullptr;
}
RefPtr<WebGLActiveInfo> ret = activeList[index];
RefPtr<WebGLActiveInfo> ret = uniforms[index]->mActiveInfo;
return ret.forget();
}
@ -545,16 +613,11 @@ WebGLProgram::GetAttribLocation(const nsAString& userName_wide) const
const NS_LossyConvertUTF16toASCII userName(userName_wide);
const WebGLActiveInfo* info;
const webgl::AttribInfo* info;
if (!LinkInfo()->FindAttrib(userName, &info))
return -1;
const nsCString& mappedName = info->mBaseMappedName;
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
return gl->fGetAttribLocation(mGLName, mappedName.BeginReading());
return GLint(info->mLoc);
}
GLint
@ -658,13 +721,12 @@ WebGLProgram::GetUniformBlockIndex(const nsAString& userName_wide) const
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
return LOCAL_GL_INVALID_INDEX;
RefPtr<const webgl::UniformBlockInfo> info;
const webgl::UniformBlockInfo* info;
if (!LinkInfo()->FindUniformBlock(baseUserName, &info)) {
return LOCAL_GL_INVALID_INDEX;
}
const nsCString& baseMappedName = info->mBaseMappedName;
nsAutoCString mappedName(baseMappedName);
nsAutoCString mappedName(info->mBaseMappedName);
if (isArray) {
mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex));
@ -799,13 +861,11 @@ WebGLProgram::GetUniformLocation(const nsAString& userName_wide) const
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
return nullptr;
const WebGLActiveInfo* activeInfo;
if (!LinkInfo()->FindUniform(baseUserName, &activeInfo))
webgl::UniformInfo* info;
if (!LinkInfo()->FindUniform(baseUserName, &info))
return nullptr;
const nsCString& baseMappedName = activeInfo->mBaseMappedName;
nsAutoCString mappedName(baseMappedName);
nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName);
if (isArray) {
mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex));
@ -820,8 +880,7 @@ WebGLProgram::GetUniformLocation(const nsAString& userName_wide) const
return nullptr;
RefPtr<WebGLUniformLocation> locObj = new WebGLUniformLocation(mContext, LinkInfo(),
loc, arrayIndex,
activeInfo);
info, loc, arrayIndex);
return locObj.forget();
}
@ -846,15 +905,13 @@ WebGLProgram::GetUniformIndices(const dom::Sequence<nsString>& uniformNames,
continue;
}
const WebGLActiveInfo* activeInfo;
if (!LinkInfo()->FindUniform(baseUserName, &activeInfo)) {
webgl::UniformInfo* info;
if (!LinkInfo()->FindUniform(baseUserName, &info)) {
arr.AppendElement(LOCAL_GL_INVALID_INDEX);
continue;
}
const nsCString& baseMappedName = activeInfo->mBaseMappedName;
nsAutoCString mappedName(baseMappedName);
nsAutoCString mappedName(info->mActiveInfo->mBaseMappedName);
if (isArray) {
mappedName.AppendLiteral("[");
mappedName.AppendInt(uint32_t(arrayIndex));
@ -879,8 +936,7 @@ WebGLProgram::UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockB
}
const webgl::LinkedProgramInfo* linkInfo = LinkInfo();
GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size();
if (uniformBlockIndex >= uniformBlockCount) {
if (uniformBlockIndex >= linkInfo->uniformBlocks.size()) {
mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex);
return;
}
@ -990,49 +1046,70 @@ WebGLProgram::LinkProgram()
}
}
static uint8_t
NumUsedLocationsByElemType(GLenum elemType)
{
// GLES 3.0.4 p55
switch (elemType) {
case LOCAL_GL_FLOAT_MAT2:
case LOCAL_GL_FLOAT_MAT2x3:
case LOCAL_GL_FLOAT_MAT2x4:
return 2;
case LOCAL_GL_FLOAT_MAT3x2:
case LOCAL_GL_FLOAT_MAT3:
case LOCAL_GL_FLOAT_MAT3x4:
return 3;
case LOCAL_GL_FLOAT_MAT4x2:
case LOCAL_GL_FLOAT_MAT4x3:
case LOCAL_GL_FLOAT_MAT4:
return 4;
default:
return 1;
}
}
bool
WebGLProgram::ValidateAfterTentativeLink(nsCString* const out_linkLog) const
{
const auto& linkInfo = mMostRecentLinkInfo;
// Check if the attrib name conflicting to uniform name
for (const auto& uniform : linkInfo->uniformMap) {
if (linkInfo->attribMap.find(uniform.first) != linkInfo->attribMap.end()) {
*out_linkLog = nsPrintfCString("The uniform name (%s) conflicts with"
" attribute name.",
uniform.first.get());
return false;
for (const auto& attrib : linkInfo->attribs) {
const auto& attribName = attrib.mActiveInfo->mBaseUserName;
for (const auto& uniform : linkInfo->uniforms) {
const auto& uniformName = uniform->mActiveInfo->mBaseUserName;
if (attribName == uniformName) {
*out_linkLog = nsPrintfCString("Attrib name conflicts with uniform name:"
" %s",
attribName.BeginReading());
return false;
}
}
}
std::map<GLuint, const WebGLActiveInfo*> attribsByLoc;
for (const auto& pair : linkInfo->activeAttribLocs) {
const auto dupe = attribsByLoc.find(pair.second);
if (dupe != attribsByLoc.end()) {
*out_linkLog = nsPrintfCString("Aliased location between active attribs"
" \"%s\" and \"%s\".",
dupe->second->mBaseUserName.BeginReading(),
pair.first->mBaseUserName.BeginReading());
return false;
}
}
std::map<uint32_t, const webgl::AttribInfo*> attribsByLoc;
for (const auto& attrib : linkInfo->attribs) {
const auto& elemType = attrib.mActiveInfo->mElemType;
const auto numUsedLocs = NumUsedLocationsByElemType(elemType);
for (uint32_t i = 0; i < numUsedLocs; i++) {
const uint32_t usedLoc = attrib.mLoc + i;
for (const auto& pair : attribsByLoc) {
const GLuint attribLoc = pair.first;
const auto attrib = pair.second;
const auto elemSize = ElemSizeFromType(attrib->mElemType);
const GLuint locationsUsed = (elemSize + 3) / 4;
for (GLuint i = 1; i < locationsUsed; i++) {
const GLuint usedLoc = attribLoc + i;
const auto dupe = attribsByLoc.find(usedLoc);
if (dupe != attribsByLoc.end()) {
*out_linkLog = nsPrintfCString("Attrib \"%s\" of type \"0x%04x\" aliases"
" \"%s\" by overhanging its location.",
attrib->mBaseUserName.BeginReading(),
attrib->mElemType,
dupe->second->mBaseUserName.BeginReading());
const auto res = attribsByLoc.insert({usedLoc, &attrib});
const bool& didInsert = res.second;
if (!didInsert) {
const auto& aliasingName = attrib.mActiveInfo->mBaseUserName;
const auto& itrExisting = res.first;
const auto& existingInfo = itrExisting->second;
const auto& existingName = existingInfo->mActiveInfo->mBaseUserName;
*out_linkLog = nsPrintfCString("Attrib \"%s\" aliases locations used by"
" attrib \"%s\".",
aliasingName.BeginReading(),
existingName.BeginReading());
return false;
}
}
@ -1234,6 +1311,50 @@ WebGLProgram::FindUniformBlockByMappedName(const nsACString& mappedName,
////////////////////////////////////////////////////////////////////////////////
bool
webgl::LinkedProgramInfo::FindAttrib(const nsCString& baseUserName,
const webgl::AttribInfo** const out) const
{
for (const auto& attrib : attribs) {
if (attrib.mActiveInfo->mBaseUserName == baseUserName) {
*out = &attrib;
return true;
}
}
return false;
}
bool
webgl::LinkedProgramInfo::FindUniform(const nsCString& baseUserName,
webgl::UniformInfo** const out) const
{
for (const auto& uniform : uniforms) {
if (uniform->mActiveInfo->mBaseUserName == baseUserName) {
*out = uniform;
return true;
}
}
return false;
}
bool
webgl::LinkedProgramInfo::FindUniformBlock(const nsCString& baseUserName,
const webgl::UniformBlockInfo** const out) const
{
for (const auto& block : uniformBlocks) {
if (block->mBaseUserName == baseUserName) {
*out = block;
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
JSObject*
WebGLProgram::WrapObject(JSContext* js, JS::Handle<JSObject*> givenProto)
{

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

@ -35,11 +35,30 @@ template<typename> class Sequence;
namespace webgl {
struct UniformBlockInfo final
: public RefCounted<UniformBlockInfo>
struct AttribInfo final
{
MOZ_DECLARE_REFCOUNTED_TYPENAME(UniformBlockInfo);
const RefPtr<WebGLActiveInfo> mActiveInfo;
uint32_t mLoc;
};
struct UniformInfo final
{
typedef decltype(WebGLContext::mBound2DTextures) TexListT;
const RefPtr<WebGLActiveInfo> mActiveInfo;
const TexListT* const mSamplerTexList;
std::vector<uint32_t> mSamplerValues;
protected:
static const TexListT*
GetTexList(WebGLActiveInfo* activeInfo);
public:
explicit UniformInfo(WebGLActiveInfo* activeInfo);
};
struct UniformBlockInfo final
{
const nsCString mBaseUserName;
const nsCString mBaseMappedName;
@ -57,61 +76,27 @@ struct LinkedProgramInfo final
MOZ_DECLARE_REFCOUNTED_TYPENAME(LinkedProgramInfo)
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(LinkedProgramInfo)
//////
WebGLProgram* const prog;
std::vector<RefPtr<WebGLActiveInfo>> activeAttribs;
std::vector<RefPtr<WebGLActiveInfo>> activeUniforms;
std::vector<AttribInfo> attribs;
std::vector<UniformInfo*> uniforms; // Owns its contents.
std::vector<const UniformBlockInfo*> uniformBlocks; // Owns its contents.
std::vector<RefPtr<WebGLActiveInfo>> transformFeedbackVaryings;
// Needed for Get{Attrib,Uniform}Location. The keys for these are non-mapped
// user-facing `GLActiveInfo::name`s, without any final "[0]".
std::map<nsCString, const WebGLActiveInfo*> attribMap;
std::map<nsCString, const WebGLActiveInfo*> uniformMap;
std::map<nsCString, const WebGLActiveInfo*> transformFeedbackVaryingsMap;
std::vector<RefPtr<UniformBlockInfo>> uniformBlocks;
// Needed for draw call validation.
std::map<const WebGLActiveInfo*, GLuint> activeAttribLocs;
std::vector<UniformInfo*> uniformSamplers;
//////
explicit LinkedProgramInfo(WebGLProgram* prog);
~LinkedProgramInfo();
bool FindAttrib(const nsCString& baseUserName,
const WebGLActiveInfo** const out_activeInfo) const
{
auto itr = attribMap.find(baseUserName);
if (itr == attribMap.end())
return false;
*out_activeInfo = itr->second;
return true;
}
bool FindUniform(const nsCString& baseUserName,
const WebGLActiveInfo** const out_activeInfo) const
{
auto itr = uniformMap.find(baseUserName);
if (itr == uniformMap.end())
return false;
*out_activeInfo = itr->second;
return true;
}
bool FindAttrib(const nsCString& baseUserName, const AttribInfo** const out) const;
bool FindUniform(const nsCString& baseUserName, UniformInfo** const out) const;
bool FindUniformBlock(const nsCString& baseUserName,
RefPtr<const UniformBlockInfo>* const out_info) const
{
const size_t count = uniformBlocks.size();
for (size_t i = 0; i < count; i++) {
if (baseUserName == uniformBlocks[i]->mBaseUserName) {
*out_info = uniformBlocks[i].get();
return true;
}
}
return false;
}
const UniformBlockInfo** const out) const;
};
} // namespace webgl

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

@ -195,7 +195,9 @@ WebGLTexture::IsMipmapComplete(uint32_t texUnit) const
MOZ_ASSERT(DoesMinFilterRequireMipmap());
// GLES 3.0.4, p161
const uint32_t maxLevel = MaxEffectiveMipmapLevel(texUnit);
uint32_t maxLevel;
if (!MaxEffectiveMipmapLevel(texUnit, &maxLevel))
return false;
// "* `level_base <= level_max`"
if (mBaseMipmapLevel > maxLevel)
@ -203,8 +205,6 @@ WebGLTexture::IsMipmapComplete(uint32_t texUnit) const
// Make a copy so we can modify it.
const ImageInfo& baseImageInfo = BaseImageInfo();
if (!baseImageInfo.IsDefined())
return false;
// Reference dimensions based on the current level.
uint32_t refWidth = baseImageInfo.mWidth;
@ -425,24 +425,26 @@ WebGLTexture::IsComplete(uint32_t texUnit, const char** const out_reason) const
return true;
}
uint32_t
WebGLTexture::MaxEffectiveMipmapLevel(uint32_t texUnit) const
bool
WebGLTexture::MaxEffectiveMipmapLevel(uint32_t texUnit, uint32_t* const out) const
{
WebGLSampler* sampler = mContext->mBoundSamplers[texUnit];
TexMinFilter minFilter = sampler ? sampler->mMinFilter : mMinFilter;
if (minFilter == LOCAL_GL_NEAREST ||
minFilter == LOCAL_GL_LINEAR)
{
// No mips used.
return mBaseMipmapLevel;
// No extra mips used.
*out = mBaseMipmapLevel;
return true;
}
const auto& imageInfo = BaseImageInfo();
MOZ_ASSERT(imageInfo.IsDefined());
if (!imageInfo.IsDefined())
return false;
uint32_t maxLevelBySize = mBaseMipmapLevel + imageInfo.MaxMipmapLevels() - 1;
return std::min<uint32_t>(maxLevelBySize, mMaxMipmapLevel);
uint32_t maxLevelBySize = mBaseMipmapLevel + imageInfo.PossibleMipmapLevels() - 1;
*out = std::min<uint32_t>(maxLevelBySize, mMaxMipmapLevel);
return true;
}
bool
@ -466,7 +468,9 @@ WebGLTexture::GetFakeBlackType(const char* funcName, uint32_t texUnit,
bool hasUninitializedData = false;
bool hasInitializedData = false;
const auto maxLevel = MaxEffectiveMipmapLevel(texUnit);
uint32_t maxLevel;
MOZ_ALWAYS_TRUE( MaxEffectiveMipmapLevel(texUnit, &maxLevel) );
MOZ_ASSERT(mBaseMipmapLevel <= maxLevel);
for (uint32_t level = mBaseMipmapLevel; level <= maxLevel; level++) {
for (uint8_t face = 0; face < mFaceCount; face++) {
@ -790,8 +794,8 @@ WebGLTexture::GenerateMipmap(TexTarget texTarget)
// Record the results.
// Note that we don't use MaxEffectiveMipmapLevel() here, since that returns
// mBaseMipmapLevel if the min filter doesn't require mipmaps.
const uint32_t lastLevel = mBaseMipmapLevel + baseImageInfo.MaxMipmapLevels() - 1;
PopulateMipChain(mBaseMipmapLevel, lastLevel);
const uint32_t maxLevel = mBaseMipmapLevel + baseImageInfo.PossibleMipmapLevels() - 1;
PopulateMipChain(mBaseMipmapLevel, maxLevel);
}
JS::Value

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

@ -154,9 +154,10 @@ public:
ImageInfo& operator =(const ImageInfo& a);
public:
uint32_t MaxMipmapLevels() const {
uint32_t PossibleMipmapLevels() const {
// GLES 3.0.4, 3.8 - Mipmapping: `floor(log2(largest_of_dims)) + 1`
uint32_t largest = std::max(std::max(mWidth, mHeight), mDepth);
const uint32_t largest = std::max(std::max(mWidth, mHeight), mDepth);
MOZ_ASSERT(largest != 0);
return FloorLog2Size(largest) + 1;
}
@ -288,7 +289,7 @@ protected:
void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel);
uint32_t MaxEffectiveMipmapLevel(uint32_t texUnit) const;
bool MaxEffectiveMipmapLevel(uint32_t texUnit, uint32_t* const out) const;
static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
GLenum rawTexImageTarget = texImageTarget.get();
@ -388,6 +389,9 @@ protected:
bool GetFakeBlackType(const char* funcName, uint32_t texUnit,
FakeBlackType* const out_fakeBlack);
public:
bool IsFeedback(WebGLContext* webgl, const char* funcName, uint32_t texUnit,
const std::vector<const WebGLFBAttachPoint*>& fbAttachments) const;
bool ResolveForDraw(const char* funcName, uint32_t texUnit,
FakeBlackType* const out_fakeBlack);

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

@ -16,34 +16,32 @@ namespace mozilla {
WebGLUniformLocation::WebGLUniformLocation(WebGLContext* webgl,
const webgl::LinkedProgramInfo* linkInfo,
GLuint loc,
size_t arrayIndex,
const WebGLActiveInfo* activeInfo)
webgl::UniformInfo* info, GLuint loc,
size_t arrayIndex)
: WebGLContextBoundObject(webgl)
, mLinkInfo(linkInfo)
, mInfo(info)
, mLoc(loc)
, mArrayIndex(arrayIndex)
, mActiveInfo(activeInfo)
{ }
WebGLUniformLocation::~WebGLUniformLocation()
{ }
bool
WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, WebGLContext* webgl,
const char* funcName) const
WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, const char* funcName) const
{
// Check the weak-pointer.
if (!mLinkInfo) {
webgl->ErrorInvalidOperation("%s: This uniform location is obsolete because its"
" program has been successfully relinked.",
funcName);
mContext->ErrorInvalidOperation("%s: This uniform location is obsolete because"
" its program has been successfully relinked.",
funcName);
return false;
}
if (mLinkInfo->prog != prog) {
webgl->ErrorInvalidOperation("%s: This uniform location corresponds to a"
" different program.", funcName);
mContext->ErrorInvalidOperation("%s: This uniform location corresponds to a"
" different program.", funcName);
return false;
}
@ -121,19 +119,22 @@ IsUniformSetterTypeValid(GLenum setterType, GLenum uniformType)
bool
WebGLUniformLocation::ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType,
WebGLContext* webgl, const char* funcName) const
const char* funcName) const
{
MOZ_ASSERT(mLinkInfo);
if (setterElemSize != mActiveInfo->mElemSize) {
webgl->ErrorInvalidOperation("%s: Bad uniform size: %i", funcName,
mActiveInfo->mElemSize);
const auto& uniformElemSize = mInfo->mActiveInfo->mElemSize;
if (setterElemSize != uniformElemSize) {
mContext->ErrorInvalidOperation("%s: Function used differs from uniform size: %i",
funcName, uniformElemSize);
return false;
}
if (!IsUniformSetterTypeValid(setterType, mActiveInfo->mElemType)) {
webgl->ErrorInvalidOperation("%s: Bad uniform type: %i", funcName,
mActiveInfo->mElemSize);
const auto& uniformElemType = mInfo->mActiveInfo->mElemType;
if (!IsUniformSetterTypeValid(setterType, uniformElemType)) {
mContext->ErrorInvalidOperation("%s: Function used is incompatible with uniform"
" type: %i",
funcName, uniformElemType);
return false;
}
@ -142,16 +143,16 @@ WebGLUniformLocation::ValidateSizeAndType(uint8_t setterElemSize, GLenum setterT
bool
WebGLUniformLocation::ValidateArrayLength(uint8_t setterElemSize, size_t setterArraySize,
WebGLContext* webgl, const char* funcName) const
const char* funcName) const
{
MOZ_ASSERT(mLinkInfo);
if (setterArraySize == 0 ||
setterArraySize % setterElemSize)
{
webgl->ErrorInvalidValue("%s: expected an array of length a multiple of"
" %d, got an array of length %d.",
funcName, setterElemSize, setterArraySize);
mContext->ErrorInvalidValue("%s: Expected an array of length a multiple of %d,"
" got an array of length %d.",
funcName, setterElemSize, setterArraySize);
return false;
}
@ -162,55 +163,34 @@ WebGLUniformLocation::ValidateArrayLength(uint8_t setterElemSize, size_t setterA
* highest array element index used, as reported by `GetActiveUniform`, will be
* ignored by GL.
*/
if (!mActiveInfo->mIsArray &&
if (!mInfo->mActiveInfo->mIsArray &&
setterArraySize != setterElemSize)
{
webgl->ErrorInvalidOperation("%s: expected an array of length exactly %d"
" (since this uniform is not an array"
" uniform), got an array of length %d.",
funcName, setterElemSize, setterArraySize);
mContext->ErrorInvalidOperation("%s: Expected an array of length exactly %d"
" (since this uniform is not an array uniform),"
" got an array of length %d.",
funcName, setterElemSize, setterArraySize);
return false;
}
return true;
}
bool
WebGLUniformLocation::ValidateSamplerSetter(GLint value, WebGLContext* webgl,
const char* funcName) const
{
MOZ_ASSERT(mLinkInfo);
if (mActiveInfo->mElemType != LOCAL_GL_SAMPLER_2D &&
mActiveInfo->mElemType != LOCAL_GL_SAMPLER_CUBE)
{
return true;
}
if (value >= 0 && value < (GLint)webgl->GLMaxTextureUnits())
return true;
webgl->ErrorInvalidValue("%s: This uniform location is a sampler, but %d is not a"
" valid texture unit.",
funcName, value);
return false;
}
JS::Value
WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
WebGLUniformLocation::GetUniform(JSContext* js) const
{
MOZ_ASSERT(mLinkInfo);
uint8_t elemSize = mActiveInfo->mElemSize;
const uint8_t elemSize = mInfo->mActiveInfo->mElemSize;
static const uint8_t kMaxElemSize = 16;
MOZ_ASSERT(elemSize <= kMaxElemSize);
GLuint prog = mLinkInfo->prog->mGLName;
gl::GLContext* gl = webgl->GL();
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
switch (mActiveInfo->mElemType) {
switch (mInfo->mActiveInfo->mElemType) {
case LOCAL_GL_INT:
case LOCAL_GL_INT_VEC2:
case LOCAL_GL_INT_VEC3:
@ -237,9 +217,9 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
if (elemSize == 1)
return JS::Int32Value(buffer[0]);
JSObject* obj = dom::Int32Array::Create(js, webgl, elemSize, buffer);
JSObject* obj = dom::Int32Array::Create(js, mContext, elemSize, buffer);
if (!obj) {
webgl->ErrorOutOfMemory("getUniform: out of memory");
mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return JS::ObjectOrNullValue(obj);
@ -263,7 +243,7 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
JS::RootedValue val(js);
// Be careful: we don't want to convert all of |uv|!
if (!dom::ToJSValue(js, boolBuffer, elemSize, &val)) {
webgl->ErrorOutOfMemory("getUniform: out of memory");
mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return val;
@ -289,9 +269,9 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
if (elemSize == 1)
return JS::DoubleValue(buffer[0]);
JSObject* obj = dom::Float32Array::Create(js, webgl, elemSize, buffer);
JSObject* obj = dom::Float32Array::Create(js, mContext, elemSize, buffer);
if (!obj) {
webgl->ErrorOutOfMemory("getUniform: out of memory");
mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return JS::ObjectOrNullValue(obj);
@ -308,9 +288,9 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const
if (elemSize == 1)
return JS::DoubleValue(buffer[0]); // This is Double because only Int32 is special cased.
JSObject* obj = dom::Uint32Array::Create(js, webgl, elemSize, buffer);
JSObject* obj = dom::Uint32Array::Create(js, mContext, elemSize, buffer);
if (!obj) {
webgl->ErrorOutOfMemory("getUniform: out of memory");
mContext->ErrorOutOfMemory("getUniform: Out of memory.");
return JS::NullValue();
}
return JS::ObjectOrNullValue(obj);

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

@ -39,24 +39,25 @@ public:
return mContext;
}
//////
const WeakPtr<const webgl::LinkedProgramInfo> mLinkInfo;
webgl::UniformInfo* const mInfo;
const GLuint mLoc;
const size_t mArrayIndex;
const WebGLActiveInfo* const mActiveInfo;
//////
WebGLUniformLocation(WebGLContext* webgl, const webgl::LinkedProgramInfo* linkInfo,
GLuint loc, size_t arrayIndex, const WebGLActiveInfo* activeInfo);
webgl::UniformInfo* info, GLuint loc, size_t arrayIndex);
bool ValidateForProgram(WebGLProgram* prog, WebGLContext* webgl,
const char* funcName) const;
bool ValidateSamplerSetter(GLint value, WebGLContext* webgl,
const char* funcName) const;
bool ValidateForProgram(WebGLProgram* prog, const char* funcName) const;
bool ValidateSizeAndType(uint8_t setterElemSize, GLenum setterType,
WebGLContext* webgl, const char* funcName) const;
const char* funcName) const;
bool ValidateArrayLength(uint8_t setterElemSize, size_t setterArraySize,
WebGLContext* webgl, const char* funcName) const;
const char* funcName) const;
JS::Value GetUniform(JSContext* js, WebGLContext* webgl) const;
JS::Value GetUniform(JSContext* js) const;
// Needed for certain helper functions like ValidateObject.
// `WebGLUniformLocation`s can't be 'Deleted' in the WebGL sense.

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

@ -5,12 +5,12 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
TEST_DIRS += [
'compiledtest',
'compiledtest',
'gtest'
]
# Change the following line(s) to avoid bug 1081323 (clobber after changing a manifest):
# * Add a regression test for triangle-then-point rendering.
# * Implement ReadPixel with PBOs.
MOCHITEST_MANIFESTS += [
'test/crash/mochitest.ini',

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

@ -6670,7 +6670,6 @@ fail-if = (os == 'android' && android_version == '10')
skip-if = (os == 'android') || (os == 'linux')
fail-if = (os == 'mac') || (os == 'win')
[generated/test_conformance__renderbuffers__feedback-loop.html]
fail-if = 1
[generated/test_conformance__renderbuffers__framebuffer-object-attachment.html]
skip-if = (os == 'android')
[generated/test_conformance__renderbuffers__framebuffer-state-restoration.html]

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

@ -36,9 +36,6 @@ fail-if = 1
fail-if = 1
[generated/test_conformance__glsl__misc__shaders-with-invariance.html]
fail-if = 1
[generated/test_conformance__glsl__misc__shaders-with-name-conflicts.html]
[generated/test_conformance__renderbuffers__feedback-loop.html]
fail-if = 1
####################
# Tests requesting non-local network connections.

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

@ -71,6 +71,7 @@ fail-if = (os == 'win' && os_version == '5.1')
[test_no_arr_points.html]
skip-if = android_version == '18' #Android 4.3 aws only; bug 1030942
[test_noprog_draw.html]
[test_pixel_pack_buffer.html]
[test_privileged_exts.html]
[test_renderer_strings.html]
[test_sab_with_webgl.html]

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

@ -0,0 +1,288 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='UTF-8'>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
</head>
<body>
<script>
var RED = [1, 0, 0, 1];
var GREEN = [0, 1, 0, 1];
var BLUE = [0, 0, 1, 1];
var WHITE = [1, 1, 1, 1];
var ZERO = [0, 0, 0, 0];
function DrawColors(gl) {
var fnClearToColor = function(color) {
gl.clearColor(color[0], color[1], color[2], color[3]);
gl.clear(gl.COLOR_BUFFER_BIT);
};
gl.enable(gl.SCISSOR_TEST);
// +---+
// |G W|
// |R B|
// +---+
gl.scissor(0, 0, 1, 1);
fnClearToColor(RED);
gl.scissor(1, 0, 1, 1);
fnClearToColor(BLUE);
gl.scissor(0, 1, 1, 1);
fnClearToColor(GREEN);
gl.scissor(1, 1, 1, 1);
fnClearToColor(WHITE);
}
function ClearBufferPair(gl, byteCount) {
// Using `null` here clears to zero according to WebGL.
gl.bufferData(gl.PIXEL_PACK_BUFFER, byteCount, gl.STREAM_READ);
var arr = new Uint8Array(byteCount);
return arr;
}
function ColorToString(color, offset=0) {
var arr = [ color[offset+0],
color[offset+1],
color[offset+2],
color[offset+3] ];
return '[' + arr.join(', ') + ']';
}
function TestIsUNormColor(refColor, testData, offset) {
if (testData.length < offset + 4) {
ok(false, 'testData not long enough.');
}
var refUNormColor = [
(refColor[0] * 255) | 0,
(refColor[1] * 255) | 0,
(refColor[2] * 255) | 0,
(refColor[3] * 255) | 0,
];
var refStr = ColorToString(refUNormColor);
var testStr = ColorToString(testData, offset);
ok(testStr == refStr, 'Expected ' + refStr + ', was ' + testStr + '.');
}
function section(text) {
ok(true, '');
ok(true, 'Section: ' + text);
}
function EnsureNoError(gl) {
var glErr = gl.getError();
while (gl.getError()) {}
if (!glErr)
return;
var extraInfo = '';
var err = new Error();
var stackStr = err.stack;
if (stackStr !== undefined) {
var stackArr = stackStr.split('\n');
stackStr = stackArr[1]; // First one after present scope.
extraInfo = ': ' + stackStr;
}
ok(false, 'Unexpected GL error: 0x' + glErr.toString(16) + extraInfo);
}
function TestError(gl, refErrVal, str='') {
if (str == '') {
str = 'gl.getError()';
} else {
str = str + ': gl.getError()';
}
var err = gl.getError();
while (gl.getError()) {}
ShouldBe(err.toString(16), refErrVal.toString(16), str);
}
function ShouldBe(val, ref, str='') {
if (str != '') {
str += ': ';
}
ok(val == ref, str + 'Should be `' + ref + '`, was `' + val + '`.');
}
var gl;
function Test() {
var canvas = document.createElement('canvas');
canvas.width = 2;
canvas.height = 2;
canvas.style = 'width: 256px; height: 256px; border: 1px solid black;';
document.body.appendChild(canvas);
var attribs = {
antialias: false,
alpha: false,
};
gl = canvas.getContext('webgl2', attribs);
if (!gl) {
todo(false, 'WebGL 2 not present, skipping.');
return;
}
////////
TestIsUNormColor(RED, new Uint8Array([255, 0, 0, 255]), 0);
////////
gl.clearColor(RED[0], RED[1], RED[2], RED[3]);
gl.clear(gl.COLOR_BUFFER_BIT);
var data = new Uint8Array(16);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log(JSON.stringify(data));
TestIsUNormColor(RED, data, 0);
////////
DrawColors(gl);
////////
EnsureNoError(gl);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, 0);
TestError(gl, gl.INVALID_OPERATION);
var data = new Uint8Array(16);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
EnsureNoError(gl);
TestIsUNormColor(RED, data, 0);
TestIsUNormColor(BLUE, data, 4);
TestIsUNormColor(GREEN, data, 8);
TestIsUNormColor(WHITE, data, 12);
////////
var a = gl.createBuffer();
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, a);
EnsureNoError(gl);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
TestError(gl, gl.INVALID_OPERATION);
////////
// Basic
section('Basic readback');
data = ClearBufferPair(gl, 16);
EnsureNoError(gl);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, 0);
EnsureNoError(gl);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data.buffer);
EnsureNoError(gl);
TestIsUNormColor(RED, data, 0);
TestIsUNormColor(BLUE, data, 4);
TestIsUNormColor(GREEN, data, 8);
TestIsUNormColor(WHITE, data, 12);
section('Subrect readback');
data = ClearBufferPair(gl, 8);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data.buffer);
EnsureNoError(gl);
TestIsUNormColor(WHITE, data, 0);
TestIsUNormColor(ZERO, data, 4);
section('ReadPixels offset:4');
data = ClearBufferPair(gl, 16);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 4);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data.buffer);
EnsureNoError(gl);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(WHITE, data, 4);
TestIsUNormColor(ZERO, data, 8);
TestIsUNormColor(ZERO, data, 12);
section('ReadPixels offset:5');
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 5);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data.buffer);
EnsureNoError(gl);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(WHITE, data, 4); // Should remain from previous read.
TestIsUNormColor(WHITE, data, 5);
TestIsUNormColor(ZERO, data, 9);
TestIsUNormColor(ZERO, data, 12);
section('GetBufferSubData src too small');
data = ClearBufferPair(gl, 16);
EnsureNoError(gl);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 1, data.buffer);
TestError(gl, gl.INVALID_VALUE);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(ZERO, data, 4);
TestIsUNormColor(ZERO, data, 8);
TestIsUNormColor(ZERO, data, 12);
section('GetBufferSubData offset:1');
data = new Uint8Array(15);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 8);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 1, data.buffer);
EnsureNoError(gl);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(ZERO, data, 3);
TestIsUNormColor(WHITE, data, 7);
TestIsUNormColor(ZERO, data, 11);
//////////////////////////////////////
section('Test packing state');
EnsureNoError(gl);
function TestPackState(enumStr, initialVal, changedVal) {
var enumVal = gl[enumStr];
ShouldBe(gl.getParameter(enumVal), initialVal, 'Initial ' + enumStr);
gl.pixelStorei(enumVal, changedVal);
ShouldBe(gl.getParameter(enumVal), changedVal, 'Changed ' + enumStr);
gl.pixelStorei(enumVal, initialVal);
ShouldBe(gl.getParameter(enumVal), initialVal, 'Reverted ' + enumStr);
EnsureNoError(gl);
}
TestPackState('PACK_ALIGNMENT', 4, 1);
TestPackState('PACK_ROW_LENGTH', 0, 16);
TestPackState('PACK_SKIP_PIXELS', 0, 3);
TestPackState('PACK_SKIP_ROWS', 0, 3);
}
function RunTest() {
Test();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
try {
var prefArrArr = [
['webgl.force-enabled', true],
['webgl.disable-angle', true],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, RunTest);
} catch (e) {
todo(false, 'No SpecialPowers, but trying anyway...');
RunTest();
}
</script>
</body>
</html>

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

@ -169,9 +169,12 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
nsContentUtils::IsCallerChrome());
AutoJSAPI jsapi;
jsapi.Init(aGlobal);
JSContext* cx = jsapi.cx();
if (!jsapi.Init(aGlobal)) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> jsGlobal(cx, aGlobal->GetGlobalJSObject());
GlobalObject global(cx, jsGlobal);
@ -1095,9 +1098,12 @@ FetchBody<Derived>::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength
MOZ_ASSERT(aResult);
AutoJSAPI jsapi;
jsapi.Init(DerivedClass()->GetParentObject());
JSContext* cx = jsapi.cx();
if (!jsapi.Init(DerivedClass()->GetParentObject())) {
localPromise->MaybeReject(NS_ERROR_UNEXPECTED);
return;
}
JSContext* cx = jsapi.cx();
ErrorResult error;
switch (mConsumeType) {

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

@ -51,9 +51,6 @@ HttpServer::Init(int32_t aPort, bool aHttps, HttpServerListener* aListener)
mHttps = aHttps;
mListener = aListener;
nsCOMPtr<nsIPrefBranch> prefService;
prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (mHttps) {
nsCOMPtr<nsILocalCertService> lcs =
do_CreateInstance("@mozilla.org/security/local-cert-service;1");

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

@ -261,7 +261,10 @@ nsBrowserElement::Download(const nsAString& aUrl,
nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
AutoJSAPI jsapi;
jsapi.Init(wrappedObj->GetJSObject());
if (!jsapi.Init(wrappedObj->GetJSObject())) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> options(cx);
aRv.MightThrowJSException();
@ -714,7 +717,10 @@ nsBrowserElement::ExecuteScript(const nsAString& aScript,
nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(mBrowserElementAPI);
MOZ_ASSERT(wrappedObj, "Failed to get wrapped JS from XPCOM component.");
AutoJSAPI jsapi;
jsapi.Init(wrappedObj->GetJSObject());
if (!jsapi.Init(wrappedObj->GetJSObject())) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> options(cx);
aRv.MightThrowJSException();

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

@ -129,6 +129,7 @@
#include "mozilla/dom/PCycleCollectWithLogsChild.h"
#include "nsIScriptSecurityManager.h"
#include "nsHostObjectProtocolHandler.h"
#ifdef MOZ_WEBRTC
#include "signaling/src/peerconnection/WebrtcGlobalChild.h"
@ -1241,11 +1242,10 @@ ContentChild::DeallocPAPZChild(PAPZChild* aActor)
return true;
}
PCompositorBridgeChild*
ContentChild::AllocPCompositorBridgeChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
bool
ContentChild::RecvInitCompositor(Endpoint<PCompositorBridgeChild>&& aEndpoint)
{
return CompositorBridgeChild::Create(aTransport, aOtherProcess);
return CompositorBridgeChild::InitForContent(Move(aEndpoint));
}
PSharedBufferManagerChild*
@ -2243,6 +2243,8 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
sFirstIdleTask->Cancel();
}
nsHostObjectProtocolHandler::RemoveDataEntries();
mAlertObservers.Clear();
mIdleObservers.Clear();
@ -2635,6 +2637,22 @@ ContentChild::RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig)
return true;
}
bool
ContentChild::RecvInitBlobURLs(nsTArray<BlobURLRegistrationData>&& aRegistrations)
{
for (uint32_t i = 0; i < aRegistrations.Length(); ++i) {
BlobURLRegistrationData& registration = aRegistrations[i];
RefPtr<BlobImpl> blobImpl =
static_cast<BlobChild*>(registration.blobChild())->GetBlobImpl();
MOZ_ASSERT(blobImpl);
nsHostObjectProtocolHandler::AddDataEntry(registration.url(), blobImpl,
registration.principal());
}
return true;
}
bool
ContentChild::RecvLastPrivateDocShellDestroyed()
{
@ -3373,6 +3391,25 @@ ContentChild::RecvNotifyPushSubscriptionModifiedObservers(const nsCString& aScop
return true;
}
bool
ContentChild::RecvBlobURLRegistration(const nsCString& aURI, PBlobChild* aBlobChild,
const IPC::Principal& aPrincipal)
{
RefPtr<BlobImpl> blobImpl = static_cast<BlobChild*>(aBlobChild)->GetBlobImpl();
MOZ_ASSERT(blobImpl);
nsHostObjectProtocolHandler::AddDataEntry(aURI, blobImpl, aPrincipal);
return true;
}
bool
ContentChild::RecvBlobURLUnregistration(const nsCString& aURI)
{
nsHostObjectProtocolHandler::RemoveDataEntry(aURI);
return true;
}
void
ContentChild::CreateGetFilesRequest(const nsAString& aDirectoryPath,
bool aRecursiveFlag,

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

@ -37,10 +37,6 @@ class PFileDescriptorSetChild;
class URIParams;
}// namespace ipc
namespace layers {
class PCompositorBridgeChild;
} // namespace layers
namespace dom {
class AlertObserver;
@ -152,9 +148,8 @@ public:
bool
DeallocPAPZChild(PAPZChild* aActor) override;
PCompositorBridgeChild*
AllocPCompositorBridgeChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
bool
RecvInitCompositor(Endpoint<PCompositorBridgeChild>&& aEndpoint) override;
PSharedBufferManagerChild*
AllocPSharedBufferManagerChild(mozilla::ipc::Transport* aTransport,
@ -462,6 +457,9 @@ public:
virtual bool
RecvInitServiceWorkers(const ServiceWorkerConfiguration& aConfig) override;
virtual bool
RecvInitBlobURLs(nsTArray<BlobURLRegistrationData>&& aRegistations) override;
virtual bool RecvLastPrivateDocShellDestroyed() override;
virtual bool RecvVolumes(InfallibleTArray<VolumeInfo>&& aVolumes) override;
@ -643,6 +641,13 @@ public:
RecvGetFilesResponse(const nsID& aUUID,
const GetFilesResponseResult& aResult) override;
virtual bool
RecvBlobURLRegistration(const nsCString& aURI, PBlobChild* aBlobChild,
const IPC::Principal& aPrincipal) override;
virtual bool
RecvBlobURLUnregistration(const nsCString& aURI) override;
private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
void StartForceKillTimer();

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

@ -191,6 +191,7 @@
#include "nsIBlocklistService.h"
#include "mozilla/StyleSheetHandle.h"
#include "mozilla/StyleSheetHandleInlines.h"
#include "nsHostObjectProtocolHandler.h"
#include "nsIBidiKeyboard.h"
@ -2059,6 +2060,13 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
if (mDriverCrashGuard) {
mDriverCrashGuard->NotifyCrashed();
}
// Unregister all the BlobURLs registered by the ContentChild.
for (uint32_t i = 0; i < mBlobURLs.Length(); ++i) {
nsHostObjectProtocolHandler::RemoveDataEntry(mBlobURLs[i]);
}
mBlobURLs.Clear();
}
void
@ -2422,8 +2430,13 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
// on demand.)
bool useOffMainThreadCompositing = !!CompositorThreadHolder::Loop();
if (useOffMainThreadCompositing) {
DebugOnly<bool> opened = PCompositorBridge::Open(this);
GPUProcessManager* gpm = GPUProcessManager::Get();
Endpoint<PCompositorBridgeChild> endpoint;
DebugOnly<bool> opened =
gpm->CreateContentCompositorBridge(OtherPid(), &endpoint);
MOZ_ASSERT(opened);
Unused << SendInitCompositor(Move(endpoint));
opened = PImageBridge::Open(this);
MOZ_ASSERT(opened);
@ -2513,13 +2526,22 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
}
#endif
RefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
MOZ_ASSERT(swr);
{
RefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
MOZ_ASSERT(swr);
nsTArray<ServiceWorkerRegistrationData> registrations;
swr->GetRegistrations(registrations);
nsTArray<ServiceWorkerRegistrationData> registrations;
swr->GetRegistrations(registrations);
Unused << SendInitServiceWorkers(ServiceWorkerConfiguration(registrations));
}
Unused << SendInitServiceWorkers(ServiceWorkerConfiguration(registrations));
{
nsTArray<BlobURLRegistrationData> registrations;
if (nsHostObjectProtocolHandler::GetAllBlobURLEntries(registrations,
this)) {
Unused << SendInitBlobURLs(registrations);
}
}
}
bool
@ -3210,14 +3232,6 @@ ContentParent::DeallocPAPZParent(PAPZParent* aActor)
return true;
}
PCompositorBridgeParent*
ContentParent::AllocPCompositorBridgeParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
{
return GPUProcessManager::Get()->CreateTabCompositorBridge(
aTransport, aOtherProcess);
}
gfx::PVRManagerParent*
ContentParent::AllocPVRManagerParent(Transport* aTransport,
ProcessId aOtherProcess)
@ -5696,6 +5710,73 @@ ContentParent::RecvNotifyLowMemory()
return true;
}
/* static */ void
ContentParent::BroadcastBlobURLRegistration(const nsACString& aURI,
BlobImpl* aBlobImpl,
nsIPrincipal* aPrincipal,
ContentParent* aIgnoreThisCP)
{
nsCString uri(aURI);
IPC::Principal principal(aPrincipal);
for (auto* cp : AllProcesses(eLive)) {
if (cp != aIgnoreThisCP) {
PBlobParent* blobParent = cp->GetOrCreateActorForBlobImpl(aBlobImpl);
if (blobParent) {
Unused << cp->SendBlobURLRegistration(uri, blobParent, principal);
}
}
}
}
/* static */ void
ContentParent::BroadcastBlobURLUnregistration(const nsACString& aURI,
ContentParent* aIgnoreThisCP)
{
nsCString uri(aURI);
for (auto* cp : AllProcesses(eLive)) {
if (cp != aIgnoreThisCP) {
Unused << cp->SendBlobURLUnregistration(uri);
}
}
}
bool
ContentParent::RecvStoreAndBroadcastBlobURLRegistration(const nsCString& aURI,
PBlobParent* aBlobParent,
const Principal& aPrincipal)
{
RefPtr<BlobImpl> blobImpl =
static_cast<BlobParent*>(aBlobParent)->GetBlobImpl();
if (NS_WARN_IF(!blobImpl)) {
return false;
}
if (NS_SUCCEEDED(nsHostObjectProtocolHandler::AddDataEntry(aURI, blobImpl,
aPrincipal))) {
BroadcastBlobURLRegistration(aURI, blobImpl, aPrincipal, this);
// We want to store this blobURL, so we can unregister it if the child
// crashes.
mBlobURLs.AppendElement(aURI);
}
BroadcastBlobURLRegistration(aURI, blobImpl, aPrincipal, this);
return true;
}
bool
ContentParent::RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aURI)
{
nsHostObjectProtocolHandler::RemoveDataEntry(aURI,
false /* Don't broadcast */);
BroadcastBlobURLUnregistration(aURI, this);
mBlobURLs.RemoveElement(aURI);
return true;
}
} // namespace dom
} // namespace mozilla

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

@ -66,7 +66,6 @@ class PJavaScriptParent;
} // namespace jsipc
namespace layers {
class PCompositorBridgeParent;
class PSharedBufferManagerParent;
struct TextureFactoryIdentifier;
} // namespace layers
@ -575,6 +574,24 @@ public:
static bool AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId);
static void
BroadcastBlobURLRegistration(const nsACString& aURI,
BlobImpl* aBlobImpl,
nsIPrincipal* aPrincipal,
ContentParent* aIgnoreThisCP = nullptr);
static void
BroadcastBlobURLUnregistration(const nsACString& aURI,
ContentParent* aIgnoreThisCP = nullptr);
virtual bool
RecvStoreAndBroadcastBlobURLRegistration(const nsCString& aURI,
PBlobParent* aBlobParent,
const Principal& aPrincipal) override;
virtual bool
RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aURI) override;
protected:
void OnChannelConnected(int32_t pid) override;
@ -728,10 +745,6 @@ private:
bool
DeallocPAPZParent(PAPZParent* aActor) override;
PCompositorBridgeParent*
AllocPCompositorBridgeParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
PImageBridgeParent*
AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
@ -1281,6 +1294,8 @@ private:
// This hashtable is used to run GetFilesHelper objects in the parent process.
// GetFilesHelper can be aborted by receiving RecvDeleteGetFilesRequest.
nsRefPtrHashtable<nsIDHashKey, GetFilesHelper> mGetFilesPendingRequests;
nsTArray<nsCString> mBlobURLs;
};
} // namespace dom

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

@ -373,11 +373,17 @@ union GetFilesResponseResult
GetFilesResponseFailure;
};
struct BlobURLRegistrationData
{
nsCString url;
PBlob blob;
Principal principal;
};
prio(normal upto urgent) sync protocol PContent
{
parent spawns PPluginModule;
parent opens PCompositorBridge;
parent opens PProcessHangMonitor;
parent opens PSharedBufferManager;
parent opens PImageBridge;
@ -464,6 +470,9 @@ both:
uint64_t aOuterWindowID);
child:
// Give the content process its endpoint to the compositor.
async InitCompositor(Endpoint<PCompositorBridgeChild> compositor);
/**
* Enable system-level sandboxing features, if available. Can
* usually only be performed zero or one times. The child may
@ -547,6 +556,11 @@ child:
*/
async InitServiceWorkers(ServiceWorkerConfiguration aConfig);
/**
* Send BlobURLRegistrationData to child process.
*/
async InitBlobURLs(BlobURLRegistrationData[] registrations);
// Notify child that last-pb-context-exited notification was observed
async LastPrivateDocShellDestroyed();
@ -676,6 +690,11 @@ child:
async GetFilesResponse(nsID aID, GetFilesResponseResult aResult);
async BlobURLRegistration(nsCString aURI, PBlob aBlob,
Principal aPrincipal);
async BlobURLUnregistration(nsCString aURI);
parent:
/**
* Tell the content process some attributes of itself. This is
@ -1188,6 +1207,11 @@ parent:
async GetFilesRequest(nsID aID, nsString aDirectory, bool aRecursiveFlag);
async DeleteGetFilesRequest(nsID aID);
async StoreAndBroadcastBlobURLRegistration(nsCString url, PBlob blob,
Principal principal);
async UnstoreAndBroadcastBlobURLUnregistration(nsCString url);
both:
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
Principal aPrincipal, ClonedMessageData aData);

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

@ -47,6 +47,16 @@ parent:
* on the chrome side. This is only currently used on Windows.
*/
sync SetNativeChildWindow(uintptr_t childWindow);
child:
/**
* Used to set the ID of a scroll capture container from the parent process,
* so that we can create a proxy container in the layer tree.
* @param aScrollCaptureId async container ID of the parent container
* @param aPluginInstanceId plugin ID on which to set the scroll capture ID
*/
async SetScrollCaptureId(uint64_t aScrollCaptureId,
uintptr_t aPluginInstanceId);
};
}

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

@ -28,9 +28,13 @@ public:
operator nsIPrincipal*() const { return mPrincipal.get(); }
Principal& operator=(const Principal& aOther)
{
mPrincipal = aOther.mPrincipal;
return *this;
}
private:
// Unimplemented
Principal& operator=(Principal&);
nsCOMPtr<nsIPrincipal> mPrincipal;
};

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

@ -80,7 +80,7 @@ public:
if (!sInstance) {
sInstance = new ReaderQueue;
sInstance->MaxNumActive(MediaPrefs::MediaDecoderLimit());
ClearOnShutdown(&sInstance);
ClearOnShutdown(&sInstance, ShutdownPhase::Shutdown);
}
MOZ_ASSERT(sInstance);
return *sInstance;

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

@ -327,11 +327,6 @@ PluginPRLibrary::GetScrollCaptureContainer(NPP aInstance, ImageContainer** aCont
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
PluginPRLibrary::UpdateScrollState(NPP aInstance, bool aIsScrolling)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
#endif
nsresult

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

@ -127,7 +127,6 @@ public:
virtual void SetHasLocalInstance() override { }
#if defined(XP_WIN)
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling) override;
#endif
virtual nsresult HandledWindowedPluginKeyEvent(
NPP aInstance,

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

@ -1161,15 +1161,6 @@ nsNPAPIPluginInstance::GetScrollCaptureContainer(ImageContainer**aContainer)
AutoPluginLibraryCall library(this);
return !library ? NS_ERROR_FAILURE : library->GetScrollCaptureContainer(&mNPP, aContainer);
}
nsresult
nsNPAPIPluginInstance::UpdateScrollState(bool aIsScrolling)
{
if (RUNNING != mRunning)
return NS_OK;
AutoPluginLibraryCall library(this);
return !library ? NS_ERROR_FAILURE : library->UpdateScrollState(&mNPP, aIsScrolling);
}
#endif
nsresult

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

@ -122,7 +122,6 @@ public:
nsresult GetMIMEType(const char* *result);
#if defined(XP_WIN)
nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer **aContainer);
nsresult UpdateScrollState(bool aIsScrolling);
#endif
nsresult HandledWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,

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

@ -322,21 +322,6 @@ nsPluginInstanceOwner::GetCurrentImageSize()
return size;
}
bool
nsPluginInstanceOwner::UpdateScrollState(bool aIsScrolling)
{
#if defined(XP_WIN)
if (!mInstance) {
return false;
}
mScrollState = aIsScrolling;
nsresult rv = mInstance->UpdateScrollState(aIsScrolling);
return NS_SUCCEEDED(rv);
#else
return false;
#endif
}
nsPluginInstanceOwner::nsPluginInstanceOwner()
: mPluginWindow(nullptr)
{
@ -384,7 +369,6 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mGotCompositionData = false;
mSentStartComposition = false;
mPluginDidNotHandleIMEComposition = false;
mScrollState = false;
#endif
}

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

@ -229,8 +229,6 @@ public:
// Returns true if this is windowed plugin that can return static captures
// for scroll operations.
bool NeedsScrollImageLayer();
// Notification we receive from nsPluginFrame about scroll state.
bool UpdateScrollState(bool aIsScrolling);
void DidComposite();
@ -411,9 +409,6 @@ private:
#endif
bool mWaitingForPaint;
#if defined(XP_WIN)
bool mScrollState;
#endif
};
#endif // nsPluginInstanceOwner_h_

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

@ -61,7 +61,6 @@
#include "nsIWidget.h"
#include "nsPluginNativeWindow.h"
#include "PluginQuirks.h"
#include "nsWindowsHelpers.h"
extern const wchar_t* kFlashFullscreenClass;
#elif defined(MOZ_WIDGET_GTK)
#include "mozilla/dom/ContentChild.h"
@ -74,13 +73,6 @@ using namespace mozilla::plugins;
using namespace mozilla::layers;
using namespace mozilla::gl;
#if defined(XP_WIN)
// Delays associated with attempting an e10s window capture for scrolling.
const int kScrollCaptureDelayMs = 100;
const int kInitScrollCaptureDelayMs = 1000;
const uint32_t kScrollCaptureFillColor = 0xFFa0a0a0; // gray
#endif
void
StreamNotifyParent::ActorDestroy(ActorDestroyReason aWhy)
{
@ -143,10 +135,6 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mShHeight(0)
, mShColorSpace(nullptr)
#endif
#if defined(XP_WIN)
, mValidFirstCapture(false)
, mIsScrolling(false)
#endif
{
#if defined(OS_WIN)
if (!sPluginInstanceList) {
@ -171,9 +159,6 @@ PluginInstanceParent::~PluginInstanceParent()
if (mShColorSpace)
::CGColorSpaceRelease(mShColorSpace);
#endif
#if defined(XP_WIN)
CancelScheduledScrollCapture();
#endif
}
bool
@ -448,12 +433,6 @@ PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
// non-pointer-sized integer.
*result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool,
(void*)(intptr_t)windowed);
#if defined(XP_WIN)
if (windowed) {
ScheduleScrollCapture(kScrollCaptureDelayMs);
}
#endif
return true;
}
@ -1207,204 +1186,27 @@ PluginInstanceParent::EndUpdateBackground(const nsIntRect& aRect)
}
#if defined(XP_WIN)
//#define CAPTURE_LOG(...) printf_stderr("CAPTURE [%X]: ", this);printf_stderr(__VA_ARGS__);printf_stderr("\n");
#define CAPTURE_LOG(...)
void
PluginInstanceParent::ScheduleScrollCapture(int aTimeout)
nsresult
PluginInstanceParent::SetScrollCaptureId(uint64_t aScrollCaptureId)
{
if (mCaptureRefreshTask) {
return;
}
CAPTURE_LOG("delayed scroll capture requested.");
mCaptureRefreshTask =
NewNonOwningCancelableRunnableMethod(this, &PluginInstanceParent::ScheduledUpdateScrollCaptureCallback);
RefPtr<Runnable> addrefedTask = mCaptureRefreshTask;
MessageLoop::current()->PostDelayedTask(addrefedTask.forget(),
kScrollCaptureDelayMs);
}
if (aScrollCaptureId == ImageContainer::sInvalidAsyncContainerId) {
return NS_ERROR_FAILURE;
}
void
PluginInstanceParent::ScheduledUpdateScrollCaptureCallback()
{
CAPTURE_LOG("taking delayed scrollcapture.");
mCaptureRefreshTask = nullptr;
bool retrigger = false;
UpdateScrollCapture(retrigger);
if (retrigger) {
// reset the async request
ScheduleScrollCapture(kScrollCaptureDelayMs);
}
}
void
PluginInstanceParent::CancelScheduledScrollCapture()
{
CAPTURE_LOG("delayed scroll capture cancelled.");
if (mCaptureRefreshTask) {
mCaptureRefreshTask->Cancel();
mCaptureRefreshTask = nullptr;
}
}
bool
PluginInstanceParent::UpdateScrollCapture(bool& aRequestNewCapture)
{
aRequestNewCapture = false;
if (!::IsWindow(mChildPluginHWND)) {
CAPTURE_LOG("invalid window");
aRequestNewCapture = true;
return false;
}
nsAutoHDC windowDC(::GetDC(mChildPluginHWND));
if (!windowDC) {
CAPTURE_LOG("no windowdc");
aRequestNewCapture = true;
return false;
}
RECT bounds = {0};
::GetWindowRect(mChildPluginHWND, &bounds);
if ((bounds.left == bounds.right && bounds.top == bounds.bottom) ||
mWindowSize.IsEmpty()) {
CAPTURE_LOG("empty bounds");
// Lots of null window plugins in content, don't capture.
return false;
}
// If we need to init mScrollCapture do so, also reset it if the size of the
// plugin window changes.
if (!mScrollCapture || mScrollCapture->GetSize() != mWindowSize) {
mValidFirstCapture = false;
mScrollCapture =
gfxPlatform::GetPlatform()->CreateOffscreenSurface(mWindowSize,
SurfaceFormat::X8R8G8B8_UINT32);
}
// Check clipping, we don't want to capture windows that are clipped by
// the viewport.
RECT clip = {0};
int rgnType = ::GetWindowRgnBox(mPluginHWND, &clip);
bool clipCorrect = !clip.left && !clip.top &&
clip.right == mWindowSize.width &&
clip.bottom == mWindowSize.height;
bool isVisible = ::IsWindowVisible(mChildPluginHWND);
CAPTURE_LOG("validcap=%d visible=%d region=%d clip=%d:%dx%dx%dx%d",
mValidFirstCapture, isVisible, rgnType, clipCorrect,
clip.left, clip.top, clip.right, clip.bottom);
// We have a good capture and can't update so keep using the existing
// capture image. Otherwise fall through so we paint the fill color to
// the layer.
if (mValidFirstCapture && (!isVisible || !clipCorrect)) {
return true;
}
// On Windows we'll need a native bitmap for BitBlt.
RefPtr<gfxWindowsSurface> nativeScrollCapture;
// Copy the plugin window if it's visible and there's no clipping, otherwise
// use a default fill color.
if (isVisible && clipCorrect) {
CAPTURE_LOG("capturing window");
nativeScrollCapture =
new gfxWindowsSurface(mWindowSize, SurfaceFormat::X8R8G8B8_UINT32);
if (!::BitBlt(nativeScrollCapture->GetDC(), 0, 0, mWindowSize.width,
mWindowSize.height, windowDC, 0, 0, SRCCOPY)) {
CAPTURE_LOG("blt failure??");
return false;
}
::GdiFlush();
mValidFirstCapture = true;
}
IntSize targetSize = mScrollCapture->GetSize();
if (targetSize.IsEmpty()) {
return false;
}
RefPtr<gfx::DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mScrollCapture,
targetSize);
if (nativeScrollCapture) {
// Copy the native capture image over to a remotable gfx surface.
RefPtr<gfx::SourceSurface> sourceSurface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
nativeScrollCapture);
dt->CopySurface(sourceSurface,
IntRect(0, 0, targetSize.width, targetSize.height),
IntPoint());
} else {
CAPTURE_LOG("using fill color");
dt->FillRect(gfx::Rect(0, 0, targetSize.width, targetSize.height),
gfx::ColorPattern(gfx::Color::FromABGR(kScrollCaptureFillColor)),
gfx::DrawOptions(1.f, CompositionOp::OP_SOURCE));
aRequestNewCapture = true;
}
dt->Flush();
// Get a source for mScrollCapture and load it into the image container.
RefPtr<gfx::SourceSurface> cachedSource =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt,
mScrollCapture);
RefPtr<SourceSurfaceImage> image =
new SourceSurfaceImage(cachedSource->GetSize(), cachedSource);
ImageContainer::NonOwningImage holder(image);
holder.mFrameID = ++mFrameID;
AutoTArray<ImageContainer::NonOwningImage,1> imageList;
imageList.AppendElement(holder);
// inits mImageContainer
ImageContainer *container = GetImageContainer();
container->SetCurrentImages(imageList);
// Invalidate our area in the page so the image gets flushed.
NPRect nprect = {0, 0, targetSize.width, targetSize.height};
RecvNPN_InvalidateRect(nprect);
return true;
mImageContainer = new ImageContainer(aScrollCaptureId);
return NS_OK;
}
nsresult
PluginInstanceParent::GetScrollCaptureContainer(ImageContainer** aContainer)
{
if (!aContainer || !::IsWindow(mPluginHWND)) {
return NS_ERROR_FAILURE;
}
if (!mImageContainer) {
ScheduleScrollCapture(kInitScrollCaptureDelayMs);
return NS_ERROR_FAILURE;
}
ImageContainer *container = GetImageContainer();
NS_IF_ADDREF(container);
*aContainer = container;
return NS_OK;
}
nsresult
PluginInstanceParent::UpdateScrollState(bool aIsScrolling)
{
bool scrollStateChanged = (mIsScrolling != aIsScrolling);
mIsScrolling = aIsScrolling;
if (scrollStateChanged && !aIsScrolling) {
// At the end of a dom scroll operation capturing now will attempt to
// capture a window that is still hidden due to the current scroll
// operation. (The browser process will update visibility after layer
// updates get pushed over.) So we delay our attempt for a bit. This
// shouldn't hurt our chances of capturing with APZ scroll since the
// delay is short.
ScheduleScrollCapture(kScrollCaptureDelayMs);
if (!aContainer || !mImageContainer) {
return NS_ERROR_FAILURE;
}
RefPtr<ImageContainer> container = GetImageContainer();
container.forget(aContainer);
return NS_OK;
}
#endif // XP_WIN
@ -1561,9 +1363,6 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
window.type = aWindow->type;
#endif
mWindowSize.width = window.width;
mWindowSize.height = window.height;
#if defined(XP_MACOSX)
double floatScaleFactor = 1.0;
mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &floatScaleFactor);
@ -1608,12 +1407,6 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
}
RecordDrawingModel();
#if defined(XP_WIN)
if (!mCaptureRefreshTask) {
ScheduleScrollCapture(kScrollCaptureDelayMs);
}
#endif
return NPERR_NO_ERROR;
}

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

@ -331,8 +331,8 @@ public:
DrawTarget** aDrawTarget);
nsresult EndUpdateBackground(const nsIntRect& aRect);
#if defined(XP_WIN)
nsresult SetScrollCaptureId(uint64_t aScrollCaptureId);
nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer** aContainer);
nsresult UpdateScrollState(bool aIsScrolling);
#endif
void DidComposite();
@ -400,7 +400,6 @@ private:
nsCString mSrcAttribute;
NPWindowType mWindowType;
int16_t mDrawingModel;
IntSize mWindowSize;
// Since plugins may request different drawing models to find a compatible
// one, we only record the drawing model after a SetWindow call and if the
@ -465,18 +464,6 @@ private:
RefPtr<gfxASurface> mBackground;
RefPtr<ImageContainer> mImageContainer;
#if defined(XP_WIN)
void ScheduleScrollCapture(int aTimeout);
void ScheduledUpdateScrollCaptureCallback();
bool UpdateScrollCapture(bool& aRequestNewCapture);
void CancelScheduledScrollCapture();
RefPtr<gfxASurface> mScrollCapture;
RefPtr<CancelableRunnable> mCaptureRefreshTask;
bool mValidFirstCapture;
bool mIsScrolling;
#endif
};

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

@ -89,7 +89,6 @@ public:
#endif
#if defined(XP_WIN)
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) = 0;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling) = 0;
#endif
virtual nsresult HandledWindowedPluginKeyEvent(
NPP aInstance,

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

@ -2033,12 +2033,6 @@ PluginModuleParent::GetScrollCaptureContainer(NPP aInstance,
PluginInstanceParent* inst = PluginInstanceParent::Cast(aInstance);
return !inst ? NS_ERROR_FAILURE : inst->GetScrollCaptureContainer(aContainer);
}
nsresult
PluginModuleParent::UpdateScrollState(NPP aInstance, bool aIsScrolling)
{
PluginInstanceParent* inst = PluginInstanceParent::Cast(aInstance);
return !inst ? NS_ERROR_FAILURE : inst->UpdateScrollState(aIsScrolling);
}
#endif
nsresult

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

@ -263,7 +263,6 @@ protected:
#if defined(XP_WIN)
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling);
#endif
virtual nsresult HandledWindowedPluginKeyEvent(

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

@ -12,6 +12,10 @@
#include "mozilla/DebugOnly.h"
#include "nsDebug.h"
#if defined(XP_WIN)
#include "mozilla/plugins/PluginInstanceParent.h"
#endif
#define PWLOG(...)
//#define PWLOG(...) printf_stderr(__VA_ARGS__)
@ -31,6 +35,25 @@ PluginWidgetChild::~PluginWidgetChild()
MOZ_COUNT_DTOR(PluginWidgetChild);
}
bool
PluginWidgetChild::RecvSetScrollCaptureId(const uint64_t& aScrollCaptureId,
const uintptr_t& aPluginInstanceId)
{
#if defined(XP_WIN)
PluginInstanceParent* instance =
PluginInstanceParent::LookupPluginInstanceByID(aPluginInstanceId);
if (instance) {
NS_WARN_IF(NS_FAILED(instance->SetScrollCaptureId(aScrollCaptureId)));
}
return true;
#else
MOZ_ASSERT_UNREACHABLE(
"PluginWidgetChild::RecvSetScrollCaptureId calls not expected.");
return false;
#endif
}
// Called by the proxy widget when it is destroyed by layout. Only gets
// called once.
void

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

@ -19,6 +19,9 @@ public:
PluginWidgetChild();
virtual ~PluginWidgetChild();
bool RecvSetScrollCaptureId(const uint64_t& aScrollCaptureId,
const uintptr_t& aPluginInstanceId) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
void SetWidget(mozilla::widget::PluginWidgetProxy* aWidget) {

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

@ -143,6 +143,11 @@ PluginWidgetParent::RecvCreate(nsresult* aResult)
mozilla::dom::kPluginWidgetContentParentProperty,
GetTabParent()->Manager()->AsContentParent());
NS_ASSERTION(winres, "SetPropW call failure");
uint64_t scrollCaptureId = mWidget->CreateScrollCaptureContainer();
uintptr_t pluginId =
reinterpret_cast<uintptr_t>(mWidget->GetNativeData(NS_NATIVE_PLUGIN_ID));
Unused << SendSetScrollCaptureId(scrollCaptureId, pluginId);
#endif
// This is a special call we make to nsBaseWidget to register this

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

@ -1904,8 +1904,11 @@ public:
!JS_DefineElement(cx, values, index, value, JSPROP_ENUMERATE)) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
JS::Rooted<JS::Value> exn(cx);
jsapi.StealException(&exn);
mPromise->MaybeReject(cx, exn);
if (!jsapi.StealException(&exn)) {
mPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
} else {
mPromise->MaybeReject(cx, exn);
}
}
--mCountdown;
@ -2761,7 +2764,7 @@ Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
if (aState == PromiseState::Rejected &&
!mHadRejectCallback &&
!NS_IsMainThread()) {
workers::WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
@ -2825,9 +2828,9 @@ Promise::RemoveWorkerHolder()
}
bool
PromiseReportRejectWorkerHolder::Notify(workers::Status aStatus)
PromiseReportRejectWorkerHolder::Notify(Status aStatus)
{
MOZ_ASSERT(aStatus > workers::Running);
MOZ_ASSERT(aStatus > Running);
mPromise->MaybeReportRejectedOnce();
// After this point, `this` has been deleted by RemoveWorkerHolder!
return true;
@ -2879,7 +2882,7 @@ Promise::GetDependentPromises(nsTArray<RefPtr<Promise>>& aPromises)
// A WorkerRunnable to resolve/reject the Promise on the worker thread.
// Calling thread MUST hold PromiseWorkerProxy's mutex before creating this.
class PromiseWorkerProxyRunnable : public workers::WorkerRunnable
class PromiseWorkerProxyRunnable : public WorkerRunnable
{
public:
PromiseWorkerProxyRunnable(PromiseWorkerProxy* aPromiseWorkerProxy,
@ -2894,7 +2897,7 @@ public:
}
virtual bool
WorkerRun(JSContext* aCx, workers::WorkerPrivate* aWorkerPrivate)
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
@ -2927,9 +2930,32 @@ private:
PromiseWorkerProxy::RunCallbackFunc mFunc;
};
class PromiseWorkerHolder final : public WorkerHolder
{
// RawPointer because this proxy keeps alive the holder.
PromiseWorkerProxy* mProxy;
public:
explicit PromiseWorkerHolder(PromiseWorkerProxy* aProxy)
: mProxy(aProxy)
{
MOZ_ASSERT(aProxy);
}
bool
Notify(Status aStatus) override
{
if (aStatus >= Canceling) {
mProxy->CleanUp();
}
return true;
}
};
/* static */
already_AddRefed<PromiseWorkerProxy>
PromiseWorkerProxy::Create(workers::WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy::Create(WorkerPrivate* aWorkerPrivate,
Promise* aWorkerPromise,
const PromiseWorkerProxyStructuredCloneCallbacks* aCb)
{
@ -2955,7 +2981,7 @@ PromiseWorkerProxy::Create(workers::WorkerPrivate* aWorkerPrivate,
NS_IMPL_ISUPPORTS0(PromiseWorkerProxy)
PromiseWorkerProxy::PromiseWorkerProxy(workers::WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy::PromiseWorkerProxy(WorkerPrivate* aWorkerPrivate,
Promise* aWorkerPromise,
const PromiseWorkerProxyStructuredCloneCallbacks* aCallbacks)
: mWorkerPrivate(aWorkerPrivate)
@ -2963,16 +2989,13 @@ PromiseWorkerProxy::PromiseWorkerProxy(workers::WorkerPrivate* aWorkerPrivate,
, mCleanedUp(false)
, mCallbacks(aCallbacks)
, mCleanUpLock("cleanUpLock")
#ifdef DEBUG
, mWorkerHolderAdded(false)
#endif
{
}
PromiseWorkerProxy::~PromiseWorkerProxy()
{
MOZ_ASSERT(mCleanedUp);
MOZ_ASSERT(!mWorkerHolderAdded);
MOZ_ASSERT(!mWorkerHolder);
MOZ_ASSERT(!mWorkerPromise);
MOZ_ASSERT(!mWorkerPrivate);
}
@ -2981,7 +3004,7 @@ void
PromiseWorkerProxy::CleanProperties()
{
#ifdef DEBUG
workers::WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
#endif
@ -3000,21 +3023,21 @@ PromiseWorkerProxy::AddRefObject()
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!mWorkerHolderAdded);
if (NS_WARN_IF(!HoldWorker(mWorkerPrivate))) {
MOZ_ASSERT(!mWorkerHolder);
mWorkerHolder.reset(new PromiseWorkerHolder(this));
if (NS_WARN_IF(!mWorkerHolder->HoldWorker(mWorkerPrivate))) {
mWorkerHolder = nullptr;
return false;
}
#ifdef DEBUG
mWorkerHolderAdded = true;
#endif
// Maintain a reference so that we have a valid object to clean up when
// removing the feature.
AddRef();
return true;
}
workers::WorkerPrivate*
WorkerPrivate*
PromiseWorkerProxy::GetWorkerPrivate() const
{
#ifdef DEBUG
@ -3025,7 +3048,7 @@ PromiseWorkerProxy::GetWorkerPrivate() const
// Safe to check this without a lock since we assert lock ownership on the
// main thread above.
MOZ_ASSERT(!mCleanedUp);
MOZ_ASSERT(mWorkerHolderAdded);
MOZ_ASSERT(mWorkerHolder);
return mWorkerPrivate;
}
@ -3034,7 +3057,7 @@ Promise*
PromiseWorkerProxy::WorkerPromise() const
{
#ifdef DEBUG
workers::WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
#endif
@ -3091,16 +3114,6 @@ PromiseWorkerProxy::RejectedCallback(JSContext* aCx,
RunCallback(aCx, aValue, &Promise::MaybeReject);
}
bool
PromiseWorkerProxy::Notify(Status aStatus)
{
if (aStatus >= Canceling) {
CleanUp();
}
return true;
}
void
PromiseWorkerProxy::CleanUp()
{
@ -3118,14 +3131,12 @@ PromiseWorkerProxy::CleanUp()
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
// Release the Promise and remove the PromiseWorkerProxy from the features of
// Release the Promise and remove the PromiseWorkerProxy from the holders of
// the worker thread since the Promise has been resolved/rejected or the
// worker thread has been cancelled.
MOZ_ASSERT(mWorkerHolderAdded);
ReleaseWorker();
#ifdef DEBUG
mWorkerHolderAdded = false;
#endif
MOZ_ASSERT(mWorkerHolder);
mWorkerHolder = nullptr;
CleanProperties();
}
Release();

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

@ -90,7 +90,7 @@ public:
protected:
static void FlushUncaughtRejectionsInternal();
friend class FlushRejections;
friend class WorkerPrivate;
friend class mozilla::dom::workers::WorkerPrivate;
private:
// Identity of the process.
// This property is:

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

@ -110,7 +110,6 @@ class WorkerPrivate;
// references to it are dropped.
class PromiseWorkerProxy : public PromiseNativeHandler
, public workers::WorkerHolder
, public StructuredCloneHolderBase
{
friend class PromiseWorkerProxyRunnable;
@ -185,8 +184,6 @@ protected:
virtual void RejectedCallback(JSContext* aCx,
JS::Handle<JS::Value> aValue) override;
virtual bool Notify(workers::Status aStatus) override;
private:
PromiseWorkerProxy(workers::WorkerPrivate* aWorkerPrivate,
Promise* aWorkerPromise,
@ -227,10 +224,7 @@ private:
// Ensure the worker and the main thread won't race to access |mCleanedUp|.
Mutex mCleanUpLock;
#ifdef DEBUG
// Maybe get rid of this entirely and rely on mCleanedUp
bool mWorkerHolderAdded;
#endif
UniquePtr<workers::WorkerHolder> mWorkerHolder;
};
} // namespace dom
} // namespace mozilla

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

@ -321,6 +321,14 @@ interface WebGL2RenderingContext : WebGLRenderingContext
void getBufferSubData(GLenum target, GLintptr offset, ArrayBuffer? returnedData);
void getBufferSubData(GLenum target, GLintptr offset, SharedArrayBuffer returnedData);
[Throws] /* Throws on readback in a write-only context. */
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
GLenum type, GLintptr offset);
/* Include our WebGL 1 function override(s) */
[Throws]
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
GLenum type, ArrayBufferView? pixels);
/* Framebuffer objects */
void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);

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

@ -541,10 +541,12 @@ private:
NS_IMPL_ISUPPORTS(LoaderListener, nsIStreamLoaderObserver, nsIRequestObserver)
class ScriptLoaderRunnable final : public WorkerHolder
, public nsIRunnable
class ScriptLoaderHolder;
class ScriptLoaderRunnable final : public nsIRunnable
{
friend class ScriptExecutorRunnable;
friend class ScriptLoaderHolder;
friend class CachePromiseHandler;
friend class CacheScriptLoader;
friend class LoaderListener;
@ -718,8 +720,8 @@ private:
return NS_OK;
}
virtual bool
Notify(Status aStatus) override
bool
Notify(Status aStatus)
{
mWorkerPrivate->AssertIsOnWorkerThread();
@ -1039,7 +1041,7 @@ private:
// Note that for data: url, where we allow it through the same-origin check
// but then give it a different origin.
aLoadInfo.mMutedErrorFlag.emplace(IsMainWorkerScript()
? false
? false
: !principal->Subsumes(channelPrincipal));
// Make sure we're not seeing the result of a 404 or something by checking
@ -1356,6 +1358,26 @@ private:
NS_IMPL_ISUPPORTS(ScriptLoaderRunnable, nsIRunnable)
class MOZ_STACK_CLASS ScriptLoaderHolder final : public WorkerHolder
{
// Raw pointer because this holder object follows the mRunnable life-time.
ScriptLoaderRunnable* mRunnable;
public:
explicit ScriptLoaderHolder(ScriptLoaderRunnable* aRunnable)
: mRunnable(aRunnable)
{
MOZ_ASSERT(aRunnable);
}
virtual bool
Notify(Status aStatus) override
{
mRunnable->Notify(aStatus);
return true;
}
};
NS_IMETHODIMP
LoaderListener::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext,
nsresult aStatus, uint32_t aStringLen,
@ -2008,7 +2030,6 @@ ScriptExecutorRunnable::ShutdownScriptLoader(JSContext* aCx,
}
}
mScriptLoader.ReleaseWorker();
aWorkerPrivate->StopSyncLoop(mSyncLoopTarget, aResult);
}
@ -2060,15 +2081,15 @@ LoadAllScripts(WorkerPrivate* aWorkerPrivate,
NS_ASSERTION(aLoadInfos.IsEmpty(), "Should have swapped!");
if (NS_WARN_IF(!loader->HoldWorker(aWorkerPrivate))) {
ScriptLoaderHolder workerHolder(loader);
if (NS_WARN_IF(!workerHolder.HoldWorker(aWorkerPrivate))) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (NS_FAILED(NS_DispatchToMainThread(loader))) {
NS_ERROR("Failed to dispatch!");
loader->ReleaseWorker();
aRv.Throw(NS_ERROR_FAILURE);
return;
}

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

@ -16,6 +16,7 @@ WorkerHolder::WorkerHolder()
WorkerHolder::~WorkerHolder()
{
NS_ASSERT_OWNINGTHREAD(WorkerHolder);
ReleaseWorkerInternal();
MOZ_ASSERT(mWorkerPrivate == nullptr);
}
@ -23,6 +24,7 @@ WorkerHolder::~WorkerHolder()
bool
WorkerHolder::HoldWorker(WorkerPrivate* aWorkerPrivate)
{
NS_ASSERT_OWNINGTHREAD(WorkerHolder);
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
@ -37,13 +39,17 @@ WorkerHolder::HoldWorker(WorkerPrivate* aWorkerPrivate)
void
WorkerHolder::ReleaseWorker()
{
NS_ASSERT_OWNINGTHREAD(WorkerHolder);
MOZ_ASSERT(mWorkerPrivate);
ReleaseWorkerInternal();
}
void
WorkerHolder::ReleaseWorkerInternal()
{
NS_ASSERT_OWNINGTHREAD(WorkerHolder);
if (mWorkerPrivate) {
mWorkerPrivate->AssertIsOnWorkerThread();
mWorkerPrivate->RemoveHolder(this);

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

@ -72,6 +72,8 @@ enum Status
class WorkerHolder
{
public:
NS_DECL_OWNINGTHREAD
WorkerHolder();
virtual ~WorkerHolder();
@ -84,6 +86,9 @@ protected:
void ReleaseWorkerInternal();
WorkerPrivate* MOZ_NON_OWNING_REF mWorkerPrivate;
private:
void AssertIsOwningThread() const;
};
END_WORKERS_NAMESPACE

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

@ -728,7 +728,8 @@ WorkerProxyToMainThreadRunnable::PostDispatchOnMainThread()
mRunnable->RunBackOnWorkerThread();
aWorkerPrivate->ModifyBusyCountFromWorker(true);
// Let's release the worker thread.
aWorkerPrivate->ModifyBusyCountFromWorker(false);
return true;
}

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

@ -903,9 +903,13 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage,
return BlitGrallocImage(static_cast<layers::GrallocImage*>(srcImage));
#endif
case ConvertPlanarYCbCr:
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
return BlitPlanarYCbCrImage(static_cast<PlanarYCbCrImage*>(srcImage));
case ConvertPlanarYCbCr: {
const auto saved = mGL->GetIntAs<GLint>(LOCAL_GL_UNPACK_ALIGNMENT);
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1);
const auto ret = BlitPlanarYCbCrImage(static_cast<PlanarYCbCrImage*>(srcImage));
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, saved);
return ret;
}
#ifdef MOZ_WIDGET_ANDROID
case ConvertSurfaceTexture:

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

@ -19,10 +19,6 @@
#include <string.h>
#endif
#ifdef WIN32
#include <windows.h>
#endif
#ifdef GetClassName
#undef GetClassName
#endif
@ -42,7 +38,6 @@
#include "nsISupportsImpl.h"
#include "plstr.h"
#include "GLContextTypes.h"
//#include "GLTextureImage.h"
#include "SurfaceTypes.h"
#include "GLContextSymbols.h"
#include "base/platform_thread.h" // for PlatformThreadId
@ -1228,6 +1223,14 @@ public:
fGetIntegerv(pname, reinterpret_cast<GLint*>(params));
}
template<typename T>
T GetIntAs(GLenum pname) {
static_assert(sizeof(T) == sizeof(GLint), "Invalid T.");
T ret = 0;
fGetIntegerv(pname, (GLint*)&ret);
return ret;
}
void fGetFloatv(GLenum pname, GLfloat* params) {
BEFORE_GL_CALL;
mSymbols.fGetFloatv(pname, params);

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

@ -6,6 +6,10 @@
#include "nsDebug.h"
#ifdef WIN32
#include <windows.h>
#endif
namespace mozilla {
namespace gl {

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

@ -7,10 +7,6 @@
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#endif
#include "GLDefs.h"
#include "nscore.h"
#include "prlink.h"

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

@ -393,22 +393,18 @@ ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest)
MOZ_ASSERT(readAlignment);
MOZ_ASSERT(reinterpret_cast<uintptr_t>(readSurf->GetData()) % readAlignment == 0);
GLint currentPackAlignment = 0;
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &currentPackAlignment);
if (currentPackAlignment != readAlignment)
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment);
GLsizei width = dest->GetSize().width;
GLsizei height = dest->GetSize().height;
gl->fReadPixels(0, 0,
width, height,
readFormat, readType,
readSurf->GetData());
{
ScopedPackState safePackState(gl);
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment);
if (currentPackAlignment != readAlignment)
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
gl->fReadPixels(0, 0,
width, height,
readFormat, readType,
readSurf->GetData());
}
if (readSurf != dest) {
MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);

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

@ -86,9 +86,6 @@ ScopedBindFramebuffer::ScopedBindFramebuffer(GLContext* aGL, GLuint aNewFB)
void
ScopedBindFramebuffer::UnwrapImpl()
{
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
if (mOldReadFB == mOldDrawFB) {
mGL->BindFB(mOldDrawFB);
} else {
@ -110,9 +107,6 @@ ScopedBindTextureUnit::ScopedBindTextureUnit(GLContext* aGL, GLenum aTexUnit)
void
ScopedBindTextureUnit::UnwrapImpl() {
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
mGL->fActiveTexture(mOldTexUnit);
}
@ -122,35 +116,26 @@ ScopedBindTextureUnit::UnwrapImpl() {
ScopedTexture::ScopedTexture(GLContext* aGL)
: ScopedGLWrapper<ScopedTexture>(aGL)
{
MOZ_ASSERT(mGL->IsCurrent());
mGL->fGenTextures(1, &mTexture);
}
void
ScopedTexture::UnwrapImpl()
{
// Check that we're not falling out of scope after
// the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
mGL->fDeleteTextures(1, &mTexture);
}
/* ScopedFramebuffer **************************************************************/
ScopedFramebuffer::ScopedFramebuffer(GLContext* aGL)
: ScopedGLWrapper<ScopedFramebuffer>(aGL)
{
MOZ_ASSERT(mGL->IsCurrent());
mGL->fGenFramebuffers(1, &mFB);
}
void
ScopedFramebuffer::UnwrapImpl()
{
// Check that we're not falling out of scope after
// the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
mGL->fDeleteFramebuffers(1, &mFB);
}
@ -160,16 +145,12 @@ ScopedFramebuffer::UnwrapImpl()
ScopedRenderbuffer::ScopedRenderbuffer(GLContext* aGL)
: ScopedGLWrapper<ScopedRenderbuffer>(aGL)
{
MOZ_ASSERT(mGL->IsCurrent());
mGL->fGenRenderbuffers(1, &mRB);
}
void
ScopedRenderbuffer::UnwrapImpl()
{
// Check that we're not falling out of scope after
// the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
mGL->fDeleteRenderbuffers(1, &mRB);
}
@ -251,10 +232,8 @@ ScopedBindRenderbuffer::ScopedBindRenderbuffer(GLContext* aGL, GLuint aNewRB)
}
void
ScopedBindRenderbuffer::UnwrapImpl() {
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
ScopedBindRenderbuffer::UnwrapImpl()
{
mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOldRB);
}
@ -455,15 +434,13 @@ ScopedGLDrawState::ScopedGLDrawState(GLContext* aGL)
, scissor (aGL, LOCAL_GL_SCISSOR_TEST, false)
, stencil (aGL, LOCAL_GL_STENCIL_TEST, false)
, mGL(aGL)
, packAlign(4)
{
mGL->GetUIntegerv(LOCAL_GL_UNPACK_ALIGNMENT, &packAlign);
mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &boundProgram);
mGL->GetUIntegerv(LOCAL_GL_ARRAY_BUFFER_BINDING, &boundBuffer);
mGL->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &maxAttrib);
attrib_enabled = MakeUnique<GLint[]>(maxAttrib);
for (unsigned int i = 0; i < maxAttrib; i++) {
for (GLuint i = 0; i < maxAttrib; i++) {
mGL->fGetVertexAttribiv(i, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &attrib_enabled[i]);
mGL->fDisableVertexAttribArray(i);
}
@ -494,8 +471,6 @@ ScopedGLDrawState::~ScopedGLDrawState()
colorMask[2],
colorMask[3]);
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, packAlign);
for (unsigned int i = 0; i < maxAttrib; i++) {
if (attrib_enabled[i])
mGL->fEnableVertexAttribArray(i);
@ -518,60 +493,47 @@ ScopedGLDrawState::~ScopedGLDrawState()
}
////////////////////////////////////////////////////////////////////////
// ScopedPackAlignment
// ScopedPackState
ScopedPackAlignment::ScopedPackAlignment(GLContext* gl, GLint scopedVal)
: ScopedGLWrapper<ScopedPackAlignment>(gl)
static bool
HasPBOState(const GLContext* gl)
{
MOZ_ASSERT(scopedVal == 1 ||
scopedVal == 2 ||
scopedVal == 4 ||
scopedVal == 8);
return (!gl->IsGLES() || gl->Version() >= 300);
}
gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &mOldVal);
ScopedPackState::ScopedPackState(GLContext* gl)
: ScopedGLWrapper<ScopedPackState>(gl)
{
mGL->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &mAlignment);
if (scopedVal != mOldVal) {
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, scopedVal);
} else {
// Don't try to re-set it during unwrap.
mOldVal = 0;
}
if (mAlignment != 4) mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
if (!HasPBOState(mGL))
return;
mGL->fGetIntegerv(LOCAL_GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&mPixelBuffer);
mGL->fGetIntegerv(LOCAL_GL_PACK_ROW_LENGTH, &mRowLength);
mGL->fGetIntegerv(LOCAL_GL_PACK_SKIP_PIXELS, &mSkipPixels);
mGL->fGetIntegerv(LOCAL_GL_PACK_SKIP_ROWS, &mSkipRows);
if (mPixelBuffer != 0) mGL->fBindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, 0);
if (mRowLength != 0) mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, 0);
if (mSkipPixels != 0) mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, 0);
if (mSkipRows != 0) mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, 0);
}
void
ScopedPackAlignment::UnwrapImpl() {
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
if (mOldVal) {
mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mOldVal);
}
}
////////////////////////////////////////////////////////////////////////
// ScopedUnpackAlignment
ScopedUnpackAlignment::ScopedUnpackAlignment(GLContext* gl, GLint scopedVal)
: ScopedGLWrapper<ScopedUnpackAlignment>(gl)
ScopedPackState::UnwrapImpl()
{
MOZ_ASSERT(scopedVal == 1 ||
scopedVal == 2 ||
scopedVal == 4 ||
scopedVal == 8);
mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mAlignment);
gl->fGetIntegerv(LOCAL_GL_UNPACK_ALIGNMENT, &mOldVal);
if (!HasPBOState(mGL))
return;
if (scopedVal != mOldVal) {
gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, scopedVal);
}
}
void
ScopedUnpackAlignment::UnwrapImpl() {
// Check that we're not falling out of scope after the current context changed.
MOZ_ASSERT(mGL->IsCurrent());
mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mOldVal);
mGL->fBindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, mPixelBuffer);
mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, mRowLength);
mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, mSkipPixels);
mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, mSkipRows);
}
} /* namespace gl */

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

@ -309,7 +309,8 @@ protected:
void UnwrapImpl();
};
struct ScopedGLDrawState {
struct ScopedGLDrawState
{
explicit ScopedGLDrawState(GLContext* gl);
~ScopedGLDrawState();
@ -339,35 +340,23 @@ struct ScopedGLDrawState {
GLint viewport[4];
GLint scissorBox[4];
GLContext* const mGL;
GLuint packAlign;
};
struct ScopedPackAlignment
: public ScopedGLWrapper<ScopedPackAlignment>
struct ScopedPackState
: public ScopedGLWrapper<ScopedPackState>
{
friend struct ScopedGLWrapper<ScopedPackAlignment>;
friend struct ScopedGLWrapper<ScopedPackState>;
protected:
GLint mOldVal;
GLint mAlignment;
GLuint mPixelBuffer;
GLint mRowLength;
GLint mSkipPixels;
GLint mSkipRows;
public:
ScopedPackAlignment(GLContext* aGL, GLint scopedVal);
protected:
void UnwrapImpl();
};
struct ScopedUnpackAlignment
: public ScopedGLWrapper<ScopedUnpackAlignment>
{
friend struct ScopedGLWrapper<ScopedUnpackAlignment>;
protected:
GLint mOldVal;
public:
ScopedUnpackAlignment(GLContext* gl, GLint scopedVal);
explicit ScopedPackState(GLContext* gl);
protected:
void UnwrapImpl();

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

@ -569,7 +569,11 @@ ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst)
size_t alignment = 8;
if (dstStride % 4 == 0)
alignment = 4;
ScopedPackAlignment autoAlign(gl, alignment);
ScopedPackState scopedPackState(gl);
if (alignment != 4) {
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, alignment);
}
gl->raw_fReadPixels(0, 0, width, height, readGLFormat, readType,
dstBytes);
@ -601,7 +605,7 @@ ReadPixel(SharedSurface* src)
ScopedReadbackFB a(src);
{
ScopedPackAlignment autoAlign(gl, 4);
ScopedPackState scopedPackState(gl);
UniquePtr<uint8_t[]> bytes(new uint8_t[4]);
gl->raw_fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,

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

@ -4,58 +4,26 @@
* 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 "CompositorSession.h"
#include "base/process_util.h"
#include "GPUChild.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/GPUProcessHost.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
#include "base/process_util.h"
namespace mozilla {
namespace layers {
using namespace gfx;
using namespace widget;
class InProcessCompositorSession final : public CompositorSession
{
public:
InProcessCompositorSession(
nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize);
CompositorBridgeParent* GetInProcessBridge() const override;
void SetContentController(GeckoContentController* aController) override;
uint64_t RootLayerTreeId() const override;
already_AddRefed<APZCTreeManager> GetAPZCTreeManager() const override;
void Shutdown() override;
private:
RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
RefPtr<CompositorWidget> mCompositorWidget;
};
already_AddRefed<CompositorSession>
CompositorSession::CreateInProcess(nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize)
{
RefPtr<InProcessCompositorSession> session = new InProcessCompositorSession(
aWidget,
aLayerManager,
aScale,
aUseAPZ,
aUseExternalSurfaceSize,
aSurfaceSize);
return session.forget();
}
CompositorSession::CompositorSession()
: mCompositorWidgetDelegate(nullptr)
CompositorSession::CompositorSession(CompositorWidgetDelegate* aDelegate,
CompositorBridgeChild* aChild,
const uint64_t& aRootLayerTreeId)
: mCompositorWidgetDelegate(aDelegate),
mCompositorBridgeChild(aChild),
mRootLayerTreeId(aRootLayerTreeId)
{
}
@ -69,65 +37,5 @@ CompositorSession::GetCompositorBridgeChild()
return mCompositorBridgeChild;
}
InProcessCompositorSession::InProcessCompositorSession(nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize)
{
CompositorWidgetInitData initData;
aWidget->GetCompositorWidgetInitData(&initData);
mCompositorWidget = CompositorWidget::CreateLocal(initData, aWidget);
mCompositorWidgetDelegate = mCompositorWidget->AsDelegate();
mCompositorBridgeParent = new CompositorBridgeParent(
mCompositorWidget,
aScale,
aUseAPZ,
aUseExternalSurfaceSize,
aSurfaceSize);
mCompositorBridgeChild = new CompositorBridgeChild(aLayerManager);
mCompositorBridgeChild->OpenSameProcess(mCompositorBridgeParent);
mCompositorBridgeParent->SetOtherProcessId(base::GetCurrentProcId());
}
CompositorBridgeParent*
InProcessCompositorSession::GetInProcessBridge() const
{
return mCompositorBridgeParent;
}
void
InProcessCompositorSession::SetContentController(GeckoContentController* aController)
{
mCompositorBridgeParent->SetControllerForLayerTree(RootLayerTreeId(), aController);
}
uint64_t
InProcessCompositorSession::RootLayerTreeId() const
{
return mCompositorBridgeParent->RootLayerTreeId();
}
already_AddRefed<APZCTreeManager>
InProcessCompositorSession::GetAPZCTreeManager() const
{
return mCompositorBridgeParent->GetAPZCTreeManager(RootLayerTreeId());
}
void
InProcessCompositorSession::Shutdown()
{
// Destroy will synchronously wait for the parent to acknowledge shutdown,
// at which point CBP will defer a Release on the compositor thread. We
// can safely release our reference now, and let the destructor run on either
// thread.
mCompositorBridgeChild->Destroy();
mCompositorBridgeChild = nullptr;
mCompositorBridgeParent = nullptr;
mCompositorWidget = nullptr;
}
} // namespace layers
} // namespace mozilla

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

@ -7,9 +7,7 @@
#define _include_mozilla_gfx_ipc_CompositorSession_h_
#include "base/basictypes.h"
#include "Units.h"
#include "nsISupportsImpl.h"
#include "mozilla/gfx/Point.h"
class nsIWidget;
@ -19,6 +17,7 @@ class CompositorWidget;
class CompositorWidgetDelegate;
} // namespace widget
namespace gfx {
class GPUProcessHost;
class GPUProcessManager;
} // namespace gfx
namespace layers {
@ -36,6 +35,7 @@ class CompositorSession
friend class gfx::GPUProcessManager;
protected:
typedef gfx::GPUProcessHost GPUProcessHost;
typedef widget::CompositorWidget CompositorWidget;
typedef widget::CompositorWidgetDelegate CompositorWidgetDelegate;
@ -50,9 +50,6 @@ public:
// Set the GeckoContentController for the root of the layer tree.
virtual void SetContentController(GeckoContentController* aController) = 0;
// Return the id of the root layer tree.
virtual uint64_t RootLayerTreeId() const = 0;
// Return the Async Pan/Zoom Tree Manager for this compositor.
virtual already_AddRefed<APZCTreeManager> GetAPZCTreeManager() const = 0;
@ -64,21 +61,21 @@ public:
return mCompositorWidgetDelegate;
}
// Return the id of the root layer tree.
uint64_t RootLayerTreeId() const {
return mRootLayerTreeId;
}
protected:
CompositorSession();
CompositorSession(CompositorWidgetDelegate* aDelegate,
CompositorBridgeChild* aChild,
const uint64_t& aRootLayerTreeId);
virtual ~CompositorSession();
static already_AddRefed<CompositorSession> CreateInProcess(
nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize);
protected:
RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
CompositorWidgetDelegate* mCompositorWidgetDelegate;
RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
uint64_t mRootLayerTreeId;
private:
DISALLOW_COPY_AND_ASSIGN(CompositorSession);

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

@ -9,11 +9,14 @@
#include "GPUProcessHost.h"
#include "mozilla/Assertions.h"
#include "mozilla/ipc/ProcessChild.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
namespace mozilla {
namespace gfx {
using namespace ipc;
using namespace layers;
GPUParent::GPUParent()
{
@ -34,7 +37,7 @@ GPUParent::Init(base::ProcessId aParentPid,
// Ensure gfxPrefs are initialized.
gfxPrefs::GetSingleton();
CompositorThreadHolder::Start();
return true;
}
@ -57,6 +60,35 @@ GPUParent::RecvUpdatePref(const GfxPrefSetting& setting)
return true;
}
static void
OpenParent(RefPtr<CompositorBridgeParent> aParent,
Endpoint<PCompositorBridgeParent>&& aEndpoint)
{
if (!aParent->Bind(Move(aEndpoint))) {
MOZ_CRASH("Failed to bind compositor");
}
}
bool
GPUParent::RecvNewWidgetCompositor(Endpoint<layers::PCompositorBridgeParent>&& aEndpoint,
const CSSToLayoutDeviceScale& aScale,
const bool& aUseExternalSurfaceSize,
const IntSize& aSurfaceSize)
{
RefPtr<CompositorBridgeParent> cbp =
new CompositorBridgeParent(aScale, aUseExternalSurfaceSize, aSurfaceSize);
MessageLoop* loop = CompositorThreadHolder::Loop();
loop->PostTask(NewRunnableFunction(OpenParent, cbp, Move(aEndpoint)));
return true;
}
bool
GPUParent::RecvNewContentCompositorBridge(Endpoint<PCompositorBridgeParent>&& aEndpoint)
{
return CompositorBridgeParent::CreateForContent(Move(aEndpoint));
}
void
GPUParent::ActorDestroy(ActorDestroyReason aWhy)
{
@ -70,9 +102,10 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
// state. Currently we quick-exit in RecvBeginShutdown so this should be
// unreachable.
ProcessChild::QuickExit();
#else
XRE_ShutdownChildProcess();
#endif
CompositorThreadHolder::Shutdown();
XRE_ShutdownChildProcess();
}
} // namespace gfx

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

@ -23,6 +23,12 @@ public:
bool RecvInit(nsTArray<GfxPrefSetting>&& prefs) override;
bool RecvUpdatePref(const GfxPrefSetting& pref) override;
bool RecvNewWidgetCompositor(
Endpoint<PCompositorBridgeParent>&& aEndpoint,
const CSSToLayoutDeviceScale& aScale,
const bool& aUseExternalSurface,
const IntSize& aSurfaceSize) override;
bool RecvNewContentCompositorBridge(Endpoint<PCompositorBridgeParent>&& aEndpoint) override;
void ActorDestroy(ActorDestroyReason aWhy) override;
};

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

@ -18,7 +18,9 @@ GPUProcessHost::GPUProcessHost(Listener* aListener)
mListener(aListener),
mTaskFactory(this),
mLaunchPhase(LaunchPhase::Unlaunched),
mShutdownRequested(false)
mProcessToken(0),
mShutdownRequested(false),
mChannelClosed(false)
{
MOZ_COUNT_CTOR(GPUProcessHost);
}
@ -109,6 +111,8 @@ GPUProcessHost::OnChannelErrorTask()
}
}
static uint64_t sProcessTokenCounter = 0;
void
GPUProcessHost::InitAfterConnect(bool aSucceeded)
{
@ -118,6 +122,7 @@ GPUProcessHost::InitAfterConnect(bool aSucceeded)
mLaunchPhase = LaunchPhase::Complete;
if (aSucceeded) {
mProcessToken = ++sProcessTokenCounter;
mGPUChild = MakeUnique<GPUChild>(this);
DebugOnly<bool> rv =
mGPUChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
@ -144,14 +149,22 @@ GPUProcessHost::Shutdown()
mShutdownRequested = true;
#ifdef NS_FREE_PERMANENT_DATA
mGPUChild->Close();
// The channel might already be closed if we got here unexpectedly.
if (!mChannelClosed) {
mGPUChild->Close();
}
#else
// No need to communicate shutdown, the GPU process doesn't need to
// communicate anything back.
KillHard("NormalShutdown");
#endif
// Wait for ActorDestroy.
// If we're shutting down unexpectedly, we're in the middle of handling an
// ActorDestroy for PGPUChild, which is still on the stack. We'll return
// back to OnChannelClosed.
//
// Otherwise, we'll wait for OnChannelClose to be called whenever PGPUChild
// acknowledges shutdown.
return;
}
@ -163,6 +176,7 @@ GPUProcessHost::OnChannelClosed()
{
if (!mShutdownRequested) {
// This is an unclean shutdown. Notify our listener that we're going away.
mChannelClosed = true;
if (mListener) {
mListener->OnProcessUnexpectedShutdown(this);
}
@ -194,6 +208,12 @@ GPUProcessHost::KillHard(const char* aReason)
NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated, handle, /*force=*/true));
}
uint64_t
GPUProcessHost::GetProcessToken() const
{
return mProcessToken;
}
static void
DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
{

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

@ -74,6 +74,10 @@ public:
return mGPUChild.get();
}
// Return a unique id for this process, guaranteed not to be shared with any
// past or future instance of GPUProcessHost.
uint64_t GetProcessToken() const;
bool IsConnected() const {
return !!mGPUChild;
}
@ -114,9 +118,10 @@ private:
LaunchPhase mLaunchPhase;
UniquePtr<GPUChild> mGPUChild;
Listener* listener_;
uint64_t mProcessToken;
bool mShutdownRequested;
bool mChannelClosed;
};
} // namespace gfx

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

@ -1,12 +1,18 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 "GPUProcessManager.h"
#include "GPUProcessHost.h"
#include "mozilla/layers/CompositorSession.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/InProcessCompositorSession.h"
#include "mozilla/layers/RemoteCompositorSession.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
# include "mozilla/widget/CompositorWidgetChild.h"
#endif
#include "nsContentUtils.h"
namespace mozilla {
@ -36,7 +42,9 @@ GPUProcessManager::Shutdown()
}
GPUProcessManager::GPUProcessManager()
: mProcess(nullptr),
: mTaskFactory(this),
mNextLayerTreeId(0),
mProcess(nullptr),
mGPUChild(nullptr)
{
mObserver = new Observer(this);
@ -127,6 +135,7 @@ GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
}
mGPUChild = mProcess->GetActor();
mProcessToken = mProcess->GetProcessToken();
}
void
@ -137,6 +146,28 @@ GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
DestroyProcess();
}
void
GPUProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken)
{
if (!NS_IsMainThread()) {
RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
&GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
NS_DispatchToMainThread(task.forget());
return;
}
if (mProcessToken != aProcessToken) {
// This token is for an older process; we can safely ignore it.
return;
}
// One of the bridged top-level actors for the GPU process has been
// prematurely terminated, and we're receiving a notification. This
// can happen if the ActorDestroy for a bridged protocol fires
// before the ActorDestroy for PGPUChild.
DestroyProcess();
}
void
GPUProcessManager::DestroyProcess()
{
@ -145,11 +176,12 @@ GPUProcessManager::DestroyProcess()
}
mProcess->Shutdown();
mProcessToken = 0;
mProcess = nullptr;
mGPUChild = nullptr;
}
already_AddRefed<CompositorSession>
RefPtr<CompositorSession>
GPUProcessManager::CreateTopLevelCompositor(nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
@ -157,20 +189,123 @@ GPUProcessManager::CreateTopLevelCompositor(nsIWidget* aWidget,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize)
{
return CompositorSession::CreateInProcess(
uint64_t layerTreeId = AllocateLayerTreeId();
if (mGPUChild) {
RefPtr<CompositorSession> session = CreateRemoteSession(
aWidget,
aLayerManager,
layerTreeId,
aScale,
aUseAPZ,
aUseExternalSurfaceSize,
aSurfaceSize);
if (session) {
return session;
}
// We couldn't create a remote compositor, so abort the process.
DisableGPUProcess("Failed to create remote compositor");
}
return InProcessCompositorSession::Create(
aWidget,
aLayerManager,
layerTreeId,
aScale,
aUseAPZ,
aUseExternalSurfaceSize,
aSurfaceSize);
}
PCompositorBridgeParent*
GPUProcessManager::CreateTabCompositorBridge(ipc::Transport* aTransport,
base::ProcessId aOtherProcess)
RefPtr<CompositorSession>
GPUProcessManager::CreateRemoteSession(nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
const uint64_t& aRootLayerTreeId,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize)
{
return CompositorBridgeParent::Create(aTransport, aOtherProcess);
#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
ipc::Endpoint<PCompositorBridgeParent> parentPipe;
ipc::Endpoint<PCompositorBridgeChild> childPipe;
nsresult rv = PCompositorBridge::CreateEndpoints(
mGPUChild->OtherPid(),
base::GetCurrentProcId(),
&parentPipe,
&childPipe);
if (NS_FAILED(rv)) {
gfxCriticalNote << "Failed to create PCompositorBridge endpoints: " << hexa(int(rv));
return nullptr;
}
RefPtr<CompositorBridgeChild> child = CompositorBridgeChild::CreateRemote(
mProcessToken,
aLayerManager,
Move(childPipe));
if (!child) {
gfxCriticalNote << "Failed to create CompositorBridgeChild";
return nullptr;
}
CompositorWidgetInitData initData;
aWidget->GetCompositorWidgetInitData(&initData);
bool ok = mGPUChild->SendNewWidgetCompositor(
Move(parentPipe),
aScale,
aUseExternalSurfaceSize,
aSurfaceSize);
if (!ok)
return nullptr;
CompositorWidgetChild* widget = new CompositorWidgetChild(aWidget);
if (!child->SendPCompositorWidgetConstructor(widget, initData))
return nullptr;
if (!child->SendInitialize(aRootLayerTreeId))
return nullptr;
RefPtr<RemoteCompositorSession> session =
new RemoteCompositorSession(child, widget, aRootLayerTreeId);
return session.forget();
#else
gfxCriticalNote << "Platform does not support out-of-process compositing";
return nullptr;
#endif
}
bool
GPUProcessManager::CreateContentCompositorBridge(base::ProcessId aOtherProcess,
ipc::Endpoint<PCompositorBridgeChild>* aOutEndpoint)
{
ipc::Endpoint<PCompositorBridgeParent> parentPipe;
ipc::Endpoint<PCompositorBridgeChild> childPipe;
base::ProcessId gpuPid = mGPUChild
? mGPUChild->OtherPid()
: base::GetCurrentProcId();
nsresult rv = PCompositorBridge::CreateEndpoints(
gpuPid,
aOtherProcess,
&parentPipe,
&childPipe);
if (NS_FAILED(rv)) {
gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
return false;
}
if (mGPUChild) {
mGPUChild->SendNewContentCompositorBridge(Move(parentPipe));
} else {
if (!CompositorBridgeParent::CreateForContent(Move(parentPipe)))
return false;
}
*aOutEndpoint = Move(childPipe);
return true;
}
already_AddRefed<APZCTreeManager>
@ -182,7 +317,8 @@ GPUProcessManager::GetAPZCTreeManagerForLayers(uint64_t aLayersId)
uint64_t
GPUProcessManager::AllocateLayerTreeId()
{
return CompositorBridgeParent::AllocateLayerTreeId();
MOZ_ASSERT(NS_IsMainThread());
return ++mNextLayerTreeId;
}
void

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

@ -12,15 +12,19 @@
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/gfx/GPUProcessHost.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/ipc/TaskFactory.h"
#include "mozilla/ipc/Transport.h"
#include "nsIObserverService.h"
namespace mozilla {
namespace layers {
class APZCTreeManager;
class CompositorSession;
class ClientLayerManager;
class CompositorUpdateObserver;
class PCompositorBridgeChild;
class PCompositorBridgeParent;
} // namespace layers
namespace widget {
@ -43,7 +47,10 @@ class GPUChild;
class GPUProcessManager final : public GPUProcessHost::Listener
{
typedef layers::APZCTreeManager APZCTreeManager;
typedef layers::ClientLayerManager ClientLayerManager;
typedef layers::CompositorSession CompositorSession;
typedef layers::CompositorUpdateObserver CompositorUpdateObserver;
typedef layers::PCompositorBridgeChild PCompositorBridgeChild;
public:
static void Initialize();
@ -60,17 +67,16 @@ public:
// Otherwise it blocks until the GPU process has finished launching.
void EnsureGPUReady();
already_AddRefed<layers::CompositorSession> CreateTopLevelCompositor(
RefPtr<CompositorSession> CreateTopLevelCompositor(
nsIWidget* aWidget,
layers::ClientLayerManager* aLayerManager,
ClientLayerManager* aLayerManager,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize);
layers::PCompositorBridgeParent* CreateTabCompositorBridge(
ipc::Transport* aTransport,
base::ProcessId aOtherProcess);
bool CreateContentCompositorBridge(base::ProcessId aOtherProcess,
ipc::Endpoint<PCompositorBridgeChild>* aOutEndpoint);
// This returns a reference to the APZCTreeManager to which
// pan/zoom-related events can be sent.
@ -106,6 +112,10 @@ public:
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
// Notify the GPUProcessManager that a top-level PGPU protocol has been
// terminated. This may be called from any thread.
void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken);
// Returns access to the PGPU protocol if a GPU process is present.
GPUChild* GetGPUChild() {
return mGPUChild;
@ -124,6 +134,15 @@ private:
// Shutdown the GPU process.
void DestroyProcess();
RefPtr<CompositorSession> CreateRemoteSession(
nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
const uint64_t& aRootLayerTreeId,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize);
DISALLOW_COPY_AND_ASSIGN(GPUProcessManager);
class Observer final : public nsIObserver {
@ -141,7 +160,11 @@ private:
private:
RefPtr<Observer> mObserver;
ipc::TaskFactory<GPUProcessManager> mTaskFactory;
uint64_t mNextLayerTreeId;
GPUProcessHost* mProcess;
uint64_t mProcessToken;
GPUChild* mGPUChild;
};

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

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 "InProcessCompositorSession.h"
namespace mozilla {
namespace layers {
InProcessCompositorSession::InProcessCompositorSession(widget::CompositorWidget* aWidget,
CompositorBridgeChild* aChild,
CompositorBridgeParent* aParent)
: CompositorSession(aWidget->AsDelegate(), aChild, aParent->RootLayerTreeId()),
mCompositorBridgeParent(aParent),
mCompositorWidget(aWidget)
{
}
/* static */ RefPtr<InProcessCompositorSession>
InProcessCompositorSession::Create(nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
const uint64_t& aRootLayerTreeId,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize)
{
CompositorWidgetInitData initData;
aWidget->GetCompositorWidgetInitData(&initData);
RefPtr<CompositorWidget> widget = CompositorWidget::CreateLocal(initData, aWidget);
RefPtr<CompositorBridgeChild> child = new CompositorBridgeChild(aLayerManager);
RefPtr<CompositorBridgeParent> parent =
child->InitSameProcess(widget, aRootLayerTreeId, aScale, aUseAPZ, aUseExternalSurfaceSize, aSurfaceSize);
return new InProcessCompositorSession(widget, child, parent);
}
CompositorBridgeParent*
InProcessCompositorSession::GetInProcessBridge() const
{
return mCompositorBridgeParent;
}
void
InProcessCompositorSession::SetContentController(GeckoContentController* aController)
{
mCompositorBridgeParent->SetControllerForLayerTree(mRootLayerTreeId, aController);
}
already_AddRefed<APZCTreeManager>
InProcessCompositorSession::GetAPZCTreeManager() const
{
return mCompositorBridgeParent->GetAPZCTreeManager(mRootLayerTreeId);
}
void
InProcessCompositorSession::Shutdown()
{
// Destroy will synchronously wait for the parent to acknowledge shutdown,
// at which point CBP will defer a Release on the compositor thread. We
// can safely release our reference now, and let the destructor run on either
// thread.
mCompositorBridgeChild->Destroy();
mCompositorBridgeChild = nullptr;
mCompositorBridgeParent = nullptr;
mCompositorWidget = nullptr;
}
} // namespace layers
} // namespace mozilla

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

@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 _include_mozilla_gfx_ipc_InProcessCompositorSession_h_
#define _include_mozilla_gfx_ipc_InProcessCompositorSession_h_
#include "CompositorSession.h"
#include "mozilla/gfx/Point.h"
#include "Units.h"
namespace mozilla {
namespace layers {
// A CompositorSession where both the child and parent CompositorBridge reside
// in the same process.
class InProcessCompositorSession final : public CompositorSession
{
public:
static RefPtr<InProcessCompositorSession> Create(
nsIWidget* aWidget,
ClientLayerManager* aLayerManager,
const uint64_t& aRootLayerTreeId,
CSSToLayoutDeviceScale aScale,
bool aUseAPZ,
bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize);
CompositorBridgeParent* GetInProcessBridge() const override;
void SetContentController(GeckoContentController* aController) override;
already_AddRefed<APZCTreeManager> GetAPZCTreeManager() const override;
void Shutdown() override;
private:
InProcessCompositorSession(widget::CompositorWidget* aWidget,
CompositorBridgeChild* aChild,
CompositorBridgeParent* aParent);
private:
RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
RefPtr<CompositorWidget> mCompositorWidget;
};
} // namespace layers
} // namespace mozilla
#endif // _include_mozilla_gfx_ipc_InProcessCompositorSession_h_

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

@ -3,7 +3,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PContent;
include protocol PCompositorBridge;
using mozilla::CSSToLayoutDeviceScale from "Units.h";
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
namespace mozilla {
namespace gfx {
@ -28,6 +31,15 @@ parent:
// Called to update a gfx preference.
async UpdatePref(GfxPrefSetting pref);
// Create a new top-level compositor.
async NewWidgetCompositor(Endpoint<PCompositorBridgeParent> endpoint,
CSSToLayoutDeviceScale scale,
bool useExternalSurface,
IntSize surfaceSize);
// Create a new content-process compositor bridge.
async NewContentCompositorBridge(Endpoint<PCompositorBridgeParent> endpoint);
};
} // namespace gfx

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

@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 "RemoteCompositorSession.h"
namespace mozilla {
namespace layers {
using namespace gfx;
using namespace widget;
RemoteCompositorSession::RemoteCompositorSession(CompositorBridgeChild* aChild,
CompositorWidgetDelegate* aWidgetDelegate,
const uint64_t& aRootLayerTreeId)
: CompositorSession(aWidgetDelegate, aChild, aRootLayerTreeId)
{
}
CompositorBridgeParent*
RemoteCompositorSession::GetInProcessBridge() const
{
return nullptr;
}
void
RemoteCompositorSession::SetContentController(GeckoContentController* aController)
{
MOZ_CRASH("NYI");
}
already_AddRefed<APZCTreeManager>
RemoteCompositorSession::GetAPZCTreeManager() const
{
return nullptr;
}
void
RemoteCompositorSession::Shutdown()
{
mCompositorBridgeChild->Destroy();
mCompositorBridgeChild = nullptr;
mCompositorWidgetDelegate = nullptr;
}
} // namespace layers
} // namespace mozilla

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

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 include_mozilla_gfx_ipc_RemoteCompositorSession_h
#define include_mozilla_gfx_ipc_RemoteCompositorSession_h
#include "CompositorSession.h"
#include "mozilla/gfx/Point.h"
#include "Units.h"
namespace mozilla {
namespace layers {
class RemoteCompositorSession final : public CompositorSession
{
public:
RemoteCompositorSession(CompositorBridgeChild* aChild,
CompositorWidgetDelegate* aWidgetDelegate,
const uint64_t& aRootLayerTreeId);
CompositorBridgeParent* GetInProcessBridge() const override;
void SetContentController(GeckoContentController* aController) override;
already_AddRefed<APZCTreeManager> GetAPZCTreeManager() const override;
void Shutdown() override;
};
} // namespace layers
} // namespace mozilla
#endif // include_mozilla_gfx_ipc_RemoteCompositorSession_h

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

@ -20,6 +20,8 @@ EXPORTS.mozilla.gfx += [
EXPORTS.mozilla.layers += [
'CompositorSession.h',
'InProcessCompositorSession.h',
'RemoteCompositorSession.h',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
@ -40,6 +42,8 @@ UNIFIED_SOURCES += [
'GPUProcessHost.cpp',
'GPUProcessImpl.cpp',
'GPUProcessManager.cpp',
'InProcessCompositorSession.cpp',
'RemoteCompositorSession.cpp',
'SharedDIB.cpp',
]

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

@ -208,11 +208,28 @@ ImageContainer::ImageContainer(Mode flag)
break;
}
}
mAsyncContainerID = mImageClient ? mImageClient->GetAsyncID()
: sInvalidAsyncContainerId;
}
ImageContainer::ImageContainer(uint64_t aAsyncContainerID)
: mReentrantMonitor("ImageContainer.mReentrantMonitor"),
mGenerationCounter(++sGenerationCounter),
mPaintCount(0),
mDroppedImageCount(0),
mImageFactory(nullptr),
mRecycleBin(nullptr),
mImageClient(nullptr),
mAsyncContainerID(aAsyncContainerID),
mCurrentProducerID(-1),
mIPDLChild(nullptr)
{
MOZ_ASSERT(mAsyncContainerID != sInvalidAsyncContainerId);
}
ImageContainer::~ImageContainer()
{
if (IsAsync()) {
if (mIPDLChild) {
mIPDLChild->ForgetImageContainer();
ImageBridgeChild::DispatchReleaseImageClient(mImageClient, mIPDLChild);
}
@ -332,7 +349,7 @@ ImageContainer::SetCurrentImages(const nsTArray<NonOwningImage>& aImages)
{
MOZ_ASSERT(!aImages.IsEmpty());
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
if (IsAsync()) {
if (mImageClient) {
ImageBridgeChild::DispatchImageClientUpdate(mImageClient, this);
}
SetCurrentImageInternal(aImages);
@ -341,7 +358,7 @@ ImageContainer::SetCurrentImages(const nsTArray<NonOwningImage>& aImages)
void
ImageContainer::ClearAllImages()
{
if (IsAsync()) {
if (mImageClient) {
// Let ImageClient release all TextureClients. This doesn't return
// until ImageBridge has called ClearCurrentImageFromImageBridge.
ImageBridgeChild::FlushAllImages(mImageClient, this);
@ -385,17 +402,13 @@ ImageContainer::SetCurrentImagesInTransaction(const nsTArray<NonOwningImage>& aI
bool ImageContainer::IsAsync() const
{
return mImageClient != nullptr;
return mAsyncContainerID != sInvalidAsyncContainerId;
}
uint64_t ImageContainer::GetAsyncContainerID() const
{
NS_ASSERTION(IsAsync(),"Shared image ID is only relevant to async ImageContainers");
if (IsAsync()) {
return mImageClient->GetAsyncID();
} else {
return 0; // zero is always an invalid AsyncID
}
return mAsyncContainerID;
}
bool

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

@ -359,8 +359,17 @@ public:
enum Mode { SYNCHRONOUS = 0x0, ASYNCHRONOUS = 0x01 };
static const uint64_t sInvalidAsyncContainerId = 0;
explicit ImageContainer(ImageContainer::Mode flag = SYNCHRONOUS);
/**
* Create ImageContainer just to hold another ASYNCHRONOUS ImageContainer's
* async container ID.
* @param aAsyncContainerID async container ID for which we are a proxy
*/
explicit ImageContainer(uint64_t aAsyncContainerID);
typedef uint32_t FrameID;
typedef uint32_t ProducerID;
@ -627,6 +636,8 @@ private:
// asynchronusly using the ImageBridge IPDL protocol.
ImageClient* mImageClient;
uint64_t mAsyncContainerID;
nsTArray<FrameID> mFrameIDsNotYetComposited;
// ProducerID for last current image(s), including the frames in
// mFrameIDsNotYetComposited

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

@ -3657,7 +3657,7 @@ void AsyncPanZoomController::DispatchStateChangeNotification(PanZoomState aOldSt
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
// Let the compositor know about scroll state changes so it can manage
// windowed plugins.
if (mCompositorBridgeParent) {
if (gfxPrefs::HidePluginsForScroll() && mCompositorBridgeParent) {
mCompositorBridgeParent->ScheduleHideAllPluginWindows();
}
#endif
@ -3665,7 +3665,7 @@ void AsyncPanZoomController::DispatchStateChangeNotification(PanZoomState aOldSt
controller->NotifyAPZStateChange(
GetGuid(), APZStateChange::eTransformEnd);
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
if (mCompositorBridgeParent) {
if (gfxPrefs::HidePluginsForScroll() && mCompositorBridgeParent) {
mCompositorBridgeParent->ScheduleShowAllPluginWindows();
}
#endif

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

@ -309,7 +309,7 @@ TexClientFromReadback(SharedSurface* src, ClientIPCAllocator* allocator,
MOZ_ASSERT(texClient);
if (!texClient)
return nullptr;
return nullptr;
// With a texClient, we can lock for writing.
TextureClientAutoLock autoLock(texClient, OpenMode::OPEN_WRITE);
@ -324,7 +324,7 @@ TexClientFromReadback(SharedSurface* src, ClientIPCAllocator* allocator,
auto height = src->mSize.height;
{
ScopedPackAlignment autoAlign(gl, 4);
ScopedPackState scopedPackState(gl);
MOZ_ASSERT(mapped.stride/4 == mapped.size.width);
gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, mapped.data);

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