Merge m-c to autoland a=merge

MozReview-Commit-ID: L0rsjIzeVij

--HG--
extra : rebase_source : 8b581702a4534fb9394f8d3f4e85f65d6f4ff293
This commit is contained in:
Wes Kocher 2017-05-15 17:02:08 -07:00
commit 54a256d920
192 changed files with 20883 additions and 20031 deletions

View File

@ -56,7 +56,7 @@ jobs:
# Match buildbot starts for now
date: [{hour: 15, minute: 0}]
mozilla-central: [{hour: 10, minute: 0}]
mozilla-aurora: [{hour: 7, minute: 45}] # Buildbot uses minute 40
mozilla-aurora: [] # bug 1358976
# No default
- name: nightly-mochitest-valgrind

View File

@ -1982,9 +1982,19 @@ DocAccessible::ContentRemoved(Accessible* aChild)
"container", parent, "child", aChild, nullptr);
#endif
// XXX: event coalescence may kill us
RefPtr<Accessible> kungFuDeathGripChild(aChild);
TreeMutation mt(parent);
mt.BeforeRemoval(aChild);
MOZ_DIAGNOSTIC_ASSERT(aChild->Parent(), "Unparented #1");
if (aChild->IsDefunct()) {
MOZ_ASSERT_UNREACHABLE("Event coalescence killed the accessible");
mt.Done();
return;
}
MOZ_DIAGNOSTIC_ASSERT(aChild->Parent(), "Alive but unparented #1");
if (aChild->IsRelocated()) {
nsTArray<RefPtr<Accessible> >* owned = mARIAOwnsHash.Get(parent);

View File

@ -5,6 +5,7 @@ var tabs = gBrowser.tabs;
var rect = ele => ele.getBoundingClientRect();
var width = ele => rect(ele).width;
var height = ele => rect(ele).height;
var left = ele => rect(ele).left;
var right = ele => rect(ele).right;
var isLeft = (ele, msg) => is(left(ele) + tabstrip._tabMarginLeft, left(scrollbox), msg);
@ -14,6 +15,11 @@ var nextLeftElement = () => elementFromPoint(left(scrollbox) - 1);
var nextRightElement = () => elementFromPoint(right(scrollbox) + 1);
var firstScrollable = () => tabs[gBrowser._numPinnedTabs];
var clickCenter = (ele, opts) => {
EventUtils.synthesizeMouse(ele, Math.ceil(width(ele) / 2),
Math.ceil(height(ele) / 2), opts);
}
function test() {
requestLongerTimeout(2);
waitForExplicitFinish();
@ -60,7 +66,7 @@ function runOverflowTests(aEvent) {
"(" + right(gBrowser.selectedTab) + " <= " + right(scrollbox) + ")");
element = nextLeftElement();
EventUtils.synthesizeMouse(upButton, 1, 1, {});
clickCenter(upButton, {});
isLeft(element, "Scrolled one tab to the left with a single click");
let elementPoint = left(scrollbox) - width(scrollbox);
@ -68,10 +74,10 @@ function runOverflowTests(aEvent) {
if (elementPoint == right(element)) {
element = element.nextSibling;
}
EventUtils.synthesizeMouse(upButton, 1, 1, {clickCount: 2});
clickCenter(upButton, {clickCount: 2});
isLeft(element, "Scrolled one page of tabs with a double click");
EventUtils.synthesizeMouse(upButton, 1, 1, {clickCount: 3});
clickCenter(upButton, {clickCount: 3});
var firstScrollableLeft = left(firstScrollable());
ok(left(scrollbox) <= firstScrollableLeft, "Scrolled to the start with a triple click " +
"(" + left(scrollbox) + " <= " + firstScrollableLeft + ")");

View File

@ -57,8 +57,6 @@ var whitelist = new Set([
{file: "chrome://global/locale/printjoboptions.dtd",
platforms: ["macosx", "win"]},
{file: "chrome://weave/locale/errors.properties"},
// devtools/client/inspector/bin/dev-server.js
{file: "chrome://devtools/content/inspector/markup/markup.xhtml",
isFromDevTools: true},

View File

@ -176,102 +176,106 @@ const CustomizableWidgets = [
tooltiptext: "history-panelmenu.tooltiptext2",
defaultArea: CustomizableUI.AREA_PANEL,
onViewShowing(aEvent) {
// Populate our list of history
const kMaxResults = 15;
let doc = aEvent.target.ownerDocument;
let win = doc.defaultView;
aEvent.detail.addBlocker(new Promise((resolve, reject) => {
// Populate our list of history
const kMaxResults = 15;
let doc = aEvent.target.ownerDocument;
let win = doc.defaultView;
let options = PlacesUtils.history.getNewQueryOptions();
options.excludeQueries = true;
options.queryType = options.QUERY_TYPE_HISTORY;
options.sortingMode = options.SORT_BY_DATE_DESCENDING;
options.maxResults = kMaxResults;
let query = PlacesUtils.history.getNewQuery();
let options = PlacesUtils.history.getNewQueryOptions();
options.excludeQueries = true;
options.queryType = options.QUERY_TYPE_HISTORY;
options.sortingMode = options.SORT_BY_DATE_DESCENDING;
options.maxResults = kMaxResults;
let query = PlacesUtils.history.getNewQuery();
let items = doc.getElementById("PanelUI-historyItems");
// Clear previous history items.
while (items.firstChild) {
items.firstChild.remove();
}
let items = doc.getElementById("PanelUI-historyItems");
// Clear previous history items.
while (items.firstChild) {
items.firstChild.remove();
}
// Get all statically placed buttons to supply them with keyboard shortcuts.
let staticButtons = items.parentNode.getElementsByTagNameNS(kNSXUL, "toolbarbutton");
for (let i = 0, l = staticButtons.length; i < l; ++i)
CustomizableUI.addShortcut(staticButtons[i]);
// Get all statically placed buttons to supply them with keyboard shortcuts.
let staticButtons = items.parentNode.getElementsByTagNameNS(kNSXUL, "toolbarbutton");
for (let i = 0, l = staticButtons.length; i < l; ++i)
CustomizableUI.addShortcut(staticButtons[i]);
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.asyncExecuteLegacyQueries([query], 1, options, {
handleResult(aResultSet) {
let onItemCommand = function(aItemCommandEvent) {
// Only handle the click event for middle clicks, we're using the command
// event otherwise.
if (aItemCommandEvent.type == "click" &&
aItemCommandEvent.button != 1) {
return;
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.asyncExecuteLegacyQueries([query], 1, options, {
handleResult(aResultSet) {
let onItemCommand = function(aItemCommandEvent) {
// Only handle the click event for middle clicks, we're using the command
// event otherwise.
if (aItemCommandEvent.type == "click" &&
aItemCommandEvent.button != 1) {
return;
}
let item = aItemCommandEvent.target;
win.openUILink(item.getAttribute("targetURI"), aItemCommandEvent);
CustomizableUI.hidePanelForNode(item);
};
let fragment = doc.createDocumentFragment();
let row;
while ((row = aResultSet.getNextRow())) {
let uri = row.getResultByIndex(1);
let title = row.getResultByIndex(2);
let item = doc.createElementNS(kNSXUL, "toolbarbutton");
item.setAttribute("label", title || uri);
item.setAttribute("targetURI", uri);
item.setAttribute("class", "subviewbutton");
item.addEventListener("command", onItemCommand);
item.addEventListener("click", onItemCommand);
item.setAttribute("image", "page-icon:" + uri);
fragment.appendChild(item);
}
let item = aItemCommandEvent.target;
win.openUILink(item.getAttribute("targetURI"), aItemCommandEvent);
CustomizableUI.hidePanelForNode(item);
};
let fragment = doc.createDocumentFragment();
let row;
while ((row = aResultSet.getNextRow())) {
let uri = row.getResultByIndex(1);
let title = row.getResultByIndex(2);
items.appendChild(fragment);
},
handleError(aError) {
log.debug("History view tried to show but had an error: " + aError);
reject();
},
handleCompletion(aReason) {
log.debug("History view is being shown!");
resolve();
},
});
let item = doc.createElementNS(kNSXUL, "toolbarbutton");
item.setAttribute("label", title || uri);
item.setAttribute("targetURI", uri);
item.setAttribute("class", "subviewbutton");
item.addEventListener("command", onItemCommand);
item.addEventListener("click", onItemCommand);
item.setAttribute("image", "page-icon:" + uri);
fragment.appendChild(item);
}
items.appendChild(fragment);
},
handleError(aError) {
log.debug("History view tried to show but had an error: " + aError);
},
handleCompletion(aReason) {
log.debug("History view is being shown!");
},
});
let recentlyClosedTabs = doc.getElementById("PanelUI-recentlyClosedTabs");
while (recentlyClosedTabs.firstChild) {
recentlyClosedTabs.firstChild.remove();
}
let recentlyClosedTabs = doc.getElementById("PanelUI-recentlyClosedTabs");
while (recentlyClosedTabs.firstChild) {
recentlyClosedTabs.firstChild.remove();
}
let recentlyClosedWindows = doc.getElementById("PanelUI-recentlyClosedWindows");
while (recentlyClosedWindows.firstChild) {
recentlyClosedWindows.firstChild.remove();
}
let recentlyClosedWindows = doc.getElementById("PanelUI-recentlyClosedWindows");
while (recentlyClosedWindows.firstChild) {
recentlyClosedWindows.firstChild.remove();
}
let utils = RecentlyClosedTabsAndWindowsMenuUtils;
let tabsFragment = utils.getTabsFragment(doc.defaultView, "toolbarbutton", true,
"menuRestoreAllTabsSubview.label");
let separator = doc.getElementById("PanelUI-recentlyClosedTabs-separator");
let elementCount = tabsFragment.childElementCount;
separator.hidden = !elementCount;
while (--elementCount >= 0) {
let element = tabsFragment.children[elementCount];
CustomizableUI.addShortcut(element);
element.classList.add("subviewbutton", "cui-withicon");
}
recentlyClosedTabs.appendChild(tabsFragment);
let utils = RecentlyClosedTabsAndWindowsMenuUtils;
let tabsFragment = utils.getTabsFragment(doc.defaultView, "toolbarbutton", true,
"menuRestoreAllTabsSubview.label");
let separator = doc.getElementById("PanelUI-recentlyClosedTabs-separator");
let elementCount = tabsFragment.childElementCount;
separator.hidden = !elementCount;
while (--elementCount >= 0) {
let element = tabsFragment.children[elementCount];
CustomizableUI.addShortcut(element);
element.classList.add("subviewbutton", "cui-withicon");
}
recentlyClosedTabs.appendChild(tabsFragment);
let windowsFragment = utils.getWindowsFragment(doc.defaultView, "toolbarbutton", true,
"menuRestoreAllWindowsSubview.label");
separator = doc.getElementById("PanelUI-recentlyClosedWindows-separator");
elementCount = windowsFragment.childElementCount;
separator.hidden = !elementCount;
while (--elementCount >= 0) {
let element = windowsFragment.children[elementCount];
CustomizableUI.addShortcut(element);
element.classList.add("subviewbutton", "cui-withicon");
}
recentlyClosedWindows.appendChild(windowsFragment);
let windowsFragment = utils.getWindowsFragment(doc.defaultView, "toolbarbutton", true,
"menuRestoreAllWindowsSubview.label");
separator = doc.getElementById("PanelUI-recentlyClosedWindows-separator");
elementCount = windowsFragment.childElementCount;
separator.hidden = !elementCount;
while (--elementCount >= 0) {
let element = windowsFragment.children[elementCount];
CustomizableUI.addShortcut(element);
element.classList.add("subviewbutton", "cui-withicon");
}
recentlyClosedWindows.appendChild(windowsFragment);
}));
},
onCreated(aNode) {
// Middle clicking recently closed items won't close the panel - cope:

View File

@ -2,6 +2,8 @@
* This file contains tests for the Preferences search bar.
*/
requestLongerTimeout(2);
/**
* Tests to see if search bar is being hidden when pref is turned off
*/

View File

@ -19,7 +19,11 @@
--backbutton-border-color: var(--urlbar-border-color-hover);
--backbutton-background: rgba(255,255,255,.15);
%ifdef MOZ_PHOTON_THEME
--toolbarbutton-border-radius: 2px;
%else
--toolbarbutton-border-radius: 1px;
%endif
--toolbarbutton-vertical-text-padding: calc(var(--toolbarbutton-vertical-inner-padding) - 1px);
@ -264,12 +268,24 @@ menuitem.bookmark-item {
#main-window {
--urlbar-border-color: ThreeDShadow;
--urlbar-border-color-hover: var(--urlbar-border-color);
--urlbar-background-color: moz-field;
}
#navigator-toolbox:-moz-lwtheme {
--urlbar-border-color: rgba(0,0,0,.3);
}
%ifdef MOZ_PHOTON_THEME
%include ../shared/location-search-bar.inc.css
#urlbar[focused="true"],
.searchbar-textbox[focused="true"] {
border-color: Highlight;
}
%else
#urlbar,
.searchbar-textbox {
-moz-appearance: none;
@ -299,6 +315,7 @@ menuitem.bookmark-item {
.searchbar-textbox:-moz-lwtheme[focused=true] {
background-color: white;
}
%endif
.urlbar-textbox-container {
-moz-appearance: none;

View File

@ -24,7 +24,11 @@
--toolbarbutton-vertical-text-padding: calc(var(--toolbarbutton-vertical-inner-padding) + 1px);
%ifdef MOZ_PHOTON_THEME
--toolbarbutton-border-radius: 4px;
%else
--toolbarbutton-border-radius: 3px;
%endif
--toolbarbutton-hover-background: hsla(0,0%,100%,.1) linear-gradient(hsla(0,0%,100%,.3), hsla(0,0%,100%,.1)) padding-box;
--toolbarbutton-hover-bordercolor: hsla(0,0%,0%,.2);
@ -515,6 +519,29 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
/* ::::: nav-bar-inner ::::: */
%ifdef MOZ_PHOTON_THEME
#main-window {
--urlbar-border-color: hsla(240, 5%, 5%, .25);
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
--urlbar-background-color: -moz-field;
}
%include ../shared/location-search-bar.inc.css
#urlbar[focused="true"],
.searchbar-textbox[focused="true"] {
border-color: -moz-mac-focusring;
box-shadow: var(--focus-ring-box-shadow);
}
#urlbar,
.searchbar-textbox {
font: icon;
}
%else
#urlbar,
.searchbar-textbox {
font: icon;
@ -563,7 +590,6 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
border-radius: var(--toolbarbutton-border-radius);
}
%ifndef MOZ_PHOTON_THEME
@conditionalForwardWithUrlbar@ > #urlbar {
border-inline-start: none;
margin-left: 0;

View File

@ -0,0 +1,30 @@
/* 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/. */
#urlbar,
.searchbar-textbox {
-moz-appearance: none;
background-clip: content-box;
background-color: var(--urlbar-background-color);
border: 1px solid var(--urlbar-border-color);
border-radius: var(--toolbarbutton-border-radius);
box-shadow: 0 1px 4px hsla(0, 0%, 0%, .05);
padding: 0;
margin: 0 2px;
}
#urlbar:-moz-lwtheme:not(:hover):not([focused="true"]),
.searchbar-textbox:-moz-lwtheme:not(:hover):not([focused="true"]) {
background-color: hsla(0, 100%, 100%, .8);
}
#urlbar:hover,
.searchbar-textbox:hover {
border: 1px solid var(--urlbar-border-color-hover);
box-shadow: 0 1px 6px hsla(0, 0%, 0%, .1), 0 0 1px 0 rgba(0, 0, 0, .1);
}
#urlbar-container {
-moz-box-align: center;
}

View File

@ -19,7 +19,11 @@
--toolbarbutton-vertical-text-padding: calc(var(--toolbarbutton-vertical-inner-padding) - 1px);
%ifdef MOZ_PHOTON_THEME
--toolbarbutton-border-radius: 2px;
%else
--toolbarbutton-border-radius: 1px;
%endif
--toolbarbutton-hover-background: rgba(0,0,0,.1);
--toolbarbutton-hover-bordercolor: rgba(0,0,0,.2);
@ -657,6 +661,25 @@ toolbar[brighttext] #close-button {
--urlbar-border-color: var(--toolbarbutton-hover-bordercolor);
}
%ifdef MOZ_PHOTON_THEME
@media (-moz-windows-default-theme) {
#main-window:not(:-moz-lwtheme) {
--urlbar-border-color: hsla(240, 5%, 5%, .25);
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
--urlbar-background-color: -moz-field;
}
}
%include ../shared/location-search-bar.inc.css
#urlbar[focused="true"],
.searchbar-textbox[focused="true"] {
border-color: Highlight;
}
%else
@media (-moz-windows-default-theme) {
@media (-moz-os-version: windows-win7),
(-moz-os-version: windows-win8) {
@ -753,7 +776,6 @@ toolbar[brighttext] #close-button {
background-color: white;
}
%ifndef MOZ_PHOTON_THEME
@conditionalForwardWithUrlbar@ > #urlbar {
border-inline-start: none;
padding-inline-start: 0;

View File

@ -10,7 +10,6 @@
font-size: 12px;
font-family: Lucida Grande, Tahoma, sans-serif;
line-height: 15px;
width: 100%;
padding: 10px;
color: red;
}

View File

@ -74,9 +74,8 @@ nsJSInspector::EnterNestedEventLoop(JS::Handle<JS::Value> requestor, uint32_t *o
mozilla::dom::AutoNoJSAPI nojsapi;
uint32_t nestLevel = ++mNestedLoopLevel;
while (NS_SUCCEEDED(rv) && mNestedLoopLevel >= nestLevel) {
if (!NS_ProcessNextEvent())
rv = NS_ERROR_UNEXPECTED;
if (!SpinEventLoopUntil([&]() { return mNestedLoopLevel < nestLevel; })) {
rv = NS_ERROR_UNEXPECTED;
}
NS_ASSERTION(mNestedLoopLevel <= nestLevel,

View File

@ -76,6 +76,7 @@
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsBindingManager.h"
#include "nsCanvasFrame.h"
#include "nsCaret.h"
#include "nsCCUncollectableMarker.h"
#include "nsCharSeparatedTokenizer.h"
@ -8127,17 +8128,19 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
}
size_t length;
int32_t stride;
Shmem surfaceData;
IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
: static_cast<IShmemAllocator*>(aParent);
GetSurfaceData(dataSurface, &length, &stride,
allocator,
&surfaceData);
Maybe<Shmem> surfaceData = GetSurfaceData(dataSurface, &length, &stride,
allocator);
if (surfaceData.isNothing()) {
continue;
}
IPCDataTransferItem* item = aIPCDataTransfer->items().AppendElement();
item->flavor() = flavorStr;
// Turn item->data() into an nsCString prior to accessing it.
item->data() = surfaceData;
item->data() = surfaceData.ref();
IPCDataTransferImage& imageDetails = item->imageDetails();
mozilla::gfx::IntSize size = dataSurface->GetSize();
@ -8287,7 +8290,7 @@ struct GetSurfaceDataRawBuffer
// a shared memory buffer.
struct GetSurfaceDataShmem
{
using ReturnType = Shmem;
using ReturnType = Maybe<Shmem>;
using BufferType = char*;
explicit GetSurfaceDataShmem(IShmemAllocator* aAllocator)
@ -8296,17 +8299,18 @@ struct GetSurfaceDataShmem
ReturnType Allocate(size_t aSize)
{
Shmem returnValue;
mAllocator->AllocShmem(aSize,
SharedMemory::TYPE_BASIC,
&returnValue);
return returnValue;
Shmem shmem;
if (!mAllocator->AllocShmem(aSize, SharedMemory::TYPE_BASIC, &shmem)) {
return Nothing();
}
return Some(shmem);
}
static BufferType
GetBuffer(const ReturnType& aReturnValue)
{
return aReturnValue.get<char>();
return aReturnValue.isSome() ? aReturnValue.ref().get<char>() : nullptr;
}
static ReturnType
@ -8374,14 +8378,13 @@ nsContentUtils::GetSurfaceData(
return GetSurfaceDataImpl(aSurface, aLength, aStride);
}
void
Maybe<Shmem>
nsContentUtils::GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
size_t* aLength, int32_t* aStride,
IShmemAllocator* aAllocator,
Shmem *aOutShmem)
IShmemAllocator* aAllocator)
{
*aOutShmem = GetSurfaceDataImpl(aSurface, aLength, aStride,
GetSurfaceDataShmem(aAllocator));
return GetSurfaceDataImpl(aSurface, aLength, aStride,
GetSurfaceDataShmem(aAllocator));
}
mozilla::Modifiers
@ -10251,7 +10254,6 @@ nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
{
MOZ_ASSERT(aDocument);
// XXXheycam This probably needs to find the nsCanvasFrame's NAC too.
if (nsIPresShell* presShell = aDocument->GetShell()) {
if (nsIFrame* scrollFrame = presShell->GetRootScrollFrame()) {
nsIAnonymousContentCreator* creator = do_QueryFrame(scrollFrame);
@ -10259,6 +10261,12 @@ nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
"scroll frame should always implement nsIAnonymousContentCreator");
creator->AppendAnonymousContentTo(aElements, 0);
}
if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
if (Element* container = canvasFrame->GetCustomContentContainer()) {
aElements.AppendElement(container);
}
}
}
}

View File

@ -35,6 +35,7 @@
#include "mozilla/net/ReferrerPolicy.h"
#include "mozilla/Logging.h"
#include "mozilla/NotNull.h"
#include "mozilla/Maybe.h"
#include "nsIContentPolicy.h"
#include "nsIDocument.h"
#include "nsPIDOMWindow.h"
@ -2673,10 +2674,10 @@ public:
* Get the pixel data from the given source surface and fill it in Shmem.
* The length and stride will be assigned from the surface.
*/
static void GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
size_t* aLength, int32_t* aStride,
mozilla::ipc::IShmemAllocator* aAlloc,
mozilla::ipc::Shmem *aOutShmem);
static mozilla::Maybe<mozilla::ipc::Shmem>
GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
size_t* aLength, int32_t* aStride,
mozilla::ipc::IShmemAllocator* aAlloc);
// Helpers shared by the implementations of nsContentUtils methods and
// nsIDOMWindowUtils methods.

View File

@ -11669,9 +11669,7 @@ nsGlobalWindow::ShowSlowScriptDialog()
// script.
RefPtr<nsGlobalWindow> outer = GetOuterWindowInternal();
outer->EnterModalState();
while (!monitor->IsDebuggerStartupComplete()) {
NS_ProcessNextEvent(nullptr, true);
}
SpinEventLoopUntil([&]() { return monitor->IsDebuggerStartupComplete(); });
outer->LeaveModalState();
return ContinueSlowScript;
}

View File

@ -1423,11 +1423,10 @@ Manager::ShutdownAll()
Factory::ShutdownAll();
while (!Factory::IsShutdownAllComplete()) {
if (!NS_ProcessNextEvent()) {
NS_WARNING("Something bad happened!");
break;
}
if (!mozilla::SpinEventLoopUntil([]() {
return Factory::IsShutdownAllComplete();
})) {
NS_WARNING("Something bad happened!");
}
}

View File

@ -4790,12 +4790,7 @@ BlobParent::RecvBlobStreamSync(const uint64_t& aStart,
// The actor is alive and will be doing asynchronous work to load the stream.
// Spin a nested loop here while we wait for it.
nsIThread* currentThread = NS_GetCurrentThread();
MOZ_ASSERT(currentThread);
while (!finished) {
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
}
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return finished; }));
return IPC_OK();
}

View File

@ -947,12 +947,7 @@ FileHandleThreadPool::Shutdown()
return;
}
nsIThread* currentThread = NS_GetCurrentThread();
MOZ_ASSERT(currentThread);
while (!mShutdownComplete) {
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
}
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return mShutdownComplete; }));
}
nsresult

View File

@ -12532,12 +12532,7 @@ ConnectionPool::Shutdown()
return;
}
nsIThread* currentThread = NS_GetCurrentThread();
MOZ_ASSERT(currentThread);
while (!mShutdownComplete) {
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
}
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return mShutdownComplete; }));
}
void
@ -13494,7 +13489,7 @@ ThreadRunnable::Run()
"ConnectionPool::ThreadRunnable::Run",
js::ProfileEntry::Category::STORAGE);
nsIThread* currentThread = NS_GetCurrentThread();
DebugOnly<nsIThread*> currentThread = NS_GetCurrentThread();
MOZ_ASSERT(currentThread);
#ifdef DEBUG
@ -13516,8 +13511,10 @@ ThreadRunnable::Run()
}
#endif // DEBUG
while (mContinueRunning) {
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
DebugOnly<bool> b = SpinEventLoopUntil([&]() -> bool {
if (!mContinueRunning) {
return true;
}
#ifdef DEBUG
if (kDEBUGTransactionThreadSleepMS) {
@ -13526,7 +13523,14 @@ ThreadRunnable::Run()
PR_SUCCESS);
}
#endif // DEBUG
}
return false;
});
// MSVC can't stringify lambdas, so we have to separate the expression
// generating the value from the assert itself.
#if DEBUG
MOZ_ALWAYS_TRUE(b);
#endif
}
return NS_OK;

View File

@ -2704,9 +2704,7 @@ ContentParent::Observe(nsISupports* aSubject,
// Wait for shutdown to complete, so that we receive any shutdown
// data (e.g. telemetry) from the child before we quit.
// This loop terminate prematurely based on mForceKillTimer.
while (mIPCOpen && !mCalledKillHard) {
NS_ProcessNextEvent(nullptr, true);
}
SpinEventLoopUntil([&]() { return !mIPCOpen || mCalledKillHard; });
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
}

View File

@ -1641,8 +1641,7 @@ MediaDecoder::IsWebMEnabled()
bool
MediaDecoder::IsAndroidMediaPluginEnabled()
{
return AndroidBridge::Bridge()
&& AndroidBridge::Bridge()->GetAPIVersion() < 16
return jni::GetAPIVersion() < 16
&& Preferences::GetBool("media.plugins.enabled");
}
#endif

View File

@ -7,7 +7,7 @@
#define MEDIA_PREFS_H
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#include "GeneratedJNIWrappers.h"
#endif
#include "mozilla/Atomics.h"
@ -201,8 +201,7 @@ private:
static int32_t MediaDecoderLimitDefault()
{
#ifdef MOZ_WIDGET_ANDROID
if (AndroidBridge::Bridge() &&
AndroidBridge::Bridge()->GetAPIVersion() < 18) {
if (jni::GetAPIVersion() < 18) {
// Older Android versions have broken support for multiple simultaneous
// decoders, see bug 1278574.
return 1;

View File

@ -299,10 +299,7 @@ GeckoMediaPluginServiceParent::Observe(nsISupports* aSubject,
NS_DISPATCH_NORMAL);
// Wait for UnloadPlugins() to do sync shutdown...
while (mWaitingForPluginsSyncShutdown) {
NS_ProcessNextEvent(NS_GetCurrentThread(), true);
}
SpinEventLoopUntil([&]() { return !mWaitingForPluginsSyncShutdown; });
} else {
// GMP thread has already shutdown.
MOZ_ASSERT(mPlugins.IsEmpty());

View File

@ -20,9 +20,7 @@ public:
void AwaitFinished()
{
MOZ_ASSERT(NS_IsMainThread());
while (!mFinished) {
NS_ProcessNextEvent(nullptr, true);
}
mozilla::SpinEventLoopUntil([&]() { return mFinished; });
mFinished = false;
}

View File

@ -1158,9 +1158,7 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
}
void AwaitFinished() {
while (!mFinished) {
NS_ProcessNextEvent(nullptr, true);
}
mozilla::SpinEventLoopUntil([&]() -> bool { return mFinished; });
mFinished = false;
}

View File

@ -35,9 +35,7 @@ public:
[&]() { done = true; });
// Wait until benchmark completes.
while (!done) {
NS_ProcessNextEvent();
}
SpinEventLoopUntil([&]() { return done; });
return result;
}

View File

@ -2,8 +2,7 @@
* 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 "AndroidDecoderModule.h"
#include "AndroidBridge.h"
#include "GeneratedJNIWrappers.h"
#include "MediaInfo.h"
#include "MediaPrefs.h"
#include "OpusDecoder.h"
@ -128,8 +127,7 @@ AndroidDecoderModule::SupportsMimeType(
const nsACString& aMimeType,
DecoderDoctorDiagnostics* aDiagnostics) const
{
if (!AndroidBridge::Bridge() ||
AndroidBridge::Bridge()->GetAPIVersion() < 16) {
if (jni::GetAPIVersion() < 16) {
return false;
}

View File

@ -4,7 +4,6 @@
#include "AndroidBridge.h"
#include "AndroidDecoderModule.h"
#include "AndroidSurfaceTexture.h"
#include "JavaCallbacksSupport.h"
#include "SimpleMap.h"
#include "GLImages.h"
@ -134,7 +133,7 @@ public:
if (size > 0) {
RefPtr<layers::Image> img = new SurfaceTextureImage(
mDecoder->mSurfaceTexture.get(), inputInfo.mImageSize,
mDecoder->mSurfaceHandle, inputInfo.mImageSize, false /* NOT continuous */,
gl::OriginPos::BottomLeft);
RefPtr<VideoData> v = VideoData::CreateFromImage(
@ -177,18 +176,12 @@ public:
RefPtr<InitPromise> Init() override
{
mSurfaceTexture = AndroidSurfaceTexture::Create();
if (!mSurfaceTexture) {
NS_WARNING("Failed to create SurfaceTexture for video decode\n");
return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR,
__func__);
GeckoSurface::LocalRef surf = GeckoSurface::LocalRef(SurfaceAllocator::AcquireSurface(mConfig.mImage.width, mConfig.mImage.height, false));
if (!surf) {
return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__);
}
if (!jni::IsFennec()) {
NS_WARNING("Remote decoding not supported in non-Fennec environment\n");
return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_FATAL_ERR,
__func__);
}
mSurfaceHandle = surf->GetHandle();
// Register native methods.
JavaCallbacksSupport::Init();
@ -199,7 +192,7 @@ public:
mJavaDecoder = CodecProxy::Create(false, // false indicates to create a decoder and true denotes encoder
mFormat,
mSurfaceTexture->JavaSurface(),
surf,
mJavaCallbacks,
mDrmStubId);
if (mJavaDecoder == nullptr) {
@ -239,7 +232,7 @@ public:
private:
layers::ImageContainer* mImageContainer;
const VideoInfo mConfig;
RefPtr<AndroidSurfaceTexture> mSurfaceTexture;
AndroidSurfaceTextureHandle mSurfaceHandle;
SimpleMap<InputInfo> mInputInfos;
bool mIsCodecSupportAdaptivePlayback = false;
};
@ -411,7 +404,6 @@ RemoteDataDecoder::CreateVideoDecoder(const CreateDecoderParams& aParams,
const nsString& aDrmStubId,
CDMProxy* aProxy)
{
const VideoInfo& config = aParams.VideoConfig();
MediaFormat::LocalRef format;
NS_ENSURE_SUCCESS(

View File

@ -122,11 +122,8 @@ UDPSocketChild::CreatePBackgroundSpinUntilDone()
return NS_ERROR_FAILURE;
}
nsIThread* thread = NS_GetCurrentThread();
while (!done) {
if (NS_WARN_IF(!NS_ProcessNextEvent(thread, true /* aMayWait */))) {
return NS_ERROR_FAILURE;
}
if (!SpinEventLoopUntil([&done]() { return done; })) {
return NS_ERROR_FAILURE;
}
if (NS_WARN_IF(!BackgroundChild::GetForCurrentThread())) {

View File

@ -58,6 +58,8 @@ using namespace mozilla::dom;
#include "TexturePoolOGL.h"
#include "SurfaceTypes.h"
#include "EGLUtils.h"
#include "GeneratedJNIWrappers.h"
#include "GeneratedJNINatives.h"
using namespace mozilla;
using namespace mozilla::gl;
@ -106,7 +108,7 @@ static bool EnsureGLContext()
static std::map<NPP, nsNPAPIPluginInstance*> sPluginNPPMap;
#endif
#endif // MOZ_WIDGET_ANDROID
using namespace mozilla;
using namespace mozilla::plugins::parent;
@ -202,14 +204,12 @@ nsNPAPIPluginInstance::Destroy()
mAudioChannelAgent = nullptr;
#if MOZ_WIDGET_ANDROID
if (mContentSurface)
mContentSurface->SetFrameAvailableCallback(nullptr);
mContentSurface = nullptr;
if (mContentSurface) {
java::SurfaceAllocator::DisposeSurface(mContentSurface);
}
std::map<void*, VideoInfo*>::iterator it;
for (it = mVideos.begin(); it != mVideos.end(); it++) {
it->second->mSurfaceTexture->SetFrameAvailableCallback(nullptr);
delete it->second;
}
mVideos.clear();
@ -858,24 +858,50 @@ GLContext* nsNPAPIPluginInstance::GLContext()
return sPluginContext;
}
already_AddRefed<AndroidSurfaceTexture> nsNPAPIPluginInstance::CreateSurfaceTexture()
class PluginTextureListener
: public java::SurfaceTextureListener::Natives<PluginTextureListener>
{
if (!EnsureGLContext())
return nullptr;
using Base = java::SurfaceTextureListener::Natives<PluginTextureListener>;
GLuint texture = TexturePoolOGL::AcquireTexture();
if (!texture)
return nullptr;
const nsCOMPtr<nsIRunnable> mCallback;
public:
using Base::AttachNative;
using Base::DisposeNative;
RefPtr<AndroidSurfaceTexture> surface = AndroidSurfaceTexture::Create(TexturePoolOGL::GetGLContext(),
texture);
if (!surface) {
PluginTextureListener(nsIRunnable* aCallback) : mCallback(aCallback) {}
void OnFrameAvailable()
{
if (NS_IsMainThread()) {
mCallback->Run();
return;
}
NS_DispatchToMainThread(mCallback);
}
};
java::GeckoSurface::LocalRef nsNPAPIPluginInstance::CreateSurface()
{
java::GeckoSurface::LocalRef surf = java::SurfaceAllocator::AcquireSurface(0, 0, false);
if (!surf) {
return nullptr;
}
nsCOMPtr<nsIRunnable> frameCallback = NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
surface->SetFrameAvailableCallback(frameCallback);
return surface.forget();
java::SurfaceTextureListener::LocalRef listener = java::SurfaceTextureListener::New();
PluginTextureListener::AttachNative(listener, MakeUnique<PluginTextureListener>(frameCallback.get()));
java::GeckoSurfaceTexture::LocalRef gst = java::GeckoSurfaceTexture::Lookup(surf->GetHandle());
if (!gst) {
return nullptr;
}
const auto& st = java::sdk::SurfaceTexture::Ref::From(gst);
st->SetOnFrameAvailableListener(listener);
return surf;
}
void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
@ -886,35 +912,29 @@ void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
void* nsNPAPIPluginInstance::AcquireContentWindow()
{
if (!mContentSurface) {
mContentSurface = CreateSurfaceTexture();
if (!mContentWindow.NativeWindow()) {
mContentSurface = CreateSurface();
if (!mContentSurface)
return nullptr;
mContentWindow = AndroidNativeWindow(mContentSurface);
}
return mContentSurface->NativeWindow();
return mContentWindow.NativeWindow();
}
AndroidSurfaceTexture*
nsNPAPIPluginInstance::AsSurfaceTexture()
java::GeckoSurface::Param
nsNPAPIPluginInstance::AsSurface()
{
if (!mContentSurface)
return nullptr;
return mContentSurface;
}
void* nsNPAPIPluginInstance::AcquireVideoWindow()
{
RefPtr<AndroidSurfaceTexture> surface = CreateSurfaceTexture();
if (!surface) {
return nullptr;
}
java::GeckoSurface::LocalRef surface = CreateSurface();
VideoInfo* info = new VideoInfo(surface);
void* window = info->mSurfaceTexture->NativeWindow();
void* window = info->mNativeWindow.NativeWindow();
mVideos.insert(std::pair<void*, VideoInfo*>(window, info));
return window;

View File

@ -21,7 +21,7 @@
#ifdef MOZ_WIDGET_ANDROID
#include "nsIRunnable.h"
#include "GLContextTypes.h"
#include "AndroidSurfaceTexture.h"
#include "AndroidNativeWindow.h"
#include "AndroidBridge.h"
#include <map>
class PluginEventRunnable;
@ -215,22 +215,24 @@ public:
// For ANPNativeWindow
void* AcquireContentWindow();
mozilla::gl::AndroidSurfaceTexture* AsSurfaceTexture();
mozilla::java::GeckoSurface::Param AsSurface();
// For ANPVideo
class VideoInfo {
public:
VideoInfo(mozilla::gl::AndroidSurfaceTexture* aSurfaceTexture) :
mSurfaceTexture(aSurfaceTexture)
VideoInfo(mozilla::java::GeckoSurface::Param aSurface)
: mSurface(aSurface)
, mNativeWindow(aSurface)
{
}
~VideoInfo()
{
mSurfaceTexture = nullptr;
mozilla::java::SurfaceAllocator::DisposeSurface(mSurface);
}
RefPtr<mozilla::gl::AndroidSurfaceTexture> mSurfaceTexture;
mozilla::java::GeckoSurface::GlobalRef mSurface;
mozilla::gl::AndroidNativeWindow mNativeWindow;
gfxRect mDimensions;
};
@ -359,7 +361,8 @@ protected:
bool mFullScreen;
mozilla::gl::OriginPos mOriginPos;
RefPtr<mozilla::gl::AndroidSurfaceTexture> mContentSurface;
mozilla::java::GeckoSurface::GlobalRef mContentSurface;
mozilla::gl::AndroidNativeWindow mContentWindow;
#endif
enum {
@ -409,8 +412,7 @@ private:
mozilla::TimeStamp mStopTime;
#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<mozilla::gl::AndroidSurfaceTexture> CreateSurfaceTexture();
mozilla::java::GeckoSurface::LocalRef CreateSurface();
std::map<void*, VideoInfo*> mVideos;
bool mOnScreen;

View File

@ -1727,9 +1727,7 @@ nsPluginHost::SiteHasData(nsIPluginTag* plugin, const nsACString& domain,
rv = library->NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback>(do_QueryInterface(closure)));
NS_ENSURE_SUCCESS(rv, rv);
// Spin the event loop while we wait for the async call to GetSitesWithData
while (closure->keepWaiting) {
NS_ProcessNextEvent(nullptr, true);
}
SpinEventLoopUntil([&]() { return !closure->keepWaiting; });
*result = closure->result;
return closure->retVal;
}

View File

@ -165,22 +165,23 @@ nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder)
#if MOZ_WIDGET_ANDROID
static void
AttachToContainerAsSurfaceTexture(ImageContainer* container,
nsNPAPIPluginInstance* instance,
const LayoutDeviceRect& rect,
RefPtr<Image>* out_image)
AttachToContainerAsSurface(ImageContainer* container,
nsNPAPIPluginInstance* instance,
const LayoutDeviceRect& rect,
RefPtr<Image>* out_image)
{
MOZ_ASSERT(out_image);
MOZ_ASSERT(!*out_image);
mozilla::gl::AndroidSurfaceTexture* surfTex = instance->AsSurfaceTexture();
if (!surfTex) {
java::GeckoSurface::LocalRef surface = instance->AsSurface();
if (!surface) {
return;
}
RefPtr<Image> img = new SurfaceTextureImage(
surfTex,
surface->GetHandle(),
gfx::IntSize::Truncate(rect.width, rect.height),
true, // continuously update without a transaction
instance->OriginPos());
*out_image = img;
}
@ -223,7 +224,7 @@ nsPluginInstanceOwner::GetImageContainer()
if (r.width && r.height) {
// Try to get it as an EGLImage first.
RefPtr<Image> img;
AttachToContainerAsSurfaceTexture(container, mInstance, r, &img);
AttachToContainerAsSurface(container, mInstance, r, &img);
if (img) {
container->SetCurrentImageInTransaction(img);
@ -1585,8 +1586,9 @@ nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInf
if (aVideoInfo->mDimensions.width && aVideoInfo->mDimensions.height) {
RefPtr<Image> img = new SurfaceTextureImage(
aVideoInfo->mSurfaceTexture,
aVideoInfo->mSurface->GetHandle(),
gfx::IntSize::Truncate(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height),
true, /* continuous */
gl::OriginPos::BottomLeft);
container->SetCurrentImageInTransaction(img);
}

View File

@ -2858,12 +2858,7 @@ ShutdownObserver::Observe(nsISupports* aSubject,
MOZ_ALWAYS_SUCCEEDS(
mBackgroundThread->Dispatch(shutdownRunnable, NS_DISPATCH_NORMAL));
nsIThread* currentThread = NS_GetCurrentThread();
MOZ_ASSERT(currentThread);
while (!done) {
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
}
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return done; }));
return NS_OK;
}

View File

@ -103,19 +103,8 @@ function testScript(script) {
}
navigator.serviceWorker.register("worker_wrapper.js", {scope: "."})
.then(function(registration) {
if (registration.installing) {
var done = false;
registration.installing.onstatechange = function() {
if (!done) {
done = true;
setupSW(registration);
}
};
} else {
setupSW(registration);
}
});
.then(swr => waitForState(swr.installing, 'activated', swr))
.then(setupSW);
});
}

View File

@ -14,10 +14,11 @@ function testScript(script) {
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true]]
}, function() {
navigator.serviceWorker.ready.then(setupSW);
var scriptURL = location.href.includes("sw_empty_reroute.html")
? "empty.js" : "reroute.js";
navigator.serviceWorker.register(scriptURL, {scope: "/"});
navigator.serviceWorker.register(scriptURL, {scope: "/"})
.then(swr => waitForState(swr.installing, 'activated', swr))
.then(setupSW);
});
}

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_fetch_basic_http.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_fetch_basic_http.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_fetch_basic.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_fetch_basic.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_fetch_cors.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_fetch_cors.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_formdataparsing.js");

View File

@ -8,6 +8,7 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_headers_common.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_request.js");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="sw_reroute.js"> </script>
<script class="testbody" type="text/javascript">
testScript("test_response.js");

View File

@ -35,3 +35,17 @@ function readAsArrayBuffer(blob) {
}
}
function waitForState(worker, state, context) {
return new Promise(resolve => {
if (worker.state === state) {
resolve(context);
return;
}
worker.addEventListener('statechange', function onStateChange() {
if (worker.state === state) {
worker.removeEventListener('statechange', onStateChange);
resolve(context);
}
});
});
}

View File

@ -902,7 +902,9 @@ private:
nsIPrincipal* principal = mWorkerPrivate->GetPrincipal();
nsCOMPtr<nsILoadGroup> loadGroup = mWorkerPrivate->GetLoadGroup();
MOZ_DIAGNOSTIC_ASSERT(principal);
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(loadGroup, principal));
NS_ENSURE_TRUE(NS_LoadGroupMatchesPrincipal(loadGroup, principal),
NS_ERROR_FAILURE);
// Figure out our base URI.
nsCOMPtr<nsIURI> baseURI = GetBaseURI(mIsMainScript, mWorkerPrivate);

View File

@ -989,13 +989,7 @@ ServiceWorkerRegistrar::ProfileStopped()
child->SendShutdownServiceWorkerRegistrar();
nsCOMPtr<nsIThread> thread(do_GetCurrentThread());
while (true) {
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(thread));
if (completed) {
break;
}
}
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return completed; }));
}
void

View File

@ -4798,6 +4798,7 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
loadInfo.mBaseURI = document->GetDocBaseURI();
loadInfo.mLoadGroup = document->GetDocumentLoadGroup();
NS_ENSURE_TRUE(loadInfo.mLoadGroup, NS_ERROR_FAILURE);
// Use the document's NodePrincipal as our principal if we're not being
// called from chrome.
@ -4833,6 +4834,10 @@ WorkerPrivate::GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
}
}
NS_ENSURE_TRUE(NS_LoadGroupMatchesPrincipal(loadInfo.mLoadGroup,
loadInfo.mPrincipal),
NS_ERROR_FAILURE);
nsCOMPtr<nsIPermissionManager> permMgr =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@ -4951,6 +4956,9 @@ WorkerPrivate::OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo)
MOZ_ALWAYS_SUCCEEDS(rv);
aLoadInfo.mLoadGroup = loadGroup.forget();
MOZ_ASSERT(NS_LoadGroupMatchesPrincipal(aLoadInfo.mLoadGroup,
aLoadInfo.mPrincipal));
}
void

View File

@ -215,6 +215,7 @@ support-files =
nofetch_handler_worker.js
service_worker.js
service_worker_client.html
utils.js
[test_bug1151916.html]
[test_bug1240436.html]

View File

@ -23,6 +23,7 @@
<pre id="test">
</pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
add_task(function setupPrefs() {
return SpecialPowers.pushPrefEnv({"set": [
@ -47,13 +48,7 @@ add_task(function* async_wait_until() {
"async_waituntil_worker.js", { scope: "./"} )
.then(function(registration) {
worker = registration.installing;
return new Promise(function(resolve) {
worker.addEventListener('statechange', function() {
if (worker.state === 'activated') {
resolve(registration);
}
});
});
return waitForState(worker, 'activated', registration);
});
// The service worker will claim us when it becomes active.

View File

@ -17,6 +17,7 @@
<p id="display"></p>
<div id="content"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
var worker;
@ -24,7 +25,10 @@
function start() {
return navigator.serviceWorker.register("client_focus_worker.js",
{ scope: "./sw_clients/focus_stealing_client.html" })
.then((swr) => registration = swr);
.then((swr) => {
registration = swr;
returun waitForState(swr.installing, 'activated', swr);
});
}
function unregister() {

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var content;
@ -22,9 +23,8 @@
function simpleRegister() {
// We use the control scope for the less specific registration. The window will register a worker on controller/
return navigator.serviceWorker.register("worker.js", { scope: "./control" })
.then(function(reg) {
registration = reg;
});;
.then(swr => waitForState(swr.installing, 'activated', swr))
.then(swr => registration = swr);
}
function unregister() {

View File

@ -13,18 +13,17 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
SimpleTest.requestCompleteLog();
var registration;
function simpleRegister() {
var p = navigator.serviceWorker.register("fetch_event_worker.js", { scope: "./fetch" });
return p.then(function(swr) {
registration = swr;
return new Promise(function(resolve) {
swr.installing.onstatechange = resolve;
return navigator.serviceWorker.register("fetch_event_worker.js", { scope: "./fetch" })
.then(swr => {
registration = swr;
return waitForState(swr.installing, 'activated');
});
});
}
function unregister() {

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
var scope = './file_blob_response/';
@ -21,14 +22,7 @@
{ scope: scope })
.then(function(swr) {
registration = swr;
return new Promise(function(resolve) {
registration.installing.onstatechange = function(evt) {
if (evt.target.state === 'activated') {
evt.target.onstate = null;
resolve();
}
}
});
return new waitForState(swr.installing, 'activated');
});
}

View File

@ -13,13 +13,17 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
var iframe;
function start() {
return navigator.serviceWorker.register("empty.js",
{ scope: "./sw_clients/" })
.then((swr) => registration = swr);
.then((swr) => {
registration = swr
return waitForState(swr.installing, 'activated', swr);
});
}
function unregister() {

View File

@ -13,12 +13,16 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
function start() {
return navigator.serviceWorker.register("gzip_redirect_worker.js",
{ scope: "./sw_clients/" })
.then((swr) => registration = swr);
.then((swr) => {
registration = swr;
return waitForState(swr.installing, 'activated', swr);
});
}
function unregister() {

View File

@ -11,11 +11,13 @@
</head>
<body>
<div id="content"></div>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
function start() {
return navigator.serviceWorker.register("importscript_worker.js",
{ scope: "./sw_clients/" })
.then((swr) => registration = swr);
.then(swr => waitForState(swr.installing, 'activated', swr))
.then(swr => registration = swr);
}
function unregister() {

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
// match_all_worker will call matchAll until the worker shuts down.
// Test passes if the browser doesn't crash on leaked promise objects.
@ -23,7 +24,10 @@
function simpleRegister() {
return navigator.serviceWorker.register("match_all_worker.js",
{ scope: "./sw_clients/" })
.then((swr) => registration = swr);
.then((swr) => {
registration = swr;
return waitForState(swr.installing, 'activated', swr);
});
}
function closeAndUnregister() {

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var client_iframes = [];
var registration;
@ -21,6 +22,8 @@
return navigator.serviceWorker.register("match_all_advanced_worker.js",
{ scope: "./sw_clients/" }).then(function(swr) {
registration = swr;
return waitForState(swr.installing, 'activated');
}).then(_ => {
window.onmessage = function (e) {
if (e.data === "READY") {
ok(registration.active, "Worker is active.");

View File

@ -13,13 +13,17 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
var clientURL = "match_all_client/match_all_client_id.html";
function start() {
return navigator.serviceWorker.register("match_all_client_id_worker.js",
{ scope: "./match_all_client/" })
.then((swr) => registration = swr);
.then((swr) => {
registration = swr;
return waitForState(swr.installing, 'activated', swr);
});
}
function unregister() {

View File

@ -13,13 +13,17 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
var clientURL = "match_all_clients/match_all_controlled.html";
function start() {
return navigator.serviceWorker.register("match_all_properties_worker.js",
{ scope: "./match_all_clients/" })
.then((swr) => registration = swr);
.then((swr) => {
registration = swr;
return waitForState(swr.installing, 'activated', swr);
});
}
function unregister() {

View File

@ -17,6 +17,7 @@
<pre id="test">
</pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
add_task(function setupPrefs() {
@ -44,16 +45,7 @@ function create_iframe(url) {
add_task(function* test_nofetch_worker() {
let registration = yield navigator.serviceWorker.register(
"nofetch_handler_worker.js", { scope: "./nofetch_handler_worker/"} )
.then(function(registration) {
var worker = registration.installing;
return new Promise(function(resolve) {
worker.addEventListener('statechange', function() {
if (worker.state === 'activated') {
resolve(registration);
}
});
});
});
.then(swr => waitForState(swr.installing, 'activated', swr));
let iframe = yield create_iframe("./nofetch_handler_worker/doesnt_exist.html");
ok(!iframe.contentDocument.body.innerHTML.includes("intercepted"), "Request was not intercepted.");

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
SimpleTest.requestCompleteLog();
@ -21,9 +22,7 @@
var p = navigator.serviceWorker.register("./fetch/plugin/worker.js", { scope: "./fetch/plugin/" });
return p.then(function(swr) {
registration = swr;
return new Promise(function(resolve) {
swr.installing.onstatechange = resolve;
});
return waitForState(swr.installing, 'activated');
});
}

View File

@ -17,6 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1172870
</div>
<pre id="test">
</pre>
<script src="utils.js"></script>
<script type="text/javascript">
SimpleTest.requestFlakyTimeout("Mock alert service dispatches show and click events.");
@ -27,17 +28,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1172870
.then(function(swr) {
ok(swr, "Registration successful");
ctx.registration = swr;
return ctx;
return waitForState(swr.installing, 'activated', ctx);
});
}
function waitForActiveServiceWorker(ctx) {
return navigator.serviceWorker.ready.then(function(result) {
ok(ctx.registration.active, "Service Worker is active");
return ctx;
});
}
function setupMessageHandler(ctx) {
return new Promise(function(res, rej) {
navigator.serviceWorker.onmessage = function(event) {
@ -87,7 +81,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1172870
function runTest() {
setup({})
.then(waitForActiveServiceWorker)
// Permission to allow popups persists for some time after a notification
// click event, so the order here is important.
.then(testPopupNotAllowed)

View File

@ -13,12 +13,14 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var magic_value = "MAGIC_VALUE_123";
var registration;
function start() {
return navigator.serviceWorker.register("message_posting_worker.js",
{ scope: "./sw_clients/" })
.then(swr => waitForState(swr.installing, 'activated', swr))
.then((swr) => registration = swr);
}

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
var base = ["string", true, 42];
@ -49,6 +50,7 @@
function start() {
return navigator.serviceWorker.register("message_posting_worker.js",
{ scope: "./sw_clients/" })
.then(swr => waitForState(swr.installing, 'activated', swr))
.then((swr) => registration = swr);
}

View File

@ -13,13 +13,14 @@
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var regisration;
function simpleRegister() {
return navigator.serviceWorker.register("service_worker.js", {
scope: 'service_worker_client.html'
});
}).then(swr => waitForState(swr.installing, 'activated', swr));
}
function unregister() {

View File

@ -11,10 +11,12 @@
</head>
<body>
<div id="container"></div>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
function simpleRegister() {
return navigator.serviceWorker.register("worker_update.js", { scope: "workerUpdate/" });
return navigator.serviceWorker.register("worker_update.js", { scope: "workerUpdate/" })
.then(swr => waitForState(swr.installing, 'activated', swr));
}
var registration;

View File

@ -13,6 +13,7 @@
<p id="display"></p>
<div id="content"></div>
<pre id="test"></pre>
<script src="utils.js"></script>
<script class="testbody" type="text/javascript">
var registration;
var worker;
@ -24,18 +25,7 @@
registration = swr;
// Ensure the registration is active before continuing
var worker = registration.installing;
return new Promise((resolve) => {
if (worker.state === 'activated') {
resolve();
return;
}
worker.addEventListener('statechange', () => {
if (worker.state === 'activated') {
resolve();
}
});
});
return waitForState(swr.installing, 'activated');
});
}

View File

@ -0,0 +1,14 @@
function waitForState(worker, state, context) {
return new Promise(resolve => {
if (worker.state === state) {
resolve(context);
return;
}
worker.addEventListener('statechange', function onStateChange() {
if (worker.state === state) {
worker.removeEventListener('statechange', onStateChange);
resolve(context);
}
});
});
}

View File

@ -3000,12 +3000,8 @@ XMLHttpRequestMainThread::SendInternal(const BodyExtractorBase* aBody)
if (NS_SUCCEEDED(rv)) {
nsAutoSyncOperation sync(mSuspendedDoc);
nsIThread *thread = NS_GetCurrentThread();
while (mFlagSyncLooping) {
if (!NS_ProcessNextEvent(thread)) {
rv = NS_ERROR_UNEXPECTED;
break;
}
if (!SpinEventLoopUntil([&]() { return !mFlagSyncLooping; })) {
rv = NS_ERROR_UNEXPECTED;
}
// Time expired... We should throw.

View File

@ -462,14 +462,9 @@ XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
}
if (!mAsync) {
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
nsAutoSyncOperation sync(this);
mLoopingForSyncLoad = true;
while (mLoopingForSyncLoad) {
if (!NS_ProcessNextEvent(thread))
break;
}
SpinEventLoopUntil([&]() { return !mLoopingForSyncLoad; });
// We set return to true unless there was a parsing error
Element* rootElement = GetRootElement();

View File

@ -310,12 +310,6 @@ nsresult nsAutoConfig::downloadAutoConfig()
if (firstTime) {
firstTime = false;
// Getting the current thread. If we start an AsyncOpen, the thread
// needs to wait before the reading of autoconfig is done
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
NS_ENSURE_STATE(thread);
/* process events until we're finished. AutoConfig.jsc reading needs
to be finished before the browser starts loading up
We are waiting for the mLoaded which will be set through
@ -323,9 +317,10 @@ nsresult nsAutoConfig::downloadAutoConfig()
There is a possibility of deadlock so we need to make sure
that mLoaded will be set to true in any case (success/failure)
*/
while (!mLoaded)
NS_ENSURE_STATE(NS_ProcessNextEvent(thread));
if (!mozilla::SpinEventLoopUntil([&]() { return mLoaded; })) {
return NS_ERROR_FAILURE;
}
int32_t minutes;
rv = mPrefBranch->GetIntPref("autoadmin.refresh_interval",

View File

@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* 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 AndroidNativeWindow_h__
#define AndroidNativeWindow_h__
#ifdef MOZ_WIDGET_ANDROID
#include <jni.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include "GeneratedJNIWrappers.h"
#include "SurfaceTexture.h"
namespace mozilla {
namespace gl {
class AndroidNativeWindow {
public:
AndroidNativeWindow() : mNativeWindow(nullptr) {
}
AndroidNativeWindow(java::sdk::Surface::Param aSurface) {
mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
aSurface.Get());
}
AndroidNativeWindow(java::GeckoSurface::Param aSurface) {
auto surf = java::sdk::Surface::LocalRef(java::sdk::Surface::Ref::From(aSurface));
mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
surf.Get());
}
~AndroidNativeWindow() {
if (mNativeWindow) {
ANativeWindow_release(mNativeWindow);
mNativeWindow = nullptr;
}
}
ANativeWindow* NativeWindow() const {
return mNativeWindow;
}
private:
ANativeWindow* mNativeWindow;
};
} // gl
} // mozilla
#endif // MOZ_WIDGET_ANDROID
#endif // AndroidNativeWindow_h__

View File

@ -1,204 +1,20 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* 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/. */
#ifdef MOZ_WIDGET_ANDROID
#include <map>
#include <android/native_window_jni.h>
#include <android/log.h>
#include "AndroidSurfaceTexture.h"
#include "gfxImageSurface.h"
#include "gfxPrefs.h"
#include "AndroidBridge.h"
#include "nsThreadUtils.h"
#include "mozilla/gfx/Matrix.h"
#include "GeneratedJNINatives.h"
#include "GLContext.h"
using namespace mozilla;
namespace mozilla {
namespace gl {
class AndroidSurfaceTexture::Listener
: public java::SurfaceTextureListener::Natives<Listener>
{
using Base = java::SurfaceTextureListener::Natives<Listener>;
const nsCOMPtr<nsIRunnable> mCallback;
public:
using Base::AttachNative;
using Base::DisposeNative;
Listener(nsIRunnable* aCallback) : mCallback(aCallback) {}
void OnFrameAvailable()
{
if (NS_IsMainThread()) {
mCallback->Run();
return;
}
NS_DispatchToMainThread(mCallback);
}
};
already_AddRefed<AndroidSurfaceTexture>
AndroidSurfaceTexture::Create()
{
return Create(nullptr, 0);
}
already_AddRefed<AndroidSurfaceTexture>
AndroidSurfaceTexture::Create(GLContext* aContext, GLuint aTexture)
{
RefPtr<AndroidSurfaceTexture> st = new AndroidSurfaceTexture();
if (!st->Init(aContext, aTexture)) {
printf_stderr("Failed to initialize AndroidSurfaceTexture");
st = nullptr;
}
return st.forget();
}
nsresult
AndroidSurfaceTexture::Attach(GLContext* aContext, PRIntervalTime aTimeout)
{
MonitorAutoLock lock(mMonitor);
if (mAttachedContext == aContext) {
NS_WARNING("Tried to attach same GLContext to AndroidSurfaceTexture");
return NS_OK;
}
if (!CanDetach()) {
return NS_ERROR_NOT_AVAILABLE;
}
while (mAttachedContext) {
// Wait until it's detached (or we time out)
if (NS_FAILED(lock.Wait(aTimeout))) {
return NS_ERROR_NOT_AVAILABLE;
}
}
MOZ_ASSERT(aContext->IsOwningThreadCurrent(), "Trying to attach GLContext from different thread");
aContext->fGenTextures(1, &mTexture);
if (NS_FAILED(mSurfaceTexture->AttachToGLContext(mTexture))) {
return NS_ERROR_NOT_AVAILABLE;
}
mAttachedContext = aContext;
mAttachedContext->MakeCurrent();
return NS_OK;
}
nsresult
AndroidSurfaceTexture::Detach()
{
MonitorAutoLock lock(mMonitor);
if (!CanDetach() ||
!mAttachedContext ||
!mAttachedContext->IsOwningThreadCurrent())
{
return NS_ERROR_FAILURE;
}
mAttachedContext->MakeCurrent();
mSurfaceTexture->DetachFromGLContext();
mTexture = 0;
mAttachedContext = nullptr;
lock.NotifyAll();
return NS_OK;
}
bool
AndroidSurfaceTexture::CanDetach() const
{
// The API for attach/detach only exists on 16+, and PowerVR has some sort of
// fencing issue. Additionally, attach/detach seems to be busted on at least
// some Mali adapters (400MP2 for sure, bug 1131793)
return AndroidBridge::Bridge()->GetAPIVersion() >= 16 &&
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::Imagination) &&
(!mAttachedContext || mAttachedContext->Vendor() != GLVendor::ARM /* Mali */) &&
gfxPrefs::SurfaceTextureDetachEnabled();
}
bool
AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
{
if (!aTexture && !CanDetach()) {
// We have no texture and cannot initialize detached, bail out
return false;
}
if (NS_WARN_IF(NS_FAILED(
java::sdk::SurfaceTexture::New(aTexture, ReturnTo(&mSurfaceTexture))))) {
return false;
}
if (!aTexture) {
mSurfaceTexture->DetachFromGLContext();
}
mAttachedContext = aContext;
if (NS_WARN_IF(NS_FAILED(
java::sdk::Surface::New(mSurfaceTexture, ReturnTo(&mSurface))))) {
return false;
}
mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
mSurface.Get());
MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface");
return true;
}
AndroidSurfaceTexture::AndroidSurfaceTexture()
: mTexture(0)
, mSurfaceTexture()
, mSurface()
, mAttachedContext(nullptr)
, mMonitor("AndroidSurfaceTexture")
{
}
AndroidSurfaceTexture::~AndroidSurfaceTexture()
{
if (mSurfaceTexture) {
SetFrameAvailableCallback(nullptr);
mSurfaceTexture = nullptr;
}
if (mNativeWindow) {
ANativeWindow_release(mNativeWindow);
mNativeWindow = nullptr;
}
}
void
AndroidSurfaceTexture::UpdateTexImage()
{
mSurfaceTexture->UpdateTexImage();
}
void
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) const
AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
gfx::Matrix4x4& aMatrix)
{
JNIEnv* const env = jni::GetEnvForThread();
auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
mSurfaceTexture->GetTransformMatrix(jarray);
aSurfaceTexture->GetTransformMatrix(jarray);
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
@ -225,36 +41,6 @@ AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) const
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
}
void
AndroidSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
{
java::SurfaceTextureListener::LocalRef newListener;
if (aRunnable) {
newListener = java::SurfaceTextureListener::New();
Listener::AttachNative(newListener, MakeUnique<Listener>(aRunnable));
}
if (aRunnable || mListener) {
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
mSurfaceTexture->SetOnFrameAvailableListener(newListener)));
}
if (mListener) {
Listener::DisposeNative(java::SurfaceTextureListener::LocalRef(
newListener.Env(), mListener));
}
mListener = newListener;
}
void
AndroidSurfaceTexture::SetDefaultSize(mozilla::gfx::IntSize size)
{
mSurfaceTexture->SetDefaultBufferSize(size.width, size.height);
}
} // gl
} // mozilla
#endif // MOZ_WIDGET_ANDROID

View File

@ -8,100 +8,23 @@
#define AndroidSurfaceTexture_h__
#ifdef MOZ_WIDGET_ANDROID
#include <jni.h>
#include <android/native_window.h>
#include "nsIRunnable.h"
#include "gfxPlatform.h"
#include "GLDefs.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/MatrixFwd.h"
#include "mozilla/Monitor.h"
#include "GeneratedJNIWrappers.h"
#include "mozilla/gfx/Matrix.h"
#include "SurfaceTexture.h"
typedef uint32_t AndroidSurfaceTextureHandle;
namespace mozilla {
namespace gl {
class GLContext;
/**
* This class is a wrapper around Android's SurfaceTexture class.
* Usage is pretty much exactly like the Java class, so see
* the Android documentation for details.
*/
class AndroidSurfaceTexture {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AndroidSurfaceTexture)
public:
static void GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
mozilla::gfx::Matrix4x4& aMatrix);
// The SurfaceTexture is created in an attached state. This method requires
// Android Ice Cream Sandwich.
static already_AddRefed<AndroidSurfaceTexture> Create(GLContext* aGLContext, GLuint aTexture);
// Here the SurfaceTexture will be created in a detached state. You must call
// Attach() with the GLContext you wish to composite with. It must be done
// on the thread where that GLContext is current. This method requires
// Android Jelly Bean.
static already_AddRefed<AndroidSurfaceTexture> Create();
// If we are on Jelly Bean, the SurfaceTexture can be detached and reattached
// to allow consumption from different GLContexts. It is recommended to only
// attach while you are consuming in order to allow this.
//
// Only one GLContext may be attached at any given time. If another is already
// attached, we try to wait for it to become detached.
nsresult Attach(GLContext* aContext, PRIntervalTime aTiemout = PR_INTERVAL_NO_TIMEOUT);
nsresult Detach();
// Ability to detach is based on API version (16+), and we also block PowerVR
// since it has some type of fencing problem. Bug 1100126.
bool CanDetach() const;
GLContext* AttachedContext() const { return mAttachedContext; }
ANativeWindow* NativeWindow() const {
return mNativeWindow;
}
// This attaches the updated data to the TEXTURE_EXTERNAL target
void UpdateTexImage();
void GetTransformMatrix(mozilla::gfx::Matrix4x4& aMatrix) const;
void SetDefaultSize(mozilla::gfx::IntSize size);
// The callback is guaranteed to be called on the main thread even
// if the upstream callback is received on a different thread
void SetFrameAvailableCallback(nsIRunnable* aRunnable);
GLuint Texture() const { return mTexture; }
const java::sdk::Surface::Ref& JavaSurface() const { return mSurface; }
private:
class Listener;
AndroidSurfaceTexture();
~AndroidSurfaceTexture();
bool Init(GLContext* aContext, GLuint aTexture);
GLuint mTexture;
java::sdk::SurfaceTexture::GlobalRef mSurfaceTexture;
java::sdk::Surface::GlobalRef mSurface;
java::SurfaceTextureListener::GlobalRef mListener;
GLContext* mAttachedContext;
ANativeWindow* mNativeWindow;
Monitor mMonitor;
};
}
}
} // gl
} // mozilla
#endif
#endif
#endif // MOZ_WIDGET_ANDROID
#endif // AndroidSurfaceTexture_h__

View File

@ -684,30 +684,8 @@ GLBlitHelper::BindAndUploadEGLImage(EGLImage image, GLuint target)
bool
GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage)
{
AndroidSurfaceTexture* surfaceTexture = stImage->GetSurfaceTexture();
ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
if (NS_FAILED(surfaceTexture->Attach(mGL, PR_MillisecondsToInterval(ATTACH_WAIT_MS))))
return false;
// UpdateTexImage() changes the EXTERNAL binding, so save it here
// so we can restore it after.
int oldBinding = 0;
mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldBinding);
surfaceTexture->UpdateTexImage();
gfx::Matrix4x4 transform;
surfaceTexture->GetTransformMatrix(transform);
mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &transform._11);
mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
surfaceTexture->Detach();
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, oldBinding);
return true;
// FIXME
return false;
}
bool

View File

@ -69,6 +69,9 @@ public:
virtual bool ReleaseTexImage() override;
void SetEGLSurfaceOverride(EGLSurface surf);
EGLSurface GetEGLSurfaceOverride() {
return mSurfaceOverride;
}
virtual bool MakeCurrentImpl(bool aForce) override;

View File

@ -90,6 +90,12 @@ GLScreenBuffer::CreateFactory(GLContext* gl,
factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
#elif defined(MOZ_WIDGET_UIKIT)
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags);
#elif defined(MOZ_WIDGET_ANDROID)
if (XRE_IsParentProcess()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
} else {
factory = SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags);
}
#else
if (gl->GetContextType() == GLContextType::EGL) {
if (XRE_IsParentProcess()) {

View File

@ -96,6 +96,10 @@ public:
// Unlocking is harmless if we're already unlocked.
void UnlockProd();
// This surface has been moved to the front buffer and will not be locked again
// until it is recycled. Do any finalization steps here.
virtual void Commit(){}
protected:
virtual void LockProdImpl() = 0;
virtual void UnlockProdImpl() = 0;

View File

@ -7,6 +7,7 @@
#include "GLBlitHelper.h"
#include "GLContextEGL.h"
#include "GLContextProvider.h"
#include "GLLibraryEGL.h"
#include "GLReadTexImageHelper.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
@ -100,12 +101,6 @@ SharedSurface_EGLImage::~SharedSurface_EGLImage()
mProdTex = 0;
}
layers::TextureFlags
SharedSurface_EGLImage::GetTextureFlags() const
{
return layers::TextureFlags::DEALLOCATE_CLIENT;
}
void
SharedSurface_EGLImage::ProducerReleaseImpl()
{
@ -185,6 +180,136 @@ SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps,
return Move(ret);
}
////////////////////////////////////////////////////////////////////////
#ifdef MOZ_WIDGET_ANDROID
/*static*/ UniquePtr<SharedSurface_SurfaceTexture>
SharedSurface_SurfaceTexture::Create(GLContext* prodGL,
const GLFormats& formats,
const gfx::IntSize& size,
bool hasAlpha,
java::GeckoSurface::Param surface)
{
MOZ_ASSERT(surface);
UniquePtr<SharedSurface_SurfaceTexture> ret;
AndroidNativeWindow window(surface);
EGLSurface eglSurface = GLContextProviderEGL::CreateEGLSurface(window.NativeWindow());
if (!eglSurface) {
return Move(ret);
}
ret.reset(new SharedSurface_SurfaceTexture(prodGL, size, hasAlpha,
formats, surface, eglSurface));
return Move(ret);
}
SharedSurface_SurfaceTexture::SharedSurface_SurfaceTexture(GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha,
const GLFormats& formats,
java::GeckoSurface::Param surface,
EGLSurface eglSurface)
: SharedSurface(SharedSurfaceType::AndroidSurfaceTexture,
AttachmentType::Screen,
gl,
size,
hasAlpha,
true)
, mSurface(surface)
, mEglSurface(eglSurface)
{
}
SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture()
{
GLContextProviderEGL::DestroyEGLSurface(mEglSurface);
java::SurfaceAllocator::DisposeSurface(mSurface);
}
void
SharedSurface_SurfaceTexture::LockProdImpl()
{
MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
GLContextEGL *gl = GLContextEGL::Cast(mGL);
mOrigEglSurface = gl->GetEGLSurfaceOverride();
gl->SetEGLSurfaceOverride(mEglSurface);
}
void
SharedSurface_SurfaceTexture::UnlockProdImpl()
{
MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
GLContextEGL *gl = GLContextEGL::Cast(mGL);
MOZ_ASSERT(gl->GetEGLSurfaceOverride() == mEglSurface);
gl->SetEGLSurfaceOverride(mOrigEglSurface);
mOrigEglSurface = nullptr;
}
void
SharedSurface_SurfaceTexture::Commit()
{
MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
LockProdImpl();
mGL->SwapBuffers();
UnlockProdImpl();
mSurface->SetAvailable(false);
}
void
SharedSurface_SurfaceTexture::WaitForBufferOwnership()
{
MOZ_RELEASE_ASSERT(!mSurface->GetAvailable());
mSurface->SetAvailable(true);
}
bool
SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
*out_descriptor = layers::SurfaceTextureDescriptor(mSurface->GetHandle(), mSize, false /* NOT continuous */);
return true;
}
////////////////////////////////////////////////////////////////////////
/*static*/ UniquePtr<SurfaceFactory_SurfaceTexture>
SurfaceFactory_SurfaceTexture::Create(GLContext* prodGL, const SurfaceCaps& caps,
const RefPtr<layers::LayersIPCChannel>& allocator,
const layers::TextureFlags& flags)
{
UniquePtr<SurfaceFactory_SurfaceTexture> ret(
new SurfaceFactory_SurfaceTexture(prodGL, caps, allocator, flags));
return Move(ret);
}
UniquePtr<SharedSurface>
SurfaceFactory_SurfaceTexture::CreateShared(const gfx::IntSize& size)
{
bool hasAlpha = mReadCaps.alpha;
jni::Object::LocalRef surface = java::SurfaceAllocator::AcquireSurface(size.width, size.height, true);
if (!surface) {
// Try multi-buffer mode
surface = java::SurfaceAllocator::AcquireSurface(size.width, size.height, false);
if (!surface) {
// Give up
NS_WARNING("Failed to allocate SurfaceTexture!");
return nullptr;
}
}
return SharedSurface_SurfaceTexture::Create(mGL, mFormats, size, hasAlpha,
java::GeckoSurface::Ref::From(surface));
}
#endif // MOZ_WIDGET_ANDROID
} // namespace gl
} /* namespace mozilla */

View File

@ -10,6 +10,11 @@
#include "mozilla/Mutex.h"
#include "SharedSurface.h"
#ifdef MOZ_WIDGET_ANDROID
#include "GeneratedJNIWrappers.h"
#include "AndroidNativeWindow.h"
#endif
namespace mozilla {
namespace gl {
@ -58,7 +63,9 @@ protected:
public:
virtual ~SharedSurface_EGLImage();
virtual layers::TextureFlags GetTextureFlags() const override;
virtual layers::TextureFlags GetTextureFlags() const override {
return layers::TextureFlags::DEALLOCATE_CLIENT;
}
virtual void LockProdImpl() override {}
virtual void UnlockProdImpl() override {}
@ -110,6 +117,90 @@ public:
}
};
#ifdef MOZ_WIDGET_ANDROID
class SharedSurface_SurfaceTexture
: public SharedSurface
{
public:
static UniquePtr<SharedSurface_SurfaceTexture> Create(GLContext* prodGL,
const GLFormats& formats,
const gfx::IntSize& size,
bool hasAlpha,
java::GeckoSurface::Param surface);
static SharedSurface_SurfaceTexture* Cast(SharedSurface* surf) {
MOZ_ASSERT(surf->mType == SharedSurfaceType::AndroidSurfaceTexture);
return (SharedSurface_SurfaceTexture*)surf;
}
java::GeckoSurface::Param JavaSurface() { return mSurface; }
protected:
java::GeckoSurface::GlobalRef mSurface;
EGLSurface mEglSurface;
EGLSurface mOrigEglSurface;
SharedSurface_SurfaceTexture(GLContext* gl,
const gfx::IntSize& size,
bool hasAlpha,
const GLFormats& formats,
java::GeckoSurface::Param surface,
EGLSurface eglSurface);
public:
virtual ~SharedSurface_SurfaceTexture();
virtual layers::TextureFlags GetTextureFlags() const override {
return layers::TextureFlags::DEALLOCATE_CLIENT;
}
virtual void LockProdImpl() override;
virtual void UnlockProdImpl() override;
virtual void ProducerAcquireImpl() override {}
virtual void ProducerReleaseImpl() override {}
virtual void ProducerReadAcquireImpl() override {}
virtual void ProducerReadReleaseImpl() override {}
// Implementation-specific functions below:
// Returns texture and target
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override { return false; }
virtual void Commit() override;
virtual void WaitForBufferOwnership() override;
};
class SurfaceFactory_SurfaceTexture
: public SurfaceFactory
{
public:
// Fallible:
static UniquePtr<SurfaceFactory_SurfaceTexture> Create(GLContext* prodGL,
const SurfaceCaps& caps,
const RefPtr<layers::LayersIPCChannel>& allocator,
const layers::TextureFlags& flags);
protected:
SurfaceFactory_SurfaceTexture(GLContext* prodGL, const SurfaceCaps& caps,
const RefPtr<layers::LayersIPCChannel>& allocator,
const layers::TextureFlags& flags)
: SurfaceFactory(SharedSurfaceType::AndroidSurfaceTexture, prodGL, caps, allocator, flags)
{ }
public:
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override;
};
#endif // MOZ_WIDGET_ANDROID
} // namespace gl
} /* namespace mozilla */

View File

@ -77,6 +77,7 @@ enum class SharedSurfaceType : uint8_t {
IOSurface,
GLXDrawable,
SharedGLTexture,
AndroidSurfaceTexture,
Max
};

View File

@ -24,6 +24,7 @@ if CONFIG['MOZ_GL_PROVIDER']:
gl_provider = CONFIG['MOZ_GL_PROVIDER']
EXPORTS += [
'AndroidNativeWindow.h',
'AndroidSurfaceTexture.h',
'DecomposeIntoNoRepeatTriangles.h',
'EGLUtils.h',

View File

@ -98,14 +98,17 @@ GLImage::GetAsSourceSurface()
}
#ifdef MOZ_WIDGET_ANDROID
SurfaceTextureImage::SurfaceTextureImage(gl::AndroidSurfaceTexture* aSurfTex,
SurfaceTextureImage::SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
const gfx::IntSize& aSize,
bool aContinuous,
gl::OriginPos aOriginPos)
: GLImage(ImageFormat::SURFACE_TEXTURE),
mSurfaceTexture(aSurfTex),
mHandle(aHandle),
mSize(aSize),
mContinuous(aContinuous),
mOriginPos(aOriginPos)
{
MOZ_ASSERT(mHandle);
}
#endif

View File

@ -64,13 +64,17 @@ private:
class SurfaceTextureImage : public GLImage {
public:
SurfaceTextureImage(gl::AndroidSurfaceTexture* aSurfTex,
SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
const gfx::IntSize& aSize,
bool aContinuous,
gl::OriginPos aOriginPos);
gfx::IntSize GetSize() override { return mSize; }
gl::AndroidSurfaceTexture* GetSurfaceTexture() const {
return mSurfaceTexture;
AndroidSurfaceTextureHandle GetHandle() const {
return mHandle;
}
bool GetContinuous() const {
return mContinuous;
}
gl::OriginPos GetOriginPos() const {
return mOriginPos;
@ -81,8 +85,9 @@ public:
}
private:
RefPtr<gl::AndroidSurfaceTexture> mSurfaceTexture;
AndroidSurfaceTextureHandle mHandle;
gfx::IntSize mSize;
bool mContinuous;
gl::OriginPos mOriginPos;
};

View File

@ -278,10 +278,15 @@ AndroidDynamicToolbarAnimator::SetCompositionSize(ScreenIntSize aSize)
return false;
}
ScreenIntCoord prevHeight = mCompositorCompositionSize.height;
ScreenIntSize prevSize = mCompositorCompositionSize;
mCompositorCompositionSize = aSize;
if (prevHeight != aSize.height) {
// The width has changed so the static snapshot needs to be updated
if ((prevSize.width != aSize.width) && (mToolbarState != eToolbarVisible)) {
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
}
if (prevSize.height != aSize.height) {
UpdateControllerCompositionHeight(aSize.height);
UpdateFixedLayerMargins();
}

View File

@ -461,6 +461,8 @@ CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRendere
mReadbackClient = nullptr;
}
surf->Commit();
if (asyncRenderer) {
// If surface type is Basic, above codes will readback
// the GLContext to mReadbackClient in order to send frame to

View File

@ -132,7 +132,7 @@ ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwar
} else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
texture = AndroidSurfaceTextureData::CreateTextureClient(
typedImage->GetSurfaceTexture(), size, typedImage->GetOriginPos(),
typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
#endif
} else {

View File

@ -601,7 +601,7 @@ protected:
/**
* Called when mCompositableCount becomes 0.
*/
void NotifyNotUsed();
virtual void NotifyNotUsed();
// for Compositor.
void CallNotifyNotUsed();

View File

@ -192,9 +192,7 @@ CompositorBridgeChild::ShutDown()
{
if (sCompositorBridge) {
sCompositorBridge->Destroy();
do {
NS_ProcessNextEvent(nullptr, true);
} while (sCompositorBridge);
SpinEventLoopUntil([&]() { return !sCompositorBridge; });
}
}

View File

@ -132,9 +132,7 @@ CompositorThreadHolder::Shutdown()
// No locking is needed around sFinishedCompositorShutDown because it is only
// ever accessed on the main thread.
while (!sFinishedCompositorShutDown) {
NS_ProcessNextEvent(nullptr, true);
}
SpinEventLoopUntil([&]() { return sFinishedCompositorShutDown; });
CompositorBridgeParent::FinishShutdown();
}

View File

@ -60,8 +60,9 @@ struct SurfaceDescriptorMacIOSurface {
};
struct SurfaceTextureDescriptor {
uintptr_t surfTex;
uint64_t handle;
IntSize size;
bool continuous;
};
struct EGLImageDescriptor {

View File

@ -79,34 +79,31 @@ EGLImageTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<TextureClient>
AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTexture* aSurfTex,
AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize,
bool aContinuous,
gl::OriginPos aOriginPos,
LayersIPCChannel* aAllocator,
TextureFlags aFlags)
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Can't pass an android surfaces between processes.");
if (!aSurfTex || !XRE_IsParentProcess()) {
return nullptr;
}
if (aOriginPos == gl::OriginPos::BottomLeft) {
aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
}
return TextureClient::CreateWithData(
new AndroidSurfaceTextureData(aSurfTex, aSize),
new AndroidSurfaceTextureData(aHandle, aSize, aContinuous),
aFlags, aAllocator
);
}
AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTexture* aSurfTex,
gfx::IntSize aSize)
: mSurfTex(aSurfTex)
AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize, bool aContinuous)
: mHandle(aHandle)
, mSize(aSize)
{}
, mContinuous(aContinuous)
{
MOZ_ASSERT(mHandle);
}
AndroidSurfaceTextureData::~AndroidSurfaceTextureData()
{}
@ -125,8 +122,7 @@ AndroidSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
bool
AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
aOutDescriptor = SurfaceTextureDescriptor((uintptr_t)mSurfTex.get(),
mSize);
aOutDescriptor = SurfaceTextureDescriptor(mHandle, mSize, mContinuous);
return true;
}

View File

@ -54,8 +54,9 @@ class AndroidSurfaceTextureData : public TextureData
{
public:
static already_AddRefed<TextureClient>
CreateTextureClient(gl::AndroidSurfaceTexture* aSurfTex,
CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize,
bool aContinuous,
gl::OriginPos aOriginPos,
LayersIPCChannel* aAllocator,
TextureFlags aFlags);
@ -75,10 +76,11 @@ public:
virtual void Deallocate(LayersIPCChannel*) override {}
protected:
AndroidSurfaceTextureData(gl::AndroidSurfaceTexture* aSurfTex, gfx::IntSize aSize);
AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous);
const RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
const AndroidSurfaceTextureHandle mHandle;
const gfx::IntSize mSize;
const bool mContinuous;
};
#endif // MOZ_WIDGET_ANDROID

View File

@ -56,9 +56,14 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
#ifdef MOZ_WIDGET_ANDROID
case SurfaceDescriptor::TSurfaceTextureDescriptor: {
const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
java::GeckoSurfaceTexture::LocalRef surfaceTexture = java::GeckoSurfaceTexture::Lookup(desc.handle());
MOZ_RELEASE_ASSERT(surfaceTexture);
result = new SurfaceTextureHost(aFlags,
(AndroidSurfaceTexture*)desc.surfTex(),
desc.size());
surfaceTexture,
desc.size(),
desc.continuous());
break;
}
#endif
@ -335,7 +340,7 @@ GLTextureSource::IsValid() const
#ifdef MOZ_WIDGET_ANDROID
SurfaceTextureSource::SurfaceTextureSource(TextureSourceProvider* aProvider,
AndroidSurfaceTexture* aSurfTex,
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
@ -361,12 +366,7 @@ SurfaceTextureSource::BindTexture(GLenum aTextureUnit,
}
gl->fActiveTexture(aTextureUnit);
// SurfaceTexture spams us if there are any existing GL errors, so
// we'll clear them here in order to avoid that.
gl->FlushErrors();
mSurfTex->UpdateTexImage();
gl->fBindTexture(mTextureTarget, mSurfTex->GetTexName());
ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
}
@ -395,7 +395,9 @@ SurfaceTextureSource::GetTextureTransform()
MOZ_ASSERT(mSurfTex);
gfx::Matrix4x4 ret;
mSurfTex->GetTransformMatrix(ret);
const auto& surf = java::sdk::SurfaceTexture::LocalRef(java::sdk::SurfaceTexture::Ref::From(mSurfTex));
AndroidSurfaceTexture::GetTransformMatrix(surf, ret);
return ret;
}
@ -409,18 +411,39 @@ SurfaceTextureSource::DeallocateDeviceData()
////////////////////////////////////////////////////////////////////////
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
AndroidSurfaceTexture* aSurfTex,
gfx::IntSize aSize)
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize,
bool aContinuousUpdate)
: TextureHost(aFlags)
, mSurfTex(aSurfTex)
, mSize(aSize)
, mContinuousUpdate(aContinuousUpdate)
{
// Continuous update makes no sense with single buffer mode
MOZ_ASSERT(!mSurfTex->IsSingleBuffer() || !mContinuousUpdate);
}
SurfaceTextureHost::~SurfaceTextureHost()
{
}
void
SurfaceTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
{
GLContext* gl = this->gl();
if (!gl || !gl->MakeCurrent()) {
return;
}
if (!mContinuousUpdate) {
// UpdateTexImage() advances the internal buffer queue, so we only want to call this
// once per transactionwhen we are not in continuous mode (as we are here). Otherwise,
// the SurfaceTexture content will be de-synced from the rest of the page in subsequent
// compositor passes.
mSurfTex->UpdateTexImage();
}
}
gl::GLContext*
SurfaceTextureHost::gl() const
{
@ -436,9 +459,13 @@ SurfaceTextureHost::Lock()
return false;
}
if (mContinuousUpdate) {
mSurfTex->UpdateTexImage();
}
if (!mTextureSource) {
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
GLenum target = LOCAL_GL_TEXTURE_EXTERNAL;
GLenum target = LOCAL_GL_TEXTURE_EXTERNAL; // This is required by SurfaceTexture
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
mTextureSource = new SurfaceTextureSource(mProvider,
mSurfTex,
@ -448,14 +475,7 @@ SurfaceTextureHost::Lock()
mSize);
}
return NS_SUCCEEDED(mSurfTex->Attach(gl));
}
void
SurfaceTextureHost::Unlock()
{
MOZ_ASSERT(mSurfTex);
mSurfTex->Detach();
return true;
}
void
@ -474,6 +494,16 @@ SurfaceTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
}
}
void
SurfaceTextureHost::NotifyNotUsed()
{
if (mSurfTex->IsSingleBuffer()) {
mSurfTex->ReleaseTexImage();
}
TextureHost::NotifyNotUsed();
}
gfx::SurfaceFormat
SurfaceTextureHost::GetFormat() const
{

View File

@ -31,15 +31,16 @@
#include "nsRegionFwd.h" // for nsIntRegion
#include "OGLShaderProgram.h" // for ShaderProgramType, etc
#ifdef MOZ_WIDGET_ANDROID
#include "GeneratedJNIWrappers.h"
#include "AndroidSurfaceTexture.h"
#endif
namespace mozilla {
namespace gfx {
class DataSourceSurface;
} // namespace gfx
namespace gl {
class AndroidSurfaceTexture;
} // namespace gl
namespace layers {
class Compositor;
@ -341,7 +342,7 @@ class SurfaceTextureSource : public TextureSource
{
public:
SurfaceTextureSource(TextureSourceProvider* aProvider,
mozilla::gl::AndroidSurfaceTexture* aSurfTex,
java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
@ -376,7 +377,7 @@ public:
protected:
RefPtr<gl::GLContext> mGL;
RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
const gfx::SurfaceFormat mFormat;
const GLenum mTextureTarget;
const GLenum mWrapMode;
@ -387,21 +388,24 @@ class SurfaceTextureHost : public TextureHost
{
public:
SurfaceTextureHost(TextureFlags aFlags,
mozilla::gl::AndroidSurfaceTexture* aSurfTex,
gfx::IntSize aSize);
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize,
bool aContinuousUpdate);
virtual ~SurfaceTextureHost();
virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) override;
virtual void DeallocateDeviceData() override;
virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
virtual bool Lock() override;
virtual void Unlock() override;
virtual gfx::SurfaceFormat GetFormat() const override;
virtual void NotifyNotUsed() override;
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override
{
aTexture = mTextureSource;
@ -420,8 +424,9 @@ public:
virtual const char* Name() override { return "SurfaceTextureHost"; }
protected:
RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
const gfx::IntSize mSize;
bool mContinuousUpdate;
RefPtr<CompositorOGL> mCompositor;
RefPtr<SurfaceTextureSource> mTextureSource;
};

View File

@ -10,6 +10,10 @@
#include "nsDebug.h" // for NS_ASSERTION, NS_ERROR, etc
#include "nsDeque.h" // for nsDeque
#ifdef MOZ_WIDGET_ANDROID
#include "GeneratedJNINatives.h"
#endif
#define TEXTURE_POOL_SIZE 10
namespace mozilla {
@ -20,6 +24,19 @@ static GLContext* sActiveContext = nullptr;
static Monitor* sMonitor = nullptr;
static nsDeque* sTextures = nullptr;
#ifdef MOZ_WIDGET_ANDROID
class GeckoSurfaceTextureSupport final
: public java::GeckoSurfaceTexture::Natives<GeckoSurfaceTextureSupport>
{
public:
static int32_t NativeAcquireTexture() {
return TexturePoolOGL::AcquireTexture();
}
};
#endif // MOZ_WIDGET_ANDROID
GLuint TexturePoolOGL::AcquireTexture()
{
NS_ASSERTION(sMonitor, "not initialized");
@ -111,6 +128,12 @@ void TexturePoolOGL::Init()
{
sMonitor = new Monitor("TexturePoolOGL.sMonitor");
sTextures = new nsDeque();
#ifdef MOZ_WIDGET_ANDROID
if (jni::IsAvailable()) {
GeckoSurfaceTextureSupport::Init();
}
#endif
}
void TexturePoolOGL::Shutdown()

Some files were not shown because too many files have changed in this diff Show More