merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-12-22 11:47:07 +01:00
Родитель 069e2428a4 2fdd9a1152
Коммит d0f1701bc8
220 изменённых файлов: 2236 добавлений и 3267 удалений

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

@ -4752,7 +4752,7 @@ var CombinedStopReload = {
var TabsProgressListener = {
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
// Collect telemetry data about tab load times.
if (aWebProgress.isTopLevel) {
if (aWebProgress.isTopLevel && (!aRequest.originalURI || aRequest.originalURI.spec.scheme != "about")) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
TelemetryStopwatch.start("FX_PAGE_LOAD_MS", aBrowser);

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

@ -5,10 +5,10 @@ support-files =
[browser_displayURI.js]
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification.js]
skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_2.js]
skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_3.js]
skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_4.js]
skip-if = (os == "linux" && (debug || asan)) || e10s # e10s - Bug ?????? - popup notification test probably confused re content process notifications etc
skip-if = (os == "linux" && (debug || asan))

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

@ -535,7 +535,7 @@ this.BrowserUITelemetry = {
let paletteItems =
CustomizableUI.getUnusedWidgets(aWindow.gNavToolbox.palette);
let defaultRemoved = [];
for (item of paletteItems) {
for (let item of paletteItems) {
if (DEFAULT_ITEMS.indexOf(item.id) != -1) {
defaultRemoved.push(item.id);
}

6
config/external/moz.build поставляемый
Просмотреть файл

@ -26,13 +26,10 @@ if CONFIG['MOZ_VORBIS']:
if CONFIG['MOZ_TREMOR']:
external_dirs += ['media/libtremor']
if CONFIG['MOZ_WEBM']:
external_dirs += ['media/libnestegg']
if CONFIG['MOZ_WEBM_ENCODER']:
external_dirs += ['media/libmkv']
if CONFIG['MOZ_VPX'] and not CONFIG['MOZ_NATIVE_LIBVPX']:
if not CONFIG['MOZ_NATIVE_LIBVPX']:
external_dirs += ['media/libvpx']
if not CONFIG['MOZ_NATIVE_PNG']:
@ -50,6 +47,7 @@ if CONFIG['MOZ_WEBSPEECH_POCKETSPHINX']:
external_dirs += [
'media/kiss_fft',
'media/libcubeb',
'media/libnestegg',
'media/libogg',
'media/libopus',
'media/libtheora',

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

@ -92,8 +92,8 @@ _PTHREAD_LDFLAGS=""
dnl Do not allow objdir == srcdir builds.
dnl ==============================================================
_topsrcdir=`cd \`dirname $0\`; pwd -W 2>/dev/null || pwd`
_objdir=`pwd`
_topsrcdir=`cd \`dirname $0\`; pwd -W 2>/dev/null || pwd -P`
_objdir=`pwd -P`
dnl TODO Don't exempt L10N builds once bug 842760 is resolved.
if test "$_topsrcdir" = "$_objdir" -a "${with_l10n_base+set}" != set; then
@ -134,7 +134,7 @@ EOF
exit 1
break
fi
MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd`
MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P`
DIST="$MOZ_BUILD_ROOT/dist"
MOZ_PYTHON
@ -157,7 +157,7 @@ if test -n "$L10NBASEDIR"; then
if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
AC_MSG_ERROR([--with-l10n-base must specify a path])
elif test -d "$L10NBASEDIR"; then
L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
L10NBASEDIR=`cd "$L10NBASEDIR" && pwd -P`
else
AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
fi
@ -3692,10 +3692,8 @@ fi
MOZ_RAW=
MOZ_VORBIS=
MOZ_TREMOR=
MOZ_WAVE=1
MOZ_SAMPLE_TYPE_FLOAT32=
MOZ_SAMPLE_TYPE_S16=
MOZ_WEBM=1
MOZ_GSTREAMER=
MOZ_DIRECTSHOW=
MOZ_WMF=
@ -3715,7 +3713,6 @@ MOZ_SCTP=
MOZ_ANDROID_OMX=
MOZ_MEDIA_NAVIGATOR=
MOZ_OMX_PLUGIN=
MOZ_VPX=
MOZ_VPX_ERROR_CONCEALMENT=
MOZ_WEBSPEECH=1
MOZ_WEBSPEECH_MODELS=
@ -4998,7 +4995,6 @@ if test -n "$MOZ_WEBRTC"; then
dnl opt/production builds (via MOZ_CRASH())
AC_DEFINE(MOZ_WEBRTC_ASSERT_ALWAYS)
MOZ_RAW=1
MOZ_VPX=1
MOZ_VPX_ERROR_CONCEALMENT=1
dnl enable once Signaling lands
@ -5143,19 +5139,6 @@ if test "${ac_cv_c_attribute_aligned}" != "0"; then
[${ac_cv_c_attribute_aligned}],[Maximum supported data alignment])
fi
dnl ========================================================
dnl = Disable VP8 decoder support
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(webm,
[ --disable-webm Disable support for WebM media (VP8 video and Vorbis audio)],
MOZ_WEBM=,
MOZ_WEBM=1)
if test -n "$MOZ_WEBM"; then
AC_DEFINE(MOZ_WEBM)
MOZ_VPX=1
fi;
dnl ========================================================
dnl = Apple platform decoder support
dnl ========================================================
@ -5361,54 +5344,49 @@ MOZ_ARG_WITH_BOOL(system-libvpx,
MOZ_LIBVPX_CFLAGS=
MOZ_LIBVPX_LIBS=
if test -n "$MOZ_VPX"; then
AC_DEFINE(MOZ_VPX)
if test -n "$MOZ_VPX_ERROR_CONCEALMENT" ; then
AC_DEFINE(MOZ_VPX_ERROR_CONCEALMENT)
fi
_SAVE_CFLAGS=$CFLAGS
_SAVE_LIBS=$LIBS
if test -n "$MOZ_NATIVE_LIBVPX"; then
dnl ============================
dnl === libvpx Version check ===
dnl ============================
dnl Check to see if we have a system libvpx package.
PKG_CHECK_MODULES(MOZ_LIBVPX, vpx >= 1.3.0)
CFLAGS="$CFLAGS $MOZ_LIBVPX_CFLAGS"
LIBS="$LIBS $MOZ_LIBVPX_LIBS"
MOZ_CHECK_HEADER([vpx/vpx_decoder.h], [],
[AC_MSG_ERROR([Couldn't find vpx/vpx_decoder.h which is required for build with system libvpx. Use --without-system-libvpx to build with in-tree libvpx.])])
AC_CHECK_LIB(vpx, vpx_codec_dec_init_ver, [],
[AC_MSG_ERROR([--with-system-libvpx requested but symbol vpx_codec_dec_init_ver not found])])
MOZ_CHECK_HEADER([vpx_mem/vpx_mem.h],
[AC_CHECK_FUNC(vpx_mem_set_functions)])
if test "$ac_cv_header_vpx_mem_vpx_mem_h" = no -o \
"$ac_cv_func_vpx_mem_set_functions" = no; then
AC_DEFINE(MOZ_VPX_NO_MEM_REPORTING)
fi
fi
CFLAGS=$_SAVE_CFLAGS
LIBS=$_SAVE_LIBS
if test -n "$MOZ_VPX_ERROR_CONCEALMENT" ; then
AC_DEFINE(MOZ_VPX_ERROR_CONCEALMENT)
fi
_SAVE_CFLAGS=$CFLAGS
_SAVE_LIBS=$LIBS
if test -n "$MOZ_NATIVE_LIBVPX"; then
dnl ============================
dnl === libvpx Version check ===
dnl ============================
dnl Check to see if we have a system libvpx package.
PKG_CHECK_MODULES(MOZ_LIBVPX, vpx >= 1.3.0)
CFLAGS="$CFLAGS $MOZ_LIBVPX_CFLAGS"
LIBS="$LIBS $MOZ_LIBVPX_LIBS"
MOZ_CHECK_HEADER([vpx/vpx_decoder.h], [],
[AC_MSG_ERROR([Couldn't find vpx/vpx_decoder.h which is required for build with system libvpx. Use --without-system-libvpx to build with in-tree libvpx.])])
AC_CHECK_LIB(vpx, vpx_codec_dec_init_ver, [],
[AC_MSG_ERROR([--with-system-libvpx requested but symbol vpx_codec_dec_init_ver not found])])
MOZ_CHECK_HEADER([vpx_mem/vpx_mem.h],
[AC_CHECK_FUNC(vpx_mem_set_functions)])
if test "$ac_cv_header_vpx_mem_vpx_mem_h" = no -o \
"$ac_cv_func_vpx_mem_set_functions" = no; then
AC_DEFINE(MOZ_VPX_NO_MEM_REPORTING)
fi
fi
CFLAGS=$_SAVE_CFLAGS
LIBS=$_SAVE_LIBS
AC_SUBST(MOZ_NATIVE_LIBVPX)
AC_SUBST_LIST(MOZ_LIBVPX_CFLAGS)
AC_SUBST_LIST(MOZ_LIBVPX_LIBS)
if test "$MOZ_WEBM"; then
if test "$MOZ_SAMPLE_TYPE_FLOAT32"; then
MOZ_VORBIS=1
else
MOZ_TREMOR=1
fi
if test "$MOZ_SAMPLE_TYPE_FLOAT32"; then
MOZ_VORBIS=1
else
MOZ_TREMOR=1
fi
if test -n "$MOZ_VPX" -a -z "$MOZ_NATIVE_LIBVPX"; then
if test -z "$MOZ_NATIVE_LIBVPX"; then
dnl Detect if we can use an assembler to compile optimized assembly for libvpx.
dnl We currently require yasm on all x86 platforms and require yasm 1.1.0 on Win32.
@ -5510,18 +5488,6 @@ if test -n "$MOZ_VPX" -a -z "$MOZ_NATIVE_LIBVPX"; then
AC_DEFINE(MOZ_VPX_NO_MEM_REPORTING)
fi
dnl ========================================================
dnl = Disable Wave decoder support
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(wave,
[ --disable-wave Disable Wave decoder support],
MOZ_WAVE=,
MOZ_WAVE=1)
if test -n "$MOZ_WAVE"; then
AC_DEFINE(MOZ_WAVE)
fi
dnl ========================================================
dnl = Handle dependent MEDIA defines
dnl ========================================================
@ -8926,10 +8892,8 @@ AC_SUBST(NS_ENABLE_TSF)
AC_SUBST(WIN32_CONSOLE_EXE_LDFLAGS)
AC_SUBST(WIN32_GUI_EXE_LDFLAGS)
AC_SUBST(MOZ_WAVE)
AC_SUBST(MOZ_VORBIS)
AC_SUBST(MOZ_TREMOR)
AC_SUBST(MOZ_WEBM)
AC_SUBST(MOZ_WMF)
AC_SUBST(MOZ_FFMPEG)
AC_SUBST(MOZ_FMP4)
@ -8939,7 +8903,6 @@ AC_SUBST(MOZ_ANDROID_OMX)
AC_SUBST(MOZ_APPLEMEDIA)
AC_SUBST(MOZ_OMX_PLUGIN)
AC_SUBST(MOZ_VPX_ERROR_CONCEALMENT)
AC_SUBST(MOZ_VPX)
AC_SUBST(VPX_AS)
AC_SUBST_LIST(VPX_ASFLAGS)
AC_SUBST(VPX_AS_CONVERSION)

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

@ -12,7 +12,7 @@ const { ActorPool, OriginalLocation, GeneratedLocation } = require("devtools/ser
const { ObjectActor, createValueGrip, longStringGrip } = require("devtools/server/actors/object");
const { DebuggerServer } = require("devtools/server/main");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const { assert, dbg_assert, dumpn, update, fetch } = DevToolsUtils;
const { assert, dumpn, update, fetch } = DevToolsUtils;
const { dirname, joinURI } = require("devtools/shared/path");
const promise = require("promise");
const PromiseDebugging = require("PromiseDebugging");
@ -354,8 +354,6 @@ EventLoop.prototype = {
}
}
dbg_assert(this._thread.state === "running", "Should be in the running state");
if (this._hooks.postNest) {
this._hooks.postNest(nestData);
}

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

@ -183,8 +183,12 @@ exports.executeSoon = function executeSoon(aFn) {
if (isWorker) {
setImmediate(aFn);
} else {
let stack = components.stack;
let executor = () => {
Cu.callFunctionWithAsyncStack(aFn, stack, "DevToolsUtils.executeSoon");
};
Services.tm.mainThread.dispatch({
run: exports.makeInfallible(aFn)
run: exports.makeInfallible(executor)
}, Ci.nsIThread.DISPATCH_NORMAL);
}
};
@ -457,24 +461,6 @@ exports.defineLazyGetter = function defineLazyGetter(aObject, aName, aLambda) {
});
};
// DEPRECATED: use DevToolsUtils.assert(condition, message) instead!
let haveLoggedDeprecationMessage = false;
exports.dbg_assert = function dbg_assert(cond, e) {
if (!haveLoggedDeprecationMessage) {
haveLoggedDeprecationMessage = true;
const deprecationMessage = "DevToolsUtils.dbg_assert is deprecated! Use DevToolsUtils.assert instead!\n"
+ Error().stack;
dump(deprecationMessage);
if (typeof console === "object" && console && console.warn) {
console.warn(deprecationMessage);
}
}
if (!cond) {
return e;
}
};
exports.defineLazyGetter(this, "AppConstants", () => {
if (isWorker) {
return {};

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

@ -0,0 +1,47 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Client request stacks should span the entire process from before making the
* request to handling the reply from the server. The server frames are not
* included, nor can they be in most cases, since the server can be a remote
* device.
*/
var { executeSoon } = require("devtools/shared/DevToolsUtils");
var promise = require("promise");
var Services = require("Services");
var asyncStackEnabled =
Services.prefs.getBoolPref("javascript.options.asyncstack");
do_register_cleanup(() => {
Services.prefs.setBoolPref("javascript.options.asyncstack",
asyncStackEnabled);
});
add_task(function*() {
Services.prefs.setBoolPref("javascript.options.asyncstack", true);
yield waitForTick();
let stack = Components.stack;
while (stack) {
do_print(stack.name);
if (stack.name == "waitForTick") {
// Reached back to outer function before executeSoon
ok(true, "Complete stack");
return;
}
stack = stack.asyncCaller || stack.caller;
}
ok(false, "Incomplete stack");
});
function waitForTick() {
let deferred = promise.defer();
executeSoon(deferred.resolve);
return deferred.promise;
}

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

@ -24,3 +24,4 @@ support-files =
[test_require_lazy.js]
[test_require.js]
[test_stack.js]
[test_executeSoon.js]

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

@ -110,6 +110,8 @@ void
DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime)
{
MOZ_ASSERT(mIsObservingRefreshDriver);
MOZ_ASSERT(GetRefreshDriver(),
"Should be able to reach refresh driver from within WillRefresh");
bool needsTicks = false;
nsTArray<Animation*> animationsToRemove(mAnimations.Count());
@ -143,10 +145,13 @@ DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime)
}
if (!needsTicks) {
// If another refresh driver observer destroys the nsPresContext,
// nsRefreshDriver will detect it and we won't be called.
// We already assert that GetRefreshDriver() is non-null at the beginning
// of this function but we check it again here to be sure that ticking
// animations does not have any side effects that cause us to lose the
// connection with the refresh driver, such as triggering the destruction
// of mDocument's PresShell.
MOZ_ASSERT(GetRefreshDriver(),
"Refresh driver should still be valid inside WillRefresh");
"Refresh driver should still be valid at end of WillRefresh");
GetRefreshDriver()->RemoveRefreshObserver(this, Flush_Style);
mIsObservingRefreshDriver = false;
}

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

@ -96,7 +96,6 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly(
, mPseudoType(aPseudoType)
{
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
ResetIsRunningOnCompositor();
}
JSObject*
@ -466,19 +465,6 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
}
}
bool
KeyframeEffectReadOnly::IsPropertyRunningOnCompositor(
nsCSSProperty aProperty) const
{
const auto& info = LayerAnimationInfo::sRecords;
for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) {
if (info[i].mProperty == aProperty) {
return mIsPropertyRunningOnCompositor[i];
}
}
return false;
}
bool
KeyframeEffectReadOnly::IsRunningOnCompositor() const
{
@ -486,8 +472,8 @@ KeyframeEffectReadOnly::IsRunningOnCompositor() const
// one property running on compositor.
// Animation.IsRunningOnCompotitor will return more fine grained
// information in bug 1196114.
for (bool isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) {
if (isPropertyRunningOnCompositor) {
for (const AnimationProperty& property : mProperties) {
if (property.mIsRunningOnCompositor) {
return true;
}
}
@ -498,19 +484,13 @@ void
KeyframeEffectReadOnly::SetIsRunningOnCompositor(nsCSSProperty aProperty,
bool aIsRunning)
{
static_assert(
MOZ_ARRAY_LENGTH(LayerAnimationInfo::sRecords) ==
MOZ_ARRAY_LENGTH(mIsPropertyRunningOnCompositor),
"The length of mIsPropertyRunningOnCompositor should equal to"
"the length of LayserAnimationInfo::sRecords");
MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty,
CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR),
"Property being animated on compositor is a recognized "
"compositor-animatable property");
const auto& info = LayerAnimationInfo::sRecords;
for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) {
if (info[i].mProperty == aProperty) {
mIsPropertyRunningOnCompositor[i] = aIsRunning;
for (AnimationProperty& property : mProperties) {
if (property.mProperty == aProperty) {
property.mIsRunningOnCompositor = aIsRunning;
return;
}
}
@ -523,8 +503,8 @@ KeyframeEffectReadOnly::~KeyframeEffectReadOnly()
void
KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
{
for (bool& isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) {
isPropertyRunningOnCompositor = false;
for (AnimationProperty& property : mProperties) {
property.mIsRunningOnCompositor = false;
}
}
@ -556,9 +536,7 @@ KeyframeEffectReadOnly::UpdateTargetRegistration()
// Any effects not in the effect set will not be included in the set of
// candidate effects for running on the compositor and hence they won't
// have their compositor status updated so we should do that now.
for (bool& isRunningOnCompositor : mIsPropertyRunningOnCompositor) {
isRunningOnCompositor = false;
}
ResetIsRunningOnCompositor();
}
}
@ -1822,7 +1800,7 @@ KeyframeEffectReadOnly::CanThrottle() const
}
// First we need to check layer generation and transform overflow
// prior to the IsPropertyRunningOnCompositor check because we should
// prior to the property.mIsRunningOnCompositor check because we should
// occasionally unthrottle these animations even if the animations are
// already running on compositor.
for (const LayerAnimationInfo::Record& record :
@ -1854,7 +1832,7 @@ KeyframeEffectReadOnly::CanThrottle() const
}
for (const AnimationProperty& property : mProperties) {
if (!IsPropertyRunningOnCompositor(property.mProperty)) {
if (!property.mIsRunningOnCompositor) {
return false;
}
}

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

@ -118,7 +118,7 @@ struct AnimationPropertySegment
struct AnimationProperty
{
nsCSSProperty mProperty;
nsCSSProperty mProperty = eCSSProperty_UNKNOWN;
// Does this property win in the CSS Cascade?
//
@ -136,16 +136,26 @@ struct AnimationProperty
// For other properties, we make it always be true.
// **NOTE 2**: This member is not included when comparing AnimationProperty
// objects for equality.
bool mWinsInCascade;
bool mWinsInCascade = true;
// If true, the propery is currently being animated on the compositor.
//
// Note that when the owning Animation requests a non-throttled restyle, in
// between calling RequestRestyle on its AnimationCollection and when the
// restyle is performed, this member may temporarily become false even if
// the animation remains on the layer after the restyle.
bool mIsRunningOnCompositor = false;
InfallibleTArray<AnimationPropertySegment> mSegments;
// NOTE: This operator does *not* compare the mWinsInCascade member.
// NOTE: This operator does *not* compare the mWinsInCascade member *or* the
// mIsRunningOnCompositor member.
// This is because AnimationProperty objects are compared when recreating
// CSS animations to determine if mutation observer change records need to
// be created or not. However, at the point when these objects are compared
// the mWinsInCascade will not have been set on the new objects so we ignore
// this member to avoid generating spurious change records.
// neither the mWinsInCascade nor the mIsRunningOnCompositor will have been
// set on the new objects so we ignore these members to avoid generating
// spurious change records.
bool operator==(const AnimationProperty& aOther) const {
return mProperty == aOther.mProperty &&
mSegments == aOther.mSegments;
@ -279,8 +289,6 @@ public:
// Any updated properties are added to |aSetProperties|.
void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
nsCSSPropertySet& aSetProperties);
// Returns true if |aProperty| is currently being animated on compositor.
bool IsPropertyRunningOnCompositor(nsCSSProperty aProperty) const;
// Returns true if at least one property is being animated on compositor.
bool IsRunningOnCompositor() const;
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
@ -341,17 +349,6 @@ protected:
InfallibleTArray<AnimationProperty> mProperties;
// Parallel array corresponding to CommonAnimationManager::sLayerAnimationInfo
// such that mIsPropertyRunningOnCompositor[x] is true only if this effect has
// an animation of CommonAnimationManager::sLayerAnimationInfo[x].mProperty
// that is currently running on the compositor.
//
// Note that when the owning Animation requests a non-throttled restyle, in
// between calling RequestRestyle on its AnimationCollection and when the
// restyle is performed, this member may temporarily become false even if
// the animation remains on the layer after the restyle.
bool mIsPropertyRunningOnCompositor[LayerAnimationInfo::kRecords];
private:
nsIFrame* GetAnimationFrame() const;

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

@ -207,6 +207,9 @@ promise_test(function(t) {
resolve();
}));
observer.observe(div, { animations: true, subtree: false });
t.add_cleanup(function() {
observer.disconnect();
});
div.style.animationDuration = "200s";
}));
}));

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

@ -2117,7 +2117,15 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
// Note that, since mTiming does not change during a reset, the
// navigationStart time remains unchanged and therefore any future new
// timeline will have the same global clock time as the old one.
mDocumentTimeline = nullptr;
if (mDocumentTimeline) {
nsRefreshDriver* rd = mPresShell && mPresShell->GetPresContext() ?
mPresShell->GetPresContext()->RefreshDriver() :
nullptr;
if (rd) {
mDocumentTimeline->NotifyRefreshDriverDestroying(rd);
}
mDocumentTimeline = nullptr;
}
nsCOMPtr<nsIPropertyBag2> bag = do_QueryInterface(aChannel);
if (bag) {

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

@ -64,6 +64,7 @@ skip-if = debug == false
[test_worker_UnwrapArg.html]
[test_unforgeablesonexpando.html]
[test_crossOriginWindowSymbolAccess.html]
[test_primitive_this.html]
[test_callback_exceptions.html]
[test_bug1123516_maplikesetlike.html]
skip-if = debug == false

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

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=603201
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 603201</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 603201 **/
SimpleTest.waitForExplicitFinish();
function runTest()
{
var nodes = document.body.childNodes;
Object.setPrototypeOf(Number.prototype, nodes);
Object.defineProperty(nodes, "getter", {get: function() {
"use strict";
is(this, 1);
return "getter";
}});
Object.defineProperty(Object.getPrototypeOf(nodes), "getter2", {get: function() {
"use strict";
is(this, 1);
return "getter2";
}});
var number = 1;
is(number.getter, "getter");
is(number.getter2, "getter2");
SimpleTest.finish();
}
</script>
</head>
<body onload="runTest();">
<pre>Test</pre>
</body>
</html>

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

@ -25,11 +25,8 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Audio)
namespace mozilla {
namespace dom {
extern bool IsAudioAPIEnabled();
NS_IMPL_ELEMENT_CLONE(HTMLAudioElement)
HTMLAudioElement::HTMLAudioElement(already_AddRefed<NodeInfo>& aNodeInfo)
: HTMLMediaElement(aNodeInfo)
{
@ -79,13 +76,9 @@ HTMLAudioElement::Audio(const GlobalObject& aGlobal,
nsresult HTMLAudioElement::SetAcceptHeader(nsIHttpChannel* aChannel)
{
nsAutoCString value(
#ifdef MOZ_WEBM
"audio/webm,"
#endif
"audio/ogg,"
#ifdef MOZ_WAVE
"audio/wav,"
#endif
"audio/*;q=0.9,"
"application/ogg;q=0.7,"
"video/*;q=0.6,*/*;q=0.5");

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

@ -936,6 +936,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLInputElement,
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFilesAndDirectoriesPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLInputElement,
@ -944,6 +945,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLInputElement,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFileList)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilesAndDirectoriesPromise)
if (tmp->IsSingleLineTextControl(false)) {
tmp->mInputData.mState->Unlink();
}

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

@ -113,9 +113,7 @@ HTMLVideoElement::GetAttributeMappingFunction() const
nsresult HTMLVideoElement::SetAcceptHeader(nsIHttpChannel* aChannel)
{
nsAutoCString value(
#ifdef MOZ_WEBM
"video/webm,"
#endif
"video/ogg,"
"video/*;q=0.9,"
"application/ogg;q=0.7,"

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

@ -458,8 +458,31 @@ static void LogChannelRelevantInfo(nsIURI* aURI,
LOG("Result principal origin: %s\n", resultPrincipalOrigin.get());
}
// This is similar to nsIScriptSecurityManager.getChannelResultPrincipal
// but taking signedPkg into account. The reason we can't rely on channel
// loadContext/loadInfo is it's dangerous to mutate them on parent process.
static already_AddRefed<nsIPrincipal>
GetChannelPrincipalWithSingedPkg(nsIChannel* aChannel, const nsACString& aSignedPkg)
{
NeckoOriginAttributes neckoAttrs;
NS_GetOriginAttributes(aChannel, neckoAttrs);
PrincipalOriginAttributes attrs;
attrs.InheritFromNecko(neckoAttrs);
attrs.mSignedPkg = NS_ConvertUTF8toUTF16(aSignedPkg);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, nullptr);
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateCodebasePrincipal(uri, attrs);
return principal.forget();
}
bool
TabParent::ShouldSwitchProcess(nsIChannel* aChannel)
TabParent::ShouldSwitchProcess(nsIChannel* aChannel, const nsACString& aSignedPkg)
{
// If we lack of any information which is required to decide the need of
// process switch, consider that we should switch process.
@ -473,19 +496,18 @@ TabParent::ShouldSwitchProcess(nsIChannel* aChannel)
NS_ENSURE_TRUE(loadingPrincipal, true);
// Prepare the channel result principal.
nsCOMPtr<nsIPrincipal> resultPrincipal;
nsContentUtils::GetSecurityManager()->
GetChannelResultPrincipal(aChannel, getter_AddRefs(resultPrincipal));
nsCOMPtr<nsIPrincipal> channelPrincipal =
GetChannelPrincipalWithSingedPkg(aChannel, aSignedPkg);
// Log the debug info which is used to decide the need of proces switch.
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
LogChannelRelevantInfo(uri, loadingPrincipal, resultPrincipal,
LogChannelRelevantInfo(uri, loadingPrincipal, channelPrincipal,
loadInfo->InternalContentPolicyType());
// Check if the signed package is loaded from the same origin.
bool sameOrigin = false;
loadingPrincipal->Equals(resultPrincipal, &sameOrigin);
loadingPrincipal->Equals(channelPrincipal, &sameOrigin);
if (sameOrigin) {
LOG("Loading singed package from the same origin. Don't switch process.\n");
return false;
@ -516,7 +538,7 @@ void
TabParent::OnStartSignedPackageRequest(nsIChannel* aChannel,
const nsACString& aPackageId)
{
if (!ShouldSwitchProcess(aChannel)) {
if (!ShouldSwitchProcess(aChannel, aPackageId)) {
return;
}
@ -2347,7 +2369,7 @@ TabParent::RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent,
return true;
}
widget->StartPluginIME(aKeyboardEvent,
(int32_t&)aPanelX,
(int32_t&)aPanelX,
(int32_t&)aPanelY,
*aCommitted);
return true;

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

@ -495,7 +495,7 @@ protected:
// Decide whether we have to use a new process to reload the URI associated
// with the given channel.
bool ShouldSwitchProcess(nsIChannel* aChannel);
bool ShouldSwitchProcess(nsIChannel* aChannel, const nsACString& aSignedPkg);
ContentCacheInParent mContentCache;

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

@ -12,15 +12,14 @@
#include "OggDecoder.h"
#include "OggReader.h"
#ifdef MOZ_WAVE
#include "WaveDecoder.h"
#include "WaveReader.h"
#endif
#ifdef MOZ_WEBM
#include "WebMDecoder.h"
#include "WebMReader.h"
#include "WebMDemuxer.h"
#endif
#ifdef MOZ_RAW
#include "RawDecoder.h"
#include "RawReader.h"
@ -128,7 +127,6 @@ IsOggType(const nsACString& aType)
return CodecListContains(gOggTypes, aType);
}
#ifdef MOZ_WAVE
// See http://www.rfc-editor.org/rfc/rfc2361.txt for the definitions
// of WAVE media types and codec types. However, the audio/vnd.wave
// MIME type described there is not used.
@ -154,33 +152,24 @@ IsWaveType(const nsACString& aType)
return CodecListContains(gWaveTypes, aType);
}
#endif
#ifdef MOZ_WEBM
static bool
IsWebMSupportedType(const nsACString& aType,
const nsAString& aCodecs = EmptyString())
{
return WebMDecoder::CanHandleMediaType(aType, aCodecs);
}
#endif
/* static */ bool
DecoderTraits::IsWebMTypeAndEnabled(const nsACString& aType)
{
#ifdef MOZ_WEBM
return IsWebMSupportedType(aType);
#endif
return false;
}
/* static */ bool
DecoderTraits::IsWebMAudioType(const nsACString& aType)
{
#ifdef MOZ_WEBM
return aType.EqualsASCII("audio/webm");
#endif
return false;
}
#ifdef MOZ_GSTREAMER
@ -367,7 +356,6 @@ IsAACSupportedType(const nsACString& aType,
/* static */
bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType)
{
#ifdef MOZ_WAVE
if (IsWaveType(nsDependentCString(aMIMEType))) {
// We should not return true for Wave types, since there are some
// Wave codecs actually in use in the wild that we don't support, and
@ -376,7 +364,6 @@ bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType)
// means.
return false;
}
#endif
return CanHandleMediaType(aMIMEType, false, EmptyString()) != CANPLAY_NO;
}
@ -394,11 +381,9 @@ DecoderTraits::CanHandleCodecsType(const char* aMIMEType,
if (IsOggType(nsDependentCString(aMIMEType))) {
codecList = MediaDecoder::IsOpusEnabled() ? gOggCodecsWithOpus : gOggCodecs;
}
#ifdef MOZ_WAVE
if (IsWaveType(nsDependentCString(aMIMEType))) {
codecList = gWaveCodecs;
}
#endif
#if !defined(MOZ_OMX_WEBM_DECODER)
if (IsWebMTypeAndEnabled(nsDependentCString(aMIMEType))) {
if (IsWebMSupportedType(nsDependentCString(aMIMEType), aRequestedCodecs)) {
@ -496,11 +481,9 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType,
if (IsOggType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#ifdef MOZ_WAVE
if (IsWaveType(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
#endif
if (IsMP4TypeAndEnabled(nsDependentCString(aMIMEType))) {
return CANPLAY_MAYBE;
}
@ -583,12 +566,10 @@ InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
decoder = new OggDecoder(aOwner);
return decoder.forget();
}
#ifdef MOZ_WAVE
if (IsWaveType(aType)) {
decoder = new WaveDecoder(aOwner);
return decoder.forget();
}
#endif
#ifdef MOZ_OMX_DECODER
if (IsOmxSupportedType(aType)) {
// we are discouraging Web and App developers from using those formats in
@ -623,12 +604,12 @@ InstantiateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
return decoder.forget();
}
#endif
#ifdef MOZ_WEBM
if (IsWebMSupportedType(aType)) {
decoder = new WebMDecoder(aOwner);
return decoder.forget();
}
#endif
#ifdef MOZ_DIRECTSHOW
// Note: DirectShow should come before WMF, so that we prefer DirectShow's
// MP3 support over WMF's.
@ -682,11 +663,9 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
if (IsOggType(aType)) {
decoderReader = new OggReader(aDecoder);
} else
#ifdef MOZ_WAVE
if (IsWaveType(aType)) {
decoderReader = new WaveReader(aDecoder);
} else
#endif
#ifdef MOZ_OMX_DECODER
if (IsOmxSupportedType(aType)) {
decoderReader = new MediaOmxReader(aDecoder);
@ -698,13 +677,13 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
decoderReader = new AndroidMediaReader(aDecoder, aType);
} else
#endif
#ifdef MOZ_WEBM
if (IsWebMSupportedType(aType)) {
decoderReader = Preferences::GetBool("media.format-reader.webm", true) ?
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new WebMDemuxer(aDecoder->GetResource()))) :
new WebMReader(aDecoder);
} else
#endif
#ifdef MOZ_DIRECTSHOW
if (IsDirectShowSupportedType(aType)) {
decoderReader = new DirectShowReader(aDecoder);
@ -735,9 +714,7 @@ bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
(IsOmxSupportedType(aType) &&
!IsB2GSupportOnlyType(aType)) ||
#endif
#ifdef MOZ_WEBM
IsWebMSupportedType(aType) ||
#endif
#ifdef MOZ_GSTREAMER
IsGStreamerSupportedType(aType) ||
#endif

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

@ -1641,21 +1641,17 @@ MediaDecoder::IsOggEnabled()
return Preferences::GetBool("media.ogg.enabled");
}
#ifdef MOZ_WAVE
bool
MediaDecoder::IsWaveEnabled()
{
return Preferences::GetBool("media.wave.enabled");
}
#endif
#ifdef MOZ_WEBM
bool
MediaDecoder::IsWebMEnabled()
{
return Preferences::GetBool("media.webm.enabled");
}
#endif
#ifdef NECKO_PROTOCOL_rtsp
bool

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

@ -662,14 +662,9 @@ private:
static bool IsOggEnabled();
static bool IsOpusEnabled();
#ifdef MOZ_WAVE
static bool IsWaveEnabled();
#endif
#ifdef MOZ_WEBM
static bool IsWebMEnabled();
#endif
#ifdef NECKO_PROTOCOL_rtsp
static bool IsRtspEnabled();
#endif

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

@ -224,6 +224,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mIsVideoPrerolling(false),
mAudioCaptured(false, "MediaDecoderStateMachine::mAudioCaptured"),
mAudioCompleted(false, "MediaDecoderStateMachine::mAudioCompleted"),
mVideoCompleted(false, "MediaDecoderStateMachine::mVideoCompleted"),
mNotifyMetadataBeforeFirstFrame(false),
mDispatchedEventToDecode(false),
mQuickBuffering(false),
@ -355,6 +356,7 @@ MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder)
mWatchManager.Watch(mBuffered, &MediaDecoderStateMachine::BufferedRangeUpdated);
mWatchManager.Watch(mState, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mAudioCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mVideoCompleted, &MediaDecoderStateMachine::UpdateNextFrameStatus);
mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged);
mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged);
mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged);
@ -2352,10 +2354,8 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
// Play the remaining media. We want to run AdvanceFrame() at least
// once to ensure the current playback position is advanced to the
// end of the media, and so that we update the readyState.
if (VideoQueue().GetSize() > 1 ||
(HasAudio() && !mAudioCompleted) ||
(mAudioCaptured && !mStreamSink->IsFinished()))
{
if ((HasVideo() && !mVideoCompleted) ||
(HasAudio() && !mAudioCompleted)) {
// Start playback if necessary to play the remaining media.
MaybeStartPlayback();
UpdatePlaybackPositionPeriodically();
@ -2425,6 +2425,7 @@ MediaDecoderStateMachine::Reset()
mDecodedVideoEndTime = -1;
mDecodedAudioEndTime = -1;
mAudioCompleted = false;
mVideoCompleted = false;
AudioQueue().Reset();
VideoQueue().Reset();
mFirstVideoFrameAfterSeek = nullptr;
@ -2836,9 +2837,11 @@ void
MediaDecoderStateMachine::OnMediaSinkVideoComplete()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mInfo.HasVideo());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkVideoPromise.Complete();
mVideoCompleted = true;
ScheduleStateMachine();
}
@ -2846,9 +2849,11 @@ void
MediaDecoderStateMachine::OnMediaSinkVideoError()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mInfo.HasVideo());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkVideoPromise.Complete();
mVideoCompleted = true;
if (HasAudio()) {
return;
}
@ -2858,11 +2863,11 @@ MediaDecoderStateMachine::OnMediaSinkVideoError()
void MediaDecoderStateMachine::OnMediaSinkAudioComplete()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mInfo.HasAudio());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkAudioPromise.Complete();
// Set true only when we have audio.
mAudioCompleted = mInfo.HasAudio();
mAudioCompleted = true;
// To notify PlaybackEnded as soon as possible.
ScheduleStateMachine();
}
@ -2870,11 +2875,11 @@ void MediaDecoderStateMachine::OnMediaSinkAudioComplete()
void MediaDecoderStateMachine::OnMediaSinkAudioError()
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(mInfo.HasAudio());
VERBOSE_LOG("[%s]", __func__);
mMediaSinkAudioPromise.Complete();
// Set true only when we have audio.
mAudioCompleted = mInfo.HasAudio();
mAudioCompleted = true;
// Make the best effort to continue playback when there is video.
if (HasVideo()) {

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

@ -1101,6 +1101,9 @@ private:
// been written to the MediaStream.
Watchable<bool> mAudioCompleted;
// True if all video frames are already rendered.
Watchable<bool> mVideoCompleted;
// Set if MDSM receives dormant request during reading metadata.
Maybe<bool> mPendingDormant;

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

@ -26,7 +26,6 @@ public:
: mMutex("DecodedStreamGraphListener::mMutex")
, mStream(aStream)
, mLastOutputTime(aStream->StreamTimeToMicroseconds(aStream->GetCurrentTime()))
, mStreamFinishedOnMainThread(false)
{
mFinishPromise = Move(aPromise);
}
@ -52,8 +51,6 @@ public:
void DoNotifyFinished()
{
mFinishPromise.ResolveIfExists(true, __func__);
MutexAutoLock lock(mMutex);
mStreamFinishedOnMainThread = true;
}
int64_t GetLastOutputTime()
@ -70,18 +67,11 @@ public:
mStream = nullptr;
}
bool IsFinishedOnMainThread()
{
MutexAutoLock lock(mMutex);
return mStreamFinishedOnMainThread;
}
private:
Mutex mMutex;
// Members below are protected by mMutex.
RefPtr<MediaStream> mStream;
int64_t mLastOutputTime; // microseconds
bool mStreamFinishedOnMainThread;
// Main thread only.
MozPromiseHolder<GenericPromise> mFinishPromise;
};
@ -119,7 +109,6 @@ public:
DecodedStreamData(SourceMediaStream* aStream,
MozPromiseHolder<GenericPromise>&& aPromise);
~DecodedStreamData();
bool IsFinished() const;
int64_t GetPosition() const;
void SetPlaying(bool aPlaying);
@ -180,12 +169,6 @@ DecodedStreamData::~DecodedStreamData()
mStream->Destroy();
}
bool
DecodedStreamData::IsFinished() const
{
return mListener->IsFinishedOnMainThread();
}
int64_t
DecodedStreamData::GetPosition() const
{
@ -346,13 +329,14 @@ DecodedStream::OnEnded(TrackType aType)
AssertOwnerThread();
MOZ_ASSERT(mStartTime.isSome());
if (aType == TrackInfo::kAudioTrack) {
if (aType == TrackInfo::kAudioTrack && mInfo.HasAudio()) {
// TODO: we should return a promise which is resolved when the audio track
// is finished. For now this promise is resolved when the whole stream is
// finished.
return mFinishPromise;
} else if (aType == TrackInfo::kVideoTrack && mInfo.HasVideo()) {
return mFinishPromise;
}
// TODO: handle video track.
return nullptr;
}
@ -883,13 +867,6 @@ DecodedStream::GetPosition(TimeStamp* aTimeStamp) const
return mStartTime.ref() + (mData ? mData->GetPosition() : 0);
}
bool
DecodedStream::IsFinished() const
{
AssertOwnerThread();
return mData && mData->IsFinished();
}
void
DecodedStream::ConnectListener()
{

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

@ -123,7 +123,6 @@ public:
void AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
void RemoveOutput(MediaStream* aStream);
void SetSameOrigin(bool aSameOrigin);
bool IsFinished() const;
bool HasConsumers() const;
protected:

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

@ -166,8 +166,29 @@ VideoSink::Start(int64_t aStartTime, const MediaInfo& aInfo)
if (mHasVideo) {
mEndPromise = mEndPromiseHolder.Ensure(__func__);
// If the underlying MediaSink has an end promise for the video track (which
// happens when mAudioSink refers to a DecodedStream), we must wait for it
// to complete before resolving our own end promise. Otherwise, MDSM might
// stop playback before DecodedStream plays to the end and cause
// test_streams_element_capture.html to time out.
RefPtr<GenericPromise> p = mAudioSink->OnEnded(TrackInfo::kVideoTrack);
if (p) {
RefPtr<VideoSink> self = this;
mVideoSinkEndRequest.Begin(p->Then(mOwnerThread, __func__,
[self] () {
self->mVideoSinkEndRequest.Complete();
self->TryUpdateRenderedVideoFrames();
}, [self] () {
self->mVideoSinkEndRequest.Complete();
self->TryUpdateRenderedVideoFrames();
}));
}
ConnectListener();
TryUpdateRenderedVideoFrames();
// Run the render loop at least once so we can resolve the end promise
// when video duration is 0.
UpdateRenderedVideoFrames();
}
}
@ -183,7 +204,8 @@ VideoSink::Stop()
mUpdateScheduler.Reset();
if (mHasVideo) {
DisconnectListener();
mEndPromiseHolder.Resolve(true, __func__);
mVideoSinkEndRequest.DisconnectIfExists();
mEndPromiseHolder.ResolveIfExists(true, __func__);
mEndPromise = nullptr;
}
mVideoFrameEndTime = -1;
@ -216,7 +238,7 @@ VideoSink::Shutdown()
}
void
VideoSink::OnVideoQueueEvent(RefPtr<MediaData>&& aSample)
VideoSink::OnVideoQueuePushed(RefPtr<MediaData>&& aSample)
{
AssertOwnerThread();
// Listen to push event, VideoSink should try rendering ASAP if first frame
@ -230,6 +252,18 @@ VideoSink::OnVideoQueueEvent(RefPtr<MediaData>&& aSample)
}
}
void
VideoSink::OnVideoQueueFinished()
{
AssertOwnerThread();
// Run render loop if the end promise is not resolved yet.
if (!mUpdateScheduler.IsScheduled() &&
mAudioSink->IsPlaying() &&
!mEndPromiseHolder.IsEmpty()) {
UpdateRenderedVideoFrames();
}
}
void
VideoSink::Redraw()
{
@ -260,7 +294,9 @@ VideoSink::ConnectListener()
{
AssertOwnerThread();
mPushListener = VideoQueue().PushEvent().Connect(
mOwnerThread, this, &VideoSink::OnVideoQueueEvent);
mOwnerThread, this, &VideoSink::OnVideoQueuePushed);
mFinishListener = VideoQueue().FinishEvent().Connect(
mOwnerThread, this, &VideoSink::OnVideoQueueFinished);
}
void
@ -268,6 +304,7 @@ VideoSink::DisconnectListener()
{
AssertOwnerThread();
mPushListener.Disconnect();
mFinishListener.Disconnect();
}
void
@ -371,6 +408,13 @@ VideoSink::UpdateRenderedVideoFrames()
}
}
// All frames are rendered, Let's resolve the promise.
if (VideoQueue().IsFinished() &&
VideoQueue().GetSize() <= 1 &&
!mVideoSinkEndRequest.Exists()) {
mEndPromiseHolder.ResolveIfExists(true, __func__);
}
RenderVideoFrames(mVideoQueueSendToCompositorSize, clockTime, nowTime);
// No next fame to render. There is no need to schedule next render

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

@ -72,7 +72,8 @@ private:
virtual ~VideoSink();
// VideoQueue listener related.
void OnVideoQueueEvent(RefPtr<MediaData>&& aSample);
void OnVideoQueuePushed(RefPtr<MediaData>&& aSample);
void OnVideoQueueFinished();
void ConnectListener();
void DisconnectListener();
@ -129,6 +130,7 @@ private:
// Event listeners for VideoQueue
MediaEventListener mPushListener;
MediaEventListener mFinishListener;
// True if this sink is going to handle video track.
bool mHasVideo;

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

@ -12,10 +12,7 @@
#include "mozilla/StateMirroring.h"
#include "SourceBufferResource.h"
#include "SourceBuffer.h"
#ifdef MOZ_WEBM
#include "WebMDemuxer.h"
#endif
#ifdef MOZ_FMP4
#include "MP4Demuxer.h"
@ -798,12 +795,10 @@ TrackBuffersManager::CreateDemuxerforMIMEType()
{
ShutdownDemuxers();
#ifdef MOZ_WEBM
if (mType.LowerCaseEqualsLiteral("video/webm") || mType.LowerCaseEqualsLiteral("audio/webm")) {
mInputDemuxer = new WebMDemuxer(mCurrentInputBuffer, true /* IsMediaSource*/ );
return;
}
#endif
#ifdef MOZ_FMP4
if (mType.LowerCaseEqualsLiteral("video/mp4") || mType.LowerCaseEqualsLiteral("audio/mp4")) {

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

@ -30,7 +30,9 @@ DIRS += [
'ogg',
'platforms',
'systemservices',
'wave',
'webaudio',
'webm',
'webrtc',
'webspeech',
'webvtt',
@ -40,12 +42,6 @@ DIRS += [
if CONFIG['MOZ_RAW']:
DIRS += ['raw']
if CONFIG['MOZ_WAVE']:
DIRS += ['wave']
if CONFIG['MOZ_WEBM']:
DIRS += ['webm']
if CONFIG['MOZ_GSTREAMER']:
DIRS += ['gstreamer']

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

@ -68,7 +68,7 @@ OmxDataDecoder::OmxDataDecoder(const TrackInfo& aTrackInfo,
, mOmxState(OMX_STATETYPE::OMX_StateInvalid, "OmxDataDecoder::mOmxState")
, mTrackInfo(aTrackInfo.Clone())
, mFlushing(false)
, mShutdown(false)
, mShuttingDown(false)
, mCheckingInputExhausted(false)
, mPortSettingsChanged(-1, "OmxDataDecoder::mPortSettingsChanged")
, mAudioCompactor(mAudioQueue)
@ -86,7 +86,6 @@ OmxDataDecoder::~OmxDataDecoder()
{
LOG("(%p)", this);
mWatchManager.Shutdown();
mOmxTaskQueue->AwaitShutdownAndIdle();
}
void
@ -207,12 +206,25 @@ OmxDataDecoder::Shutdown()
{
LOG("(%p)", this);
mShutdown = true;
mShuttingDown = true;
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableMethod(this, &OmxDataDecoder::DoAsyncShutdown);
mOmxTaskQueue->Dispatch(r.forget());
{
// DoAsyncShutdown() will be running for a while, it could be still running
// when reader releasing the decoder and then it causes problem. To avoid it,
// Shutdown() must block until DoAsyncShutdown() is completed.
MonitorAutoLock lock(mMonitor);
while (mShuttingDown) {
lock.Wait();
}
}
mOmxTaskQueue->BeginShutdown();
mOmxTaskQueue->AwaitShutdownAndIdle();
return NS_OK;
}
@ -273,9 +285,17 @@ OmxDataDecoder::DoAsyncShutdown()
[self] () {
LOG("DoAsyncShutdown: OMX_StateLoaded, it is safe to shutdown omx");
self->mOmxLayer->Shutdown();
MonitorAutoLock lock(self->mMonitor);
self->mShuttingDown = false;
self->mMonitor.Notify();
},
[self] () {
self->mOmxLayer->Shutdown();
MonitorAutoLock lock(self->mMonitor);
self->mShuttingDown = false;
self->mMonitor.Notify();
});
}
@ -400,12 +420,8 @@ OmxDataDecoder::FillAndEmptyBuffers()
MOZ_ASSERT(mOmxTaskQueue->IsCurrentThreadIn());
MOZ_ASSERT(mOmxState == OMX_StateExecuting);
// During the port setting changed, it is forbided to do any buffer operations.
if (mPortSettingsChanged != -1 || mShutdown) {
return;
}
if (mFlushing) {
// During the port setting changed, it is forbidden to do any buffer operation.
if (mPortSettingsChanged != -1 || mShuttingDown || mFlushing) {
return;
}
@ -842,7 +858,6 @@ OmxDataDecoder::DoFlush()
// 1. Call OMX command OMX_CommandFlush in Omx TaskQueue.
// 2. Remove all elements in mMediaRawDatas when flush is completed.
RefPtr<OmxDataDecoder> self = this;
mOmxLayer->SendCommand(OMX_CommandFlush, OMX_ALL, nullptr)
->Then(mOmxTaskQueue, __func__, this,
&OmxDataDecoder::FlushComplete,

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

@ -163,7 +163,7 @@ protected:
Atomic<bool> mFlushing;
// It is accessed in Omx/reader TaskQeueu.
Atomic<bool> mShutdown;
Atomic<bool> mShuttingDown;
// It is accessed in Omx TaskQeueu.
bool mCheckingInputExhausted;

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

@ -22,9 +22,10 @@ extern mozilla::LogModule* GetPDMLog();
namespace mozilla {
extern void GetPortIndex(nsTArray<uint32_t>& aPortIndex);
OmxPromiseLayer::OmxPromiseLayer(TaskQueue* aTaskQueue, OmxDataDecoder* aDataDecoder)
: mTaskQueue(aTaskQueue)
, mFlushPortIndex(0)
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21
mPlatformLayer = new GonkOmxPlatformLayer(aDataDecoder, this, aTaskQueue);
@ -196,27 +197,48 @@ OmxPromiseLayer::EmptyFillBufferDone(OMX_DIRTYPE aType, BufferData::BufferID aID
RefPtr<OmxPromiseLayer::OmxCommandPromise>
OmxPromiseLayer::SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, OMX_PTR aCmdData)
{
// No need to issue flush because of buffers are in client already.
//
// Some components fail to respond flush event when all of buffers are in
// client.
if (aCmd == OMX_CommandFlush) {
bool needFlush = false;
if ((aParam1 & OMX_DirInput && mInbufferHolders.Length()) ||
(aParam1 & OMX_DirOutput && mOutbufferHolders.Length())) {
needFlush = true;
}
if (!needFlush) {
LOG("SendCommand: buffers are in client already, no need to flush");
mRawDatas.Clear();
return OmxCommandPromise::CreateAndResolve(OMX_CommandFlush, __func__);
}
}
// It doesn't support another flush commands before previous one is completed.
MOZ_RELEASE_ASSERT(!mFlushCommands.Length());
OMX_ERRORTYPE err = mPlatformLayer->SendCommand(aCmd, aParam1, aCmdData);
if (err != OMX_ErrorNone) {
OmxCommandFailureHolder failure(OMX_ErrorNotReady, aCmd);
return OmxCommandPromise::CreateAndReject(failure, __func__);
// Some coomponents don't send event with OMX_ALL, they send flush complete
// event with input port and another event for output port.
// In prupose of better compatibility, we inteprete the OMX_ALL to OMX_DirInput
// and OMX_DirOutput flush separately.
OMX_DIRTYPE types[] = {OMX_DIRTYPE::OMX_DirInput, OMX_DIRTYPE::OMX_DirOutput};
for(const auto type : types) {
if ((aParam1 == type) || (aParam1 == OMX_ALL)) {
mFlushCommands.AppendElement(FlushCommand({type, aCmdData}));
}
if (type == OMX_DirInput) {
// Clear all buffered raw data.
mRawDatas.Clear();
}
}
// Don't overlay more than one fush command, some components can't overlay flush commands.
// So here we send another flush after receiving the previous flush completed event.
if (mFlushCommands.Length()) {
OMX_ERRORTYPE err =
mPlatformLayer->SendCommand(OMX_CommandFlush,
mFlushCommands.ElementAt(0).type,
mFlushCommands.ElementAt(0).cmd);
if (err != OMX_ErrorNone) {
OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
return OmxCommandPromise::CreateAndReject(failure, __func__);
}
} else {
LOG("SendCommand: OMX_CommandFlush parameter error");
OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
return OmxCommandPromise::CreateAndReject(failure, __func__);
}
} else {
OMX_ERRORTYPE err = mPlatformLayer->SendCommand(aCmd, aParam1, aCmdData);
if (err != OMX_ErrorNone) {
OmxCommandFailureHolder failure(OMX_ErrorNotReady, aCmd);
return OmxCommandPromise::CreateAndReject(failure, __func__);
}
}
RefPtr<OmxCommandPromise> p;
@ -224,9 +246,6 @@ OmxPromiseLayer::SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, OMX_PTR aCmd
p = mCommandStatePromise.Ensure(__func__);
} else if (aCmd == OMX_CommandFlush) {
p = mFlushPromise.Ensure(__func__);
mFlushPortIndex = aParam1;
// Clear all buffered raw data.
mRawDatas.Clear();
} else if (aCmd == OMX_CommandPortEnable) {
p = mPortEnablePromise.Ensure(__func__);
} else if (aCmd == OMX_CommandPortDisable) {
@ -248,8 +267,24 @@ OmxPromiseLayer::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2)
{
if (cmd == OMX_CommandStateSet) {
mCommandStatePromise.Resolve(OMX_CommandStateSet, __func__);
} else if (cmd == OMX_CommandFlush && mFlushPortIndex == aData2) {
mFlushPromise.Resolve(OMX_CommandFlush, __func__);
} else if (cmd == OMX_CommandFlush) {
MOZ_RELEASE_ASSERT(mFlushCommands.ElementAt(0).type == aData2);
LOG("Event: OMX_CommandFlush completed port type %d", aData2);
mFlushCommands.RemoveElementAt(0);
// Sending next flush command.
if (mFlushCommands.Length()) {
OMX_ERRORTYPE err =
mPlatformLayer->SendCommand(OMX_CommandFlush,
mFlushCommands.ElementAt(0).type,
mFlushCommands.ElementAt(0).cmd);
if (err != OMX_ErrorNone) {
OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
mFlushPromise.Reject(failure, __func__);
}
} else {
mFlushPromise.Resolve(OMX_CommandFlush, __func__);
}
} else if (cmd == OMX_CommandPortDisable) {
mPortDisablePromise.Resolve(OMX_CommandPortDisable, __func__);
} else if (cmd == OMX_CommandPortEnable) {
@ -262,7 +297,7 @@ OmxPromiseLayer::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2)
if (cmd == OMX_CommandStateSet) {
OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet);
mCommandStatePromise.Reject(failure, __func__);
} else if (cmd == OMX_CommandFlush && mFlushPortIndex == aData2) {
} else if (cmd == OMX_CommandFlush) {
OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandFlush);
mFlushPromise.Reject(failure, __func__);
} else if (cmd == OMX_CommandPortDisable) {

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

@ -183,6 +183,11 @@ public:
bool Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1, OMX_U32 aData2);
protected:
struct FlushCommand {
OMX_DIRTYPE type;
OMX_PTR cmd;
};
BUFFERLIST* GetBufferHolders(OMX_DIRTYPE aType);
already_AddRefed<MediaRawData> FindAndRemoveRawData(OMX_TICKS aTimecode);
@ -197,7 +202,7 @@ protected:
MozPromiseHolder<OmxCommandPromise> mFlushPromise;
OMX_U32 mFlushPortIndex;
nsTArray<FlushCommand> mFlushCommands;
nsAutoPtr<OmxPlatformLayer> mPlatformLayer;

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

@ -50,11 +50,12 @@ DecoderFuzzingWrapper::Input(MediaRawData* aData)
nsresult
DecoderFuzzingWrapper::Flush()
{
DFW_LOGV("");
DFW_LOGV("Calling mDecoder[%p]->Flush()", mDecoder.get());
MOZ_ASSERT(mDecoder);
// Flush may output some frames (though unlikely).
// Flush may block a bit, it's ok if we output some frames in the meantime.
nsresult result = mDecoder->Flush();
DFW_LOGV("mDecoder[%p]->Flush() -> result=%u", mDecoder.get(), uint32_t(result));
// Clear any delayed output we may have.
mCallbackWrapper->ClearDelayedOutput();
return result;
@ -254,13 +255,28 @@ void
DecoderCallbackFuzzingWrapper::ScheduleOutputDelayedFrame()
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
if (mDelayedOutputRequest.Exists()) {
// A delayed output is already scheduled, no need for more than one timer.
return;
}
RefPtr<DecoderCallbackFuzzingWrapper> self = this;
mDelayedOutputTimer->WaitUntil(
mPreviousOutput + mFrameOutputMinimumInterval,
__func__)
->Then(mTaskQueue, __func__,
[self] () -> void { self->OutputDelayedFrame(); },
[self] () -> void { self->OutputDelayedFrame(); });
mDelayedOutputRequest.Begin(
mDelayedOutputTimer->WaitUntil(
mPreviousOutput + mFrameOutputMinimumInterval,
__func__)
->Then(mTaskQueue, __func__,
[self] () -> void {
if (self->mDelayedOutputRequest.Exists()) {
self->mDelayedOutputRequest.Complete();
self->OutputDelayedFrame();
}
},
[self] () -> void {
if (self->mDelayedOutputRequest.Exists()) {
self->mDelayedOutputRequest.Complete();
self->ClearDelayedOutput();
}
}));
}
void
@ -300,11 +316,16 @@ void
DecoderCallbackFuzzingWrapper::ClearDelayedOutput()
{
if (!mTaskQueue->IsCurrentThreadIn()) {
DFW_LOGV("(dispatching self)");
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableMethod(this, &DecoderCallbackFuzzingWrapper::ClearDelayedOutput);
mTaskQueue->Dispatch(task.forget());
return;
}
DFW_LOGV("");
// In case a timer hasn't lapsed yet, before destroying the timer and its
// attached waitUntil() promise, the 'Then' request must be disconnected.
mDelayedOutputRequest.DisconnectIfExists();
mDelayedOutputTimer = nullptr;
mDelayedOutput.clear();
}
@ -312,10 +333,16 @@ DecoderCallbackFuzzingWrapper::ClearDelayedOutput()
void
DecoderCallbackFuzzingWrapper::Shutdown()
{
DFW_LOGV("Shutting down mTaskQueue");
CFW_LOGV("Clear delayed output (if any) before shutting down mTaskQueue");
ClearDelayedOutput();
// Await idle here, so that 'ClearDelayedOutput' runs to completion before
// the task queue is shutdown (and tasks can't be queued anymore).
mTaskQueue->AwaitIdle();
CFW_LOGV("Shutting down mTaskQueue");
mTaskQueue->BeginShutdown();
mTaskQueue->AwaitIdle();
DFW_LOGV("mTaskQueue shut down");
CFW_LOGV("mTaskQueue shut down");
}
} // namespace mozilla

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

@ -81,6 +81,7 @@ private:
typedef Pair<RefPtr<MediaData>, bool> MediaDataAndInputExhausted;
std::deque<MediaDataAndInputExhausted> mDelayedOutput;
RefPtr<MediaTimer> mDelayedOutputTimer;
MozPromiseRequestHolder<MediaTimerPromise> mDelayedOutputRequest;
// If draining, a 'DrainComplete' will be sent after all delayed frames have
// been output.
bool mDraining;

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

@ -851,14 +851,6 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
# The tests below contain backend-specific tests. Write backend independent
# tests rather than adding to this list.
[test_can_play_type_webm.html]
skip-if = !webm
[test_can_play_type_no_webm.html]
skip-if = webm
[test_can_play_type_wave.html]
skip-if = !wave
[test_can_play_type_no_wave.html]
skip-if = wave
[test_fragment_noplay.html]
skip-if = !wave
[test_fragment_play.html]
skip-if = !wave

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

@ -1,32 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=469247
-->
<head>
<title>Test for Bug 469247: WAVE backend disabled</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469247">Mozill
a Bug 469247</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v"></video>
<pre id="test">
<script src="can_play_type_wave.js"></script>
check_wave(document.getElementById('v'), false);
mediaTestCleanup();
</script>
</pre>
</body>
</html>

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

@ -1,32 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=566245
-->
<head>
<title>Test for Bug 566245: WebM backend disabled</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566245">Mozill
a Bug 566245</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<video id="v"></video>
<pre id="test">
<script src="can_play_type_webm.js"></script>
check_webm(document.getElementById('v'), false);
mediaTestCleanup();
</script>
</pre>
</body>
</html>

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

@ -90,11 +90,11 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' &
[test_peerConnection_basicScreenshare.html]
# no screenshare on b2g/android
# frequent timeouts/crashes on e10s (bug 1048455)
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' || e10s # Bug 1141029 Mulet parity with B2G Desktop for TC
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' # Bug 1141029 Mulet parity with B2G Desktop for TC
[test_peerConnection_basicWindowshare.html]
# no screenshare on b2g/android
# frequent timeouts/crashes on e10s (bug 1048455)
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' || e10s # Bug 1141029 Mulet parity with B2G Desktop for TC
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' # Bug 1141029 Mulet parity with B2G Desktop for TC
[test_peerConnection_basicH264Video.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || os == 'android' # bug 1043403 # Bug 1141029 Mulet parity with B2G Desktop for TC
[test_peerConnection_bug822674.html]
@ -161,16 +161,16 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' &
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) # b2g (Bug 1059867), android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_twoAudioVideoStreams.html]
# b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || android_version == '18'
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18'
[test_peerConnection_twoAudioVideoStreamsCombined.html]
# b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || android_version == '18'
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18'
[test_peerConnection_twoVideoStreams.html]
# b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || android_version == '18'
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || android_version == '18'
[test_peerConnection_twoVideoTracksInOneStream.html]
# b2g(Bug 960442, video support for WebRTC is disabled on b2g), Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug)
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug)
[test_peerConnection_addSecondAudioStream.html]
skip-if = toolkit == 'gonk' # B2G emulator is too slow to finish a renegotiation test in under 5 minutes
[test_peerConnection_answererAddSecondAudioStream.html]
@ -181,26 +181,26 @@ skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator
skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_addSecondVideoStream.html]
# B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || android_version == '18'
skip-if = toolkit == 'gonk' || android_version == '18'
[test_peerConnection_removeVideoTrack.html]
# B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug)
skip-if = toolkit == 'gonk' || (android_version == '18' && debug)
[test_peerConnection_removeThenAddVideoTrack.html]
# B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug)
skip-if = toolkit == 'gonk' || (android_version == '18' && debug)
[test_peerConnection_replaceVideoThenRenegotiate.html]
# B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || (android_version == '18' && debug)
skip-if = toolkit == 'gonk' || (android_version == '18' && debug)
[test_peerConnection_addSecondAudioStreamNoBundle.html]
skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_removeThenAddAudioTrackNoBundle.html]
skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # B2G emulator is too slow to finish a renegotiation test in under 5 minutes, android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_addSecondVideoStreamNoBundle.html]
# B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || android_version == '18'
skip-if = toolkit == 'gonk' || android_version == '18'
[test_peerConnection_removeThenAddVideoTrackNoBundle.html]
# B2G emulator is too slow to finish a renegotiation test in under 5 minutes, Bug 1180000 for Linux debug e10s, android(Bug 1189784, timeouts on 4.3 emulator)
skip-if = toolkit == 'gonk' || (os == 'linux' && debug && e10s) || android_version == '18'
skip-if = toolkit == 'gonk' || android_version == '18'
[test_peerConnection_addDataChannel.html]
skip-if = toolkit == 'gonk' # B2G emulator seems to be so slow that DTLS cannot establish properly
[test_peerConnection_addDataChannelNoBundle.html]

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

@ -2650,7 +2650,12 @@ Notification::CreateAndShow(nsIGlobalObject* aGlobal,
MOZ_ASSERT(aGlobal);
AutoJSAPI jsapi;
jsapi.Init(aGlobal);
if (NS_WARN_IF(!jsapi.Init(aGlobal)))
{
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
return nullptr;
}
JSContext* cx = jsapi.cx();
RefPtr<Notification> notification = CreateInternal(aGlobal, EmptyString(),

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

@ -1162,6 +1162,11 @@ public:
int32_t limit = 0,
int32_t allocLimit = 0);
/**
* Make sure that the given buffer size doesn't exceed the allocation limit.
*/
static bool CheckBufferSize(int32_t bufSize);
/** Make sure the given dimension satisfies the CheckSurfaceSize and is
* within 8k limit. The 8k value is chosen a bit randomly.
*/

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

@ -333,6 +333,10 @@ GetCairoSurfaceForSourceSurface(SourceSurface *aSurface,
bool aExistingOnly = false,
const IntRect& aSubImage = IntRect())
{
if (!aSurface) {
return nullptr;
}
IntRect subimage = IntRect(IntPoint(), aSurface->GetSize());
if (!aSubImage.IsEmpty()) {
MOZ_ASSERT(!aExistingOnly);
@ -792,7 +796,7 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
return;
}
if (!IsValid()) {
if (!IsValid() || !aSurface) {
gfxCriticalNote << "DrawSurface with bad surface " << cairo_surface_status(mSurface);
return;
}

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

@ -264,6 +264,12 @@ Factory::AllowedSurfaceSize(const IntSize &aSize)
return CheckSurfaceSize(aSize);
}
bool
Factory::CheckBufferSize(int32_t bufSize)
{
return !sConfig || bufSize < sConfig->mMaxAllocSize;
}
bool
Factory::CheckSurfaceSize(const IntSize &sz,
int32_t extentLimit,

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

@ -22,6 +22,7 @@
#include "mozilla/layers/AsyncDragMetrics.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/CompositorTypes.h"
#include "ImageTypes.h"
#include "FrameMetrics.h"
#include "FilterSupport.h"
#include "mozilla/layers/GeckoContentController.h"
@ -714,6 +715,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
WriteParam(aMsg, aParam.mMaskLayerIndex);
WriteParam(aMsg, aParam.mIsLayersIdRoot);
WriteParam(aMsg, aParam.mUsesContainerScrolling);
WriteParam(aMsg, aParam.mIsScrollInfoLayer);
WriteParam(aMsg, aParam.GetContentDescription());
}
@ -760,6 +762,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
ReadParam(aMsg, aIter, &aResult->mMaskLayerIndex) &&
ReadParam(aMsg, aIter, &aResult->mIsLayersIdRoot) &&
ReadParam(aMsg, aIter, &aResult->mUsesContainerScrolling) &&
ReadParam(aMsg, aIter, &aResult->mIsScrollInfoLayer) &&
ReadContentDescription(aMsg, aIter, aResult));
}
};
@ -797,7 +800,7 @@ template<>
struct ParamTraits<mozilla::layers::TextureInfo>
{
typedef mozilla::layers::TextureInfo paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mCompositableType);
@ -827,6 +830,14 @@ struct ParamTraits<mozilla::gfx::SurfaceFormat>
mozilla::gfx::SurfaceFormat::UNKNOWN>
{};
template <>
struct ParamTraits<mozilla::StereoMode>
: public ContiguousEnumSerializer<
mozilla::StereoMode,
mozilla::StereoMode::MONO,
mozilla::StereoMode::TOP_BOTTOM>
{};
template <>
struct ParamTraits<mozilla::layers::ScrollableLayerGuid>
{
@ -847,6 +858,7 @@ struct ParamTraits<mozilla::layers::ScrollableLayerGuid>
}
};
template <>
struct ParamTraits<mozilla::layers::ZoomConstraints>
{

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

@ -30,10 +30,10 @@ public:
virtual void Deallocate(ISurfaceAllocator*) override;
MemoryTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
MemoryTextureData(const BufferDescriptor& aDesc,
gfx::BackendType aMoz2DBackend,
uint8_t* aBuffer, size_t aBufferSize)
: BufferTextureData(aSize, aFormat, aMoz2DBackend)
: BufferTextureData(aDesc, aMoz2DBackend)
, mBuffer(aBuffer)
, mBufferSize(aBufferSize)
{
@ -67,9 +67,9 @@ public:
virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
ShmemTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ShmemTextureData(const BufferDescriptor& aDesc,
gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem)
: BufferTextureData(aSize, aFormat, aMoz2DBackend)
: BufferTextureData(aDesc, aMoz2DBackend)
, mShmem(aShmem)
{
MOZ_ASSERT(mShmem.Size<uint8_t>());
@ -97,43 +97,46 @@ BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
}
BufferTextureData*
BufferTextureData::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
size_t aSize,
TextureFlags aTextureFlags)
BufferTextureData::CreateInternal(ISurfaceAllocator* aAllocator,
const BufferDescriptor& aDesc,
gfx::BackendType aMoz2DBackend,
int32_t aBufferSize,
TextureFlags aTextureFlags)
{
if (aSize == 0) {
return nullptr;
}
BufferTextureData* data;
if (!aAllocator || aAllocator->IsSameProcess()) {
uint8_t* buffer = new (fallible) uint8_t[aSize];
uint8_t* buffer = new (fallible) uint8_t[aBufferSize];
if (!buffer) {
return nullptr;
}
data = new MemoryTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, buffer, aSize);
return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize);
} else {
ipc::Shmem shm;
if (!aAllocator->AllocUnsafeShmem(aSize, OptimalShmemType(), &shm)) {
if (!aAllocator->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) {
return nullptr;
}
data = new ShmemTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, shm);
return new ShmemTextureData(aDesc, aMoz2DBackend, shm);
}
}
BufferTextureData*
BufferTextureData::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
int32_t aBufferSize,
TextureFlags aTextureFlags)
{
if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) {
return nullptr;
}
// Initialize the metadata with something, even if it will have to be rewritten
// afterwards since we don't know the dimensions of the texture at this point.
if (aFormat == gfx::SurfaceFormat::YUV) {
YCbCrImageDataSerializer serializer(data->GetBuffer(), data->GetBufferSize());
serializer.InitializeBufferInfo(gfx::IntSize(0,0), gfx::IntSize(0,0), StereoMode::MONO);
} else {
ImageDataSerializer serializer(data->GetBuffer(), data->GetBufferSize());
serializer.InitializeBufferInfo(gfx::IntSize(0, 0), aFormat);
}
BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(),
0, 0, 0, StereoMode::MONO);
return data;
return CreateInternal(aAllocator, desc, gfx::BackendType::NONE, aBufferSize,
aTextureFlags);
}
BufferTextureData*
@ -143,24 +146,41 @@ BufferTextureData::CreateForYCbCr(ISurfaceAllocator* aAllocator,
StereoMode aStereoMode,
TextureFlags aTextureFlags)
{
size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize, aCbCrSize);
BufferTextureData* texture = CreateWithBufferSize(aAllocator, gfx::SurfaceFormat::YUV,
bufSize, aTextureFlags);
if (!texture) {
uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize);
if (bufSize == 0) {
return nullptr;
}
YCbCrImageDataSerializer serializer(texture->GetBuffer(), texture->GetBufferSize());
serializer.InitializeBufferInfo(aYSize, aCbCrSize, aStereoMode);
texture->mSize = aYSize;
uint32_t yOffset;
uint32_t cbOffset;
uint32_t crOffset;
ImageDataSerializer::ComputeYCbCrOffsets(aYSize.width, aYSize.height,
aCbCrSize.width, aCbCrSize.height,
yOffset, cbOffset, crOffset);
return texture;
YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset,
crOffset, aStereoMode);
return CreateInternal(aAllocator, descriptor, gfx::BackendType::NONE, bufSize,
aTextureFlags);
}
gfx::IntSize
BufferTextureData::GetSize() const
{
return ImageDataSerializer::SizeFromBufferDescriptor(mDescriptor);
}
gfx::SurfaceFormat
BufferTextureData::GetFormat() const
{
return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor);
}
bool
BufferTextureData::SupportsMoz2D() const
{
switch (mFormat) {
switch (GetFormat()) {
case gfx::SurfaceFormat::YUV:
case gfx::SurfaceFormat::NV12:
case gfx::SurfaceFormat::UNKNOWN:
@ -179,12 +199,17 @@ BufferTextureData::BorrowDrawTarget()
return dt.forget();
}
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
if (!serializer.IsValid()) {
if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
return nullptr;
}
mDrawTarget = serializer.GetAsDrawTarget(mMoz2DBackend);
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend,
GetBuffer(), rgb.size(),
stride, rgb.format());
if (mDrawTarget) {
RefPtr<gfx::DrawTarget> dt = mDrawTarget;
return dt.forget();
@ -192,7 +217,12 @@ BufferTextureData::BorrowDrawTarget()
// TODO - should we warn? should we really fallback to cairo? perhaps
// at least update mMoz2DBackend...
mDrawTarget = serializer.GetAsDrawTarget(gfx::BackendType::CAIRO);
if (mMoz2DBackend != gfx::BackendType::CAIRO) {
mDrawTarget = gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
GetBuffer(), rgb.size(),
stride, rgb.format());
}
if (!mDrawTarget) {
gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mMoz2DBackend;
}
@ -204,19 +234,16 @@ BufferTextureData::BorrowDrawTarget()
bool
BufferTextureData::BorrowMappedData(MappedTextureData& aData)
{
if (mFormat == gfx::SurfaceFormat::YUV) {
if (GetFormat() == gfx::SurfaceFormat::YUV) {
return false;
}
ImageDataDeserializer view(GetBuffer(), GetBufferSize());
if (!view.IsValid()) {
return false;
}
gfx::IntSize size = GetSize();
aData.data = view.GetData();
aData.size = view.GetSize();
aData.stride = view.GetStride();
aData.format = mFormat;
aData.data = GetBuffer();
aData.size = size;
aData.format = GetFormat();
aData.stride = ImageDataSerializer::ComputeRGBStride(aData.format, size.width);
return true;
}
@ -224,31 +251,32 @@ BufferTextureData::BorrowMappedData(MappedTextureData& aData)
bool
BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
{
if (mFormat != gfx::SurfaceFormat::YUV) {
if (mDescriptor.type() != BufferDescriptor::TYCbCrDescriptor) {
return false;
}
YCbCrImageDataDeserializer view(GetBuffer(), GetBufferSize());
if (!view.IsValid()) {
return false;
}
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
aMap.stereoMode = view.GetStereoMode();
aMap.metadata = GetBuffer();
uint8_t* data = GetBuffer();
auto ySize = desc.ySize();
auto cbCrSize = desc.cbCrSize();
aMap.y.data = view.GetYData();
aMap.y.size = view.GetYSize();
aMap.y.stride = view.GetYStride();
aMap.stereoMode = desc.stereoMode();
aMap.metadata = nullptr;
aMap.y.data = data + desc.yOffset();
aMap.y.size = ySize;
aMap.y.stride = ySize.width;
aMap.y.skip = 0;
aMap.cb.data = view.GetCbData();
aMap.cb.size = view.GetCbCrSize();
aMap.cb.stride = view.GetCbCrStride();
aMap.cb.data = data + desc.cbOffset();
aMap.cb.size = cbCrSize;
aMap.cb.stride = cbCrSize.width;
aMap.cb.skip = 0;
aMap.cr.data = view.GetCrData();
aMap.cr.size = view.GetCbCrSize();
aMap.cr.stride = view.GetCbCrStride();
aMap.cr.data = data + desc.crOffset();
aMap.cr.size = cbCrSize;
aMap.cr.stride = cbCrSize.width;
aMap.cr.skip = 0;
return true;
@ -257,9 +285,15 @@ BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
bool
BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
return false;
}
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
RefPtr<gfx::DataSourceSurface> surface = serializer.GetAsSurface();
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
RefPtr<gfx::DataSourceSurface> surface =
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), stride,
rgb.size(), rgb.format());
if (!surface) {
gfxCriticalError() << "Failed to get serializer as surface!";
@ -304,6 +338,14 @@ BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
return true;
}
void
BufferTextureData::SetDesciptor(const BufferDescriptor& aDescriptor)
{
MOZ_ASSERT(mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor);
MOZ_ASSERT(mDescriptor.get_YCbCrDescriptor().ySize() == gfx::IntSize());
mDescriptor = aDescriptor;
}
bool
MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
@ -312,14 +354,13 @@ MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
return false;
}
aOutDescriptor = SurfaceDescriptorMemory(reinterpret_cast<uintptr_t>(mBuffer),
GetFormat());
uintptr_t ptr = reinterpret_cast<uintptr_t>(mBuffer);
aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(ptr));
return true;
}
static bool InitBuffer(uint8_t* buf, size_t bufSize,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
TextureAllocationFlags aAllocFlags)
static bool InitBuffer(uint8_t* buf, size_t bufSize, TextureAllocationFlags aAllocFlags)
{
if (!buf) {
gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes";
@ -333,8 +374,6 @@ static bool InitBuffer(uint8_t* buf, size_t bufSize,
memset(buf, 0xFF, bufSize);
}
ImageDataSerializer serializer(buf, bufSize);
serializer.InitializeBufferInfo(aSize, aFormat);
return true;
}
@ -344,24 +383,29 @@ MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
TextureAllocationFlags aAllocFlags,
ISurfaceAllocator*)
{
// Should have used CreateForYCbCr.
MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);
if (aSize.width <= 0 || aSize.height <= 0) {
gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
return nullptr;
}
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, aFormat);
uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
if (!bufSize) {
return nullptr;
}
uint8_t* buf = new (fallible) uint8_t[bufSize];
if (InitBuffer(buf, bufSize, aSize, aFormat, aAllocFlags)) {
GfxMemoryImageReporter::DidAlloc(buf);
return new MemoryTextureData(aSize, aFormat, aMoz2DBackend, buf, bufSize);
if (!InitBuffer(buf, bufSize, aAllocFlags)) {
return nullptr;
}
return nullptr;
GfxMemoryImageReporter::DidAlloc(buf);
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize);
}
void
@ -378,7 +422,7 @@ MemoryTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
return MemoryTextureData::Create(mSize, mFormat, mMoz2DBackend,
return MemoryTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
aFlags, aAllocFlags, aAllocator);
}
@ -390,7 +434,7 @@ ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
return false;
}
aOutDescriptor = SurfaceDescriptorShmem(mShmem, GetFormat());
aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(mShmem));
return true;
}
@ -402,6 +446,9 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ISurfaceAllocator* aAllocator)
{
MOZ_ASSERT(aAllocator);
// Should have used CreateForYCbCr.
MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);
if (!aAllocator) {
return nullptr;
}
@ -411,7 +458,7 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
return nullptr;
}
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, aFormat);
uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
if (!bufSize) {
return nullptr;
}
@ -422,11 +469,14 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
}
uint8_t* buf = shm.get<uint8_t>();
if (InitBuffer(buf, bufSize, aSize, aFormat, aAllocFlags)) {
return new ShmemTextureData(aSize, aFormat, aMoz2DBackend, shm);
if (!InitBuffer(buf, bufSize, aAllocFlags)) {
return nullptr;
}
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
return new ShmemTextureData(descriptor, aMoz2DBackend, shm);
return nullptr;
}
@ -435,7 +485,7 @@ ShmemTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
return ShmemTextureData::Create(mSize, mFormat, mMoz2DBackend,
return ShmemTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
aFlags, aAllocFlags, aAllocator);
}

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

@ -6,8 +6,6 @@
#ifndef MOZILLA_LAYERS_BUFFERETEXTURE
#define MOZILLA_LAYERS_BUFFERETEXTURE
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/ipc/SharedMemory.h"
#include "mozilla/gfx/Types.h"
@ -25,24 +23,27 @@ public:
TextureAllocationFlags aAllocFlags,
ISurfaceAllocator* aAllocator);
static BufferTextureData* CreateWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
size_t aSize,
TextureFlags aTextureFlags);
static BufferTextureData* CreateForYCbCr(ISurfaceAllocator* aAllocator,
gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode,
TextureFlags aTextureFlags);
// It is generally better to use CreateForYCbCr instead.
// This creates a half-initialized texture since we don't know the sizes and
// offsets in the buffer.
static BufferTextureData* CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
int32_t aSize,
TextureFlags aTextureFlags);
virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; }
virtual void Unlock() override {}
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual gfx::IntSize GetSize() const override;
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual gfx::SurfaceFormat GetFormat() const override;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
@ -59,19 +60,26 @@ public:
// use TextureClient's default implementation
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
// Don't use this.
void SetDesciptor(const BufferDescriptor& aDesc);
protected:
static BufferTextureData* CreateInternal(ISurfaceAllocator* aAllocator,
const BufferDescriptor& aDesc,
gfx::BackendType aMoz2DBackend,
int32_t aBufferSize,
TextureFlags aTextureFlags);
virtual uint8_t* GetBuffer() = 0;
virtual size_t GetBufferSize() = 0;
BufferTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend)
: mSize(aSize)
, mFormat(aFormat)
BufferTextureData(const BufferDescriptor& aDescriptor, gfx::BackendType aMoz2DBackend)
: mDescriptor(aDescriptor)
, mMoz2DBackend(aMoz2DBackend)
{}
RefPtr<gfx::DrawTarget> mDrawTarget;
gfx::IntSize mSize;
gfx::SurfaceFormat mFormat;
BufferDescriptor mDescriptor;
gfx::BackendType mMoz2DBackend;
};

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

@ -68,6 +68,7 @@ public:
, mAllowVerticalScrollWithWheel(false)
, mIsLayersIdRoot(false)
, mUsesContainerScrolling(false)
, mIsScrollInfoLayer(false)
{
}
@ -104,7 +105,8 @@ public:
mClipRect == aOther.mClipRect &&
mMaskLayerIndex == aOther.mMaskLayerIndex &&
mIsLayersIdRoot == aOther.mIsLayersIdRoot &&
mUsesContainerScrolling == aOther.mUsesContainerScrolling;
mUsesContainerScrolling == aOther.mUsesContainerScrolling &&
mIsScrollInfoLayer == aOther.mIsScrollInfoLayer;
}
bool operator!=(const FrameMetrics& aOther) const
{
@ -545,6 +547,13 @@ public:
return mUsesContainerScrolling;
}
void SetIsScrollInfoLayer(bool aIsScrollInfoLayer) {
mIsScrollInfoLayer = aIsScrollInfoLayer;
}
bool IsScrollInfoLayer() const {
return mIsScrollInfoLayer;
}
private:
// The pres-shell resolution that has been induced on the document containing
@ -732,6 +741,9 @@ private:
// when containerful scrolling is eliminated.
bool mUsesContainerScrolling;
// Whether or not this frame has a "scroll info layer" to capture events.
bool mIsScrollInfoLayer;
// WARNING!!!!
//
// When adding new fields to FrameMetrics, the following places should be

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

@ -4,70 +4,27 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ImageDataSerializer.h"
#include <string.h> // for memcpy
#include "gfx2DGlue.h" // for SurfaceFormatToImageFormat
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
#include "mozilla/gfx/Logging.h" // for gfxDebug
#include "mozilla/gfx/Tools.h" // for GetAlignedStride, etc
#include "mozilla/gfx/Types.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "yuv_convert.h" // for ConvertYCbCrToRGB32, etc
namespace mozilla {
namespace layers {
namespace ImageDataSerializer {
using namespace gfx;
// The Data is layed out as follows:
//
// +-------------------+ -++ --+ <-- ImageDataSerializerBase::mData pointer
// | SurfaceBufferInfo | | |
// +-------------------+ --+ | offset
// | ... | |
// +-------------------+ ------+
// | |
// | data |
// | |
// +-------------------+
#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
// Structure written at the beginning of the data blob containing the image
// (as shown in the figure above). It contains the necessary informations to
// read the image in the blob.
namespace {
struct SurfaceBufferInfo
{
int32_t width;
int32_t height;
SurfaceFormat format;
static int32_t GetOffset()
{
return GetAlignedStride<16>(sizeof(SurfaceBufferInfo));
}
};
} // namespace
static SurfaceBufferInfo*
GetBufferInfo(uint8_t* aData, size_t aDataSize)
{
return aDataSize >= sizeof(SurfaceBufferInfo)
? reinterpret_cast<SurfaceBufferInfo*>(aData)
: nullptr;
}
void
ImageDataSerializer::InitializeBufferInfo(IntSize aSize,
SurfaceFormat aFormat)
{
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
MOZ_ASSERT(info); // OK to assert here, this method is client-side-only
info->width = aSize.width;
info->height = aSize.height;
info->format = aFormat;
Validate();
}
static inline int32_t
ComputeStride(SurfaceFormat aFormat, int32_t aWidth)
int32_t
ComputeRGBStride(SurfaceFormat aFormat, int32_t aWidth)
{
CheckedInt<int32_t> size = BytesPerPixel(aFormat);
size *= aWidth;
@ -79,9 +36,14 @@ ComputeStride(SurfaceFormat aFormat, int32_t aWidth)
return GetAlignedStride<4>(size.value());
}
int32_t
GetRGBStride(const RGBDescriptor& aDescriptor)
{
return ComputeRGBStride(aDescriptor.format(), aDescriptor.size().width);
}
uint32_t
ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
SurfaceFormat aFormat)
ComputeRGBBufferSize(IntSize aSize, SurfaceFormat aFormat)
{
MOZ_ASSERT(aSize.height >= 0 && aSize.width >= 0);
@ -91,9 +53,8 @@ ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
return 0;
}
int32_t bufsize = GetAlignedStride<16>(ComputeStride(aFormat, aSize.width)
* aSize.height)
+ SurfaceBufferInfo::GetOffset();
int32_t bufsize = GetAlignedStride<16>(ComputeRGBStride(aFormat, aSize.width)
* aSize.height);
if (bufsize < 0) {
// This should not be possible thanks to Factory::AllowedSurfaceSize
@ -103,75 +64,121 @@ ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
return bufsize;
}
void
ImageDataSerializerBase::Validate()
{
mIsValid = false;
if (!mData) {
return;
}
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
if (!info) {
return;
}
size_t requiredSize =
ComputeMinBufferSize(IntSize(info->width, info->height), info->format);
mIsValid = !!requiredSize && requiredSize <= mDataSize;
// Minimum required shmem size in bytes
uint32_t
ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride,
const gfx::IntSize& aCbCrSize, int32_t aCbCrStride)
{
MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 ||
aYSize.width > aYStride || aCbCrSize.width > aCbCrStride ||
aCbCrStride > aYStride || aCbCrSize.height > aYSize.height ||
!gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height))) {
return 0;
}
// Overflow checks are performed in AllowedSurfaceSize
return MOZ_ALIGN_WORD(aYSize.height * aYStride)
+ 2 * MOZ_ALIGN_WORD(aCbCrSize.height * aCbCrStride);
}
uint8_t*
ImageDataSerializerBase::GetData()
// Minimum required shmem size in bytes
uint32_t
ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, const gfx::IntSize& aCbCrSize)
{
MOZ_ASSERT(IsValid());
return mData + SurfaceBufferInfo::GetOffset();
return ComputeYCbCrBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width);
}
uint32_t
ImageDataSerializerBase::GetStride() const
ComputeYCbCrBufferSize(uint32_t aBufferSize)
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
return ComputeStride(GetFormat(), info->width);
return MOZ_ALIGN_WORD(aBufferSize);
}
IntSize
ImageDataSerializerBase::GetSize() const
void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight,
int32_t cbCrStride, int32_t cbCrHeight,
uint32_t& outYOffset, uint32_t& outCbOffset, uint32_t& outCrOffset)
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
return IntSize(info->width, info->height);
outYOffset = 0;
outCbOffset = outYOffset + MOZ_ALIGN_WORD(yStride * yHeight);
outCrOffset = outCbOffset + MOZ_ALIGN_WORD(cbCrStride * cbCrHeight);
}
SurfaceFormat
ImageDataSerializerBase::GetFormat() const
gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescriptor)
{
MOZ_ASSERT(IsValid());
return GetBufferInfo(mData, mDataSize)->format;
}
already_AddRefed<DrawTarget>
ImageDataSerializerBase::GetAsDrawTarget(gfx::BackendType aBackend)
{
MOZ_ASSERT(IsValid());
RefPtr<DrawTarget> dt = gfx::Factory::CreateDrawTargetForData(aBackend,
GetData(), GetSize(),
GetStride(), GetFormat());
if (!dt) {
gfxCriticalNote << "Failed GetAsDrawTarget " << IsValid() << ", " << hexa(size_t(mData)) << " + " << SurfaceBufferInfo::GetOffset() << ", " << GetSize() << ", " << GetStride() << ", " << (int)GetFormat();
switch (aDescriptor.type()) {
case BufferDescriptor::TRGBDescriptor:
return aDescriptor.get_RGBDescriptor().format();
case BufferDescriptor::TYCbCrDescriptor:
return gfx::SurfaceFormat::YUV;
default:
MOZ_CRASH();
}
return dt.forget();
}
already_AddRefed<gfx::DataSourceSurface>
ImageDataSerializerBase::GetAsSurface()
gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
{
MOZ_ASSERT(IsValid());
return Factory::CreateWrappingDataSourceSurface(GetData(),
GetStride(),
GetSize(),
GetFormat());
switch (aDescriptor.type()) {
case BufferDescriptor::TRGBDescriptor:
return aDescriptor.get_RGBDescriptor().size();
case BufferDescriptor::TYCbCrDescriptor:
return aDescriptor.get_YCbCrDescriptor().ySize();
default:
MOZ_CRASH();
}
}
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
{
return aBuffer + aDescriptor.yOffset();
}
uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
{
return aBuffer + aDescriptor.cbOffset();
}
uint8_t* GetCrChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
{
return aBuffer + aDescriptor.crOffset();
}
already_AddRefed<DataSourceSurface>
DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
{
gfx::IntSize ySize = aDescriptor.ySize();
gfx::IntSize cbCrSize = aDescriptor.cbCrSize();
int32_t yStride = ySize.width;
int32_t cbCrStride = cbCrSize.width;
RefPtr<DataSourceSurface> result =
Factory::CreateDataSourceSurface(ySize, gfx::SurfaceFormat::B8G8R8X8);
if (NS_WARN_IF(!result)) {
return nullptr;
}
DataSourceSurface::MappedSurface map;
if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) {
return nullptr;
}
gfx::YUVType type = TypeFromSize(ySize.width, ySize.height,
cbCrSize.width, cbCrSize.height);
gfx::ConvertYCbCrToRGB32(GetYChannel(aBuffer, aDescriptor),
GetCbChannel(aBuffer, aDescriptor),
GetCrChannel(aBuffer, aDescriptor),
map.mData,
0, 0, //pic x and y
ySize.width, ySize.height,
yStride, cbCrStride,
map.mStride, type);
result->Unmap();
return result.forget();
}
} // namespace ImageDataSerializer
} // namespace layers
} // namespace mozilla

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

@ -24,72 +24,49 @@ class DrawTarget;
namespace mozilla {
namespace layers {
class ImageDataSerializerBase
{
public:
bool IsValid() const { return mIsValid; }
namespace ImageDataSerializer {
uint8_t* GetData();
uint32_t GetStride() const;
gfx::IntSize GetSize() const;
gfx::SurfaceFormat GetFormat() const;
already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
already_AddRefed<gfx::DrawTarget> GetAsDrawTarget(gfx::BackendType aBackend);
// RGB
static uint32_t ComputeMinBufferSize(gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
int32_t ComputeRGBStride(gfx::SurfaceFormat aFormat, int32_t aWidth);
size_t GetBufferSize() const { return mDataSize; }
int32_t GetRGBStride(const RGBDescriptor& aDescriptor);
protected:
uint32_t ComputeRGBBufferSize(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
ImageDataSerializerBase(uint8_t* aData, size_t aDataSize)
: mData(aData)
, mDataSize(aDataSize)
, mIsValid(false)
{}
void Validate();
// YCbCr
uint8_t* mData;
size_t mDataSize;
bool mIsValid;
};
///This function is meant as a helper to know how much shared memory we need
///to allocate in a shmem in order to place a shared YCbCr image blob of
///given dimensions.
uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize,
int32_t aYStride,
const gfx::IntSize& aCbCrSize,
int32_t aCbCrStride);
uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize);
/**
* A facility to serialize an image into a buffer of memory.
* This is intended for use with the IPC code, in order to copy image data
* into shared memory.
* Note that there is a separate serializer class for YCbCr images
* (see YCbCrImageDataSerializer.h).
*/
class MOZ_STACK_CLASS ImageDataSerializer : public ImageDataSerializerBase
{
public:
ImageDataSerializer(uint8_t* aData, size_t aDataSize)
: ImageDataSerializerBase(aData, aDataSize)
{
// a serializer needs to be usable before correct buffer info has been written to it
mIsValid = !!mData;
}
void InitializeBufferInfo(gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
};
uint32_t ComputeYCbCrBufferSize(uint32_t aBufferSize);
/**
* A facility to deserialize image data that has been serialized by an
* ImageDataSerializer.
*/
class MOZ_STACK_CLASS ImageDataDeserializer : public ImageDataSerializerBase
{
public:
ImageDataDeserializer(uint8_t* aData, size_t aDataSize)
: ImageDataSerializerBase(aData, aDataSize)
{
Validate();
}
void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight,
int32_t cbCrStride, int32_t cbCrHeight,
uint32_t& outYOffset, uint32_t& outCbOffset, uint32_t& outCrOffset);
};
gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescriptor);
gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
uint8_t* GetCrChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
already_AddRefed<gfx::DataSourceSurface>
DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
} // ImageDataSerializer
} // namespace layers
} // namespace mozilla

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

@ -1,317 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include <string.h> // for memcpy
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Logging.h" // for gfxDebug
#include "mozilla/gfx/Types.h"
#include "mozilla/mozalloc.h" // for operator delete
#include "nsDebug.h" // for NS_WARN_IF
#include "yuv_convert.h" // for ConvertYCbCrToRGB32, etc
#include "nsDebug.h"
#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
namespace mozilla {
using namespace gfx;
namespace layers {
// The Data is layed out as follows:
//
// +-----------------+ -++ --+ --+ <-- Beginning of the buffer
// | YCbCrBufferInfo | | | |
// +-----------------+ --+ | |
// | data | | | YCbCrBufferInfo->[mY/mCb/mCr]Offset
// +-----------------+ ------+ |
// | data | |
// +-----------------+ ----------+
// | data |
// +-----------------+
//
// There can be padding between the blocks above to keep word alignment.
// Structure written at the beginning og the data blob containing the image
// (as shown in the figure above). It contains the necessary informations to
// read the image in the blob.
struct YCbCrBufferInfo
{
uint32_t mYOffset;
uint32_t mCbOffset;
uint32_t mCrOffset;
uint32_t mYStride;
uint32_t mYWidth;
uint32_t mYHeight;
uint32_t mCbCrStride;
uint32_t mCbCrWidth;
uint32_t mCbCrHeight;
StereoMode mStereoMode;
};
static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData, size_t aDataSize)
{
return aDataSize >= sizeof(YCbCrBufferInfo)
? reinterpret_cast<YCbCrBufferInfo*>(aData)
: nullptr;
}
void YCbCrImageDataDeserializerBase::Validate()
{
mIsValid = false;
if (!mData) {
return;
}
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
if (!info) {
return;
}
size_t requiredSize = ComputeMinBufferSize(
IntSize(info->mYWidth, info->mYHeight),
info->mYStride,
IntSize(info->mCbCrWidth, info->mCbCrHeight),
info->mCbCrStride);
mIsValid = requiredSize <= mDataSize;
}
uint8_t* YCbCrImageDataDeserializerBase::GetYData()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return reinterpret_cast<uint8_t*>(info) + info->mYOffset;
}
uint8_t* YCbCrImageDataDeserializerBase::GetCbData()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return reinterpret_cast<uint8_t*>(info) + info->mCbOffset;
}
uint8_t* YCbCrImageDataDeserializerBase::GetCrData()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return reinterpret_cast<uint8_t*>(info) + info->mCrOffset;
}
uint8_t* YCbCrImageDataDeserializerBase::GetData()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return (reinterpret_cast<uint8_t*>(info)) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
}
uint32_t YCbCrImageDataDeserializerBase::GetYStride()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return info->mYStride;
}
uint32_t YCbCrImageDataDeserializerBase::GetCbCrStride()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return info->mCbCrStride;
}
gfx::IntSize YCbCrImageDataDeserializerBase::GetYSize()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return gfx::IntSize(info->mYWidth, info->mYHeight);
}
gfx::IntSize YCbCrImageDataDeserializerBase::GetCbCrSize()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return gfx::IntSize(info->mCbCrWidth, info->mCbCrHeight);
}
StereoMode YCbCrImageDataDeserializerBase::GetStereoMode()
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
return info->mStereoMode;
}
// Offset in bytes
static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride)
{
return MOZ_ALIGN_WORD(aHeight * aStride);
}
// Minimum required shmem size in bytes
size_t
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
uint32_t aYStride,
const gfx::IntSize& aCbCrSize,
uint32_t aCbCrStride)
{
MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0) {
gfxDebug() << "Non-positive YCbCr buffer size request " << aYSize.height << "x" << aYSize.width << ", " << aCbCrSize.height << "x" << aCbCrSize.width;
return 0;
}
if (aYSize != IntSize() &&
(!gfx::Factory::AllowedSurfaceSize(aYSize) ||
aCbCrSize.width > aYSize.width ||
aCbCrSize.height > aYSize.height)) {
return 0;
}
return ComputeOffset(aYSize.height, aYStride)
+ 2 * ComputeOffset(aCbCrSize.height, aCbCrStride)
+ MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
}
// Minimum required shmem size in bytes
size_t
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize)
{
return ComputeMinBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width);
}
// Offset in bytes
static size_t ComputeOffset(uint32_t aSize)
{
return MOZ_ALIGN_WORD(aSize);
}
// Minimum required shmem size in bytes
size_t
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(uint32_t aSize)
{
return ComputeOffset(aSize) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
}
void
YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYOffset,
uint32_t aCbOffset,
uint32_t aCrOffset,
uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode)
{
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
MOZ_ASSERT(info); // OK to assert here, this method is client-side-only
uint32_t info_size = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
info->mYOffset = info_size + aYOffset;
info->mCbOffset = info_size + aCbOffset;
info->mCrOffset = info_size + aCrOffset;
info->mYStride = aYStride;
info->mYWidth = aYSize.width;
info->mYHeight = aYSize.height;
info->mCbCrStride = aCbCrStride;
info->mCbCrWidth = aCbCrSize.width;
info->mCbCrHeight = aCbCrSize.height;
info->mStereoMode = aStereoMode;
Validate();
}
void
YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode)
{
uint32_t yOffset = 0;
uint32_t cbOffset = yOffset + MOZ_ALIGN_WORD(aYStride * aYSize.height);
uint32_t crOffset = cbOffset + MOZ_ALIGN_WORD(aCbCrStride * aCbCrSize.height);
return InitializeBufferInfo(yOffset, cbOffset, crOffset,
aYStride, aCbCrStride, aYSize, aCbCrSize, aStereoMode);
}
void
YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode)
{
return InitializeBufferInfo(aYSize.width, aCbCrSize.width, aYSize, aCbCrSize, aStereoMode);
}
static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) {
for (uint32_t i = 0; i < len; ++i) {
*dst = *src;
src += 1 + skip;
++dst;
}
}
bool
YCbCrImageDataSerializer::CopyData(const uint8_t* aYData,
const uint8_t* aCbData, const uint8_t* aCrData,
gfx::IntSize aYSize, uint32_t aYStride,
gfx::IntSize aCbCrSize, uint32_t aCbCrStride,
uint32_t aYSkip, uint32_t aCbCrSkip)
{
if (!IsValid() || GetYSize() != aYSize || GetCbCrSize() != aCbCrSize) {
return false;
}
for (int i = 0; i < aYSize.height; ++i) {
if (aYSkip == 0) {
// fast path
memcpy(GetYData() + i * GetYStride(),
aYData + i * aYStride,
aYSize.width);
} else {
// slower path
CopyLineWithSkip(aYData + i * aYStride,
GetYData() + i * GetYStride(),
aYSize.width, aYSkip);
}
}
for (int i = 0; i < aCbCrSize.height; ++i) {
if (aCbCrSkip == 0) {
// fast path
memcpy(GetCbData() + i * GetCbCrStride(),
aCbData + i * aCbCrStride,
aCbCrSize.width);
memcpy(GetCrData() + i * GetCbCrStride(),
aCrData + i * aCbCrStride,
aCbCrSize.width);
} else {
// slower path
CopyLineWithSkip(aCbData + i * aCbCrStride,
GetCbData() + i * GetCbCrStride(),
aCbCrSize.width, aCbCrSkip);
CopyLineWithSkip(aCrData + i * aCbCrStride,
GetCrData() + i * GetCbCrStride(),
aCbCrSize.width, aCbCrSkip);
}
}
return true;
}
already_AddRefed<DataSourceSurface>
YCbCrImageDataDeserializer::ToDataSourceSurface()
{
RefPtr<DataSourceSurface> result =
Factory::CreateDataSourceSurface(GetYSize(), gfx::SurfaceFormat::B8G8R8X8);
if (NS_WARN_IF(!result)) {
return nullptr;
}
DataSourceSurface::MappedSurface map;
if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) {
return nullptr;
}
gfx::YUVType type = TypeFromSize(GetYSize().width, GetYSize().height,
GetCbCrSize().width, GetCbCrSize().height);
gfx::ConvertYCbCrToRGB32(GetYData(), GetCbData(), GetCrData(),
map.mData,
0, 0, //pic x and y
GetYSize().width, GetYSize().height,
GetYStride(), GetCbCrStride(),
map.mStride, type);
result->Unmap();
return result.forget();
}
} // namespace layers
} // namespace mozilla

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

@ -1,186 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_LAYERS_BLOBYCBCRSURFACE_H
#define MOZILLA_LAYERS_BLOBYCBCRSURFACE_H
#include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t, uint32_t
#include "ImageTypes.h" // for StereoMode
#include "mozilla/Attributes.h" // for MOZ_STACK_CLASS
#include "mozilla/RefPtr.h" // for already_AddRefed
#include "mozilla/gfx/Point.h" // for IntSize
namespace mozilla {
namespace gfx {
class DataSourceSurface;
} // namespace gfx
namespace layers {
class Image;
/**
* Convenience class to share code between YCbCrImageDataSerializer
* and YCbCrImageDataDeserializer.
* Do not use it.
*/
class YCbCrImageDataDeserializerBase
{
public:
bool IsValid() const { return mIsValid; }
/**
* Returns the Y channel data pointer.
*/
uint8_t* GetYData();
/**
* Returns the Cb channel data pointer.
*/
uint8_t* GetCbData();
/**
* Returns the Cr channel data pointer.
*/
uint8_t* GetCrData();
/**
* Returns the Y channel stride.
*/
uint32_t GetYStride();
/**
* Returns the stride of the Cb and Cr channels.
*/
uint32_t GetCbCrStride();
/**
* Returns the dimensions of the Y Channel.
*/
gfx::IntSize GetYSize();
/**
* Returns the dimensions of the Cb and Cr Channel.
*/
gfx::IntSize GetCbCrSize();
/**
* Stereo mode for the image.
*/
StereoMode GetStereoMode();
/**
* Return a pointer to the begining of the data buffer.
*/
uint8_t* GetData();
/**
* This function is meant as a helper to know how much shared memory we need
* to allocate in a shmem in order to place a shared YCbCr image blob of
* given dimensions.
*/
static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
uint32_t aYStride,
const gfx::IntSize& aCbCrSize,
uint32_t aCbCrStride);
static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize);
static size_t ComputeMinBufferSize(uint32_t aSize);
protected:
YCbCrImageDataDeserializerBase(uint8_t* aData, size_t aDataSize)
: mData (aData)
, mDataSize(aDataSize)
, mIsValid(false)
{}
void Validate();
uint8_t* mData;
size_t mDataSize;
bool mIsValid;
};
/**
* A view on a YCbCr image stored with its metadata in a blob of memory.
* It is only meant as a convenience to access the image data, and does not own
* the data. The instance can live on the stack and used as follows:
*
* const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
* YCbCrImageDataDeserializer deserializer(yuv.data().get<uint8_t>());
* if (!deserializer.IsValid()) {
* // handle error
* }
* size = deserializer.GetYSize(); // work with the data, etc...
*/
class MOZ_STACK_CLASS YCbCrImageDataSerializer : public YCbCrImageDataDeserializerBase
{
public:
YCbCrImageDataSerializer(uint8_t* aData, size_t aDataSize)
: YCbCrImageDataDeserializerBase(aData, aDataSize)
{
// a serializer needs to be usable before correct buffer info has been written to it
mIsValid = !!mData;
}
/**
* Write the image informations in the buffer for given dimensions.
* The provided pointer should point to the beginning of the (chunk of)
* buffer on which we want to store the image.
*/
void InitializeBufferInfo(uint32_t aYOffset,
uint32_t aCbOffset,
uint32_t aCrOffset,
uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode);
void InitializeBufferInfo(uint32_t aYStride,
uint32_t aCbCrStride,
const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode);
void InitializeBufferInfo(const gfx::IntSize& aYSize,
const gfx::IntSize& aCbCrSize,
StereoMode aStereoMode);
bool CopyData(const uint8_t* aYData,
const uint8_t* aCbData, const uint8_t* aCrData,
gfx::IntSize aYSize, uint32_t aYStride,
gfx::IntSize aCbCrSize, uint32_t aCbCrStride,
uint32_t aYSkip, uint32_t aCbCrSkip);
};
/**
* A view on a YCbCr image stored with its metadata in a blob of memory.
* It is only meant as a convenience to access the image data, and does not own
* the data. The instance can live on the stack and used as follows:
*
* const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
* YCbCrImageDataDeserializer deserializer(yuv.data().get<uint8_t>());
* if (!deserializer.IsValid()) {
* // handle error
* }
* size = deserializer.GetYSize(); // work with the data, etc...
*/
class MOZ_STACK_CLASS YCbCrImageDataDeserializer : public YCbCrImageDataDeserializerBase
{
public:
YCbCrImageDataDeserializer(uint8_t* aData, size_t aDataSize)
: YCbCrImageDataDeserializerBase(aData, aDataSize)
{
Validate();
}
/**
* Convert the YCbCr data into RGB and return a DataSourceSurface.
* This is a costly operation, so use it only when YCbCr compositing is
* not supported.
*/
already_AddRefed<gfx::DataSourceSurface> ToDataSourceSurface();
};
} // namespace layers
} // namespace mozilla
#endif

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

@ -28,7 +28,6 @@
#include "nsPoint.h" // for nsIntPoint
#include "nsThreadUtils.h" // for NS_IsMainThread
#include "OverscrollHandoffState.h" // for OverscrollHandoffState
#include "TaskThrottler.h" // for TaskThrottler
#include "TreeTraversal.h" // for generic tree traveral algorithms
#include "LayersLogging.h" // for Stringify
#include "Units.h" // for ParentlayerPixel
@ -86,11 +85,10 @@ struct APZCTreeManager::TreeBuildingState {
/*static*/ const ScreenMargin
APZCTreeManager::CalculatePendingDisplayPort(
const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity,
double aEstimatedPaintDuration)
const ParentLayerPoint& aVelocity)
{
return AsyncPanZoomController::CalculatePendingDisplayPort(
aFrameMetrics, aVelocity, aEstimatedPaintDuration);
aFrameMetrics, aVelocity);
}
APZCTreeManager::APZCTreeManager()
@ -111,11 +109,10 @@ APZCTreeManager::~APZCTreeManager()
AsyncPanZoomController*
APZCTreeManager::NewAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler)
GeckoContentController* aController)
{
return new AsyncPanZoomController(aLayersId, this, mInputQueue,
aController, aPaintThrottler, AsyncPanZoomController::USE_GESTURE_DETECTOR);
aController, AsyncPanZoomController::USE_GESTURE_DETECTOR);
}
TimeStamp
@ -201,32 +198,6 @@ APZCTreeManager::UpdateHitTestingTree(CompositorParent* aCompositor,
#endif
}
void
APZCTreeManager::InitializeForLayersId(uint64_t aLayersId)
{
MOZ_ASSERT(NS_IsMainThread());
auto throttlerInsertResult = mPaintThrottlerMap.insert(
std::make_pair(aLayersId, RefPtr<TaskThrottler>()));
if (throttlerInsertResult.second) {
throttlerInsertResult.first->second = new TaskThrottler(
GetFrameTime(), TimeDuration::FromMilliseconds(500));
}
}
void
APZCTreeManager::AdoptLayersId(uint64_t aLayersId, APZCTreeManager* aOldManager)
{
MOZ_ASSERT(aOldManager);
if (aOldManager == this) {
return;
}
auto iter = aOldManager->mPaintThrottlerMap.find(aLayersId);
if (iter != aOldManager->mPaintThrottlerMap.end()) {
mPaintThrottlerMap[aLayersId] = iter->second;
aOldManager->mPaintThrottlerMap.erase(iter);
}
}
// Compute the clip region to be used for a layer with an APZC. This function
// is only called for layers which actually have scrollable metrics and an APZC.
static ParentLayerIntRegion
@ -462,12 +433,7 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
// a destroyed APZC and so we need to throw that out and make a new one.
bool newApzc = (apzc == nullptr || apzc->IsDestroyed());
if (newApzc) {
// Look up the paint throttler for this layers id, or create it if
// this is the first APZC for this layers id.
RefPtr<TaskThrottler> throttler = mPaintThrottlerMap[aLayersId];
MOZ_ASSERT(throttler);
apzc = NewAPZCInstance(aLayersId, state->mController, throttler);
apzc = NewAPZCInstance(aLayersId, state->mController);
apzc->SetCompositorParent(aState.mCompositor);
if (state->mCrossProcessParent != nullptr) {
apzc->ShareFrameMetricsAcrossProcesses();
@ -657,23 +623,10 @@ WillHandleInput(const PanGestureOrScrollWheelInput& aPanInput)
void
APZCTreeManager::FlushApzRepaints(uint64_t aLayersId)
{
// Previously, paints were throttled and therefore this method was used to
// ensure any pending paints were flushed. Now, paints are flushed
// immediately, so it is safe to simply send a notification now.
APZCTM_LOG("Flushing repaints for layers id %" PRIu64, aLayersId);
{ // scope lock
MonitorAutoLock lock(mTreeLock);
mTreeLock.AssertCurrentThreadOwns();
ForEachNode(mRootNode.get(),
[aLayersId](HitTestingTreeNode* aNode)
{
if (aNode->IsPrimaryHolder()) {
AsyncPanZoomController* apzc = aNode->GetApzc();
MOZ_ASSERT(apzc);
if (apzc->GetGuid().mLayersId == aLayersId) {
apzc->FlushRepaintIfPending();
}
}
});
}
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
MOZ_ASSERT(state && state->mController);
NS_DispatchToMainThread(NS_NewRunnableMethod(

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

@ -52,7 +52,6 @@ class LayerMetricsWrapper;
class InputQueue;
class GeckoContentController;
class HitTestingTreeNode;
class TaskThrottler;
/**
* ****************** NOTE ON LOCK ORDERING IN APZ **************************
@ -137,17 +136,6 @@ public:
uint64_t aOriginatingLayersId,
uint32_t aPaintSequenceNumber);
/**
* Do any per-layers-id setup needed. This will be called on the main thread,
* and may be called multiple times for the same layers id.
*/
void InitializeForLayersId(uint64_t aLayersId);
/**
* Move any per-layers-id state from the old APZCTreeManager to this one.
*/
void AdoptLayersId(uint64_t aLayersId, APZCTreeManager* aOldManager);
/**
* Walk the tree of APZCs and flushes the repaint requests for all the APZCS
* corresponding to the given layers id. Finally, sends a flush complete
@ -286,8 +274,7 @@ public:
*/
static const ScreenMargin CalculatePendingDisplayPort(
const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity,
double aEstimatedPaintDuration);
const ParentLayerPoint& aVelocity);
/**
* Set the dpi value used by all AsyncPanZoomControllers.
@ -420,8 +407,7 @@ protected:
// Protected hooks for gtests subclass
virtual AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler);
GeckoContentController* aController);
public:
// Public hooks for gtests subclass
virtual TimeStamp GetFrameTime();
@ -536,10 +522,6 @@ private:
/* Holds the zoom constraints for scrollable layers, as determined by the
* the main-thread gecko code. */
std::map<ScrollableLayerGuid, ZoomConstraints> mZoomConstraints;
/* Stores a paint throttler for each layers id. There is one for each layers
* id to ensure that one child process painting slowly doesn't hold up
* another. */
std::map<uint64_t, RefPtr<TaskThrottler>> mPaintThrottlerMap;
/* This tracks the APZC that should receive all inputs for the current input event block.
* This allows touch points to move outside the thing they started on, but still have the
* touch events delivered to the same initial APZC. This will only ever be touched on the

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

@ -18,7 +18,6 @@
#include "InputBlockState.h" // for InputBlockState, TouchBlockState
#include "InputQueue.h" // for InputQueue
#include "OverscrollHandoffState.h" // for OverscrollHandoffState
#include "TaskThrottler.h" // for TaskThrottler
#include "Units.h" // for CSSRect, CSSPoint, etc
#include "UnitTransforms.h" // for TransformTo
#include "base/message_loop.h" // for MessageLoop
@ -239,9 +238,6 @@ using mozilla::gfx::PointTyped;
* rather than using the "stationary" multipliers.\n
* Units: CSS pixels per millisecond
*
* \li\b apz.num_paint_duration_samples
* Number of samples to store of how long it took to paint after the previous
*
* \li\b apz.overscroll.enabled
* Pref that enables overscrolling. If this is disabled, excess scroll that
* cannot be handed off is discarded.
@ -303,12 +299,6 @@ using mozilla::gfx::PointTyped;
* within this distance on scrollable frames.\n
* Units: (real-world, i.e. screen) inches
*
* \li\b apz.use_paint_duration
* Whether or not to use the estimated paint duration as a factor when projecting
* the displayport in the direction of scrolling. If this value is set to false,
* a constant 50ms paint time is used; the projection can be scaled as desired
* using the \b apz.velocity_bias pref below.
*
* \li\b apz.velocity_bias
* How much to adjust the displayport in the direction of scrolling. This value
* is multiplied by the velocity and added to the displayport offset.
@ -356,6 +346,12 @@ StaticAutoPtr<ComputedTimingFunction> gZoomAnimationFunction;
*/
StaticAutoPtr<ComputedTimingFunction> gVelocityCurveFunction;
/**
* The estimated duration of a paint for the purposes of calculating a new
* displayport, in milliseconds.
*/
static const double kDefaultEstimatedPaintDurationMs = 50;
/**
* Returns true if this is a high memory system and we can use
* extra memory for a larger displayport to reduce checkerboarding.
@ -851,10 +847,8 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
APZCTreeManager* aTreeManager,
const RefPtr<InputQueue>& aInputQueue,
GeckoContentController* aGeckoContentController,
TaskThrottler* aPaintThrottler,
GestureBehavior aGestures)
: mLayersId(aLayersId),
mPaintThrottler(aPaintThrottler),
mGeckoContentController(aGeckoContentController),
mRefPtrMonitor("RefPtrMonitor"),
// mTreeManager must be initialized before GetFrameTime() is called
@ -2695,9 +2689,14 @@ RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize,
/* static */
const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort(
const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity,
double aEstimatedPaintDuration)
const ParentLayerPoint& aVelocity)
{
if (aFrameMetrics.IsScrollInfoLayer()) {
// Don't compute margins. Since we can't asynchronously scroll this frame,
// we don't want to paint anything more than the composition bounds.
return ScreenMargin();
}
CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels();
CSSPoint velocity = aVelocity / aFrameMetrics.GetZoom();
CSSPoint scrollOffset = aFrameMetrics.GetScrollOffset();
@ -2712,8 +2711,7 @@ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort(
// Offset the displayport, depending on how fast we're moving and the
// estimated time it takes to paint, to try to minimise checkerboarding.
float estimatedPaintDurationMillis = (float)(aEstimatedPaintDuration * 1000.0);
float paintFactor = (gfxPrefs::APZUsePaintDuration() ? estimatedPaintDurationMillis : 50.0f);
float paintFactor = kDefaultEstimatedPaintDurationMs;
CSSRect displayPort = CSSRect(scrollOffset + (velocity * paintFactor * gfxPrefs::APZVelocityBias()),
displayPortSize);
@ -2746,11 +2744,7 @@ void AsyncPanZoomController::ScheduleComposite() {
void AsyncPanZoomController::ScheduleCompositeAndMaybeRepaint() {
ScheduleComposite();
TimeDuration timePaintDelta = mPaintThrottler->TimeSinceLastRequest(GetFrameTime());
if (timePaintDelta.ToMilliseconds() > gfxPrefs::APZPanRepaintInterval()) {
RequestContentRepaint();
}
RequestContentRepaint();
}
void AsyncPanZoomController::FlushRepaintForOverscrollHandoff() {
@ -2763,25 +2757,10 @@ void AsyncPanZoomController::FlushRepaintForNewInputBlock() {
APZC_LOG("%p flushing repaint for new input block\n", this);
ReentrantMonitorAutoEnter lock(mMonitor);
// We need to send a new repaint request unthrottled, but that
// will obsolete any pending repaint request in the paint throttler.
// Therefore we should clear out the pending task and restore the
// state of mLastPaintRequestMetrics to what it was before the
// pending task was queued.
mPaintThrottler->CancelPendingTask();
mLastPaintRequestMetrics = mLastDispatchedPaintMetrics;
RequestContentRepaint(mFrameMetrics, false /* not throttled */);
RequestContentRepaint(mFrameMetrics);
UpdateSharedCompositorFrameMetrics();
}
void AsyncPanZoomController::FlushRepaintIfPending() {
// Just tell the paint throttler to send the pending repaint request if
// there is one.
ReentrantMonitorAutoEnter lock(mMonitor);
mPaintThrottler->TaskComplete(GetFrameTime());
}
bool AsyncPanZoomController::SnapBackIfOverscrolled() {
ReentrantMonitorAutoEnter lock(mMonitor);
// It's possible that we're already in the middle of an overscroll
@ -2824,11 +2803,8 @@ void AsyncPanZoomController::RequestContentRepaint() {
RequestContentRepaint(mFrameMetrics);
}
void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics, bool aThrottled) {
aFrameMetrics.SetDisplayPortMargins(
CalculatePendingDisplayPort(aFrameMetrics,
GetVelocityVector(),
mPaintThrottler->AverageDuration().ToSeconds()));
void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics) {
aFrameMetrics.SetDisplayPortMargins(CalculatePendingDisplayPort(aFrameMetrics, GetVelocityVector()));
aFrameMetrics.SetUseDisplayPortMargins();
// If we're trying to paint what we already think is painted, discard this
@ -2852,19 +2828,8 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics,
return;
}
if (aThrottled) {
mPaintThrottler->PostTask(
FROM_HERE,
UniquePtr<CancelableTask>(NewRunnableMethod(this,
&AsyncPanZoomController::DispatchRepaintRequest,
aFrameMetrics)),
GetFrameTime());
} else {
DispatchRepaintRequest(aFrameMetrics);
}
DispatchRepaintRequest(aFrameMetrics);
aFrameMetrics.SetPresShellId(mLastContentPaintMetrics.GetPresShellId());
mLastPaintRequestMetrics = aFrameMetrics;
}
/*static*/ CSSRect
@ -2881,18 +2846,21 @@ GetDisplayPortRect(const FrameMetrics& aFrameMetrics)
void
AsyncPanZoomController::DispatchRepaintRequest(const FrameMetrics& aFrameMetrics) {
RefPtr<GeckoContentController> controller = GetGeckoContentController();
if (controller) {
APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this);
LogRendertraceRect(GetGuid(), "requested displayport", "yellow", GetDisplayPortRect(aFrameMetrics));
if (NS_IsMainThread()) {
controller->RequestContentRepaint(aFrameMetrics);
} else {
NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<FrameMetrics>(
controller, &GeckoContentController::RequestContentRepaint, aFrameMetrics));
}
mLastDispatchedPaintMetrics = aFrameMetrics;
if (!controller) {
return;
}
APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this);
LogRendertraceRect(GetGuid(), "requested displayport", "yellow", GetDisplayPortRect(aFrameMetrics));
if (NS_IsMainThread()) {
controller->RequestContentRepaint(aFrameMetrics);
} else {
NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<FrameMetrics>(
controller, &GeckoContentController::RequestContentRepaint, aFrameMetrics));
}
mExpectedGeckoMetrics = aFrameMetrics;
mLastPaintRequestMetrics = aFrameMetrics;
}
bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
@ -2913,16 +2881,11 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
if (mAnimation) {
bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta);
*aOutDeferredTasks = mAnimation->TakeDeferredTasks();
if (continueAnimation) {
if (mPaintThrottler->TimeSinceLastRequest(aSampleTime) >
mAnimation->mRepaintInterval) {
RequestContentRepaint();
}
} else {
if (!continueAnimation) {
mAnimation = nullptr;
SetState(NOTHING);
RequestContentRepaint();
}
RequestContentRepaint();
UpdateSharedCompositorFrameMetrics();
return true;
}
@ -3071,7 +3034,7 @@ Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {
ReentrantMonitorAutoEnter lock(mMonitor);
LayerPoint scrollChange =
(mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset())
(mLastContentPaintMetrics.GetScrollOffset() - mExpectedGeckoMetrics.GetScrollOffset())
* mLastContentPaintMetrics.GetDevPixelsPerCSSPixel()
* mLastContentPaintMetrics.GetCumulativeResolution();
@ -3081,7 +3044,7 @@ Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {
LayoutDeviceToParentLayerScale2D lastContentZoom =
mLastContentPaintMetrics.GetZoom() / mLastContentPaintMetrics.GetDevPixelsPerCSSPixel();
LayoutDeviceToParentLayerScale2D lastDispatchedZoom =
mLastDispatchedPaintMetrics.GetZoom() / mLastDispatchedPaintMetrics.GetDevPixelsPerCSSPixel();
mExpectedGeckoMetrics.GetZoom() / mExpectedGeckoMetrics.GetDevPixelsPerCSSPixel();
gfxSize zoomChange = lastContentZoom / lastDispatchedZoom;
return Matrix4x4::Translation(scrollChange.x, scrollChange.y, 0).
@ -3159,7 +3122,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset());
}
mPaintThrottler->TaskComplete(GetFrameTime());
bool needContentRepaint = false;
bool viewportUpdated = false;
if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().width, mFrameMetrics.GetCompositionBounds().width) &&
@ -3190,16 +3152,13 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
if (aIsFirstPaint || isDefault) {
// Initialize our internal state to something sane when the content
// that was just painted is something we knew nothing about previously
mPaintThrottler->ClearHistory();
mPaintThrottler->SetMaxDurations(gfxPrefs::APZNumPaintDurationSamples());
CancelAnimation();
mFrameMetrics = aLayerMetrics;
if (scrollOffsetUpdated) {
AcknowledgeScrollUpdate();
}
mLastDispatchedPaintMetrics = aLayerMetrics;
mExpectedGeckoMetrics = aLayerMetrics;
ShareCompositorFrameMetrics();
if (mFrameMetrics.GetDisplayPortMargins() != ScreenMargin()) {
@ -3252,6 +3211,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
mFrameMetrics.SetMaskLayerIndex(aLayerMetrics.GetMaskLayerIndex());
mFrameMetrics.SetIsLayersIdRoot(aLayerMetrics.IsLayersIdRoot());
mFrameMetrics.SetUsesContainerScrolling(aLayerMetrics.UsesContainerScrolling());
mFrameMetrics.SetIsScrollInfoLayer(aLayerMetrics.IsScrollInfoLayer());
if (scrollOffsetUpdated) {
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
@ -3261,13 +3221,13 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
// Send an acknowledgement with the new scroll generation so that any
// repaint requests later in this function go through.
// Because of the scroll generation update, any inflight paint requests are
// going to be ignored by layout, and so mLastDispatchedPaintMetrics
// going to be ignored by layout, and so mExpectedGeckoMetrics
// becomes incorrect for the purposes of calculating the LD transform. To
// correct this we need to update mLastDispatchedPaintMetrics to be the
// correct this we need to update mExpectedGeckoMetrics to be the
// last thing we know was painted by Gecko.
mFrameMetrics.CopyScrollInfoFrom(aLayerMetrics);
AcknowledgeScrollUpdate();
mLastDispatchedPaintMetrics = aLayerMetrics;
mExpectedGeckoMetrics = aLayerMetrics;
// Cancel the animation (which might also trigger a repaint request)
// after we update the scroll offset above. Otherwise we can be left
@ -3299,7 +3259,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
// above.
mFrameMetrics.CopySmoothScrollInfoFrom(aLayerMetrics);
AcknowledgeScrollUpdate();
mLastDispatchedPaintMetrics = aLayerMetrics;
mExpectedGeckoMetrics = aLayerMetrics;
if (mState == SMOOTH_SCROLL && mAnimation) {
APZC_LOG("%p updating destination on existing animation\n", this);
@ -3438,9 +3398,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
endZoomToMetrics.SetScrollOffset(aRect.TopLeft());
endZoomToMetrics.SetDisplayPortMargins(
CalculatePendingDisplayPort(endZoomToMetrics,
ParentLayerPoint(0,0),
0));
CalculatePendingDisplayPort(endZoomToMetrics, ParentLayerPoint(0,0)));
endZoomToMetrics.SetUseDisplayPortMargins();
StartAnimation(new ZoomAnimation(

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

@ -24,7 +24,6 @@
#include "APZUtils.h"
#include "Layers.h" // for Layer::ScrollDirection
#include "LayersTypes.h"
#include "TaskThrottler.h"
#include "mozilla/gfx/Matrix.h"
#include "nsRegion.h"
@ -104,7 +103,6 @@ public:
APZCTreeManager* aTreeManager,
const RefPtr<InputQueue>& aInputQueue,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler,
GestureBehavior aGestures = DEFAULT_GESTURES);
// --------------------------------------------------------------------------
@ -186,11 +184,6 @@ public:
*/
void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint);
/**
* Flush any pending repaint request.
*/
void FlushRepaintIfPending();
/**
* The platform implementation must set the compositor parent so that we can
* request composites.
@ -269,8 +262,7 @@ public:
*/
static const ScreenMargin CalculatePendingDisplayPort(
const FrameMetrics& aFrameMetrics,
const ParentLayerPoint& aVelocity,
double aEstimatedPaintDuration);
const ParentLayerPoint& aVelocity);
nsEventStatus HandleDragEvent(const MouseInput& aEvent,
const AsyncDragMetrics& aDragMetrics);
@ -597,7 +589,7 @@ protected:
* the paint throttler. In particular, the GeckoContentController::RequestContentRepaint
* function will be invoked before this function returns.
*/
void RequestContentRepaint(FrameMetrics& aFrameMetrics, bool aThrottled = true);
void RequestContentRepaint(FrameMetrics& aFrameMetrics);
/**
* Actually send the next pending paint request to gecko.
@ -651,7 +643,6 @@ protected:
uint64_t mLayersId;
RefPtr<CompositorParent> mCompositorParent;
RefPtr<TaskThrottler> mPaintThrottler;
/* Access to the following two fields is protected by the mRefPtrMonitor,
since they are accessed on the UI thread but can be cleared on the
@ -699,15 +690,12 @@ private:
// the Gecko state, it should be used as a basis for untransformation when
// sending messages back to Gecko.
FrameMetrics mLastContentPaintMetrics;
// The last metrics that we requested a paint for. These are used to make sure
// that we're not requesting a paint of the same thing that's already drawn.
// If we don't do this check, we don't get a ShadowLayersUpdated back.
// The last metrics used for a content repaint request.
FrameMetrics mLastPaintRequestMetrics;
// The last metrics that we actually sent to Gecko. This allows us to transform
// inputs into a coordinate space that Gecko knows about. This assumes the pipe
// through which input events and repaint requests are sent to Gecko operates
// in a FIFO manner.
FrameMetrics mLastDispatchedPaintMetrics;
// The metrics that we expect content to have. This is updated when we
// request a content repaint, and when we receive a shadow layers update.
// This allows us to transform events into Gecko's coordinate space.
FrameMetrics mExpectedGeckoMetrics;
AxisX mX;
AxisY mY;

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

@ -1,173 +0,0 @@
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
/* vim: set sw=2 sts=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TaskThrottler.h"
#include "mozilla/layers/APZThreadUtils.h"
#define TASK_LOG(...)
// #define TASK_LOG(...) printf_stderr("TASK: " __VA_ARGS__)
namespace mozilla {
namespace layers {
TaskThrottler::TaskThrottler(const TimeStamp& aTimeStamp, const TimeDuration& aMaxWait)
: mMonitor("TaskThrottler")
, mOutstanding(false)
, mQueuedTask(nullptr)
, mStartTime(aTimeStamp)
, mMaxWait(aMaxWait)
, mMean(1)
, mTimeoutTask(nullptr)
{
}
TaskThrottler::~TaskThrottler()
{
// The timeout task holds a strong reference to the TaskThrottler, so if the
// TaskThrottler is being destroyed, there's no need to cancel the task.
}
void
TaskThrottler::PostTask(const tracked_objects::Location& aLocation,
UniquePtr<CancelableTask> aTask, const TimeStamp& aTimeStamp)
{
MonitorAutoLock lock(mMonitor);
TASK_LOG("%p got a task posted; mOutstanding=%d\n", this, mOutstanding);
aTask->SetBirthPlace(aLocation);
if (mOutstanding) {
CancelPendingTask(lock);
if (TimeSinceLastRequest(aTimeStamp, lock) < mMaxWait) {
mQueuedTask = Move(aTask);
TASK_LOG("%p queued task %p\n", this, mQueuedTask.get());
// Make sure the queued task is sent after mMaxWait time elapses,
// even if we don't get a TaskComplete() until then.
TimeDuration timeout = mMaxWait - TimeSinceLastRequest(aTimeStamp, lock);
mTimeoutTask = NewRunnableMethod(this, &TaskThrottler::OnTimeout);
APZThreadUtils::RunDelayedTaskOnCurrentThread(mTimeoutTask, timeout);
return;
}
// we've been waiting for more than the max-wait limit, so just fall through
// and send the new task already.
}
mStartTime = aTimeStamp;
aTask->Run();
mOutstanding = true;
}
void
TaskThrottler::OnTimeout()
{
MonitorAutoLock lock(mMonitor);
if (mQueuedTask) {
RunQueuedTask(TimeStamp::Now(), lock);
}
// The message loop will delete the posted timeout task. Make sure we don't
// keep a dangling pointer to it.
mTimeoutTask = nullptr;
}
void
TaskThrottler::TaskComplete(const TimeStamp& aTimeStamp)
{
MonitorAutoLock lock(mMonitor);
if (!mOutstanding) {
return;
}
mMean.insert(aTimeStamp - mStartTime);
if (mQueuedTask) {
RunQueuedTask(aTimeStamp, lock);
CancelTimeoutTask(lock);
} else {
mOutstanding = false;
}
}
TimeDuration
TaskThrottler::AverageDuration()
{
MonitorAutoLock lock(mMonitor);
return mMean.empty() ? TimeDuration() : mMean.mean();
}
void
TaskThrottler::RunQueuedTask(const TimeStamp& aTimeStamp,
const MonitorAutoLock& aProofOfLock)
{
TASK_LOG("%p running task %p\n", this, mQueuedTask.get());
mStartTime = aTimeStamp;
mQueuedTask->Run();
mQueuedTask = nullptr;
}
void
TaskThrottler::CancelPendingTask()
{
MonitorAutoLock lock(mMonitor);
CancelPendingTask(lock);
}
void
TaskThrottler::CancelPendingTask(const MonitorAutoLock& aProofOfLock)
{
if (mQueuedTask) {
TASK_LOG("%p cancelling task %p\n", this, mQueuedTask.get());
mQueuedTask->Cancel();
mQueuedTask = nullptr;
CancelTimeoutTask(aProofOfLock);
}
}
void
TaskThrottler::CancelTimeoutTask(const MonitorAutoLock& aProofOfLock)
{
if (mTimeoutTask) {
mTimeoutTask->Cancel();
mTimeoutTask = nullptr; // the MessageLoop will destroy it
}
}
TimeDuration
TaskThrottler::TimeSinceLastRequest(const TimeStamp& aTimeStamp)
{
MonitorAutoLock lock(mMonitor);
return TimeSinceLastRequest(aTimeStamp, lock);
}
TimeDuration
TaskThrottler::TimeSinceLastRequest(const TimeStamp& aTimeStamp,
const MonitorAutoLock& aProofOfLock)
{
return aTimeStamp - mStartTime;
}
void
TaskThrottler::ClearHistory()
{
MonitorAutoLock lock(mMonitor);
mMean.clear();
}
void
TaskThrottler::SetMaxDurations(uint32_t aMaxDurations)
{
MonitorAutoLock lock(mMonitor);
if (aMaxDurations != mMean.maxValues()) {
mMean = RollingMean<TimeDuration, TimeDuration>(aMaxDurations);
}
}
} // namespace layers
} // namespace mozilla

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

@ -1,119 +0,0 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_TaskThrottler_h
#define mozilla_dom_TaskThrottler_h
#include <stdint.h> // for uint32_t
#include "base/task.h" // for CancelableTask
#include "mozilla/Monitor.h" // for Monitor
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/RollingMean.h" // for RollingMean
#include "mozilla/TimeStamp.h" // for TimeDuration, TimeStamp
#include "mozilla/UniquePtr.h" // for UniquePtr
#include "nsCOMPtr.h" // for nsCOMPtr
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING
#include "nsTArray.h" // for nsTArray
namespace tracked_objects {
class Location;
} // namespace tracked_objects
namespace mozilla {
namespace layers {
/** The TaskThrottler prevents update event overruns. It is used in cases where
* you're sending an async message and waiting for a reply. You need to call
* PostTask to queue a task and TaskComplete when you get a response.
*
* The call to TaskComplete will run the most recent task posted since the last
* request was sent, if any. This means that at any time there can be at most 1
* outstanding request being processed and at most 1 queued behind it.
*
* However, to guard against task runs that error out and fail to call TaskComplete,
* the TaskThrottler also has a max-wait timeout. If the caller requests a new
* task be posted, and it has been greater than the max-wait timeout since the
* last one was sent, then we send the new one regardless of whether or not the
* last one was marked as completed.
*
* This is used in the context of repainting a scrollable region. While another
* process is painting you might get several updates from the UI thread but when
* the paint is complete you want to send the most recent.
*/
class TaskThrottler {
public:
TaskThrottler(const TimeStamp& aTimeStamp, const TimeDuration& aMaxWait);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TaskThrottler)
/** Post a task to be run as soon as there are no outstanding tasks, or
* post it immediately if it has been more than the max-wait time since
* the last task was posted.
*
* @param aLocation Use the macro FROM_HERE
* @param aTask Ownership of this object is transferred to TaskThrottler
* which will delete it when it is either run or becomes
* obsolete or the TaskThrottler is destructed.
*/
void PostTask(const tracked_objects::Location& aLocation,
UniquePtr<CancelableTask> aTask, const TimeStamp& aTimeStamp);
/**
* Mark the task as complete and process the next queued task.
*/
void TaskComplete(const TimeStamp& aTimeStamp);
/**
* Calculate the average time between processing the posted task and getting
* the TaskComplete() call back.
*/
TimeDuration AverageDuration();
/**
* Cancel the queued task if there is one.
*/
void CancelPendingTask();
/**
* Return the time elapsed since the last request was processed
*/
TimeDuration TimeSinceLastRequest(const TimeStamp& aTimeStamp);
/**
* Clear average history.
*/
void ClearHistory();
/**
* @param aMaxDurations The maximum number of durations to measure.
*/
void SetMaxDurations(uint32_t aMaxDurations);
private:
mutable Monitor mMonitor;
bool mOutstanding;
UniquePtr<CancelableTask> mQueuedTask;
TimeStamp mStartTime;
TimeDuration mMaxWait;
RollingMean<TimeDuration, TimeDuration> mMean;
CancelableTask* mTimeoutTask; // not owned because it's posted to a MessageLoop
// which deletes it
~TaskThrottler();
void RunQueuedTask(const TimeStamp& aTimeStamp,
const MonitorAutoLock& aProofOfLock);
void CancelPendingTask(const MonitorAutoLock& aProofOfLock);
TimeDuration TimeSinceLastRequest(const TimeStamp& aTimeStamp,
const MonitorAutoLock& aProofOfLock);
void OnTimeout();
void CancelTimeoutTask(const MonitorAutoLock& aProofOfLock);
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_dom_TaskThrottler_h

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

@ -154,8 +154,7 @@ public:
protected:
AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler) override;
GeckoContentController* aController) override;
TimeStamp GetFrameTime() override {
return mcc->Time();
@ -169,10 +168,9 @@ class TestAsyncPanZoomController : public AsyncPanZoomController {
public:
TestAsyncPanZoomController(uint64_t aLayersId, MockContentControllerDelayed* aMcc,
TestAPZCTreeManager* aTreeManager,
TaskThrottler* aPaintThrottler,
GestureBehavior aBehavior = DEFAULT_GESTURES)
: AsyncPanZoomController(aLayersId, aTreeManager, aTreeManager->GetInputQueue(),
aMcc, aPaintThrottler, aBehavior)
aMcc, aBehavior)
, mWaitForMainThread(false)
, mcc(aMcc)
{}
@ -261,11 +259,10 @@ private:
AsyncPanZoomController*
TestAPZCTreeManager::NewAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler)
GeckoContentController* aController)
{
MockContentControllerDelayed* mcc = static_cast<MockContentControllerDelayed*>(aController);
return new TestAsyncPanZoomController(aLayersId, mcc, this, aPaintThrottler,
return new TestAsyncPanZoomController(aLayersId, mcc, this,
AsyncPanZoomController::USE_GESTURE_DETECTOR);
}
@ -297,9 +294,8 @@ protected:
APZThreadUtils::SetControllerThread(MessageLoop::current());
mcc = new NiceMock<MockContentControllerDelayed>();
mPaintThrottler = new TaskThrottler(mcc->Time(), TimeDuration::FromMilliseconds(500));
tm = new TestAPZCTreeManager(mcc);
apzc = new TestAsyncPanZoomController(0, mcc, tm, mPaintThrottler, mGestureBehavior);
apzc = new TestAsyncPanZoomController(0, mcc, tm, mGestureBehavior);
apzc->SetFrameMetrics(TestFrameMetrics());
}
@ -382,7 +378,6 @@ protected:
AsyncPanZoomController::GestureBehavior mGestureBehavior;
RefPtr<MockContentControllerDelayed> mcc;
RefPtr<TaskThrottler> mPaintThrottler;
RefPtr<TestAPZCTreeManager> tm;
RefPtr<TestAsyncPanZoomController> apzc;
};
@ -819,7 +814,8 @@ protected:
MakeApzcZoomable();
if (aShouldTriggerPinch) {
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
// One repaint request for each gesture.
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(2);
} else {
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
}
@ -1141,7 +1137,7 @@ TEST_F(APZCBasicTester, ComplexTransform) {
// sides.
RefPtr<TestAsyncPanZoomController> childApzc =
new TestAsyncPanZoomController(0, mcc, tm, mPaintThrottler);
new TestAsyncPanZoomController(0, mcc, tm);
const char* layerTreeSyntax = "c(c)";
// LayerID 0 1
@ -1248,7 +1244,8 @@ protected:
void DoPanTest(bool aShouldTriggerScroll, bool aShouldBeConsumed, uint32_t aBehavior)
{
if (aShouldTriggerScroll) {
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
// One repaint request for each pan.
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(2);
} else {
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(0);
}
@ -1357,8 +1354,6 @@ TEST_F(APZCPanningTester, PanWithPreventDefault) {
}
TEST_F(APZCBasicTester, Fling) {
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
int touchStart = 50;
int touchEnd = 10;
ParentLayerPoint pointOut;
@ -2422,10 +2417,8 @@ TEST_F(APZHitTestingTester, HitTesting2) {
// because we have already issued a paint request with it.
EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(12.5, 75));
// This second pan will move the APZC by another 50 pixels but since the paint
// request dispatched above has not "completed", we will not dispatch another
// one yet. Now we have an async transform on top of the pending paint request
// transform.
// This second pan will move the APZC by another 50 pixels.
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
ApzcPanNoFling(apzcroot, mcc, 100, 50);
// Hit where layers[3] used to be. It should now hit the root.
@ -2433,18 +2426,16 @@ TEST_F(APZHitTestingTester, HitTesting2) {
EXPECT_EQ(apzcroot, hit.get());
// transformToApzc doesn't unapply the root's own async transform
EXPECT_EQ(ParentLayerPoint(75, 75), transformToApzc * ScreenPoint(75, 75));
// transformToGecko unapplies the full async transform of -100 pixels, and then
// reapplies the "D" transform of -50 leading to an overall adjustment of +50
EXPECT_EQ(ScreenPoint(75, 125), transformToGecko * ParentLayerPoint(75, 75));
// transformToGecko unapplies the full async transform of -100 pixels
EXPECT_EQ(ScreenPoint(75, 75), transformToGecko * ParentLayerPoint(75, 75));
// Hit where layers[1] used to be. It should now hit the root.
hit = GetTargetAPZC(ScreenPoint(25, 25));
EXPECT_EQ(apzcroot, hit.get());
// transformToApzc doesn't unapply the root's own async transform
EXPECT_EQ(ParentLayerPoint(25, 25), transformToApzc * ScreenPoint(25, 25));
// transformToGecko unapplies the full async transform of -100 pixels, and then
// reapplies the "D" transform of -50 leading to an overall adjustment of +50
EXPECT_EQ(ScreenPoint(25, 75), transformToGecko * ParentLayerPoint(25, 25));
// transformToGecko unapplies the full async transform of -100 pixels
EXPECT_EQ(ScreenPoint(25, 25), transformToGecko * ParentLayerPoint(25, 25));
}
TEST_F(APZCTreeManagerTester, ScrollablePaintedLayers) {
@ -3497,89 +3488,3 @@ public:
private:
TaskRunMetrics& mMetrics;
};
class APZTaskThrottlerTester : public ::testing::Test {
public:
APZTaskThrottlerTester()
{
now = TimeStamp::Now();
throttler = new TaskThrottler(now, TimeDuration::FromMilliseconds(100));
}
protected:
TimeStamp Advance(int aMillis = 5)
{
now = now + TimeDuration::FromMilliseconds(aMillis);
return now;
}
UniquePtr<CancelableTask> NewTask()
{
return MakeUnique<MockTask>(metrics);
}
TimeStamp now;
RefPtr<TaskThrottler> throttler;
TaskRunMetrics metrics;
};
TEST_F(APZTaskThrottlerTester, BasicTest) {
// Check that posting the first task runs right away
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 1
EXPECT_EQ(1, metrics.GetAndClearRunCount());
// Check that posting the second task doesn't run until the first one is done
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 2
EXPECT_EQ(0, metrics.GetAndClearRunCount());
throttler->TaskComplete(Advance()); // for task 1
EXPECT_EQ(1, metrics.GetAndClearRunCount());
EXPECT_EQ(0, metrics.GetAndClearCancelCount());
// Check that tasks are coalesced: dispatch 5 tasks
// while there is still one outstanding, and ensure
// that only one of the 5 runs
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 3
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 4
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 5
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 6
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 7
EXPECT_EQ(0, metrics.GetAndClearRunCount());
EXPECT_EQ(4, metrics.GetAndClearCancelCount());
throttler->TaskComplete(Advance()); // for task 2
EXPECT_EQ(1, metrics.GetAndClearRunCount());
throttler->TaskComplete(Advance()); // for task 7 (tasks 3..6 were cancelled)
EXPECT_EQ(0, metrics.GetAndClearRunCount());
EXPECT_EQ(0, metrics.GetAndClearCancelCount());
}
TEST_F(APZTaskThrottlerTester, TimeoutTest) {
// Check that posting the first task runs right away
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 1
EXPECT_EQ(1, metrics.GetAndClearRunCount());
// Because we let 100ms pass, the second task should
// run immediately even though the first one isn't
// done yet
throttler->PostTask(FROM_HERE, NewTask(), Advance(100)); // task 2; task 1 is assumed lost
EXPECT_EQ(1, metrics.GetAndClearRunCount());
throttler->TaskComplete(Advance()); // for task 1, but TaskThrottler thinks it's for task 2
throttler->TaskComplete(Advance()); // for task 2, TaskThrottler ignores it
EXPECT_EQ(0, metrics.GetAndClearRunCount());
EXPECT_EQ(0, metrics.GetAndClearCancelCount());
// This time queue up a few tasks before the timeout expires
// and ensure cancellation still works as expected
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 3
EXPECT_EQ(1, metrics.GetAndClearRunCount());
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 4
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 5
throttler->PostTask(FROM_HERE, NewTask(), Advance()); // task 6
EXPECT_EQ(0, metrics.GetAndClearRunCount());
throttler->PostTask(FROM_HERE, NewTask(), Advance(100)); // task 7; task 3 is assumed lost
EXPECT_EQ(1, metrics.GetAndClearRunCount());
EXPECT_EQ(3, metrics.GetAndClearCancelCount()); // tasks 4..6 should have been cancelled
throttler->TaskComplete(Advance()); // for task 7
EXPECT_EQ(0, metrics.GetAndClearRunCount());
EXPECT_EQ(0, metrics.GetAndClearCancelCount());
}

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

@ -41,26 +41,26 @@ static void
AdjustDisplayPortForScrollDelta(mozilla::layers::FrameMetrics& aFrameMetrics,
const CSSPoint& aActualScrollOffset)
{
// Correct the display-port by the difference between the requested scroll
// offset and the resulting scroll offset after setting the requested value.
ScreenPoint shift =
(aFrameMetrics.GetScrollOffset() - aActualScrollOffset) *
aFrameMetrics.DisplayportPixelsPerCSSPixel();
ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins();
margins.left -= shift.x;
margins.right += shift.x;
margins.top -= shift.y;
margins.bottom += shift.y;
aFrameMetrics.SetDisplayPortMargins(margins);
// Correct the display-port by the difference between the requested scroll
// offset and the resulting scroll offset after setting the requested value.
ScreenPoint shift =
(aFrameMetrics.GetScrollOffset() - aActualScrollOffset) *
aFrameMetrics.DisplayportPixelsPerCSSPixel();
ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins();
margins.left -= shift.x;
margins.right += shift.x;
margins.top -= shift.y;
margins.bottom += shift.y;
aFrameMetrics.SetDisplayPortMargins(margins);
}
static void
RecenterDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics)
{
ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins();
margins.right = margins.left = margins.LeftRight() / 2;
margins.top = margins.bottom = margins.TopBottom() / 2;
aFrameMetrics.SetDisplayPortMargins(margins);
ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins();
margins.right = margins.left = margins.LeftRight() / 2;
margins.top = margins.bottom = margins.TopBottom() / 2;
aFrameMetrics.SetDisplayPortMargins(margins);
}
static CSSPoint
@ -128,9 +128,20 @@ ScrollFrame(nsIContent* aContent,
CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated);
if (scrollUpdated) {
// Correct the display port due to the difference between mScrollOffset and the
// actual scroll offset.
AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
if (aMetrics.IsScrollInfoLayer()) {
// In cases where the APZ scroll offset is different from the content scroll
// offset, we want to interpret the margins as relative to the APZ scroll
// offset except when the frame is not scrollable by APZ. Therefore, if the
// layer is a scroll info layer, we leave the margins as-is and they will
// be interpreted as relative to the content scroll offset.
if (nsIFrame* frame = aContent->GetPrimaryFrame()) {
frame->SchedulePaint();
}
} else {
// Correct the display port due to the difference between mScrollOffset and the
// actual scroll offset.
AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
}
} else {
// For whatever reason we couldn't update the scroll offset on the scroll frame,
// which means the data APZ used for its displayport calculation is stale. Fall

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

@ -7,7 +7,6 @@
#include "BasicLayersImpl.h" // for FillRectWithMask
#include "TextureHostBasic.h"
#include "mozilla/layers/Effects.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "nsIWidget.h"
#include "gfx2DGlue.h"
#include "mozilla/gfx/2D.h"

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

@ -15,7 +15,6 @@
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/TextureClientRecycleAllocator.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
#include "ImageContainer.h" // for PlanarYCbCrData, etc
@ -838,10 +837,10 @@ TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator,
// static
already_AddRefed<TextureClient>
TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
size_t aSize,
TextureFlags aTextureFlags)
TextureClient::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
size_t aSize,
TextureFlags aTextureFlags)
{
// also test the validity of aAllocator
MOZ_ASSERT(aAllocator && aAllocator->IPCOpen());
@ -849,8 +848,9 @@ TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
return nullptr;
}
TextureData* data = BufferTextureData::CreateWithBufferSize(aAllocator, aFormat, aSize,
aTextureFlags);
TextureData* data =
BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aFormat, aSize,
aTextureFlags);
if (!data) {
return nullptr;
}

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

@ -297,10 +297,10 @@ public:
// pointers) with a certain buffer size. It's unfortunate that we need this.
// providing format and sizes could let us do more optimization.
static already_AddRefed<TextureClient>
CreateWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
size_t aSize,
TextureFlags aTextureFlags);
CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
size_t aSize,
TextureFlags aTextureFlags);
// Creates and allocates a TextureClient of the same type.
already_AddRefed<TextureClient>

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

@ -13,10 +13,9 @@
#include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "nsAString.h"
#include "mozilla/RefPtr.h" // for nsRefPtr
#include "nsPrintfCString.h" // for nsPrintfCString
@ -95,7 +94,8 @@ TextureHost::CreateIPDLActor(CompositableParentManager* aManager,
LayersBackend aLayersBackend,
TextureFlags aFlags)
{
if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorMemory &&
if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
aSharedData.get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::Tuintptr_t &&
!aManager->IsSameProcess())
{
NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
@ -202,8 +202,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
TextureFlags aFlags)
{
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem:
case SurfaceDescriptor::TSurfaceDescriptorMemory:
case SurfaceDescriptor::TSurfaceDescriptorBuffer:
case SurfaceDescriptor::TSurfaceDescriptorDIB:
case SurfaceDescriptor::TSurfaceDescriptorFileMapping:
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
@ -252,19 +251,26 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
{
RefPtr<TextureHost> result;
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem: {
const SurfaceDescriptorShmem& descriptor = aDesc.get_SurfaceDescriptorShmem();
result = new ShmemTextureHost(descriptor.data(),
descriptor.format(),
aDeallocator,
aFlags);
break;
}
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
const SurfaceDescriptorMemory& descriptor = aDesc.get_SurfaceDescriptorMemory();
result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(descriptor.data()),
descriptor.format(),
aFlags);
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
const SurfaceDescriptorBuffer& bufferDesc = aDesc.get_SurfaceDescriptorBuffer();
const MemoryOrShmem& data = bufferDesc.data();
switch (data.type()) {
case MemoryOrShmem::TShmem: {
result = new ShmemTextureHost(data.get_Shmem(),
bufferDesc.desc(),
aDeallocator,
aFlags);
break;
}
case MemoryOrShmem::Tuintptr_t: {
result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(data.get_uintptr_t()),
bufferDesc.desc(),
aFlags);
break;
}
default:
MOZ_CRASH();
}
break;
}
#ifdef XP_WIN
@ -368,15 +374,30 @@ TextureSource::~TextureSource()
MOZ_COUNT_DTOR(TextureSource);
}
BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
TextureFlags aFlags)
: TextureHost(aFlags)
, mCompositor(nullptr)
, mFormat(aFormat)
, mUpdateSerial(1)
, mLocked(false)
, mNeedsFullUpdate(false)
{
mDescriptor = aDesc;
switch (mDescriptor.type()) {
case BufferDescriptor::TYCbCrDescriptor: {
const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor();
mSize = ycbcr.ySize();
mFormat = gfx::SurfaceFormat::YUV;
break;
}
case BufferDescriptor::TRGBDescriptor: {
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
mSize = rgb.size();
mFormat = rgb.format();
break;
}
default: MOZ_CRASH();
}
if (aFlags & TextureFlags::COMPONENT_ALPHA) {
// One texture of a component alpha texture pair will start out all white.
// This hack allows us to easily make sure that white will be uploaded.
@ -385,22 +406,6 @@ BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
}
}
void
BufferTextureHost::InitSize()
{
if (mFormat == gfx::SurfaceFormat::YUV) {
YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
if (yuvDeserializer.IsValid()) {
mSize = yuvDeserializer.GetYSize();
}
} else if (mFormat != gfx::SurfaceFormat::UNKNOWN) {
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
if (deserializer.IsValid()) {
mSize = deserializer.GetSize();
}
}
}
BufferTextureHost::~BufferTextureHost()
{}
@ -512,7 +517,8 @@ BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
bool
BufferTextureHost::Upload(nsIntRegion *aRegion)
{
if (!GetBuffer()) {
uint8_t* buf = GetBuffer();
if (!buf) {
// We don't have a buffer; a possible cause is that the IPDL actor
// is already dead. This inevitably happens as IPDL actors can die
// at any time, so we want to silently return in this case.
@ -527,11 +533,11 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
NS_WARNING("BufferTextureHost: unsupported format!");
return false;
} else if (mFormat == gfx::SurfaceFormat::YUV) {
YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
MOZ_ASSERT(yuvDeserializer.IsValid());
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
if (!mCompositor->SupportsEffect(EffectTypes::YCBCR)) {
RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface();
RefPtr<gfx::DataSourceSurface> surf =
ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(buf, mDescriptor.get_YCbCrDescriptor());
if (NS_WARN_IF(!surf)) {
return false;
}
@ -565,21 +571,20 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
}
RefPtr<gfx::DataSourceSurface> tempY =
gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(),
yuvDeserializer.GetYStride(),
yuvDeserializer.GetYSize(),
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc),
desc.ySize().width,
desc.ySize(),
gfx::SurfaceFormat::A8);
RefPtr<gfx::DataSourceSurface> tempCb =
gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(),
yuvDeserializer.GetCbCrStride(),
yuvDeserializer.GetCbCrSize(),
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc),
desc.cbCrSize().width,
desc.cbCrSize(),
gfx::SurfaceFormat::A8);
RefPtr<gfx::DataSourceSurface> tempCr =
gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(),
yuvDeserializer.GetCbCrStride(),
yuvDeserializer.GetCbCrSize(),
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc),
desc.cbCrSize().width,
desc.cbCrSize(),
gfx::SurfaceFormat::A8);
// We don't support partial updates for Y U V textures
NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
@ -602,13 +607,10 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
regionToUpdate = nullptr;
}
}
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
if (!deserializer.IsValid()) {
NS_ERROR("Failed to deserialize image!");
return false;
}
RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface();
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat);
if (!surf) {
return false;
}
@ -630,35 +632,29 @@ BufferTextureHost::GetAsSurface()
NS_WARNING("BufferTextureHost: unsupported format!");
return nullptr;
} else if (mFormat == gfx::SurfaceFormat::YUV) {
YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
if (!yuvDeserializer.IsValid()) {
return nullptr;
}
result = yuvDeserializer.ToDataSourceSurface();
result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(
GetBuffer(), mDescriptor.get_YCbCrDescriptor());
if (NS_WARN_IF(!result)) {
return nullptr;
}
} else {
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
if (!deserializer.IsValid()) {
NS_ERROR("Failed to deserialize image!");
return nullptr;
}
result = deserializer.GetAsSurface();
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
ImageDataSerializer::GetRGBStride(mDescriptor.get_RGBDescriptor()),
mSize, mFormat);
}
return result.forget();
}
ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
gfx::SurfaceFormat aFormat,
const BufferDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
TextureFlags aFlags)
: BufferTextureHost(aFormat, aFlags)
: BufferTextureHost(aDesc, aFlags)
, mShmem(MakeUnique<ipc::Shmem>(aShmem))
, mDeallocator(aDeallocator)
{
MOZ_COUNT_CTOR(ShmemTextureHost);
InitSize();
}
ShmemTextureHost::~ShmemTextureHost()
@ -705,13 +701,12 @@ size_t ShmemTextureHost::GetBufferSize()
}
MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
gfx::SurfaceFormat aFormat,
const BufferDescriptor& aDesc,
TextureFlags aFlags)
: BufferTextureHost(aFormat, aFlags)
: BufferTextureHost(aDesc, aFlags)
, mBuffer(aBuffer)
{
MOZ_COUNT_CTOR(MemoryTextureHost);
InitSize();
}
MemoryTextureHost::~MemoryTextureHost()

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

@ -19,6 +19,7 @@
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
#include "mozilla/layers/FenceUtils.h" // for FenceHandle
#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/UniquePtr.h" // for UniquePtr
#include "nsCOMPtr.h" // for already_AddRefed
@ -37,6 +38,7 @@ class Shmem;
namespace layers {
class BufferDescriptor;
class Compositor;
class CompositableParentManager;
class SurfaceDescriptor;
@ -567,8 +569,7 @@ protected:
class BufferTextureHost : public TextureHost
{
public:
BufferTextureHost(gfx::SurfaceFormat aFormat,
TextureFlags aFlags);
BufferTextureHost(const BufferDescriptor& aDescriptor, TextureFlags aFlags);
~BufferTextureHost();
@ -605,15 +606,13 @@ protected:
bool Upload(nsIntRegion *aRegion = nullptr);
bool MaybeUpload(nsIntRegion *aRegion = nullptr);
void InitSize();
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
BufferDescriptor mDescriptor;
RefPtr<Compositor> mCompositor;
RefPtr<DataTextureSource> mFirstSource;
nsIntRegion mMaybeUpdatedRegion;
gfx::IntSize mSize;
// format of the data that is shared with the content process.
gfx::SurfaceFormat mFormat;
uint32_t mUpdateSerial;
bool mLocked;
@ -629,7 +628,7 @@ class ShmemTextureHost : public BufferTextureHost
{
public:
ShmemTextureHost(const mozilla::ipc::Shmem& aShmem,
gfx::SurfaceFormat aFormat,
const BufferDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
TextureFlags aFlags);
@ -664,7 +663,7 @@ class MemoryTextureHost : public BufferTextureHost
{
public:
MemoryTextureHost(uint8_t* aBuffer,
gfx::SurfaceFormat aFormat,
const BufferDescriptor& aDesc,
TextureFlags aFlags);
protected:

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

@ -7,7 +7,6 @@
#include "CompositorD3D11.h"
#include "gfxContext.h"
#include "Effects.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "gfxWindowsPlatform.h"
#include "gfx2DGlue.h"
#include "gfxPrefs.h"
@ -665,8 +664,7 @@ CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
{
RefPtr<TextureHost> result;
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem:
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
break;
}

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

@ -8,7 +8,6 @@
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "Effects.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "gfxWindowsPlatform.h"
#include "gfx2DGlue.h"
#include "gfxUtils.h"
@ -53,8 +52,7 @@ CreateTextureHostD3D9(const SurfaceDescriptor& aDesc,
{
RefPtr<TextureHost> result;
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem:
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
break;
}
@ -192,7 +190,7 @@ TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager,
}
tmpTexture->GetSurfaceLevel(0, getter_AddRefs(aSurface));
HRESULT hr = aSurface->LockRect(&aLockedRect, nullptr, 0);
if (FAILED(hr) || !aLockedRect.pBits) {
gfxCriticalError() << "Failed to lock rect initialize texture in D3D9 " << hexa(hr);

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

@ -1546,10 +1546,6 @@ CompositorParent::RecvNotifyChildCreated(const uint64_t& child)
void
CompositorParent::NotifyChildCreated(const uint64_t& aChild)
{
if (mApzcTreeManager) {
NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<uint64_t>(
mApzcTreeManager, &APZCTreeManager::InitializeForLayersId, aChild));
}
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
sIndirectLayerTrees[aChild].mParent = this;
sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
@ -1559,9 +1555,6 @@ bool
CompositorParent::RecvAdoptChild(const uint64_t& child)
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
if (mApzcTreeManager) {
mApzcTreeManager->AdoptLayersId(child, sIndirectLayerTrees[child].mParent->mApzcTreeManager.get());
}
NotifyChildCreated(child);
if (sIndirectLayerTrees[child].mLayerTree) {
sIndirectLayerTrees[child].mLayerTree->mLayerManager = mLayerManager;
@ -1633,7 +1626,6 @@ ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(APZCTreeManager* aApzct
: mLayersId(aLayersId)
{
EnsureLayerTreeMapReady();
aApzctm->InitializeForLayersId(aLayersId);
MonitorAutoLock lock(*sIndirectLayerTreesLock);
sIndirectLayerTrees[aLayersId].mRoot = aRoot;
sIndirectLayerTrees[aLayersId].mController = aController;
@ -1649,9 +1641,6 @@ ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration()
CompositorParent::SetControllerForLayerTree(uint64_t aLayersId,
GeckoContentController* aController)
{
if (APZCTreeManager* apzctm = GetAPZCTreeManager(aLayersId)) {
apzctm->InitializeForLayersId(aLayersId);
}
// This ref is adopted by UpdateControllerForLayersId().
aController->AddRef();
CompositorLoop()->PostTask(FROM_HERE,

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

@ -60,38 +60,38 @@ ISurfaceAllocator::Finalize()
}
static inline uint8_t*
GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor, size_t& aSize)
GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor)
{
MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor));
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem ||
aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorMemory);
if (aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem) {
Shmem shmem(aDescriptor.get_SurfaceDescriptorShmem().data());
aSize = shmem.Size<uint8_t>();
return shmem.get<uint8_t>();
MOZ_RELEASE_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer);
auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data();
if (memOrShmem.type() == MemoryOrShmem::TShmem) {
return memOrShmem.get_Shmem().get<uint8_t>();
} else {
const SurfaceDescriptorMemory& image = aDescriptor.get_SurfaceDescriptorMemory();
aSize = std::numeric_limits<size_t>::max();
return reinterpret_cast<uint8_t*>(image.data());
return reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
}
}
already_AddRefed<gfx::DrawTarget>
GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend)
{
size_t size;
uint8_t* data = GetAddressFromDescriptor(aDescriptor, size);
ImageDataDeserializer image(data, size);
return image.GetAsDrawTarget(aBackend);
uint8_t* data = GetAddressFromDescriptor(aDescriptor);
auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
return gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
data, rgb.size(),
stride, rgb.format());
}
already_AddRefed<gfx::DataSourceSurface>
GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor)
{
size_t size;
uint8_t* data = GetAddressFromDescriptor(aDescriptor, size);
ImageDataDeserializer image(data, size);
return image.GetAsSurface();
uint8_t* data = GetAddressFromDescriptor(aDescriptor);
auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
return gfx::Factory::CreateWrappingDataSourceSurface(data, stride, rgb.size(),
rgb.format());
}
bool
@ -116,12 +116,14 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
}
gfx::SurfaceFormat format =
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent);
size_t size = ImageDataSerializer::ComputeMinBufferSize(aSize, format);
size_t size = ImageDataSerializer::ComputeRGBBufferSize(aSize, format);
if (!size) {
return false;
}
MemoryOrShmem bufferDesc;
if (IsSameProcess()) {
uint8_t *data = new (std::nothrow) uint8_t[size];
uint8_t* data = new (std::nothrow) uint8_t[size];
if (!data) {
return false;
}
@ -133,7 +135,7 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
memset(data, 0, size);
}
#endif
*aBuffer = SurfaceDescriptorMemory((uintptr_t)data, format);
bufferDesc = reinterpret_cast<uintptr_t>(data);
} else {
mozilla::ipc::SharedMemory::SharedMemoryType shmemType = OptimalShmemType();
@ -142,19 +144,19 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
return false;
}
*aBuffer = SurfaceDescriptorShmem(shmem, format);
bufferDesc = shmem;
}
uint8_t* data = GetAddressFromDescriptor(*aBuffer, size);
ImageDataSerializer serializer(data, size);
serializer.InitializeBufferInfo(aSize, format);
*aBuffer = SurfaceDescriptorBuffer(RGBDescriptor(aSize, format), bufferDesc);
return true;
}
/* static */ bool
ISurfaceAllocator::IsShmem(SurfaceDescriptor* aSurface)
{
return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorShmem);
return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer)
&& (aSurface->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem);
}
void
@ -172,17 +174,18 @@ ISurfaceAllocator::DestroySharedSurface(SurfaceDescriptor* aSurface)
if (!IPCOpen()) {
return;
}
switch (aSurface->type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem:
DeallocShmem(aSurface->get_SurfaceDescriptorShmem().data());
SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer();
switch (desc.data().type()) {
case MemoryOrShmem::TShmem: {
DeallocShmem(desc.data().get_Shmem());
break;
case SurfaceDescriptor::TSurfaceDescriptorMemory:
GfxMemoryImageReporter::WillFree((uint8_t*)aSurface->get_SurfaceDescriptorMemory().data());
delete [] (uint8_t*)aSurface->get_SurfaceDescriptorMemory().data();
break;
case SurfaceDescriptor::Tnull_t:
case SurfaceDescriptor::T__None:
}
case MemoryOrShmem::Tuintptr_t: {
uint8_t* ptr = (uint8_t*)desc.data().get_uintptr_t();
GfxMemoryImageReporter::WillFree(ptr);
delete [] ptr;
break;
}
default:
NS_RUNTIMEABORT("surface type not implemented!");
}

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

@ -7,6 +7,7 @@ using nsIntRegion from "nsRegion.h";
using struct mozilla::layers::MagicGrallocBufferHandle from "gfxipc/ShadowLayerUtils.h";
using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h";
using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
using mozilla::StereoMode from "ImageTypes.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
@ -95,25 +96,37 @@ struct SurfaceDescriptorGralloc {
bool isOpaque;
};
/**
* Used for shmem-backed YCbCr and (flavors of) RGBA textures
*/
struct SurfaceDescriptorShmem {
Shmem data;
struct RGBDescriptor {
IntSize size;
SurfaceFormat format;
};
/**
* Used for "raw memory"-backed YCbCr and (flavors of) RGBA textures
*/
struct SurfaceDescriptorMemory {
uintptr_t data;
SurfaceFormat format;
struct YCbCrDescriptor {
IntSize ySize;
IntSize cbCrSize;
uint32_t yOffset;
uint32_t cbOffset;
uint32_t crOffset;
StereoMode stereoMode;
};
union BufferDescriptor {
RGBDescriptor;
YCbCrDescriptor;
};
union MemoryOrShmem {
uintptr_t;
Shmem;
};
struct SurfaceDescriptorBuffer {
BufferDescriptor desc;
MemoryOrShmem data;
};
union SurfaceDescriptor {
SurfaceDescriptorShmem;
SurfaceDescriptorMemory;
SurfaceDescriptorBuffer;
SurfaceDescriptorD3D9;
SurfaceDescriptorDIB;
SurfaceDescriptorD3D10;

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

@ -319,11 +319,12 @@ ShadowLayerForwarder::CheckSurfaceDescriptor(const SurfaceDescriptor* aDescripto
return;
}
if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorShmem) {
const SurfaceDescriptorShmem& shmem = aDescriptor->get_SurfaceDescriptorShmem();
shmem.data().AssertInvariants();
if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
aDescriptor->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem) {
const Shmem& shmem = aDescriptor->get_SurfaceDescriptorBuffer().data().get_Shmem();
shmem.AssertInvariants();
MOZ_ASSERT(mShadowManager &&
mShadowManager->IsTrackingSharedMemory(shmem.data().mSegment));
mShadowManager->IsTrackingSharedMemory(shmem.mSegment));
}
}
#endif

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

@ -15,7 +15,7 @@
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/BufferTexture.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
#include "mozilla/mozalloc.h" // for operator delete
#include "nsISupportsImpl.h" // for Image::AddRef
@ -112,14 +112,14 @@ uint8_t*
SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
{
MOZ_ASSERT(!mTextureClient, "This image already has allocated data");
size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aSize);
size_t size = ImageDataSerializer::ComputeYCbCrBufferSize(aSize);
if (!size) {
return nullptr;
}
mTextureClient = TextureClient::CreateWithBufferSize(mCompositable->GetForwarder(),
gfx::SurfaceFormat::YUV, size,
mCompositable->GetTextureFlags());
mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(),
gfx::SurfaceFormat::YUV, size,
mCompositable->GetTextureFlags());
// get new buffer _without_ setting mBuffer.
if (!mTextureClient) {
@ -132,11 +132,7 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
MappedYCbCrTextureData mapped;
if (mTextureClient->BorrowMappedYCbCrData(mapped)) {
// The caller expects a pointer to the beginning of the writable part of the
// buffer (after the metadata) which is where the y channel starts by default.
// The caller might choose to write the y channel at a different offset and
// if it does so, it will also update the metadata.
// Anyway, we return the y channel here but the intent is to obtain the start of
// the writable part of the buffer.
// buffer which is where the y channel starts by default.
return mapped.y.data;
} else {
MOZ_CRASH();
@ -146,35 +142,26 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
bool
SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
{
// SetDataNoCopy is used to update YUV plane offsets without (re)allocating
// memory previously allocated with AllocateAndGetNewBuffer().
MOZ_ASSERT(mTextureClient, "This Image should have already allocated data");
if (!mTextureClient) {
return false;
}
mData = aData;
mSize = aData.mPicSize;
/* SetDataNoCopy is used to update YUV plane offsets without (re)allocating
* memory previously allocated with AllocateAndGetNewBuffer().
* serializer.GetData() returns the address of the memory previously allocated
* with AllocateAndGetNewBuffer(), that we subtract from the Y, Cb, Cr
* channels to compute 0-based offsets to pass to InitializeBufferInfo.
*/
MappedYCbCrTextureData mapped;
if(!mTextureClient->BorrowMappedYCbCrData(mapped)) {
MOZ_CRASH();
}
YCbCrImageDataSerializer serializer(mapped.metadata, mBufferSize);
uint8_t *base = serializer.GetData();
uint8_t *base = GetBuffer();
uint32_t yOffset = aData.mYChannel - base;
uint32_t cbOffset = aData.mCbChannel - base;
uint32_t crOffset = aData.mCrChannel - base;
serializer.InitializeBufferInfo(yOffset,
cbOffset,
crOffset,
aData.mYStride,
aData.mCbCrStride,
aData.mYSize,
aData.mCbCrSize,
aData.mStereoMode);
static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor(
YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset,
aData.mStereoMode)
);
return true;
}
@ -232,8 +219,7 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
// do not set mBuffer like in PlanarYCbCrImage because the later
// will try to manage this memory without knowing it belongs to a
// shmem.
mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
mData.mCbCrSize);
mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(mData.mYSize, mData.mCbCrSize);
mSize = mData.mPicSize;
mTextureClient->Unlock();

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

@ -180,7 +180,6 @@ EXPORTS.mozilla.layers += [
'RenderTrace.h',
'TextureWrapperImage.h',
'TransactionIdAllocator.h',
'YCbCrImageDataSerializer.h',
]
if CONFIG['MOZ_X11']:
@ -250,7 +249,6 @@ UNIFIED_SOURCES += [
'apz/src/InputBlockState.cpp',
'apz/src/InputQueue.cpp',
'apz/src/OverscrollHandoffState.cpp',
'apz/src/TaskThrottler.cpp',
'apz/src/TouchCounter.cpp',
'apz/src/WheelScrollAnimation.cpp',
'apz/testutil/APZTestData.cpp',
@ -352,7 +350,6 @@ UNIFIED_SOURCES += [
'RenderTrace.cpp',
'RotatedBuffer.cpp',
'TextureWrapperImage.cpp',
'YCbCrImageDataSerializer.cpp',
]
SOURCES += [

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

@ -16,7 +16,6 @@
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Logging.h" // for gfxCriticalError
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "mozilla/layers/GrallocTextureHost.h"
#include "nsRegion.h" // for nsIntRegion
#include "AndroidSurfaceTexture.h"
@ -52,8 +51,7 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
{
RefPtr<TextureHost> result;
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem:
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
result = CreateBackendIndependentTextureHost(aDesc,
aDeallocator, aFlags);
break;

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

@ -16,7 +16,7 @@
#include "gfxImageSurface.h"
#include "gfxTypes.h"
#include "ImageContainer.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
#include "mozilla/layers/ImageDataSerializer.h"
using namespace mozilla;
using namespace mozilla::gfx;
@ -119,31 +119,6 @@ void AssertSurfacesEqual(SourceSurface* surface1,
dataSurface2->Unmap();
}
// Same as above, for YCbCr surfaces
void AssertYCbCrSurfacesEqual(PlanarYCbCrData* surface1,
PlanarYCbCrData* surface2)
{
ASSERT_EQ(surface1->mYSize, surface2->mYSize);
ASSERT_EQ(surface1->mCbCrSize, surface2->mCbCrSize);
ASSERT_EQ(surface1->mStereoMode, surface2->mStereoMode);
ASSERT_EQ(surface1->mPicSize, surface2->mPicSize);
for (int y = 0; y < surface1->mYSize.height; ++y) {
for (int x = 0; x < surface1->mYSize.width; ++x) {
ASSERT_EQ(surface1->mYChannel[y*surface1->mYStride + x*(1+surface1->mYSkip)],
surface2->mYChannel[y*surface2->mYStride + x*(1+surface2->mYSkip)]);
}
}
for (int y = 0; y < surface1->mCbCrSize.height; ++y) {
for (int x = 0; x < surface1->mCbCrSize.width; ++x) {
ASSERT_EQ(surface1->mCbChannel[y*surface1->mCbCrStride + x*(1+surface1->mCbSkip)],
surface2->mCbChannel[y*surface2->mCbCrStride + x*(1+surface2->mCbSkip)]);
ASSERT_EQ(surface1->mCrChannel[y*surface1->mCbCrStride + x*(1+surface1->mCrSkip)],
surface2->mCrChannel[y*surface2->mCbCrStride + x*(1+surface2->mCrSkip)]);
}
}
}
// Run the test for a texture client and a surface
void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {
@ -206,7 +181,13 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
SurfaceDescriptor descriptor;
ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));
ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
ASSERT_EQ(descriptor.type(), SurfaceDescriptor::TSurfaceDescriptorBuffer);
auto bufferDesc = descriptor.get_SurfaceDescriptorBuffer();
ASSERT_EQ(bufferDesc.desc().type(), BufferDescriptor::TYCbCrDescriptor);
auto ycbcrDesc = bufferDesc.desc().get_YCbCrDescriptor();
ASSERT_EQ(ycbcrDesc.ySize(), ycbcrData.mYSize);
ASSERT_EQ(ycbcrDesc.cbCrSize(), ycbcrData.mCbCrSize);
ASSERT_EQ(ycbcrDesc.stereoMode(), ycbcrData.mStereoMode);
// host deserialization
RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
@ -222,26 +203,6 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
if (host->Lock()) {
// This will work iff the compositor is not BasicCompositor
ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV);
YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer(), host->GetBufferSize());
ASSERT_TRUE(yuvDeserializer.IsValid());
PlanarYCbCrData data;
data.mYChannel = yuvDeserializer.GetYData();
data.mCbChannel = yuvDeserializer.GetCbData();
data.mCrChannel = yuvDeserializer.GetCrData();
data.mYStride = yuvDeserializer.GetYStride();
data.mCbCrStride = yuvDeserializer.GetCbCrStride();
data.mStereoMode = yuvDeserializer.GetStereoMode();
data.mYSize = yuvDeserializer.GetYSize();
data.mCbCrSize = yuvDeserializer.GetCbCrSize();
data.mYSkip = 0;
data.mCbSkip = 0;
data.mCrSkip = 0;
data.mPicSize = data.mYSize;
data.mPicX = 0;
data.mPicY = 0;
AssertYCbCrSurfacesEqual(&ycbcrData, &data);
host->Unlock();
}
}

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

@ -167,7 +167,6 @@ private:
DECL_GFX_PREF(Once, "apz.max_velocity_queue_size", APZMaxVelocityQueueSize, uint32_t, 5);
DECL_GFX_PREF(Live, "apz.min_skate_speed", APZMinSkateSpeed, float, 1.0f);
DECL_GFX_PREF(Live, "apz.minimap.enabled", APZMinimap, bool, false);
DECL_GFX_PREF(Live, "apz.num_paint_duration_samples", APZNumPaintDurationSamples, int32_t, 3);
DECL_GFX_PREF(Live, "apz.overscroll.enabled", APZOverscrollEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.overscroll.min_pan_distance_ratio", APZMinPanDistanceRatio, float, 1.0f);
DECL_GFX_PREF(Live, "apz.overscroll.spring_friction", APZOverscrollSpringFriction, float, 0.015f);
@ -181,7 +180,6 @@ private:
DECL_GFX_PREF(Live, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.touch_move_tolerance", APZTouchMoveTolerance, float, 0.0);
DECL_GFX_PREF(Live, "apz.touch_start_tolerance", APZTouchStartTolerance, float, 1.0f/4.5f);
DECL_GFX_PREF(Live, "apz.use_paint_duration", APZUsePaintDuration, bool, true);
DECL_GFX_PREF(Live, "apz.velocity_bias", APZVelocityBias, float, 1.0f);
DECL_GFX_PREF(Live, "apz.velocity_relevance_time_ms", APZVelocityRelevanceTime, uint32_t, 150);
DECL_GFX_PREF(Live, "apz.x_skate_highmem_adjust", APZXSkateHighMemAdjust, float, 0.0f);

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

@ -6870,7 +6870,7 @@ Warn(AsmJSParser& parser, int errorNumber, const char* str)
static bool
EstablishPreconditions(ExclusiveContext* cx, AsmJSParser& parser)
{
#ifdef JS_CODEGEN_NONE
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by lack of a JIT compiler");
#endif
@ -6980,7 +6980,7 @@ js::IsAsmJSCompilationAvailable(JSContext* cx, unsigned argc, Value* vp)
CallArgs args = CallArgsFromVp(argc, vp);
// See EstablishPreconditions.
#ifdef JS_CODEGEN_NONE
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
bool available = false;
#else
bool available = cx->jitSupportsFloatingPoint() &&

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

@ -2946,7 +2946,7 @@ wasm::CompileFunction(CompileTask* task)
MIRGraph graph(&results.alloc());
CompileInfo compileInfo(func.numLocals());
MIRGenerator mir(nullptr, options, &results.alloc(), &graph, &compileInfo,
IonOptimizations.get(Optimization_AsmJS),
IonOptimizations.get(OptimizationLevel::AsmJS),
args.usesSignalHandlersForOOB);
// Build MIR graph

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

@ -199,11 +199,7 @@ Reflect_enumerate(JSContext* cx, unsigned argc, Value* vp)
}
#endif
/*
* ES6 26.1.6 Reflect.get(target, propertyKey [, receiver])
*
* Primitive receivers are not supported yet (see bug 603201).
*/
/* ES6 26.1.6 Reflect.get(target, propertyKey [, receiver]) */
static bool
Reflect_get(JSContext* cx, unsigned argc, Value* vp)
{
@ -221,16 +217,10 @@ Reflect_get(JSContext* cx, unsigned argc, Value* vp)
return false;
// Step 4.
RootedValue receiver(cx, argc > 2 ? args[2] : args.get(0));
// Non-standard hack: Throw a TypeError if the receiver isn't an object.
// See bug 603201.
RootedObject receiverObj(cx, NonNullObject(cx, receiver));
if (!receiverObj)
return false;
RootedValue receiver(cx, args.length() > 2 ? args[2] : args.get(0));
// Step 5.
return GetProperty(cx, obj, receiverObj, key, args.rval());
return GetProperty(cx, obj, receiver, key, args.rval());
}
/* ES6 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey) */
@ -336,7 +326,7 @@ Reflect_set(JSContext* cx, unsigned argc, Value* vp)
return false;
// Step 4.
RootedValue receiver(cx, argc > 3 ? args[3] : args.get(0));
RootedValue receiver(cx, args.length() > 3 ? args[3] : args.get(0));
// Step 5.
ObjectOpResult result;

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

@ -306,8 +306,8 @@ GC(JSContext* cx, unsigned argc, Value* vp)
char buf[256] = { '\0' };
#ifndef JS_MORE_DETERMINISTIC
JS_snprintf(buf, sizeof(buf), "before %lu, after %lu\n",
(unsigned long)preBytes, (unsigned long)cx->runtime()->gc.usage.gcBytes());
JS_snprintf(buf, sizeof(buf), "before %" PRIuSIZE ", after %" PRIuSIZE "\n",
preBytes, cx->runtime()->gc.usage.gcBytes());
#endif
JSString* str = JS_NewStringCopyZ(cx, buf);
if (!str)

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

@ -73,8 +73,8 @@ _PTHREAD_LDFLAGS=""
dnl Do not allow objdir == srcdir builds
dnl ==============================================================
_topsrcdir=`cd $srcdir; pwd -W 2>/dev/null || pwd`
_objdir=`pwd`
_topsrcdir=`cd $srcdir; pwd -W 2>/dev/null || pwd -P`
_objdir=`pwd -P`
if test "$_topsrcdir" = "$_objdir"
then
@ -112,7 +112,7 @@ if test "$_conflict_files"; then
exit 1
break
fi
MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd`
MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd -P`
MOZ_BUILD_BACKEND

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

@ -0,0 +1,52 @@
ecma/Date/15.9.5.10-2.js
ecma/Date/15.9.5.11-2.js
ecma/Date/15.9.5.12-2.js
ecma/Date/15.9.5.8.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-01-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-02-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-03-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-04-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-05-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-06-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-07-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-08-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-09-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-10-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-11-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-12-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-13-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-14-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-15-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-16-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-17-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-18-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-19-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-20-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-21-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-22-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-23-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-24-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-25-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-26-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-27-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-30-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-31-of-32.js
ecma_5/Object/15.2.3.6-dictionary-redefinition-32-of-32.js
ecma_5/Object/15.2.3.6-middle-redefinition-1-of-8.js
ecma_5/Object/15.2.3.6-middle-redefinition-2-of-8.js
ecma_5/Object/15.2.3.6-middle-redefinition-3-of-8.js
ecma_5/Object/15.2.3.6-middle-redefinition-4-of-8.js
ecma_5/Object/15.2.3.6-middle-redefinition-5-of-8.js
ecma_5/Object/15.2.3.6-middle-redefinition-6-of-8.js
ecma_5/Object/15.2.3.6-middle-redefinition-7-of-8.js
ecma_5/Object/15.2.3.6-middle-redefinition-8-of-8.js
ecma_5/Object/15.2.3.6-redefinition-1-of-4.js
ecma_5/Object/15.2.3.6-redefinition-2-of-4.js
ecma_5/Object/15.2.3.6-redefinition-3-of-4.js
ecma_5/Object/15.2.3.6-redefinition-4-of-4.js
ecma_6/Comprehensions/sudoku.js
js1_8/extensions/regress-476427.js
js1_8_5/extensions/clone-complex-object.js
js1_8_5/reflect-parse/classes.js
js1_8_5/reflect-parse/destructuring-variable-declarations.js
js1_8_5/regress/no-array-comprehension-length-limit.js

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

@ -217,10 +217,10 @@ elif [[ "$VARIANT" = "arm-sim" ||
"$VARIANT" = "plaindebug" ]]; then
export JSTESTS_EXTRA_ARGS=--jitflags=debug
elif [[ "$VARIANT" = arm64* ]]; then
# The ARM64 JIT is not yet fully functional, and asm.js does not work.
# Just run "make check" and jsapi-tests.
RUN_JITTEST=false
RUN_JSTESTS=false
# The ARM64 simulator is slow, so some tests are timing out.
# Run a reduced set of test cases so this doesn't take hours.
export JSTESTS_EXTRA_ARGS="--exclude-file=$ABSDIR/arm64-jstests-slow.txt"
export JITTEST_EXTRA_ARGS="--jitflags=none --args=--baseline-eager -x ion/ -x asm.js/"
fi
$COMMAND_PREFIX $MAKE check || exit 1

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

@ -6780,6 +6780,13 @@ Parser<FullParseHandler>::classDefinition(YieldHandling yieldHandling,
if (tt == TOK_NAME && tokenStream.currentName() == context->names().static_) {
if (!tokenStream.peekToken(&tt, TokenStream::KeywordIsName))
return null();
if (tt == TOK_RC) {
tokenStream.consumeKnownToken(tt, TokenStream::KeywordIsName);
report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN,
"property name", TokenKindToDesc(tt));
return null();
}
if (tt != TOK_LP) {
if (!checkUnescapedName())
return null();
@ -9249,8 +9256,7 @@ Parser<ParseHandler>::propertyName(YieldHandling yieldHandling, Node propList,
if (!tokenStream.getToken(&ltok, TokenStream::KeywordIsName))
return null();
// TOK_RC should be handled in caller.
MOZ_ASSERT(ltok != TOK_RC);
MOZ_ASSERT(ltok != TOK_RC, "caller should have handled TOK_RC");
bool isGenerator = false;
if (ltok == TOK_MUL) {

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

@ -501,15 +501,15 @@ JS_GetTraceThingInfo(char* buf, size_t bufsize, JSTracer* trc, void* thing,
bool willFit = str->length() + strlen("<length > ") +
CountDecimalDigits(str->length()) < bufsize;
n = JS_snprintf(buf, bufsize, "<length %d%s> ",
(int)str->length(),
n = JS_snprintf(buf, bufsize, "<length %" PRIuSIZE "%s> ",
str->length(),
willFit ? "" : " (truncated)");
buf += n;
bufsize -= n;
PutEscapedString(buf, bufsize, &str->asLinear(), 0);
} else {
JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length());
JS_snprintf(buf, bufsize, "<rope: length %" PRIuSIZE ">", str->length());
}
break;
}

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

@ -122,8 +122,7 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
#ifdef JS_CODEGEN_ARM64
// ARM64 communicates stack address via sp, but uses a pseudo-sp for addressing.
MOZ_ASSERT(!masm.GetStackPointer64().Is(sp));
masm.Mov(masm.GetStackPointer64(), sp);
masm.initStackPtr();
#endif
// Push non-volatile registers which might be modified by jitcode.

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

@ -9,6 +9,12 @@ function jitTogglesMatch(opts) {
if (k.indexOf(".enable") > 0 && opts[k] != currentOpts[k])
return false;
}
// ARM64 does not yet have an Ion code generator, so return false if
// ion.enable is requested.
if (getBuildConfiguration()['arm64-simulator'] && opts['ion.enable'])
return false;
return true;
}

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

@ -19,5 +19,7 @@ runOffThreadScript();
var msg = getLastWarning().message;
assertEq(msg === "asm.js type error: Disabled by debugger" ||
msg === "asm.js type error: Disabled by lack of a JIT compiler" ||
msg === "asm.js type error: Disabled by javascript.options.asmjs in about:config" ||
msg === "asm.js type error: Disabled by lack of floating point support",
true);

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

@ -2108,8 +2108,6 @@ IonCompile(JSContext* cx, JSScript* script,
AutoTraceLog logScript(logger, event);
AutoTraceLog logCompile(logger, TraceLogger_IonCompilation);
MOZ_ASSERT(optimizationLevel > Optimization_DontCompile);
// Make sure the script's canonical function isn't lazy. We can't de-lazify
// it in a helper thread.
script->ensureNonLazyCanonicalFunction(cx);
@ -2396,7 +2394,7 @@ Compile(JSContext* cx, HandleScript script, BaselineFrame* osrFrame, jsbytecode*
bool recompile = false;
OptimizationLevel optimizationLevel = GetOptimizationLevel(script, osrPc);
if (optimizationLevel == Optimization_DontCompile)
if (optimizationLevel == OptimizationLevel::DontCompile)
return Method_Skipped;
if (script->hasIonScript()) {

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

@ -3683,7 +3683,7 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun,
script->needsArgsObj(),
inlineScriptTree);
const OptimizationInfo* optimizationInfo = IonOptimizations.get(Optimization_Normal);
const OptimizationInfo* optimizationInfo = IonOptimizations.get(OptimizationLevel::Normal);
CompilerConstraintList* constraints = NewCompilerConstraintList(temp);
if (!constraints) {
@ -3904,7 +3904,7 @@ jit::AnalyzeArgumentsUsage(JSContext* cx, JSScript* scriptArg)
/* needsArgsObj = */ true,
inlineScriptTree);
const OptimizationInfo* optimizationInfo = IonOptimizations.get(Optimization_Normal);
const OptimizationInfo* optimizationInfo = IonOptimizations.get(OptimizationLevel::Normal);
CompilerConstraintList* constraints = NewCompilerConstraintList(temp);
if (!constraints) {

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

@ -16,27 +16,28 @@ using namespace js::jit;
namespace js {
namespace jit {
OptimizationInfos IonOptimizations;
OptimizationLevelInfo IonOptimizations;
void
OptimizationInfo::initNormalOptimizationInfo()
{
level_ = Optimization_Normal;
level_ = OptimizationLevel::Normal;
autoTruncate_ = true;
eaa_ = true;
eagerSimdUnbox_ = true;
edgeCaseAnalysis_ = true;
eliminateRedundantChecks_ = true;
inlineInterpreted_ = true;
inlineNative_ = true;
eagerSimdUnbox_ = true;
gvn_ = true;
licm_ = true;
rangeAnalysis_ = true;
loopUnrolling_ = true;
gvn_ = true;
rangeAnalysis_ = true;
reordering_ = true;
autoTruncate_ = true;
sincos_ = true;
sink_ = true;
registerAllocator_ = RegisterAllocator_Backtracking;
inlineMaxBytecodePerCallSiteMainThread_ = 500;
@ -61,16 +62,16 @@ OptimizationInfo::initAsmjsOptimizationInfo()
// Take normal option values for not specified values.
initNormalOptimizationInfo();
level_ = OptimizationLevel::AsmJS;
ama_ = true;
level_ = Optimization_AsmJS;
autoTruncate_ = false;
eagerSimdUnbox_ = false; // AsmJS has no boxing / unboxing.
edgeCaseAnalysis_ = false;
eliminateRedundantChecks_ = false;
autoTruncate_ = false;
scalarReplacement_ = false; // AsmJS has no objects.
sincos_ = false;
sink_ = false;
registerAllocator_ = RegisterAllocator_Backtracking;
scalarReplacement_ = false; // AsmJS has no objects.
}
uint32_t
@ -108,49 +109,51 @@ OptimizationInfo::compilerWarmUpThreshold(JSScript* script, jsbytecode* pc) cons
return warmUpThreshold + loopDepth * 100;
}
OptimizationInfos::OptimizationInfos()
OptimizationLevelInfo::OptimizationLevelInfo()
{
infos_[Optimization_Normal - 1].initNormalOptimizationInfo();
infos_[Optimization_AsmJS - 1].initAsmjsOptimizationInfo();
infos_[OptimizationLevel::Normal].initNormalOptimizationInfo();
infos_[OptimizationLevel::AsmJS].initAsmjsOptimizationInfo();
#ifdef DEBUG
OptimizationLevel level = firstLevel();
while (!isLastLevel(level)) {
OptimizationLevel next = nextLevel(level);
MOZ_ASSERT(level < next);
MOZ_ASSERT_IF(level != OptimizationLevel::DontCompile, level < next);
level = next;
}
#endif
}
OptimizationLevel
OptimizationInfos::nextLevel(OptimizationLevel level) const
OptimizationLevelInfo::nextLevel(OptimizationLevel level) const
{
MOZ_ASSERT(!isLastLevel(level));
switch (level) {
case Optimization_DontCompile:
return Optimization_Normal;
default:
MOZ_CRASH("Unknown optimization level.");
case OptimizationLevel::DontCompile:
return OptimizationLevel::Normal;
case OptimizationLevel::Normal:
case OptimizationLevel::AsmJS:
case OptimizationLevel::Count:;
}
MOZ_CRASH("Unknown optimization level.");
}
OptimizationLevel
OptimizationInfos::firstLevel() const
OptimizationLevelInfo::firstLevel() const
{
return nextLevel(Optimization_DontCompile);
return nextLevel(OptimizationLevel::DontCompile);
}
bool
OptimizationInfos::isLastLevel(OptimizationLevel level) const
OptimizationLevelInfo::isLastLevel(OptimizationLevel level) const
{
return level == Optimization_Normal;
return level == OptimizationLevel::Normal;
}
OptimizationLevel
OptimizationInfos::levelForScript(JSScript* script, jsbytecode* pc) const
OptimizationLevelInfo::levelForScript(JSScript* script, jsbytecode* pc) const
{
OptimizationLevel prev = Optimization_DontCompile;
OptimizationLevel prev = OptimizationLevel::DontCompile;
while (!isLastLevel(prev)) {
OptimizationLevel level = nextLevel(prev);

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

@ -7,6 +7,8 @@
#ifndef jit_IonOptimizationLevels_h
#define jit_IonOptimizationLevels_h
#include "mozilla/EnumeratedArray.h"
#include "jsbytecode.h"
#include "jstypes.h"
@ -16,12 +18,12 @@
namespace js {
namespace jit {
enum OptimizationLevel
enum class OptimizationLevel : uint8_t
{
Optimization_DontCompile,
Optimization_Normal,
Optimization_AsmJS,
Optimization_Count
Normal,
AsmJS,
Count,
DontCompile
};
#ifdef JS_JITSPEW
@ -29,15 +31,15 @@ inline const char*
OptimizationLevelString(OptimizationLevel level)
{
switch (level) {
case Optimization_DontCompile:
case OptimizationLevel::DontCompile:
return "Optimization_DontCompile";
case Optimization_Normal:
case OptimizationLevel::Normal:
return "Optimization_Normal";
case Optimization_AsmJS:
case OptimizationLevel::AsmJS:
return "Optimization_AsmJS";
default:
MOZ_CRASH("Invalid OptimizationLevel");
case OptimizationLevel::Count:;
}
MOZ_CRASH("Invalid OptimizationLevel");
}
#endif
@ -263,19 +265,16 @@ class OptimizationInfo
}
};
class OptimizationInfos
class OptimizationLevelInfo
{
private:
OptimizationInfo infos_[Optimization_Count - 1];
mozilla::EnumeratedArray<OptimizationLevel, OptimizationLevel::Count, OptimizationInfo> infos_;
public:
OptimizationInfos();
OptimizationLevelInfo();
const OptimizationInfo* get(OptimizationLevel level) const {
MOZ_ASSERT(level < Optimization_Count);
MOZ_ASSERT(level != Optimization_DontCompile);
return &infos_[level - 1];
return &infos_[level];
}
OptimizationLevel nextLevel(OptimizationLevel level) const;
@ -284,7 +283,7 @@ class OptimizationInfos
OptimizationLevel levelForScript(JSScript* script, jsbytecode* pc = nullptr) const;
};
extern OptimizationInfos IonOptimizations;
extern OptimizationLevelInfo IonOptimizations;
} // namespace jit
} // namespace js

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

@ -407,13 +407,6 @@ MacroAssemblerARMCompat::incrementInt32Value(const Address& addr)
asMasm().add32(Imm32(1), ToPayload(addr));
}
void
MacroAssemblerARMCompat::decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label)
{
asMasm().subPtr(imm, lhs);
branch32(cond, lhs, Imm32(0), label);
}
} // namespace jit
} // namespace js

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

@ -971,7 +971,10 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
branch32(cond, lhs, imm, label);
}
inline void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label);
void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
ma_sub(imm, lhs, SetCC);
as_b(label, cond);
}
void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label);
void moveValue(const Value& val, Register type, Register data);

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

@ -1346,8 +1346,8 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
}
void branch(JitCode* target) {
syncStackPtr();
addPendingJump(nextOffset(), ImmPtr(target->raw()), Relocation::JITCODE);
b(-1); // The jump target will be patched by executableCopy().
BufferOffset loc = b(-1); // The jump target will be patched by executableCopy().
addPendingJump(loc, ImmPtr(target->raw()), Relocation::JITCODE);
}
void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) {

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

@ -1564,11 +1564,14 @@ void MacroAssembler::Claim(const Operand& size) {
}
}
if (!sp.Is(GetStackPointer64())) {
BumpSystemStackPointer(size);
}
Sub(GetStackPointer64(), GetStackPointer64(), size);
// Make sure the real stack pointer reflects the claimed stack space.
// We can't use stack memory below the stack pointer, it could be clobbered by
// interupts and signal handlers.
if (!sp.Is(GetStackPointer64())) {
Mov(sp, GetStackPointer64());
}
}

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

@ -206,11 +206,6 @@ class MozBaseAssembler : public js::jit::AssemblerShared {
protected:
// The buffer into which code and relocation info are generated.
ARMBuffer armbuffer_;
js::jit::CompactBufferWriter jumpRelocations_;
js::jit::CompactBufferWriter dataRelocations_;
js::jit::CompactBufferWriter relocations_;
js::jit::CompactBufferWriter preBarriers_;
};

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

@ -3107,9 +3107,9 @@ SliceBudget::describe(char* buffer, size_t maxlen) const
if (isUnlimited())
return JS_snprintf(buffer, maxlen, "unlimited");
else if (isWorkBudget())
return JS_snprintf(buffer, maxlen, "work(%lld)", workBudget.budget);
return JS_snprintf(buffer, maxlen, "work(%" PRId64 ")", workBudget.budget);
else
return JS_snprintf(buffer, maxlen, "%lldms", timeBudget.budget);
return JS_snprintf(buffer, maxlen, "%" PRId64 "ms", timeBudget.budget);
}
bool

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