diff --git a/accessible/generic/Accessible-inl.h b/accessible/generic/Accessible-inl.h index ec92e9e6f2f3..cfe4eece79f3 100644 --- a/accessible/generic/Accessible-inl.h +++ b/accessible/generic/Accessible-inl.h @@ -67,14 +67,6 @@ Accessible::ScrollTo(uint32_t aHow) const nsCoreUtils::ScrollTo(mDoc->PresShell(), mContent, aHow); } -inline bool -Accessible::UpdateChildren() -{ - AutoTreeMutation mut(this); - InvalidateChildren(); - return EnsureChildren(); -} - } // namespace a11y } // namespace mozilla diff --git a/accessible/generic/Accessible.cpp b/accessible/generic/Accessible.cpp index 07ab7fc29308..8ee79e62995f 100644 --- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -2012,8 +2012,7 @@ Accessible::InvalidateChildren() { int32_t childCount = mChildren.Length(); for (int32_t childIdx = 0; childIdx < childCount; childIdx++) { - Accessible* child = mChildren.ElementAt(childIdx); - child->UnbindFromParent(); + mChildren.ElementAt(childIdx)->UnbindFromParent(); } mEmbeddedObjCollector = nullptr; @@ -2446,23 +2445,17 @@ Accessible::TestChildCache(Accessible* aCachedChild) const #endif } -// Accessible public -bool +void Accessible::EnsureChildren() { - if (IsDefunct()) { - SetChildrenFlag(eChildrenUninitialized); - return true; - } + NS_ASSERTION(!IsDefunct(), "Caching children for defunct accessible!"); if (!IsChildrenFlag(eChildrenUninitialized)) - return false; + return; // State is embedded children until text leaf accessible is appended. SetChildrenFlag(eEmbeddedChildren); // Prevent reentry - CacheChildren(); - return false; } Accessible* diff --git a/accessible/generic/Accessible.h b/accessible/generic/Accessible.h index b1009074b782..bb235b85f435 100644 --- a/accessible/generic/Accessible.h +++ b/accessible/generic/Accessible.h @@ -366,14 +366,9 @@ public: { mRoleMapEntry = aRoleMapEntry; } /** - * Update the children cache. + * Cache children if necessary. */ - bool UpdateChildren(); - - /** - * Cache children if necessary. Return true if the accessible is defunct. - */ - bool EnsureChildren(); + void EnsureChildren(); /** * Set the child count to -1 (unknown) and null out cached child pointers. @@ -587,6 +582,7 @@ public: HyperTextAccessible* AsHyperText(); bool IsHTMLBr() const { return mType == eHTMLBRType; } + bool IsHTMLCombobox() const { return mType == eHTMLComboboxType; } bool IsHTMLFileInput() const { return mType == eHTMLFileInputType; } bool IsHTMLListItem() const { return mType == eHTMLLiType; } @@ -870,6 +866,19 @@ public: bool NeedsDOMUIEvent() const { return !(mStateFlags & eIgnoreDOMUIEvent); } + /** + * Get/set survivingInUpdate bit on child indicating that parent recollects + * its children. + */ + bool IsSurvivingInUpdate() const { return mStateFlags & eSurvivingInUpdate; } + void SetSurvivingInUpdate(bool aIsSurviving) + { + if (aIsSurviving) + mStateFlags |= eSurvivingInUpdate; + else + mStateFlags &= ~eSurvivingInUpdate; + } + /** * Return true if this accessible has a parent whose name depends on this * accessible. @@ -953,8 +962,9 @@ protected: eGroupInfoDirty = 1 << 5, // accessible needs to update group info eSubtreeMutating = 1 << 6, // subtree is being mutated eIgnoreDOMUIEvent = 1 << 7, // don't process DOM UI events for a11y events + eSurvivingInUpdate = 1 << 8, // parent drops children to recollect them - eLastStateFlag = eIgnoreDOMUIEvent + eLastStateFlag = eSurvivingInUpdate }; /** @@ -1068,7 +1078,7 @@ protected: int32_t mIndexInParent; static const uint8_t kChildrenFlagsBits = 2; - static const uint8_t kStateFlagsBits = 8; + static const uint8_t kStateFlagsBits = 9; static const uint8_t kContextFlagsBits = 1; static const uint8_t kTypeBits = 6; static const uint8_t kGenericTypesBits = 13; diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index 2dcb0a66669f..7c72a7390ec1 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -1308,19 +1308,10 @@ DocAccessible::ProcessInvalidationList() // children are recached. for (uint32_t idx = 0; idx < mInvalidationList.Length(); idx++) { nsIContent* content = mInvalidationList[idx]; - Accessible* accessible = GetAccessible(content); - if (!accessible) { + if (!HasAccessible(content)) { Accessible* container = GetContainerAccessible(content); - if (container) { - container->UpdateChildren(); - accessible = GetAccessible(content); - } - } - - // Make sure the subtree is created. - if (accessible) { - AutoTreeMutation mut(accessible); - CacheChildrenInSubtree(accessible); + if (container) + UpdateTreeOnInsertion(container); } } @@ -1633,8 +1624,6 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, if (!HasAccessible(aContainer->GetNode())) return; - bool containerNotUpdated = true; - for (uint32_t idx = 0; idx < aInsertedContent->Length(); idx++) { // The container might be changed, for example, because of the subsequent // overlapping content insertion (i.e. other content was inserted between @@ -1644,108 +1633,73 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer, // Note, the inserted content might be not in tree at all at this point what // means there's no container. Ignore the insertion too. - Accessible* presentContainer = + Accessible* container = GetContainerAccessible(aInsertedContent->ElementAt(idx)); - if (presentContainer != aContainer) + if (container != aContainer) continue; - if (containerNotUpdated) { - containerNotUpdated = false; - - if (aContainer == this) { - // If new root content has been inserted then update it. - nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocumentNode); - if (rootContent != mContent) { - mContent = rootContent; - SetRoleMapEntry(aria::GetRoleMap(mContent)); - } - - // Continue to update the tree even if we don't have root content. - // For example, elements may be inserted under the document element while - // there is no HTML body element. + if (container == this) { + // If new root content has been inserted then update it. + nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocumentNode); + if (rootContent != mContent) { + mContent = rootContent; + SetRoleMapEntry(aria::GetRoleMap(mContent)); } - // XXX: Invalidate parent-child relations for container accessible and its - // children because there's no good way to find insertion point of new child - // accessibles into accessible tree. We need to invalidate children even - // there's no inserted accessibles in the end because accessible children - // are created while parent recaches child accessibles. - // XXX Group invalidation here may be redundant with invalidation in - // UpdateTree. - AutoTreeMutation mut(aContainer); - aContainer->InvalidateChildren(); - CacheChildrenInSubtree(aContainer); + // Continue to update the tree even if we don't have root content. + // For example, elements may be inserted under the document element while + // there is no HTML body element. } - UpdateTree(aContainer, aInsertedContent->ElementAt(idx), true); + // HTML comboboxes have no-content list accessible as an intermidiate + // containing all options. + if (container->IsHTMLCombobox()) + container = container->FirstChild(); + + // We have a DOM/layout change under the container accessible, and its tree + // might need an update. Since DOM/layout change of the element may affect + // on the accessibleness of adjacent elements (for example, insertion of + // extra HTML:body make the old body accessible) then we have to recache + // children of the container, and then fire show/hide events for a change. + UpdateTreeOnInsertion(container); + break; } } void -DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode, - bool aIsInsert) +DocAccessible::UpdateTreeOnInsertion(Accessible* aContainer) { - uint32_t updateFlags = eNoAccessible; + for (uint32_t idx = 0; idx < aContainer->ContentChildCount(); idx++) { + Accessible* child = aContainer->ContentChildAt(idx); + child->SetSurvivingInUpdate(true); + } - // If child node is not accessible then look for its accessible children. - Accessible* child = GetAccessible(aChildNode); -#ifdef A11Y_LOG - if (logging::IsEnabled(logging::eTree)) { - logging::MsgBegin("TREE", "process content %s", - (aIsInsert ? "insertion" : "removal")); - logging::Node("container", aContainer->GetNode()); - logging::Node("child", aChildNode); - if (child) - logging::Address("child", child); - else - logging::MsgEntry("child accessible: null"); - - logging::MsgEnd(); - } -#endif + AutoTreeMutation mut(aContainer); + aContainer->InvalidateChildren(); + aContainer->EnsureChildren(); nsRefPtr reorderEvent = new AccReorderEvent(aContainer); - AutoTreeMutation mut(aContainer); - if (child) { - updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent); - } else { - if (aIsInsert) { - TreeWalker walker(aContainer, aChildNode, TreeWalker::eWalkCache); - - while ((child = walker.NextChild())) - updateFlags |= UpdateTreeInternal(child, aIsInsert, reorderEvent); - } else { - // aChildNode may not coorespond to a particular accessible, to handle - // this we go through all the children of aContainer. Then if a child - // has aChildNode as an ancestor, or does not have the node for - // aContainer as an ancestor remove that child of aContainer. Note that - // when we are called aChildNode may already have been removed - // from the DOM so we can't expect it to have a parent or what was it's - // parent to have it as a child. - nsINode* containerNode = aContainer->GetNode(); - for (uint32_t idx = 0; idx < aContainer->ContentChildCount();) { - Accessible* child = aContainer->ContentChildAt(idx); - - // If accessible doesn't have its own content then we assume parent - // will handle its update. If child is DocAccessible then we don't - // handle updating it here either. - if (!child->HasOwnContent() || child->IsDoc()) { - idx++; - continue; - } - - nsINode* childNode = child->GetContent(); - while (childNode != aChildNode && childNode != containerNode && - (childNode = childNode->GetParentNode())); - - if (childNode != containerNode) { - updateFlags |= UpdateTreeInternal(child, false, reorderEvent); - } else { - idx++; - } - } + uint32_t updateFlags = eNoAccessible; + for (uint32_t idx = 0; idx < aContainer->ContentChildCount(); idx++) { + Accessible* child = aContainer->ContentChildAt(idx); + if (child->IsSurvivingInUpdate()) { + child->SetSurvivingInUpdate(false); + continue; } + + // A new child has been created, update its tree. +#ifdef A11Y_LOG + if (logging::IsEnabled(logging::eTree)) { + logging::MsgBegin("TREE", "process content insertion"); + logging::Node("container", aContainer->GetNode()); + logging::Node("child", child->GetContent()); + logging::Address("child", child); + logging::MsgEnd(); + } +#endif + + updateFlags |= UpdateTreeInternal(child, true, reorderEvent); } // Content insertion/removal is not cause of accessible tree change. @@ -1754,7 +1708,7 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode, // Check to see if change occurred inside an alert, and fire an EVENT_ALERT // if it did. - if (aIsInsert && !(updateFlags & eAlertAccessible)) { + if (!(updateFlags & eAlertAccessible)) { // XXX: tree traversal is perf issue, accessible should know if they are // children of alert accessible to avoid this. Accessible* ancestor = aContainer; @@ -1773,9 +1727,71 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode, } MaybeNotifyOfValueChange(aContainer); + FireDelayedEvent(reorderEvent); +} - // Fire reorder event so the MSAA clients know the children have changed. Also - // the event is used internally by MSAA layer. +void +DocAccessible::UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNode) +{ + // If child node is not accessible then look for its accessible children. + Accessible* child = GetAccessible(aChildNode); +#ifdef A11Y_LOG + if (logging::IsEnabled(logging::eTree)) { + logging::MsgBegin("TREE", "process content removal"); + logging::Node("container", aContainer->GetNode()); + logging::Node("child", aChildNode); + if (child) + logging::Address("child", child); + else + logging::MsgEntry("child accessible: null"); + + logging::MsgEnd(); + } +#endif + + uint32_t updateFlags = eNoAccessible; + nsRefPtr reorderEvent = new AccReorderEvent(aContainer); + AutoTreeMutation mut(aContainer); + + if (child) { + updateFlags |= UpdateTreeInternal(child, false, reorderEvent); + } else { + // aChildNode may not coorespond to a particular accessible, to handle + // this we go through all the children of aContainer. Then if a child + // has aChildNode as an ancestor, or does not have the node for + // aContainer as an ancestor remove that child of aContainer. Note that + // when we are called aChildNode may already have been removed from the DOM + // so we can't expect it to have a parent or what was it's parent to have + // it as a child. + nsINode* containerNode = aContainer->GetNode(); + for (uint32_t idx = 0; idx < aContainer->ContentChildCount();) { + Accessible* child = aContainer->ContentChildAt(idx); + + // If accessible doesn't have its own content then we assume parent + // will handle its update. If child is DocAccessible then we don't + // handle updating it here either. + if (!child->HasOwnContent() || child->IsDoc()) { + idx++; + continue; + } + + nsINode* childNode = child->GetContent(); + while (childNode != aChildNode && childNode != containerNode && + (childNode = childNode->GetParentNode())); + + if (childNode != containerNode) { + updateFlags |= UpdateTreeInternal(child, false, reorderEvent); + } else { + idx++; + } + } + } + + // Content insertion/removal is not cause of accessible tree change. + if (updateFlags == eNoAccessible) + return; + + MaybeNotifyOfValueChange(aContainer); FireDelayedEvent(reorderEvent); } diff --git a/accessible/generic/DocAccessible.h b/accessible/generic/DocAccessible.h index d75a41e73301..8c007b8378f3 100644 --- a/accessible/generic/DocAccessible.h +++ b/accessible/generic/DocAccessible.h @@ -321,7 +321,7 @@ public: { // Update the whole tree of this document accessible when the container is // null (document element is removed). - UpdateTree((aContainer ? aContainer : this), aChildNode, false); + UpdateTreeOnRemoval((aContainer ? aContainer : this), aChildNode); } void ContentRemoved(nsIContent* aContainerNode, nsIContent* aChildNode) { @@ -465,13 +465,17 @@ protected: void ProcessInvalidationList(); /** - * Update the accessible tree for content insertion or removal. + * Update the tree on content insertion. */ - void UpdateTree(Accessible* aContainer, nsIContent* aChildNode, - bool aIsInsert); + void UpdateTreeOnInsertion(Accessible* aContainer); /** - * Helper for UpdateTree() method. Go down to DOM subtree and updates + * Update the accessible tree for content removal. + */ + void UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNode); + + /** + * Helper for UpdateTreeOn methods. Go down to DOM subtree and updates * accessible tree. Return one of these flags. */ enum EUpdateTreeFlags { diff --git a/accessible/html/HTMLSelectAccessible.cpp b/accessible/html/HTMLSelectAccessible.cpp index 97e06d4429b8..3a7447d6a9dd 100644 --- a/accessible/html/HTMLSelectAccessible.cpp +++ b/accessible/html/HTMLSelectAccessible.cpp @@ -359,6 +359,7 @@ HTMLComboboxAccessible:: HTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc) : AccessibleWrap(aContent, aDoc) { + mType = eHTMLComboboxType; mGenericTypes |= eCombobox; } diff --git a/accessible/tests/mochitest/events/test_mutation.html b/accessible/tests/mochitest/events/test_mutation.html index ac2143f4c759..8eadd521ccb8 100644 --- a/accessible/tests/mochitest/events/test_mutation.html +++ b/accessible/tests/mochitest/events/test_mutation.html @@ -336,6 +336,28 @@ } } + function insertReferredElm(aContainerID) + { + this.containerNode = getNode(aContainerID); + + this.eventSeq = [ + new invokerChecker(EVENT_SHOW, function(aNode) { return aNode.lastChild; }, this.containerNode), + new invokerChecker(EVENT_SHOW, function(aNode) { return aNode.firstChild; }, this.containerNode), + new invokerChecker(EVENT_REORDER, this.containerNode) + ]; + + this.invoke = function insertReferredElm_invoke() + { + this.containerNode.innerHTML = + ""; + } + + this.getID = function insertReferredElm_getID() + { + return "insert inaccessible element and then insert referring element to make it accessible"; + } + } + /** * Target getters. */ @@ -343,6 +365,10 @@ { return [aNode.firstChild]; } + function getLastChild(aNode) + { + return [aNode.lastChild]; + } function getNEnsureFirstChild(aNode) { @@ -457,6 +483,7 @@ gQueue.push(new test2("testContainer", "testContainer2")); gQueue.push(new test2("testContainer", "testNestedContainer")); gQueue.push(new test3("testContainer")); + gQueue.push(new insertReferredElm("testContainer3")); gQueue.invoke(); // Will call SimpleTest.finish(); } @@ -516,5 +543,6 @@
+
diff --git a/accessible/tests/mochitest/tree/test_select.html b/accessible/tests/mochitest/tree/test_select.html index 45a1b48e65d4..151985622636 100644 --- a/accessible/tests/mochitest/tree/test_select.html +++ b/accessible/tests/mochitest/tree/test_select.html @@ -86,7 +86,7 @@ ] }, ] -}, + }, { role: ROLE_COMBOBOX_OPTION, children: [ diff --git a/accessible/tests/mochitest/treeupdate/test_optgroup.html b/accessible/tests/mochitest/treeupdate/test_optgroup.html index 360e1bbc08f8..999a253ddeca 100644 --- a/accessible/tests/mochitest/treeupdate/test_optgroup.html +++ b/accessible/tests/mochitest/treeupdate/test_optgroup.html @@ -21,6 +21,7 @@ { this.selectNode = getNode(aID); this.select = getAccessible(this.selectNode); + this.selectList = this.select.firstChild; this.invoke = function addOptGroup_invoke() { @@ -39,7 +40,7 @@ } this.eventSeq = [ - new invokerChecker(EVENT_REORDER, this.select) + new invokerChecker(EVENT_REORDER, this.selectList) ]; this.finalCheck = function addOptGroup_finalCheck() diff --git a/accessible/tests/mochitest/treeupdate/test_select.html b/accessible/tests/mochitest/treeupdate/test_select.html index 520b8dab20dd..006618b80fb0 100644 --- a/accessible/tests/mochitest/treeupdate/test_select.html +++ b/accessible/tests/mochitest/treeupdate/test_select.html @@ -21,6 +21,7 @@ { this.selectNode = getNode(aID); this.select = getAccessible(this.selectNode); + this.selectList = this.select.firstChild; this.invoke = function addOptions_invoke() { @@ -34,7 +35,7 @@ } this.eventSeq = [ - new invokerChecker(EVENT_REORDER, this.select) + new invokerChecker(EVENT_REORDER, this.selectList) ]; this.finalCheck = function addOptions_finalCheck() diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 1a722739aa35..e63a056a3894 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + @@ -139,7 +139,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 968d6e58b8a1..7820a78821d5 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 7cdef5ec6ee2..3ba15f6b524e 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,10 +17,10 @@ - + - + @@ -136,7 +136,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 141a0213e914..278e9752ae3c 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 968d6e58b8a1..7820a78821d5 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index b8c87d0c33e9..8991f934a22d 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + @@ -158,7 +158,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index dcf581af61b6..fbffd0f04583 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,10 +17,10 @@ - + - + @@ -145,7 +145,7 @@ - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 14c4645b1eb4..92dda06cf21d 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "e704a7447a7fce238197a7f5429b2282090f1d13", + "revision": "8db023189f8d58a474eaf31d25cbd56b711c5567", "repo_path": "integration/gaia-central" } diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index d16d5c6b2600..61e96e38218b 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,11 +17,11 @@ - + - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index ad5eda2a66a2..4904855ab156 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index c47a45406f39..0917e1ff3228 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,10 +17,10 @@ - + - + @@ -131,7 +131,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index d4d91d7697a3..2397f6a864e9 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,12 +17,12 @@ - + - + diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index b82c2cda7758..74bbe06fe05a 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -89,8 +89,6 @@ public: mStream = aStream; mAudioSource = aAudioSource; mVideoSource = aVideoSource; - mLastEndTimeAudio = 0; - mLastEndTimeVideo = 0; mStream->AddListener(this); } @@ -187,10 +185,10 @@ public: // Currently audio sources ignore NotifyPull, but they could // watch it especially for fake audio. if (mAudioSource) { - mAudioSource->NotifyPull(aGraph, mStream, kAudioTrack, aDesiredTime, mLastEndTimeAudio); + mAudioSource->NotifyPull(aGraph, mStream, kAudioTrack, aDesiredTime); } if (mVideoSource) { - mVideoSource->NotifyPull(aGraph, mStream, kVideoTrack, aDesiredTime, mLastEndTimeVideo); + mVideoSource->NotifyPull(aGraph, mStream, kVideoTrack, aDesiredTime); } } @@ -239,8 +237,6 @@ private: nsRefPtr mAudioSource; // threadsafe refcnt nsRefPtr mVideoSource; // threadsafe refcnt nsRefPtr mStream; // threadsafe refcnt - StreamTime mLastEndTimeAudio; - StreamTime mLastEndTimeVideo; bool mFinished; // Accessed from MainThread and MSG thread diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index 2a18c14fb67c..47ee1c0baf39 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -206,6 +206,7 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream, aStream, data->mID, int64_t(data->mStart), int64_t(segment->GetDuration()))); + data->mEndOfFlushedData += segment->GetDuration(); aStream->mBuffer.AddTrack(data->mID, data->mStart, segment); // The track has taken ownership of data->mData, so let's replace // data->mData with an empty clone. @@ -217,6 +218,7 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream, aStream, data->mID, int64_t(dest->GetDuration()), int64_t(dest->GetDuration() + data->mData->GetDuration()))); + data->mEndOfFlushedData += data->mData->GetDuration(); dest->AppendFrom(data->mData); } if (data->mCommands & SourceMediaStream::TRACK_END) { @@ -2279,6 +2281,7 @@ SourceMediaStream::AddTrackInternal(TrackID aID, TrackRate aRate, StreamTime aSt data->mID = aID; data->mInputRate = aRate; data->mStart = aStart; + data->mEndOfFlushedData = aStart; data->mCommands = TRACK_CREATE; data->mData = aSegment; data->mHaveEnough = false; @@ -2437,6 +2440,18 @@ SourceMediaStream::HaveEnoughBuffered(TrackID aID) return false; } +StreamTime +SourceMediaStream::GetEndOfAppendedData(TrackID aID) +{ + MutexAutoLock lock(mMutex); + TrackData *track = FindDataForTrack(aID); + if (track) { + return track->mEndOfFlushedData + track->mData->GetDuration(); + } + NS_ERROR("Track not found"); + return 0; +} + void SourceMediaStream::DispatchWhenNotEnoughBuffered(TrackID aID, nsIEventTarget* aSignalThread, nsIRunnable* aSignalRunnable) diff --git a/dom/media/MediaStreamGraph.h b/dom/media/MediaStreamGraph.h index 7ac84eb5487d..e38e11379e36 100644 --- a/dom/media/MediaStreamGraph.h +++ b/dom/media/MediaStreamGraph.h @@ -750,6 +750,13 @@ public: * Returns false if there isn't enough data or if no such track exists. */ bool HaveEnoughBuffered(TrackID aID); + /** + * Get the stream time of the end of the data that has been appended so far. + * Can be called from any thread but won't be useful if it can race with + * an AppendToTrack call, so should probably just be called from the thread + * that also calls AppendToTrack. + */ + StreamTime GetEndOfAppendedData(TrackID aID); /** * Ensures that aSignalRunnable will be dispatched to aSignalThread * when we don't have enough buffered data in the track (which could be @@ -848,13 +855,15 @@ protected: int mResamplerChannelCount; #endif StreamTime mStart; - // Each time the track updates are flushed to the media graph thread, - // this is cleared. - uint32_t mCommands; + // End-time of data already flushed to the track (excluding mData) + StreamTime mEndOfFlushedData; // Each time the track updates are flushed to the media graph thread, // the segment buffer is emptied. nsAutoPtr mData; nsTArray mDispatchWhenNotEnough; + // Each time the track updates are flushed to the media graph thread, + // this is cleared. + uint32_t mCommands; bool mHaveEnough; }; diff --git a/dom/media/fmp4/android/AndroidDecoderModule.cpp b/dom/media/fmp4/android/AndroidDecoderModule.cpp index a252f953eef0..ada7c3eda7ca 100644 --- a/dom/media/fmp4/android/AndroidDecoderModule.cpp +++ b/dom/media/fmp4/android/AndroidDecoderModule.cpp @@ -79,7 +79,7 @@ public: layers::SurfaceTextureImage::Data data; data.mSurfTex = mSurfaceTexture.get(); data.mSize = gfx::IntSize(mConfig.display_width, mConfig.display_height); - data.mInverted = true; + data.mOriginPos = gl::OriginPos::BottomLeft; layers::SurfaceTextureImage* stImg = static_cast(img.get()); stImg->SetData(data); @@ -138,7 +138,7 @@ public: data.mSync = eglSync; data.mOwns = true; data.mSize = gfx::IntSize(mConfig.display_width, mConfig.display_height); - data.mInverted = false; + data.mOriginPos = gl::OriginPos::TopLeft; layers::EGLImageImage* typedImg = static_cast(img.get()); typedImg->SetData(data); diff --git a/dom/media/gmp/GMPAudioDecoderParent.cpp b/dom/media/gmp/GMPAudioDecoderParent.cpp index 55b9fde9f8b9..b8a72922d50a 100644 --- a/dom/media/gmp/GMPAudioDecoderParent.cpp +++ b/dom/media/gmp/GMPAudioDecoderParent.cpp @@ -149,7 +149,7 @@ GMPAudioDecoderParent::Close() // In case this is the last reference nsRefPtr kungfudeathgrip(this); - NS_RELEASE(kungfudeathgrip); + Release(); Shutdown(); return NS_OK; diff --git a/dom/media/gmp/GMPVideoDecoderParent.cpp b/dom/media/gmp/GMPVideoDecoderParent.cpp index 319f78d42288..33690f0438e4 100644 --- a/dom/media/gmp/GMPVideoDecoderParent.cpp +++ b/dom/media/gmp/GMPVideoDecoderParent.cpp @@ -76,7 +76,7 @@ GMPVideoDecoderParent::Close() // In case this is the last reference nsRefPtr kungfudeathgrip(this); - NS_RELEASE(kungfudeathgrip); + Release(); Shutdown(); } diff --git a/dom/media/gmp/GMPVideoEncoderParent.cpp b/dom/media/gmp/GMPVideoEncoderParent.cpp index 6f2af86d9d61..f17190dab6c8 100644 --- a/dom/media/gmp/GMPVideoEncoderParent.cpp +++ b/dom/media/gmp/GMPVideoEncoderParent.cpp @@ -91,7 +91,7 @@ GMPVideoEncoderParent::Close() // In case this is the last reference nsRefPtr kungfudeathgrip(this); - NS_RELEASE(kungfudeathgrip); + Release(); Shutdown(); } diff --git a/dom/media/mediasource/SourceBuffer.cpp b/dom/media/mediasource/SourceBuffer.cpp index 838e02c56ba9..88b352b42f9c 100644 --- a/dom/media/mediasource/SourceBuffer.cpp +++ b/dom/media/mediasource/SourceBuffer.cpp @@ -49,6 +49,10 @@ SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv) aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } + if (aMode == SourceBufferAppendMode::Sequence) { + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } MOZ_ASSERT(mMediaSource->ReadyState() != MediaSourceReadyState::Closed); if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) { mMediaSource->SetReadyState(MediaSourceReadyState::Open); diff --git a/dom/media/mediasource/test/mochitest.ini b/dom/media/mediasource/test/mochitest.ini index fa80aa756b8f..fa06f72d2c77 100644 --- a/dom/media/mediasource/test/mochitest.ini +++ b/dom/media/mediasource/test/mochitest.ini @@ -19,6 +19,7 @@ skip-if = (toolkit == 'android' || buildapp == 'mulet') #timeout android/mulet o [test_SeekableAfterEndOfStreamSplit.html] [test_SeekableBeforeEndOfStream.html] [test_SeekableBeforeEndOfStreamSplit.html] +[test_SetModeThrows.html] [test_SplitAppendDelay.html] [test_SplitAppend.html] [test_WaitingOnMissingData.html] diff --git a/dom/media/mediasource/test/test_SetModeThrows.html b/dom/media/mediasource/test/test_SetModeThrows.html new file mode 100644 index 000000000000..8254b8ca0507 --- /dev/null +++ b/dom/media/mediasource/test/test_SetModeThrows.html @@ -0,0 +1,34 @@ + + + + MSE: append initialization only + + + + + +
+
+
+ + diff --git a/dom/media/webrtc/MediaEngine.h b/dom/media/webrtc/MediaEngine.h index cb62def6aada..b7c33405b9c3 100644 --- a/dom/media/webrtc/MediaEngine.h +++ b/dom/media/webrtc/MediaEngine.h @@ -110,8 +110,7 @@ public: virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aId, - StreamTime aDesiredTime, - StreamTime &aLastEndTime) = 0; + StreamTime aDesiredTime) = 0; /* Stop the device and release the corresponding MediaStream */ virtual nsresult Stop(SourceMediaStream *aSource, TrackID aID) = 0; diff --git a/dom/media/webrtc/MediaEngineDefault.cpp b/dom/media/webrtc/MediaEngineDefault.cpp index a7a8cfadb743..bb0015da25b0 100644 --- a/dom/media/webrtc/MediaEngineDefault.cpp +++ b/dom/media/webrtc/MediaEngineDefault.cpp @@ -244,8 +244,7 @@ void MediaEngineDefaultVideoSource::NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aID, - StreamTime aDesiredTime, - StreamTime &aLastEndTime) + StreamTime aDesiredTime) { // AddTrack takes ownership of segment VideoSegment segment; @@ -256,7 +255,7 @@ MediaEngineDefaultVideoSource::NotifyPull(MediaStreamGraph* aGraph, // Note: we're not giving up mImage here nsRefPtr image = mImage; - StreamTime delta = aDesiredTime - aLastEndTime; + StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID); if (delta > 0) { // nullptr images are allowed @@ -264,9 +263,7 @@ MediaEngineDefaultVideoSource::NotifyPull(MediaStreamGraph* aGraph, segment.AppendFrame(image.forget(), delta, size); // This can fail if either a) we haven't added the track yet, or b) // we've removed or finished the track. - if (aSource->AppendToTrack(aID, &segment)) { - aLastEndTime = aDesiredTime; - } + aSource->AppendToTrack(aID, &segment); // Generate null data for fake tracks. if (mHasFakeTracks) { for (int i = 0; i < kFakeVideoTrackCount; ++i) { diff --git a/dom/media/webrtc/MediaEngineDefault.h b/dom/media/webrtc/MediaEngineDefault.h index e64863855f63..efb6b05eb784 100644 --- a/dom/media/webrtc/MediaEngineDefault.h +++ b/dom/media/webrtc/MediaEngineDefault.h @@ -53,8 +53,7 @@ public: virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aId, - StreamTime aDesiredTime, - StreamTime &aLastEndTime); + StreamTime aDesiredTime) MOZ_OVERRIDE; virtual bool SatisfiesConstraintSets( const nsTArray& aConstraintSets) { @@ -122,8 +121,7 @@ public: virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aId, - StreamTime aDesiredTime, - StreamTime &aLastEndTime) {} + StreamTime aDesiredTime) MOZ_OVERRIDE {} virtual bool IsFake() { return true; diff --git a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp index 4dcc4a39ee5c..dbc2a390def6 100644 --- a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp @@ -70,8 +70,7 @@ void MediaEngineGonkVideoSource::NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream* aSource, TrackID aID, - StreamTime aDesiredTime, - StreamTime& aLastEndTime) + StreamTime aDesiredTime) { VideoSegment segment; @@ -82,7 +81,7 @@ MediaEngineGonkVideoSource::NotifyPull(MediaStreamGraph* aGraph, // Note: we're not giving up mImage here nsRefPtr image = mImage; - StreamTime delta = aDesiredTime - aLastEndTime; + StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID); LOGFRAME(("NotifyPull, desired = %ld, delta = %ld %s", (int64_t) aDesiredTime, (int64_t) delta, image ? "" : "")); @@ -102,9 +101,7 @@ MediaEngineGonkVideoSource::NotifyPull(MediaStreamGraph* aGraph, segment.AppendFrame(image.forget(), delta, size); // This can fail if either a) we haven't added the track yet, or b) // we've removed or finished the track. - if (aSource->AppendToTrack(aID, &(segment))) { - aLastEndTime = aDesiredTime; - } + aSource->AppendToTrack(aID, &(segment)); } } diff --git a/dom/media/webrtc/MediaEngineGonkVideoSource.h b/dom/media/webrtc/MediaEngineGonkVideoSource.h index 2d361705b8d9..c03a9d4a049a 100644 --- a/dom/media/webrtc/MediaEngineGonkVideoSource.h +++ b/dom/media/webrtc/MediaEngineGonkVideoSource.h @@ -68,8 +68,7 @@ public: virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream* aSource, TrackID aId, - StreamTime aDesiredTime, - StreamTime &aLastEndTime) MOZ_OVERRIDE; + StreamTime aDesiredTime) MOZ_OVERRIDE; virtual bool SatisfiesConstraintSets( const nsTArray& aConstraintSets) { diff --git a/dom/media/webrtc/MediaEngineTabVideoSource.cpp b/dom/media/webrtc/MediaEngineTabVideoSource.cpp index 0b0a44aaa11d..32fb303df0d7 100644 --- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp @@ -192,24 +192,21 @@ MediaEngineTabVideoSource::Start(SourceMediaStream* aStream, TrackID aID) void MediaEngineTabVideoSource::NotifyPull(MediaStreamGraph*, SourceMediaStream* aSource, - TrackID aID, StreamTime aDesiredTime, - StreamTime& aLastEndTime) + TrackID aID, StreamTime aDesiredTime) { VideoSegment segment; MonitorAutoLock mon(mMonitor); // Note: we're not giving up mImage here nsRefPtr image = mImage; - StreamTime delta = aDesiredTime - aLastEndTime; + StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID); if (delta > 0) { // nullptr images are allowed gfx::IntSize size = image ? image->GetSize() : IntSize(0, 0); segment.AppendFrame(image.forget().downcast(), delta, size); // This can fail if either a) we haven't added the track yet, or b) // we've removed or finished the track. - if (aSource->AppendToTrack(aID, &(segment))) { - aLastEndTime = aDesiredTime; - } + aSource->AppendToTrack(aID, &(segment)); } } diff --git a/dom/media/webrtc/MediaEngineTabVideoSource.h b/dom/media/webrtc/MediaEngineTabVideoSource.h index 6820788663ff..ae4b3abb979d 100644 --- a/dom/media/webrtc/MediaEngineTabVideoSource.h +++ b/dom/media/webrtc/MediaEngineTabVideoSource.h @@ -25,7 +25,7 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList virtual nsresult Deallocate(); virtual nsresult Start(mozilla::SourceMediaStream*, mozilla::TrackID); virtual void SetDirectListeners(bool aHasDirectListeners) {}; - virtual void NotifyPull(mozilla::MediaStreamGraph*, mozilla::SourceMediaStream*, mozilla::TrackID, mozilla::StreamTime, mozilla::StreamTime&); + virtual void NotifyPull(mozilla::MediaStreamGraph*, mozilla::SourceMediaStream*, mozilla::TrackID, mozilla::StreamTime) MOZ_OVERRIDE; virtual nsresult Stop(mozilla::SourceMediaStream*, mozilla::TrackID); virtual nsresult Config(bool, uint32_t, bool, uint32_t, bool, uint32_t, int32_t); virtual bool IsFake(); diff --git a/dom/media/webrtc/MediaEngineWebRTC.h b/dom/media/webrtc/MediaEngineWebRTC.h index 0954380e2470..7ebb9d99992b 100644 --- a/dom/media/webrtc/MediaEngineWebRTC.h +++ b/dom/media/webrtc/MediaEngineWebRTC.h @@ -97,8 +97,7 @@ public: virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream* aSource, TrackID aId, - StreamTime aDesiredTime, - StreamTime &aLastEndTime); + StreamTime aDesiredTime) MOZ_OVERRIDE; virtual const MediaSourceType GetMediaSource() { return mMediaSource; @@ -180,8 +179,7 @@ public: virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream* aSource, TrackID aId, - StreamTime aDesiredTime, - StreamTime &aLastEndTime); + StreamTime aDesiredTime) MOZ_OVERRIDE; virtual bool IsFake() { return false; diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp index b95fea5641b6..ba5378ab966a 100644 --- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp +++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -398,16 +398,10 @@ void MediaEngineWebRTCAudioSource::NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aID, - StreamTime aDesiredTime, - StreamTime &aLastEndTime) + StreamTime aDesiredTime) { // Ignore - we push audio data -#ifdef DEBUG - StreamTime delta = aDesiredTime - aLastEndTime; - LOG(("Audio: NotifyPull: aDesiredTime %ld, delta %ld",(int64_t) aDesiredTime, - (int64_t) delta)); - aLastEndTime = aDesiredTime; -#endif + LOG_FRAMES(("NotifyPull, desired = %ld", (int64_t) aDesiredTime)); } void diff --git a/dom/media/webrtc/MediaEngineWebRTCVideo.cpp b/dom/media/webrtc/MediaEngineWebRTCVideo.cpp index 14d9a95fb579..b2c73861c511 100644 --- a/dom/media/webrtc/MediaEngineWebRTCVideo.cpp +++ b/dom/media/webrtc/MediaEngineWebRTCVideo.cpp @@ -124,8 +124,7 @@ void MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream* aSource, TrackID aID, - StreamTime aDesiredTime, - StreamTime &aLastEndTime) + StreamTime aDesiredTime) { VideoSegment segment; @@ -134,7 +133,7 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph, // So mState could be kReleased here. We really don't care about the state, // though. - StreamTime delta = aDesiredTime - aLastEndTime; + StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID); LOGFRAME(("NotifyPull, desired = %ld, delta = %ld %s", (int64_t) aDesiredTime, (int64_t) delta, mImage.get() ? "" : "")); @@ -150,9 +149,7 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph, // Doing so means a negative delta and thus messes up handling of the graph if (delta > 0) { // nullptr images are allowed - if (AppendToTrack(aSource, mImage, aID, delta)) { - aLastEndTime = aDesiredTime; - } + AppendToTrack(aSource, mImage, aID, delta); } } diff --git a/dom/nfc/NfcContentHelper.js b/dom/nfc/NfcContentHelper.js index 06b0273d8ef1..30fdbf298762 100644 --- a/dom/nfc/NfcContentHelper.js +++ b/dom/nfc/NfcContentHelper.js @@ -312,7 +312,7 @@ NfcContentHelper.prototype = { result.isFormatable); } - let tagInfo = new TagInfo(result.techList); + let tagInfo = new TagInfo(result.techList, result.tagId); this.eventListener.notifyTagFound(result.sessionToken, tagInfo, ndefInfo, @@ -411,13 +411,15 @@ TagNDEFInfo.prototype = { isFormatable: false }; -function TagInfo(techList) { +function TagInfo(techList, tagId) { this.techList = techList; + this.tagId = tagId; } TagInfo.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsITagInfo]), techList: null, + tagId: null, }; if (NFC_ENABLED) { diff --git a/dom/nfc/gonk/NfcGonkMessage.h b/dom/nfc/gonk/NfcGonkMessage.h index 624ebba52163..5b5ce3cd3ef2 100644 --- a/dom/nfc/gonk/NfcGonkMessage.h +++ b/dom/nfc/gonk/NfcGonkMessage.h @@ -8,7 +8,7 @@ namespace mozilla { #define NFCD_MAJOR_VERSION 1 -#define NFCD_MINOR_VERSION 18 +#define NFCD_MINOR_VERSION 19 enum NfcRequest { ChangeRFStateReq = 0, diff --git a/dom/nfc/gonk/NfcMessageHandler.cpp b/dom/nfc/gonk/NfcMessageHandler.cpp index 23450fe770ef..0c44417eb309 100644 --- a/dom/nfc/gonk/NfcMessageHandler.cpp +++ b/dom/nfc/gonk/NfcMessageHandler.cpp @@ -254,8 +254,8 @@ NfcMessageHandler::InitializeNotification(const Parcel& aParcel, EventOptions& a if (aOptions.mMajorVersion != NFCD_MAJOR_VERSION || aOptions.mMinorVersion != NFCD_MINOR_VERSION) { - NMH_LOG("NFCD version mismatched. majorVersion: %d, minorVersion: %d", - aOptions.mMajorVersion, aOptions.mMinorVersion); + NMH_LOG("NFCD version mismatched. majorVersion: %d, minorVersion: %d", + aOptions.mMajorVersion, aOptions.mMinorVersion); } return true; @@ -267,9 +267,14 @@ NfcMessageHandler::TechDiscoveredNotification(const Parcel& aParcel, EventOption aOptions.mType = NS_ConvertUTF8toUTF16(kTechDiscoveredNotification); aOptions.mSessionId = aParcel.readInt32(); aOptions.mIsP2P = aParcel.readInt32(); + int32_t techCount = aParcel.readInt32(); aOptions.mTechList.AppendElements( - static_cast(aParcel.readInplace(techCount)), techCount); + static_cast(aParcel.readInplace(techCount)), techCount); + + int32_t idCount = aParcel.readInt32(); + aOptions.mTagId.AppendElements( + static_cast(aParcel.readInplace(idCount)), idCount); int32_t ndefMsgCount = aParcel.readInt32(); if (ndefMsgCount != 0) { @@ -327,15 +332,15 @@ NfcMessageHandler::ReadNDEFMessage(const Parcel& aParcel, EventOptions& aOptions int32_t typeLength = aParcel.readInt32(); record.mType.AppendElements( - static_cast(aParcel.readInplace(typeLength)), typeLength); + static_cast(aParcel.readInplace(typeLength)), typeLength); int32_t idLength = aParcel.readInt32(); record.mId.AppendElements( - static_cast(aParcel.readInplace(idLength)), idLength); + static_cast(aParcel.readInplace(idLength)), idLength); int32_t payloadLength = aParcel.readInt32(); record.mPayload.AppendElements( - static_cast(aParcel.readInplace(payloadLength)), payloadLength); + static_cast(aParcel.readInplace(payloadLength)), payloadLength); aOptions.mRecords.AppendElement(record); } diff --git a/dom/nfc/gonk/NfcOptions.h b/dom/nfc/gonk/NfcOptions.h index 77588c9ac692..d337aedd35e3 100644 --- a/dom/nfc/gonk/NfcOptions.h +++ b/dom/nfc/gonk/NfcOptions.h @@ -99,6 +99,7 @@ struct EventOptions int32_t mMajorVersion; int32_t mMinorVersion; nsTArray mTechList; + nsTArray mTagId; int32_t mIsP2P; nsTArray mRecords; int32_t mTagType; diff --git a/dom/nfc/gonk/NfcService.cpp b/dom/nfc/gonk/NfcService.cpp index cc4cd71183eb..0faf8e953e43 100644 --- a/dom/nfc/gonk/NfcService.cpp +++ b/dom/nfc/gonk/NfcService.cpp @@ -132,6 +132,11 @@ public: } } + if (mEvent.mTagId.Length() > 0) { + event.mTagId.Construct(); + event.mTagId.Value().Init(Uint8Array::Create(cx, mEvent.mTagId.Length(), mEvent.mTagId.Elements())); + } + if (mEvent.mRecords.Length() > 0) { int length = mEvent.mRecords.Length(); event.mRecords.Construct(); diff --git a/dom/nfc/nsINfcContentHelper.idl b/dom/nfc/nsINfcContentHelper.idl index 5ddd0be54e94..e44253766996 100644 --- a/dom/nfc/nsINfcContentHelper.idl +++ b/dom/nfc/nsINfcContentHelper.idl @@ -7,13 +7,15 @@ interface nsIVariant; interface nsIDOMWindow; -[scriptable, uuid(30d77baf-50ed-4a6b-ab75-25bade40977a)] +[scriptable, uuid(a694c7e8-10dd-416e-a3d9-433edf40647e)] interface nsITagInfo : nsISupports { /** * Array of technolgies supported. See NFCTechType in MozNFCTag.webidl */ readonly attribute nsIVariant techList; + + readonly attribute nsIVariant tagId; // Uint8Array }; [scriptable, uuid(74d70ebb-557f-4ac8-8296-7885961cd1dc)] diff --git a/dom/nfc/nsNfc.js b/dom/nfc/nsNfc.js index 90465e601d51..78c88167333e 100644 --- a/dom/nfc/nsNfc.js +++ b/dom/nfc/nsNfc.js @@ -104,6 +104,7 @@ function MozNFCTagImpl(window, sessionToken, tagInfo, ndefInfo) { this._window = window; this.session = sessionToken; this.techList = tagInfo.techList; + this.id = Cu.cloneInto(tagInfo.tagId, window); if (ndefInfo) { this.type = ndefInfo.tagType; @@ -119,6 +120,7 @@ MozNFCTagImpl.prototype = { _window: null, session: null, techList: null, + id: null, type: null, maxNDEFSize: null, isReadOnly: null, @@ -191,7 +193,7 @@ MozNFCTagImpl.prototype = { }, classID: Components.ID("{4e1e2e90-3137-11e3-aa6e-0800200c9a66}"), - contractID: "@mozilla.org/nfc/NFCTag;1", + contractID: "@mozilla.org/nfc/tag;1", QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIDOMGlobalPropertyInitializer]), }; @@ -243,7 +245,7 @@ MozNFCPeerImpl.prototype = { }, classID: Components.ID("{c1b2bcf0-35eb-11e3-aa6e-0800200c9a66}"), - contractID: "@mozilla.org/nfc/NFCPeer;1", + contractID: "@mozilla.org/nfc/peer;1", QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIDOMGlobalPropertyInitializer]), }; @@ -537,7 +539,7 @@ MozNFCImpl.prototype = { }, classID: Components.ID("{6ff2b290-2573-11e3-8224-0800200c9a66}"), - contractID: "@mozilla.org/navigatorNfc;1", + contractID: "@mozilla.org/nfc/manager;1", QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIDOMGlobalPropertyInitializer, Ci.nsINfcEventListener, diff --git a/dom/nfc/nsNfc.manifest b/dom/nfc/nsNfc.manifest index f851b381c6c2..3856cecbd9df 100644 --- a/dom/nfc/nsNfc.manifest +++ b/dom/nfc/nsNfc.manifest @@ -1,11 +1,11 @@ component {6ff2b290-2573-11e3-8224-0800200c9a66} nsNfc.js -contract @mozilla.org/navigatorNfc;1 {6ff2b290-2573-11e3-8224-0800200c9a66} +contract @mozilla.org/nfc/manager;1 {6ff2b290-2573-11e3-8224-0800200c9a66} component {4e1e2e90-3137-11e3-aa6e-0800200c9a66} nsNfc.js -contract @mozilla.org/nfc/NFCTag;1 {4e1e2e90-3137-11e3-aa6e-0800200c9a66} +contract @mozilla.org/nfc/tag;1 {4e1e2e90-3137-11e3-aa6e-0800200c9a66} component {c1b2bcf0-35eb-11e3-aa6e-0800200c9a66} nsNfc.js -contract @mozilla.org/nfc/NFCPeer;1 {c1b2bcf0-35eb-11e3-aa6e-0800200c9a66} +contract @mozilla.org/nfc/peer;1 {c1b2bcf0-35eb-11e3-aa6e-0800200c9a66} component {c5063a5c-8cb9-41d2-baf5-56062a2e30e9} nsNfc.js contract @mozilla.org/dom/system-messages/wrapper/nfc-manager-send-file;1 {c5063a5c-8cb9-41d2-baf5-56062a2e30e9} diff --git a/dom/plugins/base/android/ANPNativeWindow.cpp b/dom/plugins/base/android/ANPNativeWindow.cpp index 4579c7ae7b5f..0de5518c7214 100644 --- a/dom/plugins/base/android/ANPNativeWindow.cpp +++ b/dom/plugins/base/android/ANPNativeWindow.cpp @@ -12,7 +12,6 @@ #include "nsNPAPIPluginInstance.h" #include "gfxRect.h" -using namespace mozilla; using namespace mozilla; #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) @@ -24,8 +23,13 @@ static ANPNativeWindow anp_native_window_acquireNativeWindow(NPP instance) { } static void anp_native_window_invertPluginContent(NPP instance, bool isContentInverted) { + // NativeWindow is TopLeft if uninverted. + gl::OriginPos newOriginPos = gl::OriginPos::TopLeft; + if (isContentInverted) + newOriginPos = gl::OriginPos::BottomLeft; + nsNPAPIPluginInstance* pinst = static_cast(instance->ndata); - pinst->SetInverted(isContentInverted); + pinst->SetOriginPos(newOriginPos); pinst->RedrawPlugin(); } diff --git a/dom/plugins/base/android/ANPOpenGL.cpp b/dom/plugins/base/android/ANPOpenGL.cpp index 71fa201d9f55..60c532505514 100644 --- a/dom/plugins/base/android/ANPOpenGL.cpp +++ b/dom/plugins/base/android/ANPOpenGL.cpp @@ -60,10 +60,14 @@ static void anp_opengl_releaseTexture(NPP instance, const ANPTextureInfo* info) } static void anp_opengl_invertPluginContent(NPP instance, bool isContentInverted) { + // OpenGL is BottomLeft if uninverted. + gl::OriginPos newOriginPos = gl::OriginPos::BottomLeft; + if (isContentInverted) + newOriginPos = gl::OriginPos::TopLeft; + nsNPAPIPluginInstance* pinst = static_cast(instance->ndata); - // Our definition of inverted is the opposite of the plugin's - pinst->SetInverted(!isContentInverted); + pinst->SetOriginPos(newOriginPos); pinst->RedrawPlugin(); } diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index cf16dce7a330..7b47fee5cc77 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -179,7 +179,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance() , mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary) , mWakeLocked(false) , mFullScreen(false) - , mInverted(false) + , mOriginPos(gl::OriginPos::TopLeft) #endif , mRunning(NOT_STARTED) , mWindowless(false) @@ -1056,14 +1056,6 @@ void nsNPAPIPluginInstance::GetVideos(nsTArray& aVideos) aVideos.AppendElement(it->second); } -void nsNPAPIPluginInstance::SetInverted(bool aInverted) -{ - if (aInverted == mInverted) - return; - - mInverted = aInverted; -} - nsNPAPIPluginInstance* nsNPAPIPluginInstance::GetFromNPP(NPP npp) { std::map::iterator it; diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index 1c9f8ae016dd..c0a4d9040318 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -220,8 +220,10 @@ public: void GetVideos(nsTArray& aVideos); - void SetInverted(bool aInverted); - bool Inverted() { return mInverted; } + void SetOriginPos(mozilla::gl::OriginPos aOriginPos) { + mOriginPos = aOriginPos; + } + mozilla::gl::OriginPos OriginPos() const { return mOriginPos; } static nsNPAPIPluginInstance* GetFromNPP(NPP npp); #endif @@ -328,7 +330,7 @@ protected: uint32_t mFullScreenOrientation; bool mWakeLocked; bool mFullScreen; - bool mInverted; + mozilla::gl::OriginPos mOriginPos; mozilla::RefPtr mContentTexture; mozilla::RefPtr mContentSurface; diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 1e6e3f233f30..9adadcb9f857 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -176,7 +176,7 @@ AttachToContainerAsEGLImage(ImageContainer* container, EGLImageImage::Data data; data.mImage = image; data.mSize = gfx::IntSize(rect.width, rect.height); - data.mInverted = instance->Inverted(); + data.mOriginPos = instance->OriginPos(); EGLImageImage* typedImg = static_cast(img.get()); typedImg->SetData(data); @@ -203,7 +203,7 @@ AttachToContainerAsSurfaceTexture(ImageContainer* container, SurfaceTextureImage::Data data; data.mSurfTex = surfTex; data.mSize = gfx::IntSize(rect.width, rect.height); - data.mInverted = instance->Inverted(); + data.mOriginPos = instance->OriginPos(); SurfaceTextureImage* typedImg = static_cast(img.get()); typedImg->SetData(data); @@ -1386,7 +1386,8 @@ nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInf // The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate // inverted flag for video. - data.mInverted = AndroidBridge::Bridge()->IsHoneycomb() ? true : mInstance->Inverted(); + data.mOriginPos = AndroidBridge::Bridge()->IsHoneycomb() ? gl::OriginPos::BottomLeft + : mInstance->OriginPos(); data.mSize = gfx::IntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height); SurfaceTextureImage* typedImg = static_cast(img.get()); diff --git a/dom/telephony/gonk/TelephonyService.js b/dom/telephony/gonk/TelephonyService.js index 941d8a0b108f..95b66f8faf7a 100644 --- a/dom/telephony/gonk/TelephonyService.js +++ b/dom/telephony/gonk/TelephonyService.js @@ -125,10 +125,6 @@ function TelephonyService() { this._cdmaCallWaitingNumber = null; - // _isActiveCall[clientId][callIndex] shows the active status of the call. - this._isActiveCall = {}; - this._numActiveCall = 0; - this._updateDebugFlag(); this.defaultServiceId = this._getDefaultServiceId(); @@ -139,7 +135,6 @@ function TelephonyService() { for (let i = 0; i < this._numClients; ++i) { this._enumerateCallsForClient(i); - this._isActiveCall[i] = {}; this._audioStates[i] = RIL.AUDIO_STATE_NO_CALL; } } @@ -215,37 +210,6 @@ TelephonyService.prototype = { } }, - /** - * Track the active call and update the audio system as its state changes. - */ - _updateActiveCall: function(aCall) { - let active = false; - let incoming = false; - - switch (aCall.state) { - case nsITelephonyService.CALL_STATE_DIALING: // Fall through... - case nsITelephonyService.CALL_STATE_ALERTING: - case nsITelephonyService.CALL_STATE_CONNECTED: - active = true; - break; - case nsITelephonyService.CALL_STATE_INCOMING: - incoming = true; - break; - case nsITelephonyService.CALL_STATE_HELD: // Fall through... - case nsITelephonyService.CALL_STATE_DISCONNECTED: - break; - } - - // Update active count and info. - let oldActive = this._isActiveCall[aCall.clientId][aCall.callIndex]; - if (!oldActive && active) { - this._numActiveCall++; - } else if (oldActive && !active) { - this._numActiveCall--; - } - this._isActiveCall[aCall.clientId][aCall.callIndex] = active; - }, - _updateAudioState: function(aAudioState) { switch (aAudioState) { case RIL.AUDIO_STATE_NO_CALL: @@ -1160,8 +1124,6 @@ TelephonyService.prototype = { } } - this._updateActiveCall(aCall); - if (!aCall.failCause || aCall.failCause === RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) { this._notifyAllListeners("callStateChanged", [aClientId, @@ -1217,7 +1179,6 @@ TelephonyService.prototype = { } aCall.clientId = aClientId; - this._updateActiveCall(aCall); function pick(arg, defaultValue) { return typeof arg !== 'undefined' ? arg : defaultValue; diff --git a/dom/webidl/MozNFC.webidl b/dom/webidl/MozNFC.webidl index 5db6ef8c65af..2351148cd9f2 100644 --- a/dom/webidl/MozNFC.webidl +++ b/dom/webidl/MozNFC.webidl @@ -69,7 +69,7 @@ interface MozNFCManager { Promise powerOff(); }; -[JSImplementation="@mozilla.org/navigatorNfc;1", +[JSImplementation="@mozilla.org/nfc/manager;1", NavigatorProperty="mozNfc", Func="Navigator::HasNFCSupport", CheckPermissions="nfc nfc-share", diff --git a/dom/webidl/MozNFCPeer.webidl b/dom/webidl/MozNFCPeer.webidl index 5f251905361b..a98b7a635c5d 100644 --- a/dom/webidl/MozNFCPeer.webidl +++ b/dom/webidl/MozNFCPeer.webidl @@ -8,7 +8,7 @@ * Copyright © 2013 Deutsche Telekom, Inc. */ -[JSImplementation="@mozilla.org/nfc/NFCPeer;1", AvailableIn="PrivilegedApps"] +[JSImplementation="@mozilla.org/nfc/peer;1", AvailableIn="PrivilegedApps"] interface MozNFCPeer { /** * Send NDEF data to peer device. diff --git a/dom/webidl/MozNFCTag.webidl b/dom/webidl/MozNFCTag.webidl index fcf8c522c993..07749ad7ff97 100644 --- a/dom/webidl/MozNFCTag.webidl +++ b/dom/webidl/MozNFCTag.webidl @@ -32,13 +32,18 @@ enum NFCTagType { "mifare_classic" }; -[JSImplementation="@mozilla.org/nfc/NFCTag;1", AvailableIn="PrivilegedApps"] +[JSImplementation="@mozilla.org/nfc/tag;1", AvailableIn="PrivilegedApps"] interface MozNFCTag { /** * The supported technologies of this tag, null if unknown. */ [Cached, Pure] readonly attribute sequence? techList; + /** + * The identifier of this tag. + */ + [Pure, Constant] readonly attribute Uint8Array? id; + /** * The type of this tag, null if unknown. */ diff --git a/dom/webidl/NfcOptions.webidl b/dom/webidl/NfcOptions.webidl index e6fa43155ef5..7ff86b06fa32 100644 --- a/dom/webidl/NfcOptions.webidl +++ b/dom/webidl/NfcOptions.webidl @@ -37,6 +37,7 @@ dictionary NfcEventOptions boolean isP2P; sequence techList; + Uint8Array tagId; sequence records; NFCTagType tagType; diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp index a05076f5200c..d1b27b8514fb 100644 --- a/gfx/gl/GLBlitHelper.cpp +++ b/gfx/gl/GLBlitHelper.cpp @@ -690,7 +690,7 @@ GLBlitHelper::BindAndUploadEGLImage(EGLImage image, GLuint target) #ifdef MOZ_WIDGET_GONK bool -GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) +GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yflip) { ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT); @@ -711,7 +711,7 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) BindAndUploadEGLImage(image, LOCAL_GL_TEXTURE_EXTERNAL_OES); - mGL->fUniform1f(mYFlipLoc, yFlip ? (float)1.0f : (float)0.0f); + mGL->fUniform1f(mYFlipLoc, yflip ? (float)1.0f : (float)0.0f); mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); @@ -724,18 +724,14 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) #ifdef MOZ_WIDGET_ANDROID bool -GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yFlip) +GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yflip) { AndroidSurfaceTexture* surfaceTexture = stImage->GetData()->mSurfTex; - if (stImage->GetData()->mInverted) { - yFlip = !yFlip; - } ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); - if (NS_FAILED(surfaceTexture->Attach(mGL))) { + if (NS_FAILED(surfaceTexture->Attach(mGL))) return false; - } // UpdateTexImage() changes the EXTERNAL binding, so save it here // so we can restore it after. @@ -748,7 +744,7 @@ GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool surfaceTexture->GetTransformMatrix(transform); mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &transform._11); - mGL->fUniform1f(mYFlipLoc, yFlip ? 1.0f : 0.0f); + mGL->fUniform1f(mYFlipLoc, yflip ? 1.0f : 0.0f); mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); surfaceTexture->Detach(); @@ -758,15 +754,11 @@ GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool } bool -GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image, bool yFlip) +GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image, bool yflip) { EGLImage eglImage = image->GetData()->mImage; EGLSync eglSync = image->GetData()->mSync; - if (image->GetData()->mInverted) { - yFlip = !yFlip; - } - if (eglSync) { EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), eglSync, 0, LOCAL_EGL_FOREVER); if (status != LOCAL_EGL_CONDITION_SATISFIED) { @@ -781,7 +773,7 @@ GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image, bool yFlip) BindAndUploadEGLImage(eglImage, LOCAL_GL_TEXTURE_2D); - mGL->fUniform1f(mYFlipLoc, yFlip ? 1.0f : 0.0f); + mGL->fUniform1f(mYFlipLoc, yflip ? 1.0f : 0.0f); mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); @@ -792,7 +784,7 @@ GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image, bool yFlip) #endif bool -GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip) +GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yflip) { ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); const PlanarYCbCrData* yuvData = yuvImage->GetData(); @@ -813,7 +805,7 @@ GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFli BindAndUploadYUVTexture(Channel_Cb, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCbChannel, needsAllocation); BindAndUploadYUVTexture(Channel_Cr, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCrChannel, needsAllocation); - mGL->fUniform1f(mYFlipLoc, yFlip ? (float)1.0 : (float)0.0); + mGL->fUniform1f(mYFlipLoc, yflip ? (float)1.0 : (float)0.0); if (needsAllocation) { mGL->fUniform2f(mYTexScaleLoc, (float)yuvData->mYSize.width/yuvData->mYStride, 1.0f); @@ -832,7 +824,7 @@ bool GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage, const gfx::IntSize& destSize, GLuint destFB, - bool yFlip, + bool yflip, GLuint xoffset, GLuint yoffset, GLuint cropWidth, @@ -878,22 +870,22 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage, #ifdef MOZ_WIDGET_GONK if (type == ConvertGralloc) { layers::GrallocImage* grallocImage = static_cast(srcImage); - return BlitGrallocImage(grallocImage, yFlip); + return BlitGrallocImage(grallocImage, yflip); } #endif if (type == ConvertPlanarYCbCr) { mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); PlanarYCbCrImage* yuvImage = static_cast(srcImage); - return BlitPlanarYCbCrImage(yuvImage, yFlip); + return BlitPlanarYCbCrImage(yuvImage, yflip); } #ifdef MOZ_WIDGET_ANDROID if (type == ConvertSurfaceTexture) { layers::SurfaceTextureImage* stImage = static_cast(srcImage); - return BlitSurfaceTextureImage(stImage, yFlip); + return BlitSurfaceTextureImage(stImage, yflip); } if (type == ConvertEGLImage) { layers::EGLImageImage* eglImage = static_cast(srcImage); - return BlitEGLImageImage(eglImage, yFlip); + return BlitEGLImageImage(eglImage, yflip); } #endif @@ -905,7 +897,7 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, const gfx::IntSize& destSize, GLuint destTex, GLenum destTarget, - bool yFlip, + bool yflip, GLuint xoffset, GLuint yoffset, GLuint cropWidth, @@ -913,13 +905,13 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, { ScopedGLDrawState autoStates(mGL); - if (!mFBO) { + if (!mFBO) mGL->fGenFramebuffers(1, &mFBO); - } ScopedBindFramebuffer boundFB(mGL, mFBO); - mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, destTarget, destTex, 0); - return BlitImageToFramebuffer(srcImage, destSize, mFBO, yFlip, xoffset, yoffset, + mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, + destTarget, destTex, 0); + return BlitImageToFramebuffer(srcImage, destSize, mFBO, yflip, xoffset, yoffset, cropWidth, cropHeight); } @@ -1027,5 +1019,5 @@ GLBlitHelper::BlitTextureToTexture(GLuint srcTex, GLuint destTex, srcSize, destSize, destTarget); } -} -} +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/GLBlitHelper.h b/gfx/gl/GLBlitHelper.h index 4df7a0089aab..2814e76267f4 100644 --- a/gfx/gl/GLBlitHelper.h +++ b/gfx/gl/GLBlitHelper.h @@ -145,12 +145,13 @@ class GLBlitHelper MOZ_FINAL void BindAndUploadEGLImage(EGLImage image, GLuint target); #ifdef MOZ_WIDGET_GONK - bool BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip = false); + bool BlitGrallocImage(layers::GrallocImage* grallocImage, bool yflip); #endif - bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip = false); + bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yflip); #ifdef MOZ_WIDGET_ANDROID - bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yFlip = false); - bool BlitEGLImageImage(layers::EGLImageImage* eglImage, bool yFlip = false); + // Blit onto the current FB. + bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yflip); + bool BlitEGLImageImage(layers::EGLImageImage* eglImage, bool yflip); #endif public: @@ -186,14 +187,15 @@ public: GLenum srcTarget = LOCAL_GL_TEXTURE_2D, GLenum destTarget = LOCAL_GL_TEXTURE_2D); bool BlitImageToFramebuffer(layers::Image* srcImage, const gfx::IntSize& destSize, - GLuint destFB, bool yFlip = false, GLuint xoffset = 0, + GLuint destFB, bool yflip = false, GLuint xoffset = 0, GLuint yoffset = 0, GLuint width = 0, GLuint height = 0); bool BlitImageToTexture(layers::Image* srcImage, const gfx::IntSize& destSize, - GLuint destTex, GLenum destTarget, bool yFlip = false, GLuint xoffset = 0, - GLuint yoffset = 0, GLuint width = 0, GLuint height = 0); + GLuint destTex, GLenum destTarget, bool yflip = false, + GLuint xoffset = 0, GLuint yoffset = 0, GLuint width = 0, + GLuint height = 0); }; -} -} +} // namespace gl +} // namespace mozilla #endif // GLBLITHELPER_H_ diff --git a/gfx/gl/GLContextTypes.h b/gfx/gl/GLContextTypes.h index 27ae4813d755..1cdc12aeb220 100644 --- a/gfx/gl/GLContextTypes.h +++ b/gfx/gl/GLContextTypes.h @@ -22,6 +22,11 @@ MOZ_BEGIN_ENUM_CLASS(GLContextType) EGL MOZ_END_ENUM_CLASS(GLContextType) +MOZ_BEGIN_ENUM_CLASS(OriginPos, uint8_t) + TopLeft, + BottomLeft +MOZ_END_ENUM_CLASS(OriginPos) + struct GLFormats { // Constructs a zeroed object: @@ -39,7 +44,6 @@ struct GLFormats GLsizei samples; }; - struct PixelBufferFormat { // Constructs a zeroed object: @@ -53,7 +57,6 @@ struct PixelBufferFormat int ColorBits() const { return red + green + blue; } }; - } /* namespace gl */ } /* namespace mozilla */ diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index 01751a9bdc2d..0f36523ff60c 100755 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -49,7 +49,7 @@ GLScreenBuffer::Create(GLContext* gl, XRE_GetProcessType() != GeckoProcessType_Default) { layers::TextureFlags flags = layers::TextureFlags::DEALLOCATE_CLIENT | - layers::TextureFlags::NEEDS_Y_FLIP; + layers::TextureFlags::ORIGIN_BOTTOM_LEFT; if (!caps.premultAlpha) { flags |= layers::TextureFlags::NON_PREMULTIPLIED; } diff --git a/gfx/gl/GLTextureImage.cpp b/gfx/gl/GLTextureImage.cpp index 61358a4d5566..8dd8f2f5a310 100644 --- a/gfx/gl/GLTextureImage.cpp +++ b/gfx/gl/GLTextureImage.cpp @@ -597,9 +597,9 @@ gfx::IntRect TiledTextureImage::GetTileRect() gfx::IntRect TiledTextureImage::GetSrcTileRect() { gfx::IntRect rect = GetTileRect(); - unsigned int srcY = mFlags & NeedsYFlip - ? mSize.height - rect.height - rect.y - : rect.y; + const bool needsYFlip = mFlags & OriginBottomLeft; + unsigned int srcY = needsYFlip ? mSize.height - rect.height - rect.y + : rect.y; return gfx::IntRect(rect.x, srcY, rect.width, rect.height); } diff --git a/gfx/gl/GLTextureImage.h b/gfx/gl/GLTextureImage.h index f204a456955f..dc67f1028d02 100644 --- a/gfx/gl/GLTextureImage.h +++ b/gfx/gl/GLTextureImage.h @@ -58,7 +58,7 @@ public: enum Flags { NoFlags = 0x0, UseNearestFilter = 0x1, - NeedsYFlip = 0x2, + OriginBottomLeft = 0x2, DisallowBigImage = 0x4 }; @@ -381,7 +381,8 @@ CreateBasicTextureImage(GLContext* aGL, * |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by * default, GL_LINEAR filtering. Specify * |aFlags=UseNearestFilter| for GL_NEAREST filtering. Specify - * |aFlags=NeedsYFlip| if the image is flipped. Return + * |aFlags=OriginBottomLeft| if the image is origin-bottom-left, instead of the + * default origin-top-left. Return * nullptr if creating the TextureImage fails. * * The returned TextureImage may only be used with this GLContext. diff --git a/gfx/layers/CompositorTypes.h b/gfx/layers/CompositorTypes.h index 9642f00058bb..b2cd511dae9d 100644 --- a/gfx/layers/CompositorTypes.h +++ b/gfx/layers/CompositorTypes.h @@ -29,8 +29,8 @@ MOZ_BEGIN_ENUM_CLASS(TextureFlags, uint32_t) NO_FLAGS = 0, // Use nearest-neighbour texture filtering (as opposed to linear filtering). USE_NEAREST_FILTER = 1 << 0, - // The texture should be flipped along the y-axis when composited. - NEEDS_Y_FLIP = 1 << 1, + // The compositor assumes everything is origin-top-left by default. + ORIGIN_BOTTOM_LEFT = 1 << 1, // Force the texture to be represented using a single tile (note that this means // tiled textures, not tiled layers). DISALLOW_BIGIMAGE = 1 << 2, diff --git a/gfx/layers/CopyableCanvasLayer.cpp b/gfx/layers/CopyableCanvasLayer.cpp index bdf3f0672851..3889920faac0 100644 --- a/gfx/layers/CopyableCanvasLayer.cpp +++ b/gfx/layers/CopyableCanvasLayer.cpp @@ -32,6 +32,7 @@ CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImp CanvasLayer(aLayerManager, aImplData) , mGLFrontbuffer(nullptr) , mIsAlphaPremultiplied(true) + , mOriginPos(gl::OriginPos::TopLeft) { MOZ_COUNT_CTOR(CopyableCanvasLayer); } @@ -49,7 +50,8 @@ CopyableCanvasLayer::Initialize(const Data& aData) if (aData.mGLContext) { mGLContext = aData.mGLContext; mIsAlphaPremultiplied = aData.mIsGLAlphaPremult; - mNeedsYFlip = true; + mOriginPos = gl::OriginPos::BottomLeft; + MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen"); if (aData.mFrontbufferGLTex) { @@ -63,9 +65,8 @@ CopyableCanvasLayer::Initialize(const Data& aData) } else if (aData.mDrawTarget) { mDrawTarget = aData.mDrawTarget; mSurface = mDrawTarget->Snapshot(); - mNeedsYFlip = false; } else { - NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?"); + MOZ_CRASH("CanvasLayer created without mSurface, mDrawTarget or mGLContext?"); } mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); diff --git a/gfx/layers/CopyableCanvasLayer.h b/gfx/layers/CopyableCanvasLayer.h index c8c4df1a9ee9..4f6125efb463 100644 --- a/gfx/layers/CopyableCanvasLayer.h +++ b/gfx/layers/CopyableCanvasLayer.h @@ -55,7 +55,7 @@ protected: UniquePtr mGLFrontbuffer; bool mIsAlphaPremultiplied; - bool mNeedsYFlip; + gl::OriginPos mOriginPos; RefPtr mCachedTempSurface; diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 1547c611ebad..a204e4b41cd1 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -40,9 +40,9 @@ public: FrameMetrics() : mCompositionBounds(0, 0, 0, 0) - , mCriticalDisplayPort(0, 0, 0, 0) , mPresShellResolution(1) , mDisplayPort(0, 0, 0, 0) + , mCriticalDisplayPort(0, 0, 0, 0) , mScrollableRect(0, 0, 0, 0) , mCumulativeResolution(1) , mDevPixelsPerCSSPixel(1) @@ -251,19 +251,6 @@ public: // layout/paint time. ParentLayerRect mCompositionBounds; - // --------------------------------------------------------------------------- - // The following metrics are all in CSS pixels. They are not in any uniform - // space, so each is explained separately. - // - - // If non-empty, the area of a frame's contents that is considered critical - // to paint. Area outside of this area (i.e. area inside mDisplayPort, but - // outside of mCriticalDisplayPort) is considered low-priority, and may be - // painted with lower precision, or not painted at all. - // - // The same restrictions for mDisplayPort apply here. - CSSRect mCriticalDisplayPort; - // --------------------------------------------------------------------------- // The following metrics are dimensionless. // @@ -288,6 +275,16 @@ public: return mDisplayPort; } + void SetCriticalDisplayPort(const CSSRect& aCriticalDisplayPort) + { + mCriticalDisplayPort = aCriticalDisplayPort; + } + + CSSRect GetCriticalDisplayPort() const + { + return mCriticalDisplayPort; + } + void SetCumulativeResolution(const LayoutDeviceToLayerScale& aCumulativeResolution) { mCumulativeResolution = aCumulativeResolution; @@ -539,6 +536,14 @@ private: // width = window.innerWidth + 200, height = window.innerHeight + 200 } CSSRect mDisplayPort; + // If non-empty, the area of a frame's contents that is considered critical + // to paint. Area outside of this area (i.e. area inside mDisplayPort, but + // outside of mCriticalDisplayPort) is considered low-priority, and may be + // painted with lower precision, or not painted at all. + // + // The same restrictions for mDisplayPort apply here. + CSSRect mCriticalDisplayPort; + // The scrollable bounds of a frame. This is determined by reflow. // Ordinarily the x and y will be 0 and the width and height will be the // size of the element being scrolled. However for RTL pages or elements diff --git a/gfx/layers/GLImages.cpp b/gfx/layers/GLImages.cpp index 5a6f780fc707..ee519a1a6c05 100644 --- a/gfx/layers/GLImages.cpp +++ b/gfx/layers/GLImages.cpp @@ -40,7 +40,6 @@ GLImage::GetAsSourceSurface() if (!sSnapshotContext) { sSnapshotContext = GLContextProvider::CreateHeadless(); - if (!sSnapshotContext) { NS_WARNING("Failed to create snapshot GLContext"); return nullptr; @@ -63,6 +62,7 @@ GLImage::GetAsSourceSurface() GLBlitHelper helper(sSnapshotContext); helper.BlitImageToFramebuffer(this, size, fb.FB(), false); + ScopedBindFramebuffer bind(sSnapshotContext, fb.FB()); RefPtr source = diff --git a/gfx/layers/GLImages.h b/gfx/layers/GLImages.h index fc6d86a4c22e..e18612636497 100644 --- a/gfx/layers/GLImages.h +++ b/gfx/layers/GLImages.h @@ -6,6 +6,7 @@ #ifndef GFX_GLIMAGES_H #define GFX_GLIMAGES_H +#include "GLContextTypes.h" #include "GLTypes.h" #include "ImageContainer.h" // for Image #include "ImageTypes.h" // for ImageFormat::SHARED_GLTEXTURE @@ -31,10 +32,11 @@ public: EGLImage mImage; EGLSync mSync; gfx::IntSize mSize; - bool mInverted; + gl::OriginPos mOriginPos; bool mOwns; - Data() : mImage(nullptr), mSync(nullptr), mSize(0, 0), mInverted(false), mOwns(false) + Data() : mImage(nullptr), mSync(nullptr), mSize(0, 0), + mOriginPos(gl::OriginPos::TopLeft), mOwns(false) { } }; @@ -60,7 +62,7 @@ public: struct Data { mozilla::gl::AndroidSurfaceTexture* mSurfTex; gfx::IntSize mSize; - bool mInverted; + gl::OriginPos mOriginPos; }; void SetData(const Data& aData) { mData = aData; } diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index fa90eef33d4b..7d68e8f692f6 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -176,7 +176,7 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, AppendToString(aStream, m.GetSmoothScrollOffset(), "] [ss="); } AppendToString(aStream, m.GetDisplayPort(), "] [dp="); - AppendToString(aStream, m.mCriticalDisplayPort, "] [cdp="); + AppendToString(aStream, m.GetCriticalDisplayPort(), "] [cdp="); AppendToString(aStream, m.GetBackgroundColor(), "] [color="); if (!detailed) { AppendToString(aStream, m.GetScrollId(), "] [scrollId="); @@ -289,7 +289,7 @@ AppendToString(std::stringstream& aStream, TextureFlags flags, } bool previous = false; AppendFlag(TextureFlags::USE_NEAREST_FILTER); - AppendFlag(TextureFlags::NEEDS_Y_FLIP); + AppendFlag(TextureFlags::ORIGIN_BOTTOM_LEFT); AppendFlag(TextureFlags::DISALLOW_BIGIMAGE); #undef AppendFlag diff --git a/gfx/layers/LayersTypes.h b/gfx/layers/LayersTypes.h index 23ab87522e09..ddcbb2dea684 100644 --- a/gfx/layers/LayersTypes.h +++ b/gfx/layers/LayersTypes.h @@ -79,7 +79,7 @@ MOZ_END_ENUM_CLASS(SurfaceMode) // by other surfaces we will need a more generic LayerRenderState. MOZ_BEGIN_ENUM_CLASS(LayerRenderStateFlags, int8_t) LAYER_RENDER_STATE_DEFAULT = 0, - Y_FLIPPED = 1 << 0, + ORIGIN_BOTTOM_LEFT = 1 << 0, BUFFER_ROTATION = 1 << 1, // Notify Composer2D to swap the RB pixels of gralloc buffer FORMAT_RB_SWAP = 1 << 2, @@ -116,8 +116,8 @@ struct LayerRenderState { , mTexture(aTexture) {} - bool YFlipped() const - { return bool(mFlags & LayerRenderStateFlags::Y_FLIPPED); } + bool OriginBottomLeft() const + { return bool(mFlags & LayerRenderStateFlags::ORIGIN_BOTTOM_LEFT); } bool BufferRotated() const { return bool(mFlags & LayerRenderStateFlags::BUFFER_ROTATION); } diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 6e0334a5017b..51e346a604b9 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2707,9 +2707,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri LogRendertraceRect(GetGuid(), "page", "brown", aLayerMetrics.GetScrollableRect()); LogRendertraceRect(GetGuid(), "painted displayport", "lightgreen", aLayerMetrics.GetDisplayPort() + aLayerMetrics.GetScrollOffset()); - if (!aLayerMetrics.mCriticalDisplayPort.IsEmpty()) { + if (!aLayerMetrics.GetCriticalDisplayPort().IsEmpty()) { LogRendertraceRect(GetGuid(), "painted critical displayport", "darkgreen", - aLayerMetrics.mCriticalDisplayPort + aLayerMetrics.GetScrollOffset()); + aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset()); } mPaintThrottler.TaskComplete(GetFrameTime()); diff --git a/gfx/layers/basic/BasicCanvasLayer.cpp b/gfx/layers/basic/BasicCanvasLayer.cpp index 25ab6865e070..656a770b0cc6 100644 --- a/gfx/layers/basic/BasicCanvasLayer.cpp +++ b/gfx/layers/basic/BasicCanvasLayer.cpp @@ -40,8 +40,10 @@ BasicCanvasLayer::Paint(DrawTarget* aDT, return; } + const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft); + Matrix oldTM; - if (mNeedsYFlip) { + if (needsYFlip) { oldTM = aDT->GetTransform(); aDT->SetTransform(Matrix(oldTM). PreTranslate(0.0f, mBounds.height). @@ -54,7 +56,7 @@ BasicCanvasLayer::Paint(DrawTarget* aDT, DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)), aMaskLayer); - if (mNeedsYFlip) { + if (needsYFlip) { aDT->SetTransform(oldTM); } } diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index a4435c2b7a96..a01da3feb9ea 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -72,8 +72,8 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(contentType); TextureFlags flags = TextureFlags::DEFAULT; - if (mTextureFlags & TextureFlags::NEEDS_Y_FLIP) { - flags |= TextureFlags::NEEDS_Y_FLIP; + if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) { + flags |= TextureFlags::ORIGIN_BOTTOM_LEFT; } gfx::SurfaceFormat surfaceFormat = gfx::ImageFormatToSurfaceFormat(format); diff --git a/gfx/layers/client/ClientCanvasLayer.cpp b/gfx/layers/client/ClientCanvasLayer.cpp index 8aaa4aeff75a..fadfd5d230b1 100644 --- a/gfx/layers/client/ClientCanvasLayer.cpp +++ b/gfx/layers/client/ClientCanvasLayer.cpp @@ -78,7 +78,7 @@ ClientCanvasLayer::Initialize(const Data& aData) if (mGLContext->GetContextType() == GLContextType::EGL) { #ifdef MOZ_WIDGET_GONK TextureFlags flags = TextureFlags::DEALLOCATE_CLIENT | - TextureFlags::NEEDS_Y_FLIP; + TextureFlags::ORIGIN_BOTTOM_LEFT; if (!aData.mIsGLAlphaPremult) { flags |= TextureFlags::NON_PREMULTIPLIED; } @@ -153,8 +153,8 @@ ClientCanvasLayer::RenderLayer() if (!mCanvasClient) { TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD; - if (mNeedsYFlip) { - flags |= TextureFlags::NEEDS_Y_FLIP; + if (mOriginPos == gl::OriginPos::BottomLeft) { + flags |= TextureFlags::ORIGIN_BOTTOM_LEFT; } if (!mGLContext) { diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index d266e34adade..b1c52387ad13 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -752,8 +752,8 @@ ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. CSSToLayerScale paintScale = aMetrics.LayersPixelsPerCSSPixel(); const CSSRect& metricsDisplayPort = - (aDrawingCritical && !aMetrics.mCriticalDisplayPort.IsEmpty()) ? - aMetrics.mCriticalDisplayPort : aMetrics.GetDisplayPort(); + (aDrawingCritical && !aMetrics.GetCriticalDisplayPort().IsEmpty()) ? + aMetrics.GetCriticalDisplayPort() : aMetrics.GetDisplayPort(); LayerRect displayPort = (metricsDisplayPort + aMetrics.GetScrollOffset()) * paintScale; ParentLayerPoint scrollOffset; diff --git a/gfx/layers/client/ClientTiledPaintedLayer.cpp b/gfx/layers/client/ClientTiledPaintedLayer.cpp index d3190b209866..c219fa354a17 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -152,7 +152,7 @@ ClientTiledPaintedLayer::BeginPaint() // Compute the critical display port that applies to this layer in the // LayoutDevice space of this layer. ParentLayerRect criticalDisplayPort = - (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoom()) + (displayportMetrics.GetCriticalDisplayPort() * displayportMetrics.GetZoom()) + displayportMetrics.mCompositionBounds.TopLeft(); mPaintData.mCriticalDisplayPort = RoundedOut( ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort)); @@ -189,7 +189,7 @@ ClientTiledPaintedLayer::UseFastPath() bool multipleTransactionsNeeded = gfxPlatform::GetPlatform()->UseProgressivePaint() || gfxPrefs::UseLowPrecisionBuffer() - || !parentMetrics.mCriticalDisplayPort.IsEmpty(); + || !parentMetrics.GetCriticalDisplayPort().IsEmpty(); bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition(); return !multipleTransactionsNeeded || isFixed || parentMetrics.GetDisplayPort().IsEmpty(); } diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index ec6b438d79e5..05aa876cbe69 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -202,7 +202,7 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag const SurfaceTextureImage::Data* data = typedImage->GetData(); texture = new SurfaceTextureClient(GetForwarder(), mTextureFlags, data->mSurfTex, size, - data->mInverted); + data->mOriginPos); #endif } else { MOZ_ASSERT(false, "Bad ImageFormat."); diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index e7bb13b60332..7dc70ed31f6e 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -257,9 +257,9 @@ SharedFrameMetricsHelper::AboutToCheckerboard(const FrameMetrics& aContentMetric // converted to app units and then back to CSS pixels before being put in the FrameMetrics. // This process can introduce some rounding error, so we inflate the rect by one app unit // to account for that. - CSSRect painted = (aContentMetrics.mCriticalDisplayPort.IsEmpty() + CSSRect painted = (aContentMetrics.GetCriticalDisplayPort().IsEmpty() ? aContentMetrics.GetDisplayPort() - : aContentMetrics.mCriticalDisplayPort) + : aContentMetrics.GetCriticalDisplayPort()) + aContentMetrics.GetScrollOffset(); painted.Inflate(CSSMargin::FromAppUnits(nsMargin(1, 1, 1, 1))); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 4bc35e454fe4..876f010ccd6c 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -604,8 +604,8 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) const FrameMetrics& metrics = aLayer->GetFrameMetrics(i); CSSToLayerScale paintScale = metrics.LayersPixelsPerCSSPixel(); - CSSRect displayPort(metrics.mCriticalDisplayPort.IsEmpty() ? - metrics.GetDisplayPort() : metrics.mCriticalDisplayPort); + CSSRect displayPort(metrics.GetCriticalDisplayPort().IsEmpty() ? + metrics.GetDisplayPort() : metrics.GetCriticalDisplayPort()); ScreenPoint offset(0, 0); // XXX this call to SyncFrameMetrics is not currently being used. It will be cleaned // up as part of bug 776030 or one of its dependencies. @@ -859,9 +859,9 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // notifications, so that Java can take these into account in its response. // Calculate the absolute display port to send to Java LayerIntRect displayPort = RoundedToInt( - (metrics.mCriticalDisplayPort.IsEmpty() + (metrics.GetCriticalDisplayPort().IsEmpty() ? metrics.GetDisplayPort() - : metrics.mCriticalDisplayPort + : metrics.GetCriticalDisplayPort() ) * geckoZoom); displayPort += scrollOffsetLayerPixels; diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index c9a267553c42..f9f247b09075 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -151,7 +151,7 @@ ImageHost::Composite(EffectChain& aEffectChain, } else { effect->mTextureCoords = Rect(0, 0, 1, 1); } - if (mFrontBuffer->GetFlags() & TextureFlags::NEEDS_Y_FLIP) { + if (mFrontBuffer->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT) { effect->mTextureCoords.y = effect->mTextureCoords.YMost(); effect->mTextureCoords.height = -effect->mTextureCoords.height; } @@ -179,7 +179,7 @@ ImageHost::Composite(EffectChain& aEffectChain, rect = gfx::Rect(0, 0, textureSize.width, textureSize.height); } - if (mFrontBuffer->GetFlags() & TextureFlags::NEEDS_Y_FLIP) { + if (mFrontBuffer->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT) { effect->mTextureCoords.y = effect->mTextureCoords.YMost(); effect->mTextureCoords.height = -effect->mTextureCoords.height; } diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 8e19491533eb..4b1768e8830f 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -928,10 +928,10 @@ LayerManagerComposite::ComputeRenderIntegrity() // Work out how much of the critical display-port covers the screen bool hasLowPrecision = false; - if (!metrics.mCriticalDisplayPort.IsEmpty()) { + if (!metrics.GetCriticalDisplayPort().IsEmpty()) { hasLowPrecision = true; highPrecisionMultiplier = - GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect); + GetDisplayportCoverage(metrics.GetCriticalDisplayPort(), transform, screenRect); } // Work out how much of the display-port covers the screen diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.cpp b/gfx/layers/d3d10/CanvasLayerD3D10.cpp index b0c3d008153e..bfb11bea2a9e 100644 --- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp +++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp @@ -23,8 +23,8 @@ using namespace mozilla::gfx; CanvasLayerD3D10::CanvasLayerD3D10(LayerManagerD3D10 *aManager) : CanvasLayer(aManager, nullptr) , LayerD3D10(aManager) - , mDataIsPremultiplied(false) - , mNeedsYFlip(false) + , mDataIsPremultiplied(true) + , mOriginPos(gl::OriginPos::TopLeft) , mHasAlpha(true) { mImplData = static_cast(this); @@ -43,7 +43,7 @@ CanvasLayerD3D10::Initialize(const Data& aData) mGLContext = aData.mGLContext; NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen."); mDataIsPremultiplied = aData.mIsGLAlphaPremult; - mNeedsYFlip = true; + mOriginPos = gl::OriginPos::TopLeft; GLScreenBuffer* screen = mGLContext->Screen(); @@ -60,8 +60,6 @@ CanvasLayerD3D10::Initialize(const Data& aData) } } else if (aData.mDrawTarget) { mDrawTarget = aData.mDrawTarget; - mNeedsYFlip = false; - mDataIsPremultiplied = true; void *texture = mDrawTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE); if (texture) { @@ -79,7 +77,7 @@ CanvasLayerD3D10::Initialize(const Data& aData) // bypassing Thebes mSurface = mDrawTarget->Snapshot(); } else { - NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?"); + MOZ_CRASH("CanvasLayer created without mSurface, mDrawTarget or mGLContext?"); } mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); @@ -213,7 +211,9 @@ CanvasLayerD3D10::RenderLayer() (float)mBounds.height) ); - if (mNeedsYFlip) { + const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft); + + if (needsYFlip) { effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector( ShaderConstantRectD3D10( 0, @@ -226,7 +226,7 @@ CanvasLayerD3D10::RenderLayer() technique->GetPassByIndex(0)->Apply(0); device()->Draw(4, 0); - if (mNeedsYFlip) { + if (needsYFlip) { effect()->GetVariableByName("vTextureCoords")->AsVector()-> SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); } diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.h b/gfx/layers/d3d10/CanvasLayerD3D10.h index e8066519cd93..34733f0d37b9 100644 --- a/gfx/layers/d3d10/CanvasLayerD3D10.h +++ b/gfx/layers/d3d10/CanvasLayerD3D10.h @@ -6,8 +6,8 @@ #ifndef GFX_CANVASLAYERD3D10_H #define GFX_CANVASLAYERD3D10_H +#include "GLContextTypes.h" #include "LayerManagerD3D10.h" - #include "mozilla/Preferences.h" namespace mozilla { @@ -45,7 +45,7 @@ private: nsRefPtr mSRView; bool mDataIsPremultiplied; - bool mNeedsYFlip; + gl::OriginPos mOriginPos; bool mIsD2DTexture; bool mHasAlpha; diff --git a/gfx/layers/d3d9/CanvasLayerD3D9.cpp b/gfx/layers/d3d9/CanvasLayerD3D9.cpp index 70b4250bf107..f8ce2e67df18 100644 --- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp +++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp @@ -22,8 +22,8 @@ namespace layers { CanvasLayerD3D9::CanvasLayerD3D9(LayerManagerD3D9 *aManager) : CanvasLayer(aManager, nullptr) , LayerD3D9(aManager) - , mDataIsPremultiplied(false) - , mNeedsYFlip(false) + , mDataIsPremultiplied(true) + , mOriginPos(gl::OriginPos::TopLeft) , mHasAlpha(true) { mImplData = static_cast(this); @@ -44,13 +44,11 @@ CanvasLayerD3D9::Initialize(const Data& aData) if (aData.mDrawTarget) { mDrawTarget = aData.mDrawTarget; - mNeedsYFlip = false; - mDataIsPremultiplied = true; } else if (aData.mGLContext) { mGLContext = aData.mGLContext; NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen."); mDataIsPremultiplied = aData.mIsGLAlphaPremult; - mNeedsYFlip = true; + mOriginPos = gl::OriginPos::BottomLeft; } else { NS_ERROR("CanvasLayer created without mGLContext or mDrawTarget?"); } @@ -137,9 +135,10 @@ CanvasLayerD3D9::RenderLayer() * We flip the Y axis here, note we can only do this because we are in * CULL_NONE mode! */ - ShaderConstantRect quad(0, 0, mBounds.width, mBounds.height); - if (mNeedsYFlip) { + + const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft); + if (needsYFlip) { quad.mHeight = (float)-mBounds.height; quad.mY = (float)mBounds.height; } diff --git a/gfx/layers/d3d9/CanvasLayerD3D9.h b/gfx/layers/d3d9/CanvasLayerD3D9.h index 602d2f0720b6..3a4234ea0437 100644 --- a/gfx/layers/d3d9/CanvasLayerD3D9.h +++ b/gfx/layers/d3d9/CanvasLayerD3D9.h @@ -6,8 +6,8 @@ #ifndef GFX_CANVASLAYERD3D9_H #define GFX_CANVASLAYERD3D9_H -#include "LayerManagerD3D9.h" #include "GLContextTypes.h" +#include "LayerManagerD3D9.h" namespace mozilla { namespace layers { @@ -42,7 +42,7 @@ protected: RefPtr mDrawTarget; bool mDataIsPremultiplied; - bool mNeedsYFlip; + gl::OriginPos mOriginPos; bool mHasAlpha; nsAutoArrayPtr mCachedTempBlob; diff --git a/gfx/layers/opengl/GrallocTextureClient.cpp b/gfx/layers/opengl/GrallocTextureClient.cpp index 4f5fa6a30d32..769c5459d041 100644 --- a/gfx/layers/opengl/GrallocTextureClient.cpp +++ b/gfx/layers/opengl/GrallocTextureClient.cpp @@ -348,7 +348,7 @@ GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf, RefPtr ret = surf->GetTextureClient(); - TextureFlags mask = TextureFlags::NEEDS_Y_FLIP | + TextureFlags mask = TextureFlags::ORIGIN_BOTTOM_LEFT | TextureFlags::RB_SWAPPED | TextureFlags::NON_PREMULTIPLIED; TextureFlags required = flags & mask; diff --git a/gfx/layers/opengl/GrallocTextureHost.cpp b/gfx/layers/opengl/GrallocTextureHost.cpp index ee1f60822f9c..849205ef7486 100644 --- a/gfx/layers/opengl/GrallocTextureHost.cpp +++ b/gfx/layers/opengl/GrallocTextureHost.cpp @@ -212,8 +212,8 @@ GrallocTextureHostOGL::GetRenderState() if (mIsOpaque) { flags |= LayerRenderStateFlags::OPAQUE; } - if (mFlags & TextureFlags::NEEDS_Y_FLIP) { - flags |= LayerRenderStateFlags::Y_FLIPPED; + if (mFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) { + flags |= LayerRenderStateFlags::ORIGIN_BOTTOM_LEFT; } if (mFlags & TextureFlags::RB_SWAPPED) { flags |= LayerRenderStateFlags::FORMAT_RB_SWAP; diff --git a/gfx/layers/opengl/TextureClientOGL.cpp b/gfx/layers/opengl/TextureClientOGL.cpp index 8aa64ed73457..d6b35eb76782 100644 --- a/gfx/layers/opengl/TextureClientOGL.cpp +++ b/gfx/layers/opengl/TextureClientOGL.cpp @@ -34,8 +34,8 @@ EGLImageTextureClient::EGLImageTextureClient(ISurfaceAllocator* aAllocator, AddFlags(TextureFlags::DEALLOCATE_CLIENT); - if (aImage->GetData()->mInverted) { - AddFlags(TextureFlags::NEEDS_Y_FLIP); + if (aImage->GetData()->mOriginPos == gl::OriginPos::BottomLeft) { + AddFlags(TextureFlags::ORIGIN_BOTTOM_LEFT); } } @@ -77,7 +77,7 @@ SurfaceTextureClient::SurfaceTextureClient(ISurfaceAllocator* aAllocator, TextureFlags aFlags, AndroidSurfaceTexture* aSurfTex, gfx::IntSize aSize, - bool aInverted) + gl::OriginPos aOriginPos) : TextureClient(aAllocator, aFlags) , mSurfTex(aSurfTex) , mSize(aSize) @@ -89,8 +89,8 @@ SurfaceTextureClient::SurfaceTextureClient(ISurfaceAllocator* aAllocator, // Our data is always owned externally. AddFlags(TextureFlags::DEALLOCATE_CLIENT); - if (aInverted) { - AddFlags(TextureFlags::NEEDS_Y_FLIP); + if (aOriginPos == gl::OriginPos::BottomLeft) { + AddFlags(TextureFlags::ORIGIN_BOTTOM_LEFT); } } diff --git a/gfx/layers/opengl/TextureClientOGL.h b/gfx/layers/opengl/TextureClientOGL.h index 3130a0008e47..15c8cad9e125 100644 --- a/gfx/layers/opengl/TextureClientOGL.h +++ b/gfx/layers/opengl/TextureClientOGL.h @@ -77,7 +77,7 @@ public: TextureFlags aFlags, gl::AndroidSurfaceTexture* aSurfTex, gfx::IntSize aSize, - bool aInverted); + gl::OriginPos aOriginPos); ~SurfaceTextureClient(); diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index d98eb93021fa..3a445c1ac1de 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -103,8 +103,8 @@ FlagsToGLFlags(TextureFlags aFlags) if (aFlags & TextureFlags::USE_NEAREST_FILTER) result |= TextureImage::UseNearestFilter; - if (aFlags & TextureFlags::NEEDS_Y_FLIP) - result |= TextureImage::NeedsYFlip; + if (aFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) + result |= TextureImage::OriginBottomLeft; if (aFlags & TextureFlags::DISALLOW_BIGIMAGE) result |= TextureImage::DisallowBigImage; diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index c29310745700..1204401dd2b3 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -225,7 +225,7 @@ TestFrameMetrics() fm.SetDisplayPort(CSSRect(0, 0, 10, 10)); fm.mCompositionBounds = ParentLayerRect(0, 0, 10, 10); - fm.mCriticalDisplayPort = CSSRect(0, 0, 10, 10); + fm.SetCriticalDisplayPort(CSSRect(0, 0, 10, 10)); fm.SetScrollableRect(CSSRect(0, 0, 100, 100)); return fm; diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 05f50e8cc050..68d40f6e6936 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -429,7 +429,7 @@ class GCRuntime void disallowIncrementalGC() { incrementalAllowed = false; } bool isIncrementalGCEnabled() { return mode == JSGC_MODE_INCREMENTAL && incrementalAllowed; } - bool isIncrementalGCInProgress() { return state() != gc::NO_INCREMENTAL && !verifyPreData; } + bool isIncrementalGCInProgress() { return state() != gc::NO_INCREMENTAL; } bool isGenerationalGCEnabled() { return generationalDisabled == 0; } void disableGenerationalGC(); diff --git a/js/src/gc/Statistics.cpp b/js/src/gc/Statistics.cpp index 7190dea2faa0..ae763a878ed0 100644 --- a/js/src/gc/Statistics.cpp +++ b/js/src/gc/Statistics.cpp @@ -773,7 +773,7 @@ Statistics::endGC() runtime->addTelemetry(JS_TELEMETRY_GC_INCREMENTAL_DISABLED, !runtime->gc.isIncrementalGCAllowed()); runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_TOTAL_MS, t(sccTotal)); runtime->addTelemetry(JS_TELEMETRY_GC_SCC_SWEEP_MAX_PAUSE_MS, t(sccLongest)); - + double mmu50 = computeMMU(50 * PRMJ_USEC_PER_MSEC); runtime->addTelemetry(JS_TELEMETRY_GC_MMU_50, mmu50 * 100); @@ -792,7 +792,7 @@ Statistics::beginSlice(const ZoneGCStats &zoneStats, JSGCInvocationKind gckind, { this->zoneStats = zoneStats; - bool first = runtime->gc.state() == gc::NO_INCREMENTAL; + bool first = !runtime->gc.isIncrementalGCInProgress(); if (first) beginGC(gckind); @@ -820,7 +820,7 @@ Statistics::endSlice() runtime->addTelemetry(JS_TELEMETRY_GC_SLICE_MS, t(slices.back().end - slices.back().start)); runtime->addTelemetry(JS_TELEMETRY_GC_RESET, !!slices.back().resetReason); - bool last = runtime->gc.state() == gc::NO_INCREMENTAL; + bool last = !runtime->gc.isIncrementalGCInProgress(); if (last) endGC(); diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index c78c33b4bfbd..e8fce62f3403 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -170,7 +170,7 @@ NextNode(VerifyNode *node) void gc::GCRuntime::startVerifyPreBarriers() { - if (verifyPreData || incrementalState != NO_INCREMENTAL) + if (verifyPreData || isIncrementalGCInProgress()) return; /* @@ -403,11 +403,8 @@ struct VerifyPostTracer : JSTracer void gc::GCRuntime::startVerifyPostBarriers() { - if (verifyPostData || - incrementalState != NO_INCREMENTAL) - { + if (verifyPostData || isIncrementalGCInProgress()) return; - } evictNursery(); diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 997f9ad800e7..898cd63c6fd4 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -107,13 +107,6 @@ Zone::onTooMuchMalloc() } } -bool -Zone::isCloseToAllocTrigger(bool highFrequencyGC) const -{ - double factor = highFrequencyGC ? 0.85 : 0.9; - return usage.gcBytes() >= factor * threshold.gcTriggerBytes(); -} - void Zone::beginSweepTypes(FreeOp *fop, bool releaseTypes) { diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 3a867e43f717..b96ed801fae2 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -62,6 +62,7 @@ class ZoneHeapThreshold double gcHeapGrowthFactor() const { return gcHeapGrowthFactor_; } size_t gcTriggerBytes() const { return gcTriggerBytes_; } + bool isCloseToAllocTrigger(const js::gc::HeapUsage& usage, bool highFrequencyGC) const; void updateAfterGC(size_t lastBytes, JSGCInvocationKind gckind, const GCSchedulingTunables &tunables, const GCSchedulingState &state); @@ -153,8 +154,6 @@ struct Zone : public JS::shadow::Zone, bool isTooMuchMalloc() const { return gcMallocBytes <= 0; } void onTooMuchMalloc(); - bool isCloseToAllocTrigger(bool highFrequencyGC) const; - void *onOutOfMemory(void *p, size_t nbytes) { return runtimeFromMainThread()->onOutOfMemory(p, nbytes); } diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp index 049d24456222..e526ce1c1173 100644 --- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp +++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp @@ -25,7 +25,7 @@ BEGIN_TEST(testGCFinalizeCallback) FinalizeCalls = 0; JS::PrepareForFullGC(rt); JS::IncrementalGC(rt, JS::gcreason::API, 1000000); - CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL); + CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(rt->gc.isFullGc()); CHECK(checkMultipleGroups()); CHECK(checkFinalizeStatus()); @@ -62,7 +62,7 @@ BEGIN_TEST(testGCFinalizeCallback) FinalizeCalls = 0; JS::PrepareZoneForGC(global1->zone()); JS::IncrementalGC(rt, JS::gcreason::API, 1000000); - CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL); + CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(!rt->gc.isFullGc()); CHECK(checkSingleGroup()); CHECK(checkFinalizeStatus()); @@ -74,7 +74,7 @@ BEGIN_TEST(testGCFinalizeCallback) JS::PrepareZoneForGC(global2->zone()); JS::PrepareZoneForGC(global3->zone()); JS::IncrementalGC(rt, JS::gcreason::API, 1000000); - CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL); + CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(!rt->gc.isFullGc()); CHECK(checkMultipleGroups()); CHECK(checkFinalizeStatus()); @@ -95,7 +95,7 @@ BEGIN_TEST(testGCFinalizeCallback) JS::RootedObject global4(cx, createTestGlobal()); budget = js::SliceBudget(js::WorkBudget(1)); rt->gc.gcDebugSlice(budget); - CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL); + CHECK(!rt->gc.isIncrementalGCInProgress()); CHECK(!rt->gc.isFullGc()); CHECK(checkMultipleGroups()); CHECK(checkFinalizeStatus()); diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index be799cead774..c9645f7853a6 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -1114,7 +1114,7 @@ JS::IsIncrementalGCEnabled(JSRuntime *rt) JS_FRIEND_API(bool) JS::IsIncrementalGCInProgress(JSRuntime *rt) { - return rt->gc.isIncrementalGCInProgress(); + return rt->gc.isIncrementalGCInProgress() && !rt->gc.isVerifyPreBarriersEnabled(); } JS_FRIEND_API(void) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 88b5275df4bc..3a13ac5ad573 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1627,10 +1627,10 @@ GCRuntime::addRoot(T *rp, const char *name, JSGCRootType rootType) * or ModifyBusyCount in workers). We need a read barrier to cover these * cases. */ - if (rt->gc.incrementalState != NO_INCREMENTAL) + if (isIncrementalGCInProgress()) BarrierOwner::result::writeBarrierPre(*rp); - return rt->gc.rootsHash.put((void *)rp, RootInfo(name, rootType)); + return rootsHash.put((void *)rp, RootInfo(name, rootType)); } void @@ -1748,6 +1748,13 @@ GCRuntime::onTooMuchMalloc() mallocGCTriggered = triggerGC(JS::gcreason::TOO_MUCH_MALLOC); } +bool +ZoneHeapThreshold::isCloseToAllocTrigger(const js::gc::HeapUsage& usage, bool highFrequencyGC) const +{ + double factor = highFrequencyGC ? 0.85 : 0.9; + return usage.gcBytes() >= factor * gcTriggerBytes(); +} + /* static */ double ZoneHeapThreshold::computeZoneHeapGrowthFactorForHeapSize(size_t lastBytes, const GCSchedulingTunables &tunables, @@ -3009,8 +3016,9 @@ template /* static */ void * GCRuntime::refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind) { - MOZ_ASSERT(!cx->runtime()->isHeapBusy(), "allocating while under GC"); - MOZ_ASSERT_IF(allowGC, !cx->runtime()->currentThreadHasExclusiveAccess()); + JSRuntime *rt = cx->runtime(); + MOZ_ASSERT(!rt->isHeapBusy(), "allocating while under GC"); + MOZ_ASSERT_IF(allowGC, !rt->currentThreadHasExclusiveAccess()); Allocator *allocator = cx->allocator(); Zone *zone = allocator->zone_; @@ -3018,8 +3026,7 @@ GCRuntime::refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind) // If we have grown past our GC heap threshold while in the middle of an // incremental GC, we're growing faster than we're GCing, so stop the world // and do a full, non-incremental GC right now, if possible. - const bool mustCollectNow = allowGC && - cx->runtime()->gc.incrementalState != NO_INCREMENTAL && + const bool mustCollectNow = allowGC && rt->gc.isIncrementalGCInProgress() && zone->usage.gcBytes() > zone->threshold.gcTriggerBytes(); bool outOfMemory = false; // Set true if we fail to allocate. @@ -3047,7 +3054,7 @@ GCRuntime::refillFreeListFromMainThread(JSContext *cx, AllocKind thingKind) // finalization task may be running (freeing more memory); wait for it // to finish, then try to allocate again in case it freed up the memory // we need. - cx->runtime()->gc.waitBackgroundSweepEnd(); + rt->gc.waitBackgroundSweepEnd(); thing = allocator->arenas.allocateFromArena(zone, thingKind, maybeStartBGAlloc); if (MOZ_LIKELY(thing)) @@ -3309,8 +3316,8 @@ GCRuntime::maybeGC(Zone *zone) return true; if (zone->usage.gcBytes() > 1024 * 1024 && - zone->isCloseToAllocTrigger(schedulingState.inHighFrequencyGCMode()) && - incrementalState == NO_INCREMENTAL && + zone->threshold.isCloseToAllocTrigger(zone->usage, schedulingState.inHighFrequencyGCMode()) && + !isIncrementalGCInProgress() && !isBackgroundSweeping()) { PrepareZoneForGC(zone); @@ -3666,7 +3673,7 @@ GCHelperState::waitBackgroundSweepEnd() AutoLockGC lock(rt); while (state() == SWEEPING) waitForBackgroundThread(); - if (rt->gc.incrementalState == NO_INCREMENTAL) + if (!rt->gc.isIncrementalGCInProgress()) rt->gc.assertBackgroundSweepingFinished(); } @@ -5880,7 +5887,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget &budget, JS::gcreason::Reason rea } #endif - MOZ_ASSERT_IF(incrementalState != NO_INCREMENTAL, isIncremental); + MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental); isIncremental = !budget.isUnlimited(); if (zeal == ZealIncrementalRootsThenFinish || zeal == ZealIncrementalMarkAllThenFinish) { @@ -6038,11 +6045,8 @@ GCRuntime::budgetIncrementalGC(SliceBudget &budget) stats.nonincremental("allocation trigger"); } - if (incrementalState != NO_INCREMENTAL && - zone->isGCScheduled() != zone->wasGCStarted()) - { + if (isIncrementalGCInProgress() && zone->isGCScheduled() != zone->wasGCStarted()) reset = true; - } if (zone->isTooMuchMalloc()) { budget.makeUnlimited(); @@ -6101,7 +6105,7 @@ GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gck interFrameGC = true; number++; - if (incrementalState == NO_INCREMENTAL) + if (!isIncrementalGCInProgress()) majorGCNumber++; // It's ok if threads other than the main thread have suppressGC set, as @@ -6116,7 +6120,7 @@ GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gck // As we are about to clear the mark bits, wait for background // finalization to finish. We only need to wait on the first slice. - if (incrementalState == NO_INCREMENTAL) + if (!isIncrementalGCInProgress()) waitBackgroundSweepEnd(); // We must also wait for background allocation to finish so we can @@ -6143,13 +6147,13 @@ GCRuntime::gcCycle(bool incremental, SliceBudget &budget, JSGCInvocationKind gck } /* The GC was reset, so we need a do-over. */ - if (prevState != NO_INCREMENTAL && incrementalState == NO_INCREMENTAL) + if (prevState != NO_INCREMENTAL && !isIncrementalGCInProgress()) return true; TraceMajorGCStart(); /* Set the invocation kind in the first slice. */ - if (incrementalState == NO_INCREMENTAL) + if (!isIncrementalGCInProgress()) invocationKind = gckind; incrementalCollectSlice(budget, reason); @@ -6215,11 +6219,11 @@ GCRuntime::scanZonesBeforeGC() zone->scheduleGC(); /* This is a heuristic to avoid resets. */ - if (incrementalState != NO_INCREMENTAL && zone->needsIncrementalBarrier()) + if (isIncrementalGCInProgress() && zone->needsIncrementalBarrier()) zone->scheduleGC(); /* This is a heuristic to reduce the total number of collections. */ - if (zone->isCloseToAllocTrigger(schedulingState.inHighFrequencyGCMode())) + if (zone->threshold.isCloseToAllocTrigger(zone->usage, schedulingState.inHighFrequencyGCMode())) zone->scheduleGC(); zoneStats.zoneCount++; @@ -6274,7 +6278,7 @@ GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gck * Let the API user decide to defer a GC if it wants to (unless this * is the last context). Invoke the callback regardless. */ - if (incrementalState == NO_INCREMENTAL) { + if (!isIncrementalGCInProgress()) { gcstats::AutoPhase ap(stats, gcstats::PHASE_GC_BEGIN); if (gcCallback.op) gcCallback.op(rt, JSGC_BEGIN, gcCallback.data); @@ -6283,7 +6287,7 @@ GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gck poked = false; bool wasReset = gcCycle(incremental, budget, gckind, reason); - if (incrementalState == NO_INCREMENTAL) { + if (!isIncrementalGCInProgress()) { gcstats::AutoPhase ap(stats, gcstats::PHASE_GC_END); if (gcCallback.op) gcCallback.op(rt, JSGC_END, gcCallback.data); @@ -6299,7 +6303,7 @@ GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gck * beginMarkPhase. */ bool repeatForDeadZone = false; - if (incremental && incrementalState == NO_INCREMENTAL) { + if (incremental && !isIncrementalGCInProgress()) { for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) { if (c->scheduledForDestruction) { incremental = false; @@ -6319,7 +6323,7 @@ GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gck repeat = (poked && cleanUpEverything) || wasReset || repeatForDeadZone; } while (repeat); - if (incrementalState == NO_INCREMENTAL) + if (!isIncrementalGCInProgress()) EnqueuePendingParseTasksAfterGC(rt); } @@ -6677,7 +6681,7 @@ GCRuntime::runDebugGC() * ensure that we get multiple slices, and collection runs to * completion. */ - if (initialState == NO_INCREMENTAL) + if (!isIncrementalGCInProgress()) incrementalLimit = zealFrequency / 2; else incrementalLimit *= 2; diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index b55ec690ef89..ddaca9a725db 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -2902,10 +2902,10 @@ ElementRestyler::ComputeRestyleResultFromNewContext(nsIFrame* aSelf, return eRestyleResult_Continue; } - if (oldContext->IsDirectlyInsideRuby() != - aNewContext->IsDirectlyInsideRuby()) { - LOG_RESTYLE_CONTINUE("NS_STYLE_IS_DIRECTLY_INSIDE_RUBY differes between old" - " and new style contexts"); + if (oldContext->IsInlineDescendantOfRuby() != + aNewContext->IsInlineDescendantOfRuby()) { + LOG_RESTYLE_CONTINUE("NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY differes" + "between old and new style contexts"); return eRestyleResult_Continue; } diff --git a/layout/base/crashtests/1116104.html b/layout/base/crashtests/1116104.html new file mode 100644 index 000000000000..3f3f0169af15 --- /dev/null +++ b/layout/base/crashtests/1116104.html @@ -0,0 +1,15 @@ + + + + + + + + + + +t +
+ + + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 577cc9aaca33..72541c868594 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -454,4 +454,5 @@ load 973390-1.html load 1001237.html load 1043163-1.html load 1061028.html +load 1116104.html load 1107508-1.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 66f8a4bf8d7c..7c6aefbb9529 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -6070,8 +6070,11 @@ AdjustAppendParentForAfterContent(nsFrameManager* aFrameManager, if (child && child->IsPseudoFrame(aContainer) && !child->IsGeneratedContentFrame()) { // Drill down into non-generated pseudo frames of aContainer. - parent = nsLayoutUtils::LastContinuationWithChild(do_QueryFrame(child)); - continue; + nsContainerFrame* childAsContainer = do_QueryFrame(child); + if (childAsContainer) { + parent = nsLayoutUtils::LastContinuationWithChild(childAsContainer); + continue; + } } for (; child; child = child->GetPrevSibling()) { diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 46e02da2242f..16bf27a3e426 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -721,7 +721,7 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, metrics.GetDisplayPort()); } if (nsLayoutUtils::GetCriticalDisplayPort(content, &dp)) { - metrics.mCriticalDisplayPort = CSSRect::FromAppUnits(dp); + metrics.SetCriticalDisplayPort(CSSRect::FromAppUnits(dp)); } DisplayPortMarginsPropertyData* marginsData = static_cast(content->GetProperty(nsGkAtoms::DisplayPortMargins)); diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp index 9fafc94cc08e..8d519f288443 100644 --- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -97,7 +97,7 @@ BRFrame::Reflow(nsPresContext* aPresContext, // Only when the BR is operating in a line-layout situation will it // behave like a BR. BR is suppressed when it is inside ruby frames. nsLineLayout* ll = aReflowState.mLineLayout; - if (ll && !StyleContext()->IsDirectlyInsideRuby()) { + if (ll && !StyleContext()->IsInlineDescendantOfRuby()) { // Note that the compatibility mode check excludes AlmostStandards // mode, since this is the inline box model. See bug 161691. if ( ll->LineIsEmpty() || diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index 487b8194c238..890a873afeac 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -442,7 +442,7 @@ nsLineLayout::BeginSpan(nsIFrame* aFrame, nsIFrame* frame = aSpanReflowState->frame; psd->mNoWrap = !frame->StyleText()->WhiteSpaceCanWrap(frame) || - frame->StyleContext()->IsDirectlyInsideRuby(); + frame->StyleContext()->IsInlineDescendantOfRuby(); psd->mWritingMode = aSpanReflowState->GetWritingMode(); // Switch to new span @@ -2854,13 +2854,13 @@ nsLineLayout::TextAlignLine(nsLineBox* aLine, ComputeFrameJustification(psd, computeState); if (mHasRuby && computeState.mFirstParticipant) { PerFrameData* firstFrame = computeState.mFirstParticipant; - if (firstFrame->mFrame->StyleContext()->IsDirectlyInsideRuby()) { + if (firstFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) { MOZ_ASSERT(!firstFrame->mJustificationAssignment.mGapsAtStart); firstFrame->mJustificationAssignment.mGapsAtStart = 1; additionalGaps++; } PerFrameData* lastFrame = computeState.mLastParticipant; - if (lastFrame->mFrame->StyleContext()->IsDirectlyInsideRuby()) { + if (lastFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) { MOZ_ASSERT(!lastFrame->mJustificationAssignment.mGapsAtEnd); lastFrame->mJustificationAssignment.mGapsAtEnd = 1; additionalGaps++; diff --git a/layout/generic/nsRubyBaseContainerFrame.cpp b/layout/generic/nsRubyBaseContainerFrame.cpp index c1fb2ddc51e1..f584e6dd16e1 100644 --- a/layout/generic/nsRubyBaseContainerFrame.cpp +++ b/layout/generic/nsRubyBaseContainerFrame.cpp @@ -344,7 +344,7 @@ nsRubyBaseContainerFrame::Reflow(nsPresContext* aPresContext, startEdge, endEdge, &mBaseline); nsIFrame* parent = GetParent(); - bool inNestedRuby = parent->StyleContext()->IsDirectlyInsideRuby(); + bool inNestedRuby = parent->StyleContext()->IsInlineDescendantOfRuby(); // Allow line break between ruby bases when white-space allows, // we are not inside a nested ruby, and there is no span. bool allowLineBreak = !inNestedRuby && StyleText()->WhiteSpaceCanWrap(this); diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index b0009d789cea..01ecc28b2f1b 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1896,7 +1896,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) textFlags |= GetSpacingFlags(WordSpacing(f)); nsTextFrameUtils::CompressionMode compression = CSSWhitespaceToCompressionMode[textStyle->mWhiteSpace]; - if ((enabledJustification || f->StyleContext()->IsDirectlyInsideRuby()) && + if ((enabledJustification || f->StyleContext()->IsInlineDescendantOfRuby()) && !textStyle->WhiteSpaceIsSignificant() && !isSVG) { textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING; } @@ -2761,7 +2761,7 @@ static int32_t FindChar(const nsTextFragment* frag, static bool IsChineseOrJapanese(nsIFrame* aFrame) { - if (aFrame->StyleContext()->IsDirectlyInsideRuby()) { + if (aFrame->StyleContext()->IsInlineDescendantOfRuby()) { // Always treat ruby as CJ language so that those characters can // be expanded properly even when surrounded by other language. return true; @@ -8241,7 +8241,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, gfxBreakPriority breakPriority; aLineLayout.GetLastOptionalBreakPosition(&unusedOffset, &breakPriority); gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak; - if (StyleContext()->IsDirectlyInsideRuby()) { + if (StyleContext()->IsInlineDescendantOfRuby()) { suppressBreak = gfxTextRun::eSuppressAllBreaks; } else if (!aLineLayout.LineIsBreakable()) { suppressBreak = gfxTextRun::eSuppressInitialBreak; @@ -8510,7 +8510,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, if (!textStyle->WhiteSpaceIsSignificant() && (lineContainer->StyleText()->mTextAlign == NS_STYLE_TEXT_ALIGN_JUSTIFY || lineContainer->StyleText()->mTextAlignLast == NS_STYLE_TEXT_ALIGN_JUSTIFY || - StyleContext()->IsDirectlyInsideRuby()) && + StyleContext()->IsInlineDescendantOfRuby()) && !lineContainer->IsSVGText()) { AddStateBits(TEXT_JUSTIFICATION_ENABLED); provider.ComputeJustification(offset, charsFit); diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 9990af2d3873..99b56c2b28f4 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -563,9 +563,9 @@ nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) // The display change should only occur for "in-flow" children if (!disp->IsOutOfFlowStyle() && ((containerDisp->mDisplay == NS_STYLE_DISPLAY_INLINE && - containerContext->IsDirectlyInsideRuby()) || + containerContext->IsInlineDescendantOfRuby()) || containerDisp->IsRubyDisplayType())) { - mBits |= NS_STYLE_IS_DIRECTLY_INSIDE_RUBY; + mBits |= NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY; uint8_t displayVal = disp->mDisplay; nsRuleNode::EnsureInlineDisplay(displayVal); if (displayVal != disp->mDisplay) { diff --git a/layout/style/nsStyleContext.h b/layout/style/nsStyleContext.h index 2c2081e05dd0..91945e93dcd6 100644 --- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -133,8 +133,8 @@ public: // Whether this style context or any of its inline-level ancestors // is directly contained by a ruby box? It is used to inlinize // block-level descendants and suppress line breaks inside ruby. - bool IsDirectlyInsideRuby() const - { return !!(mBits & NS_STYLE_IS_DIRECTLY_INSIDE_RUBY); } + bool IsInlineDescendantOfRuby() const + { return !!(mBits & NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY); } // Does this style context represent the style for a pseudo-element or // inherit data from such a style context? Whether this returns true diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 456bbe12f68f..f451c3be7810 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -56,8 +56,8 @@ class imgIContainer; // See nsStyleContext::AssertStructsNotUsedElsewhere // (This bit is currently only used in #ifdef DEBUG code.) #define NS_STYLE_IS_GOING_AWAY 0x040000000 -// See nsStyleContext::IsDirectlyInsideRuby -#define NS_STYLE_IS_DIRECTLY_INSIDE_RUBY 0x080000000 +// See nsStyleContext::IsInlineDescendantOfRuby +#define NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY 0x080000000 // See nsStyleContext::GetPseudoEnum #define NS_STYLE_CONTEXT_TYPE_SHIFT 32 diff --git a/mobile/android/base/tests/components/ToolbarComponent.java b/mobile/android/base/tests/components/ToolbarComponent.java index e92e145292ca..3b795b606ad9 100644 --- a/mobile/android/base/tests/components/ToolbarComponent.java +++ b/mobile/android/base/tests/components/ToolbarComponent.java @@ -83,6 +83,7 @@ public class ToolbarComponent extends BaseComponent { * Returns the root View for the browser toolbar. */ private View getToolbarView() { + mSolo.waitForView(R.id.browser_toolbar); return mSolo.getView(R.id.browser_toolbar); } diff --git a/mobile/android/base/tests/helpers/WaitHelper.java b/mobile/android/base/tests/helpers/WaitHelper.java index e74be0450470..32eee8ed37ce 100644 --- a/mobile/android/base/tests/helpers/WaitHelper.java +++ b/mobile/android/base/tests/helpers/WaitHelper.java @@ -25,7 +25,9 @@ import com.jayway.android.robotium.solo.Solo; public final class WaitHelper { // TODO: Make public for when Solo.waitForCondition is used directly (i.e. do not want // assertion from waitFor)? - private static final int DEFAULT_MAX_WAIT_MS = 5000; + // DEFAULT_MAX_WAIT_MS of 5000 was intermittently insufficient during + // initialization on Android 2.3 emulator -- bug 1114655 + private static final int DEFAULT_MAX_WAIT_MS = 15000; private static final int PAGE_LOAD_WAIT_MS = 10000; private static final int CHANGE_WAIT_MS = 15000; diff --git a/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini b/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini index 85f1f83353d6..527f68c3a455 100644 --- a/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-sourcebuffer-mode.html.ini @@ -2,4 +2,6 @@ type: testharness [Test setting SourceBuffer.mode and SourceBuffer.timestampOffset while parsing media segment.] expected: FAIL + [Test setting SourceBuffer.mode] + expected: FAIL # Not supported yet - see bug 1116353 diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp index fd47c602400c..de5d88e437f7 100644 --- a/toolkit/components/telemetry/Telemetry.cpp +++ b/toolkit/components/telemetry/Telemetry.cpp @@ -234,26 +234,37 @@ public: */ struct AnnotationInfo { AnnotationInfo(uint32_t aHangIndex, - HangAnnotations* aAnnotations) + UniquePtr aAnnotations) : mHangIndex(aHangIndex) - , mAnnotations(aAnnotations) + , mAnnotations(Move(aAnnotations)) {} - AnnotationInfo(const AnnotationInfo& aOther) + AnnotationInfo(AnnotationInfo&& aOther) : mHangIndex(aOther.mHangIndex) - , mAnnotations(aOther.mAnnotations) + , mAnnotations(Move(aOther.mAnnotations)) {} ~AnnotationInfo() {} + AnnotationInfo& operator=(AnnotationInfo&& aOther) + { + mHangIndex = aOther.mHangIndex; + mAnnotations = Move(aOther.mAnnotations); + return *this; + } uint32_t mHangIndex; - mutable nsAutoPtr mAnnotations; + UniquePtr mAnnotations; + + private: + // Force move constructor + AnnotationInfo(const AnnotationInfo& aOther) MOZ_DELETE; + void operator=(const AnnotationInfo& aOther) MOZ_DELETE; }; size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; void AddHang(const Telemetry::ProcessedStack& aStack, uint32_t aDuration, int32_t aSystemUptime, int32_t aFirefoxUptime, - HangAnnotations* aAnnotations); + UniquePtr aAnnotations); uint32_t GetDuration(unsigned aIndex) const; int32_t GetSystemUptime(unsigned aIndex) const; int32_t GetFirefoxUptime(unsigned aIndex) const; - const std::vector& GetAnnotationInfo() const; + const nsTArray& GetAnnotationInfo() const; const CombinedStacks& GetStacks() const; private: /** @@ -269,7 +280,7 @@ private: int32_t mFirefoxUptime; }; std::vector mHangInfo; - std::vector mAnnotationInfo; + nsTArray mAnnotationInfo; CombinedStacks mStacks; }; @@ -278,13 +289,13 @@ HangReports::AddHang(const Telemetry::ProcessedStack& aStack, uint32_t aDuration, int32_t aSystemUptime, int32_t aFirefoxUptime, - HangAnnotations* aAnnotations) { + UniquePtr aAnnotations) { HangInfo info = { aDuration, aSystemUptime, aFirefoxUptime }; mHangInfo.push_back(info); if (aAnnotations) { AnnotationInfo ainfo(static_cast(mHangInfo.size() - 1), - aAnnotations); - mAnnotationInfo.push_back(ainfo); + Move(aAnnotations)); + mAnnotationInfo.AppendElement(Move(ainfo)); } mStacks.AddStack(aStack); } @@ -296,10 +307,9 @@ HangReports::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { // This is a crude approximation. See comment on // CombinedStacks::SizeOfExcludingThis. n += mHangInfo.capacity() * sizeof(HangInfo); - n += mAnnotationInfo.capacity() * sizeof(AnnotationInfo); - for (std::vector::const_iterator i = mAnnotationInfo.begin(), - e = mAnnotationInfo.end(); i != e; ++i) { - n += i->mAnnotations->SizeOfIncludingThis(aMallocSizeOf); + n += mAnnotationInfo.Capacity() * sizeof(AnnotationInfo); + for (int32_t i = 0, l = mAnnotationInfo.Length(); i < l; ++i) { + n += mAnnotationInfo[i].mAnnotations->SizeOfIncludingThis(aMallocSizeOf); } return n; } @@ -324,7 +334,7 @@ HangReports::GetFirefoxUptime(unsigned aIndex) const { return mHangInfo[aIndex].mFirefoxUptime; } -const std::vector& +const nsTArray& HangReports::GetAnnotationInfo() const { return mAnnotationInfo; } @@ -816,7 +826,7 @@ public: Telemetry::ProcessedStack &aStack, int32_t aSystemUptime, int32_t aFirefoxUptime, - HangAnnotations* aAnnotations); + UniquePtr aAnnotations); #endif static void RecordThreadHangStats(Telemetry::ThreadHangStats& aStats); static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id); @@ -2405,18 +2415,16 @@ TelemetryImpl::GetChromeHangs(JSContext *cx, JS::MutableHandle ret) if (!JS_SetElement(cx, firefoxUptimeArray, i, mHangReports.GetFirefoxUptime(i))) { return NS_ERROR_FAILURE; } - const std::vector& annotationInfo = + const nsTArray& annotationInfo = mHangReports.GetAnnotationInfo(); - uint32_t annotationsArrayIndex = 0; - for (std::vector::const_iterator - ai = annotationInfo.begin(), e = annotationInfo.end(); ai != e; - ++ai, ++annotationsArrayIndex) { + for (uint32_t iterIndex = 0, arrayLen = annotationInfo.Length(); + iterIndex < arrayLen; ++iterIndex) { JS::Rooted keyValueArray(cx, JS_NewArrayObject(cx, 0)); if (!keyValueArray) { return NS_ERROR_FAILURE; } JS::RootedValue indexValue(cx); - indexValue.setNumber(ai->mHangIndex); + indexValue.setNumber(annotationInfo[iterIndex].mHangIndex); if (!JS_SetElement(cx, keyValueArray, 0, indexValue)) { return NS_ERROR_FAILURE; } @@ -2427,7 +2435,8 @@ TelemetryImpl::GetChromeHangs(JSContext *cx, JS::MutableHandle ret) return NS_ERROR_FAILURE; } nsAutoPtr annotationsEnum; - if (!ai->mAnnotations->GetEnumerator(annotationsEnum.StartAssignment())) { + if (!annotationInfo[iterIndex].mAnnotations->GetEnumerator( + annotationsEnum.StartAssignment())) { return NS_ERROR_FAILURE; } nsAutoString key; @@ -2443,7 +2452,7 @@ TelemetryImpl::GetChromeHangs(JSContext *cx, JS::MutableHandle ret) if (!JS_SetElement(cx, keyValueArray, 1, jsAnnotation)) { return NS_ERROR_FAILURE; } - if (!JS_SetElement(cx, annotationsArray, annotationsArrayIndex, + if (!JS_SetElement(cx, annotationsArray, iterIndex, keyValueArray)) { return NS_ERROR_FAILURE; } @@ -3200,7 +3209,7 @@ TelemetryImpl::RecordChromeHang(uint32_t aDuration, Telemetry::ProcessedStack &aStack, int32_t aSystemUptime, int32_t aFirefoxUptime, - HangAnnotations* aAnnotations) + UniquePtr aAnnotations) { if (!sTelemetry || !sTelemetry->mCanRecord) return; @@ -3209,7 +3218,7 @@ TelemetryImpl::RecordChromeHang(uint32_t aDuration, sTelemetry->mHangReports.AddHang(aStack, aDuration, aSystemUptime, aFirefoxUptime, - aAnnotations); + Move(aAnnotations)); } #endif @@ -3473,10 +3482,11 @@ void RecordChromeHang(uint32_t duration, ProcessedStack &aStack, int32_t aSystemUptime, int32_t aFirefoxUptime, - HangAnnotations* aAnnotations) + UniquePtr aAnnotations) { TelemetryImpl::RecordChromeHang(duration, aStack, - aSystemUptime, aFirefoxUptime, aAnnotations); + aSystemUptime, aFirefoxUptime, + Move(aAnnotations)); } #endif diff --git a/toolkit/components/telemetry/Telemetry.h b/toolkit/components/telemetry/Telemetry.h index ae30fd7d5537..f572ef0e61ed 100644 --- a/toolkit/components/telemetry/Telemetry.h +++ b/toolkit/components/telemetry/Telemetry.h @@ -238,7 +238,8 @@ void RecordChromeHang(uint32_t aDuration, ProcessedStack &aStack, int32_t aSystemUptime, int32_t aFirefoxUptime, - mozilla::HangMonitor::HangAnnotations* aAnnotations = nullptr); + mozilla::UniquePtr + aAnnotations); #endif class ThreadHangStats; diff --git a/widget/gonk/HwcComposer2D.cpp b/widget/gonk/HwcComposer2D.cpp index 2474de48e853..bc161f649c9b 100644 --- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -426,13 +426,16 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer, return false; } + const bool needsYFlip = state.OriginBottomLeft() ? true + : false; + hwc_rect_t sourceCrop, displayFrame; if(!HwcUtils::PrepareLayerRects(visibleRect, layerTransform, layerBufferTransform, clip, bufferRect, - state.YFlipped(), + needsYFlip, &(sourceCrop), &(displayFrame))) { @@ -609,7 +612,10 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer, } } - if (state.YFlipped()) { + const bool needsYFlip = state.OriginBottomLeft() ? true + : false; + + if (needsYFlip) { // Invert vertical reflection flag if it was already set hwcLayer.transform ^= HWC_TRANSFORM_FLIP_V; } diff --git a/xpcom/threads/HangMonitor.cpp b/xpcom/threads/HangMonitor.cpp index 58805c567559..a2e3d7b4f81d 100644 --- a/xpcom/threads/HangMonitor.cpp +++ b/xpcom/threads/HangMonitor.cpp @@ -8,14 +8,14 @@ #include +#include "mozilla/Atomics.h" #include "mozilla/BackgroundHangMonitor.h" #include "mozilla/Monitor.h" #include "mozilla/Preferences.h" -#include "mozilla/Telemetry.h" #include "mozilla/ProcessedStack.h" -#include "mozilla/Atomics.h" +#include "mozilla/Telemetry.h" #include "mozilla/StaticPtr.h" -#include "nsAutoPtr.h" +#include "mozilla/UniquePtr.h" #include "nsReadableUtils.h" #include "nsStackWalk.h" #include "nsThreadUtils.h" @@ -363,7 +363,7 @@ ThreadMain(void*) Telemetry::ProcessedStack stack; int32_t systemUptime = -1; int32_t firefoxUptime = -1; - nsAutoPtr annotations = new ChromeHangAnnotations(); + auto annotations = MakeUnique(); #endif while (true) { @@ -410,10 +410,9 @@ ThreadMain(void*) if (waitCount >= 2) { uint32_t hangDuration = PR_IntervalToSeconds(now - lastTimestamp); Telemetry::RecordChromeHang(hangDuration, stack, systemUptime, - firefoxUptime, annotations->IsEmpty() ? - nullptr : annotations.forget()); + firefoxUptime, Move(annotations)); stack.Clear(); - annotations = new ChromeHangAnnotations(); + annotations = MakeUnique(); } #endif lastTimestamp = timestamp;