Merge m-c to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-10-14 15:52:03 +02:00
commit c3882ca06a
133 changed files with 1787 additions and 1378 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Merge day clobber
Bug 1061335 - CLOBBER for Win32 compiler update.

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "291b607f32e6173d8fe225c644cc7397cdf82fa5",
"revision": "3e3eb020773e765f4cb7775356ae9c22896db875",
"repo_path": "/integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -15,7 +15,7 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
. $topsrcdir/build/win32/mozconfig.vs2013-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi

View File

@ -14,7 +14,7 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
. $topsrcdir/build/win32/mozconfig.vs2013-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>

View File

@ -17,7 +17,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f86c631e0465c0e56ccebeb1324fd28be9ea32f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="de254419f3553f48187d003ee8e38034b429f069"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -115,7 +115,6 @@
#ifdef XP_UNIX
#ifndef XP_MACOSX
@BINPATH@/run-mozilla.sh
@BINPATH@/mozilla-xremote-client
#endif
#endif

View File

@ -342,86 +342,6 @@ nsBrowserContentHandler.prototype = {
cmdLine.preventDefault = true;
}
try {
var remoteCommand = cmdLine.handleFlagWithParam("remote", true);
}
catch (e) {
throw NS_ERROR_ABORT;
}
if (remoteCommand != null) {
try {
var a = /^\s*(\w+)\(([^\)]*)\)\s*$/.exec(remoteCommand);
var remoteVerb;
if (a) {
remoteVerb = a[1].toLowerCase();
var remoteParams = [];
var sepIndex = a[2].lastIndexOf(",");
if (sepIndex == -1)
remoteParams[0] = a[2];
else {
remoteParams[0] = a[2].substring(0, sepIndex);
remoteParams[1] = a[2].substring(sepIndex + 1);
}
}
switch (remoteVerb) {
case "openurl":
case "openfile":
// openURL(<url>)
// openURL(<url>,new-window)
// openURL(<url>,new-tab)
// First param is the URL, second param (if present) is the "target"
// (tab, window)
var url = remoteParams[0];
var target = nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW;
if (remoteParams[1]) {
var targetParam = remoteParams[1].toLowerCase()
.replace(/^\s*|\s*$/g, "");
if (targetParam == "new-tab")
target = nsIBrowserDOMWindow.OPEN_NEWTAB;
else if (targetParam == "new-window")
target = nsIBrowserDOMWindow.OPEN_NEWWINDOW;
else {
// The "target" param isn't one of our supported values, so
// assume it's part of a URL that contains commas.
url += "," + remoteParams[1];
}
}
var uri = resolveURIInternal(cmdLine, url);
handURIToExistingBrowser(uri, target, cmdLine);
break;
case "xfedocommand":
// xfeDoCommand(openBrowser)
if (remoteParams[0].toLowerCase() != "openbrowser")
throw NS_ERROR_ABORT;
// Passing defaultArgs, so use NO_EXTERNAL_URIS
openWindow(null, this.chromeURL, "_blank",
"chrome,dialog=no,all" + this.getFeatures(cmdLine),
this.defaultArgs, NO_EXTERNAL_URIS);
break;
default:
// Somebody sent us a remote command we don't know how to process:
// just abort.
throw "Unknown remote command.";
}
cmdLine.preventDefault = true;
}
catch (e) {
Components.utils.reportError(e);
// If we had a -remote flag but failed to process it, throw
// NS_ERROR_ABORT so that the xremote code knows to return a failure
// back to the handling code.
throw NS_ERROR_ABORT;
}
}
var uriparam;
try {
while ((uriparam = cmdLine.handleFlagWithParam("new-window", false))) {

View File

@ -27,7 +27,7 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
. $topsrcdir/build/win32/mozconfig.vs2013-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi

View File

@ -20,7 +20,7 @@ ac_add_options --with-google-oauth-api-keyfile=${_google_oauth_api_keyfile}
export MOZILLA_OFFICIAL=1
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
. $topsrcdir/build/win32/mozconfig.vs2013-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi

View File

@ -8,7 +8,7 @@ ac_add_options --with-windows-version=601
export MOZILLA_OFFICIAL=1
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
. $topsrcdir/build/win32/mozconfig.vs2013-win64
else
. $topsrcdir/build/win32/mozconfig.vs2010
fi

View File

@ -161,7 +161,6 @@
#ifdef XP_UNIX
#ifndef XP_MACOSX
@BINPATH@/run-mozilla.sh
@BINPATH@/mozilla-xremote-client
#endif
#endif

View File

@ -675,10 +675,19 @@ ifeq (,$(filter $(OS_TARGET),WINNT Darwin))
CHECK_TEXTREL = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep TEXTREL > /dev/null && echo 'TEST-UNEXPECTED-FAIL | check_textrel | We do not want text relocations in libraries and programs' || true
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),android)
# While this is very unlikely (libc being added by the compiler at the end
# of the linker command line), if libmozglue.so ends up after libc.so, all
# hell breaks loose, so better safe than sorry, and check it's actually the
# case.
CHECK_MOZGLUE_ORDER = @$(TOOLCHAIN_PREFIX)readelf -d $(1) | grep NEEDED | awk '{ libs[$$NF] = ++n } END { if (libs["[libmozglue.so]"] && libs["[libc.so]"] < libs["[libmozglue.so]"]) { print "libmozglue.so must be linked before libc.so"; exit 1 } }'
endif
define CHECK_BINARY
$(call CHECK_STDCXX,$(1))
$(call CHECK_TEXTREL,$(1))
$(call LOCAL_CHECKS,$(1))
$(call CHECK_MOZGLUE_ORDER,$(1))
endef
# autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including

View File

@ -330,7 +330,7 @@ nss_def_file := $(srcdir)/nss.def
ifeq (WINNT,$(OS_TARGET))
# Create a .def file based on the various .def files for nss, smime, ssl and
# nssutil.
nss3.def: $(nss_def_file) $(DEPTH)/db/sqlite3/src/sqlite-processed.def
nss3.def: $(nss_def_file) $(DEPTH)/db/sqlite3/src/sqlite-processed.def $(NSS_EXTRA_SYMBOLS_FILE)
echo LIBRARY nss3$(DLL_SUFFIX) > $@.tmp
echo EXPORTS >> $@.tmp
grep -v -h -e ^LIBRARY -e ^EXPORTS -e ^\; $^ >> $@.tmp
@ -340,10 +340,9 @@ ifdef GCC_USE_GNU_LD
sqlite_def_file := $(topsrcdir)/db/sqlite3/src/sqlite.def
nspr_def_file := $(srcdir)/nspr-dummy.def
nss3.def: $(nss_def_file) $(sqlite_def_file) $(nspr_def_file)
nss3.def: $(nss_def_file) $(sqlite_def_file) $(nspr_def_file) $(NSS_EXTRA_SYMBOLS_FILE)
@$(call py_action,convert_def_file, \
$(DEFINES) $(ACDEFINES) $(XULPPFLAGS) -o $@ \
$(nss_def_file) $(sqlite_def_file) $(nspr_def_file))
$(DEFINES) $(ACDEFINES) $(XULPPFLAGS) -o $@ $^)
GARBAGE += \
nss3.def \

View File

@ -7192,9 +7192,7 @@ else
*-android*|*-linuxandroid*)
AC_DEFINE(MOZ_MEMORY_LINUX)
AC_DEFINE(MOZ_MEMORY_ANDROID)
if test -z "$gonkdir"; then
_WRAP_MALLOC=1
else
if test -n "$gonkdir"; then
AC_DEFINE(MOZ_MEMORY_GONK)
fi
MOZ_GLUE_LDFLAGS=
@ -7243,11 +7241,7 @@ dnl our own linker.
if test "$OS_TARGET" = Android; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozglue"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_GetEnv,--wrap=PR_SetEnv"
if test "$MOZ_WIDGET_TOOLKIT" = android; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
fi
if test -z "$gonkdir"; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=memccpy,--wrap=memchr,--wrap=memrchr,--wrap=memcmp,--wrap=memcpy,--wrap=memmove,--wrap=memset,--wrap=memmem,--wrap=index,--wrap=strchr,--wrap=strrchr,--wrap=strlen,--wrap=strcmp,--wrap=strcpy,--wrap=strcat,--wrap=strcasecmp,--wrap=strncasecmp,--wrap=strstr,--wrap=strcasestr,--wrap=strtok,--wrap=strtok_r,--wrap=strerror,--wrap=strerror_r,--wrap=strnlen,--wrap=strncat,--wrap=strncmp,--wrap=strncpy,--wrap=strlcat,--wrap=strlcpy,--wrap=strcspn,--wrap=strpbrk,--wrap=strsep,--wrap=strspn,--wrap=strcoll,--wrap=strxfrm"
fi
if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then
@ -7255,39 +7249,6 @@ if test "$OS_TARGET" = Android; then
fi
fi
dnl ========================================================
dnl = Use malloc wrapper lib
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(wrap-malloc,
[ --enable-wrap-malloc Wrap malloc calls (gnu linker only)],
_WRAP_MALLOC=1,
_WRAP_MALLOC= )
if test -n "$_WRAP_MALLOC"; then
if test -n "$GNU_CC"; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=vasprintf,--wrap=asprintf"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size"
dnl Wrap operator new and operator delete on Android.
if test "$OS_TARGET" = "Android"; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=_Znwj,--wrap=_Znaj,--wrap=_ZdlPv,--wrap=_ZdaPv"
dnl Wrap the nothrow variants too.
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=_ZnwjRKSt9nothrow_t,--wrap=_ZnajRKSt9nothrow_t,--wrap=_ZdlPvRKSt9nothrow_t,--wrap=_ZdaPvRKSt9nothrow_t"
fi
else
AC_MSG_ERROR([--enable-wrap-malloc is not supported for non-GNU toolchains])
fi
fi
dnl ========================================================
dnl = Location of malloc wrapper lib
dnl ========================================================
MOZ_ARG_WITH_STRING(wrap-malloc,
[ --with-wrap-malloc=DIR Location of malloc wrapper library],
WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval")
dnl ========================================================
dnl = Use JS Call tracing
dnl ========================================================
@ -8938,6 +8899,8 @@ if test "$MOZ_DEBUG"; then
fi
AC_SUBST(MOZ_EM_DEBUG)
AC_SUBST(NSS_EXTRA_SYMBOLS_FILE)
if test -n "$COMPILE_ENVIRONMENT"; then
AC_CHECK_FUNCS(posix_fadvise posix_fallocate)
@ -9136,9 +9099,6 @@ if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" && test -n "$MOZ_JEMALLOC3" -
fi
if test -n "$MANGLE"; then
MANGLED=
if test -n "$_WRAP_MALLOC" -a -z "$JEMALLOC_WRAPPER"; then
JEMALLOC_WRAPPER=__wrap_
fi
for mangle in ${MANGLE}; do
if test -n "$MANGLED"; then
MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle,$MANGLED"
@ -9232,11 +9192,6 @@ if test "$COMPILE_ENVIRONMENT" -a -z "$LIBXUL_SDK_DIR"; then
export WRAP_LDFLAGS
if test -n "$_WRAP_MALLOC"; then
# Avoid doubling wrap malloc arguments
_SUBDIR_CONFIG_ARGS="`echo $_SUBDIR_CONFIG_ARGS | sed -e 's/--enable-wrap-malloc *//'`"
fi
if test -n "$MOZ_USING_CCACHE"; then
# Avoid double prepending ccache by omitting --with-ccache in building NSPR.
_SUBDIR_CONFIG_ARGS="`echo $_SUBDIR_CONFIG_ARGS | sed -e 's/--with-ccache[[^ ]]*//'`"

View File

@ -285,13 +285,6 @@ public:
void NotifyMediaTrackEnabled(MediaTrack* aTrack);
/**
* Called by a DOMMediaStream when it has tracks available.
* This allows us to setup audio and video outputs after the stream
* has already reported that playback started, in case they are added late.
*/
void NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream);
virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
/**
@ -623,7 +616,6 @@ protected:
class MediaLoadListener;
class StreamListener;
class MediaStreamTracksAvailableCallback;
virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
@ -1026,9 +1018,6 @@ protected:
nsMediaNetworkState mNetworkState;
nsMediaReadyState mReadyState;
// Last value passed from codec or stream source to UpdateReadyStateForData.
NextFrameStatus mLastNextFrameStatus;
enum LoadAlgorithmState {
// No load algorithm instance is waiting for a source to be added to the
// media in order to continue loading.

View File

@ -71,8 +71,6 @@
#include "mozilla/dom/MediaSource.h"
#include "MediaMetadataManager.h"
#include "MediaSourceDecoder.h"
#include "AudioStreamTrack.h"
#include "VideoStreamTrack.h"
#include "AudioChannelService.h"
@ -666,10 +664,7 @@ void HTMLMediaElement::AbortExistingLoads()
mHaveQueuedSelectResource = false;
mSuspendedForPreloadNone = false;
mDownloadSuspendedByCache = false;
mHasAudio = false;
mHasVideo = false;
mSourcePointer = nullptr;
mLastNextFrameStatus = NEXT_FRAME_UNINITIALIZED;
mTags = nullptr;
@ -903,39 +898,6 @@ void HTMLMediaElement::NotifyMediaTrackEnabled(MediaTrack* aTrack)
}
}
void HTMLMediaElement::NotifyMediaStreamTracksAvailable(DOMMediaStream* aStream)
{
if (!mSrcStream || mSrcStream != aStream) {
return;
}
bool oldHasAudio = mHasAudio;
bool oldHasVideo = mHasVideo;
nsAutoTArray<nsRefPtr<AudioStreamTrack>,1> audioTracks;
aStream->GetAudioTracks(audioTracks);
nsAutoTArray<nsRefPtr<VideoStreamTrack>,1> videoTracks;
aStream->GetVideoTracks(videoTracks);
mHasAudio = !audioTracks.IsEmpty();
mHasVideo = !videoTracks.IsEmpty();
if (!oldHasAudio && mHasAudio) {
GetSrcMediaStream()->AddAudioOutput(this);
GetSrcMediaStream()->SetAudioOutputVolume(this, float(mMuted ? 0.0 : mVolume));
}
if (!oldHasVideo && mHasVideo ) {
VideoFrameContainer* container = GetVideoFrameContainer();
if (container) {
GetSrcMediaStream()->AddVideoOutput(container);
}
// mHasVideo changed so make sure the screen wakelock is updated
NotifyOwnerDocumentActivityChanged();
}
CheckAutoplayDataReady();
}
void HTMLMediaElement::LoadFromSourceChildren()
{
NS_ASSERTION(mDelayingLoadEvent,
@ -2025,7 +1987,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mCurrentLoadID(0),
mNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY),
mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING),
mLastNextFrameStatus(NEXT_FRAME_UNINITIALIZED),
mLoadWaitStatus(NOT_WAITING),
mVolume(1.0),
mPreloadAction(PRELOAD_UNDEFINED),
@ -2854,28 +2815,6 @@ private:
bool mPendingNotifyOutput;
};
class HTMLMediaElement::MediaStreamTracksAvailableCallback:
public DOMMediaStream::OnTracksAvailableCallback
{
public:
explicit MediaStreamTracksAvailableCallback(HTMLMediaElement* aElement,
DOMMediaStream::TrackTypeHints aExpectedTracks = 0):
DOMMediaStream::OnTracksAvailableCallback(aExpectedTracks),
mElement(aElement)
{}
virtual void NotifyTracksAvailable(DOMMediaStream* aStream)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
if (!mElement) {
return;
}
mElement->NotifyMediaStreamTracksAvailable(aStream);
}
private:
HTMLMediaElement* mElement;
};
void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
{
NS_ASSERTION(!mSrcStream && !mSrcStreamListener, "Should have been ended already");
@ -2897,24 +2836,22 @@ void HTMLMediaElement::SetupSrcMediaStreamPlayback(DOMMediaStream* aStream)
if (mPausedForInactiveDocumentOrChannel) {
GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
}
mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this, DOMMediaStream::HINT_CONTENTS_AUDIO));
mSrcStream->OnTracksAvailable(new MediaStreamTracksAvailableCallback(this, DOMMediaStream::HINT_CONTENTS_VIDEO));
MediaInfo mediaInfo;
mediaInfo.mAudio.mHasAudio = mHasAudio;
mediaInfo.mVideo.mHasVideo = mHasVideo;
MetadataLoaded(&mediaInfo, nullptr);
DispatchAsyncEvent(NS_LITERAL_STRING("suspend"));
mNetworkState = nsIDOMHTMLMediaElement::NETWORK_IDLE;
ChangeDelayLoadStatus(false);
GetSrcMediaStream()->AddAudioOutput(this);
GetSrcMediaStream()->SetAudioOutputVolume(this, float(mMuted ? 0.0 : mVolume));
VideoFrameContainer* container = GetVideoFrameContainer();
if (container) {
GetSrcMediaStream()->AddVideoOutput(container);
}
// Note: we must call DisconnectTrackListListeners(...) before dropping
// mSrcStream
mSrcStream->ConstructMediaTracks(AudioTracks(), VideoTracks());
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_IDLE);
AddRemoveSelfReference();
// FirstFrameLoaded() will be called when the stream has current data.
}
@ -2930,12 +2867,12 @@ void HTMLMediaElement::EndSrcMediaStreamPlayback()
// Kill its reference to this element
mSrcStreamListener->Forget();
mSrcStreamListener = nullptr;
if (stream && mHasAudio) {
if (stream) {
stream->RemoveAudioOutput(this);
}
VideoFrameContainer* container = GetVideoFrameContainer();
if (container) {
if (stream && mHasVideo) {
if (stream) {
stream->RemoveVideoOutput(container);
}
container->ClearCurrentFrame();
@ -2987,11 +2924,6 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
mVideoFrameContainer->ForgetElement();
mVideoFrameContainer = nullptr;
}
if (IsVideo()) {
// Update the screen wakelock in case mHasVideo changed
NotifyOwnerDocumentActivityChanged();
}
}
void HTMLMediaElement::FirstFrameLoaded()
@ -2999,7 +2931,6 @@ void HTMLMediaElement::FirstFrameLoaded()
NS_ASSERTION(!mSuspendedAfterFirstFrame, "Should not have already suspended");
ChangeDelayLoadStatus(false);
UpdateReadyStateForData(NEXT_FRAME_UNAVAILABLE);
if (mDecoder && mAllowSuspendAfterFirstFrame && mPaused &&
!HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
@ -3162,18 +3093,10 @@ bool HTMLMediaElement::ShouldCheckAllowOrigin()
void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatus aNextFrame)
{
mLastNextFrameStatus = aNextFrame;
if (mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) {
// aNextFrame might have a next frame because the decoder can advance
// on its own thread before MetadataLoaded gets a chance to run.
// The arrival of more data can't change us out of this readyState.
return;
}
if (!mHasAudio && !mHasVideo) {
// No tracks available yet, don't advance from HAVE_METADATA
return;
}
@ -3196,14 +3119,6 @@ void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatu
return;
}
if (mReadyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA && mHasVideo) {
VideoFrameContainer* container = GetVideoFrameContainer();
if (container && mMediaSize == nsIntSize(-1,-1)) {
// No frame has been set yet. Don't advance.
return;
}
}
if (aNextFrame != MediaDecoderOwner::NEXT_FRAME_AVAILABLE) {
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
if (!mWaitingFired && aNextFrame == MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING) {
@ -3344,15 +3259,14 @@ void HTMLMediaElement::ChangeNetworkState(nsMediaNetworkState aState)
bool HTMLMediaElement::CanActivateAutoplay()
{
// For stream inputs, we activate autoplay on HAVE_METADATA because
// For stream inputs, we activate autoplay on HAVE_CURRENT_DATA because
// this element itself might be blocking the stream from making progress by
// being paused.
return !mPausedForInactiveDocumentOrChannel &&
mAutoplaying &&
mPaused &&
((mDecoder && mReadyState >= nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA) ||
(mSrcStream && mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA)) &&
(mHasAudio || mHasVideo) &&
(mSrcStream && mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA)) &&
HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay) &&
mAutoplayEnabled &&
!IsEditable();
@ -3381,14 +3295,24 @@ void HTMLMediaElement::CheckAutoplayDataReady()
VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()
{
if (mVideoFrameContainer)
return mVideoFrameContainer;
// If we have loaded the metadata, and the size of the video is still
// (-1, -1), the media has no video. Don't go a create a video frame
// container.
if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA &&
mMediaSize == nsIntSize(-1, -1)) {
return nullptr;
}
// Only video frames need an image container.
if (!IsVideo()) {
return nullptr;
}
mHasVideo = true;
if (mVideoFrameContainer)
return mVideoFrameContainer;
mVideoFrameContainer =
new VideoFrameContainer(this, LayerManager::CreateAsynchronousImageContainer());
@ -3501,7 +3425,6 @@ void HTMLMediaElement::NotifyDecoderPrincipalChanged()
void HTMLMediaElement::UpdateMediaSize(nsIntSize size)
{
mMediaSize = size;
UpdateReadyStateForData(mLastNextFrameStatus);
}
void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents)

View File

@ -39,6 +39,9 @@ public:
// True if this reader is waiting media resource allocation
virtual bool IsWaitingMediaResources() { return false; }
// True if this reader is waiting for a Content Decryption Module to become
// available.
virtual bool IsWaitingOnCDMResource() { return false; }
// True when this reader need to become dormant state
virtual bool IsDormantNeeded() { return false; }
// Release media resources they should be released in dormant state

View File

@ -16,9 +16,16 @@
#include "nsContentUtils.h"
#include "nsIScriptObjectPrincipal.h"
#include "mozilla/Preferences.h"
#include "nsContentTypeParser.h"
#ifdef MOZ_FMP4
#include "MP4Decoder.h"
#endif
#ifdef XP_WIN
#include "mozilla/WindowsVersion.h"
#endif
#include "nsContentCID.h"
#include "nsServiceManagerUtils.h"
#include "mozIGeckoMediaPluginService.h"
namespace mozilla {
@ -107,15 +114,86 @@ MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, Error
}
static bool
IsSupportedKeySystem(const nsAString& aKeySystem)
HaveGMPFor(const nsCString& aKeySystem,
const nsCString& aAPI,
const nsCString& aTag = EmptyCString())
{
return aKeySystem.EqualsASCII("org.w3.clearkey") ||
#ifdef XP_WIN
(aKeySystem.EqualsASCII("com.adobe.access") &&
IsVistaOrLater() &&
Preferences::GetBool("media.eme.adobe-access.enabled", false)) ||
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (NS_WARN_IF(!mps)) {
return false;
}
nsTArray<nsCString> tags;
tags.AppendElement(aKeySystem);
if (!aTag.IsEmpty()) {
tags.AppendElement(aTag);
}
// Note: EME plugins need a non-null nodeId here, as they must
// not be shared across origins.
bool hasPlugin = false;
if (NS_FAILED(mps->HasPluginForAPI(aAPI,
&tags,
&hasPlugin))) {
return false;
}
return hasPlugin;
}
static bool
IsPlayableMP4Type(const nsAString& aContentType)
{
#ifdef MOZ_FMP4
nsContentTypeParser parser(aContentType);
nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv)) {
return false;
}
nsAutoString codecs;
parser.GetParameter("codecs", codecs);
NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType);
return MP4Decoder::CanHandleMediaType(mimeTypeUTF8, codecs);
#else
return false;
#endif
false;
}
bool
MediaKeys::IsTypeSupported(const nsAString& aKeySystem,
const Optional<nsAString>& aInitDataType,
const Optional<nsAString>& aContentType)
{
if (aKeySystem.EqualsLiteral("org.w3.clearkey") &&
(!aInitDataType.WasPassed() || aInitDataType.Value().EqualsLiteral("cenc")) &&
(!aContentType.WasPassed() || IsPlayableMP4Type(aContentType.Value())) &&
HaveGMPFor(NS_LITERAL_CSTRING("org.w3.clearkey"),
NS_LITERAL_CSTRING("eme-decrypt"))) {
return true;
}
#ifdef XP_WIN
// Note: Adobe Access's GMP uses WMF to decode, so anything our MP4Reader
// thinks it can play on Windows, the Access GMP should be able to play.
if (aKeySystem.EqualsLiteral("com.adobe.access") &&
Preferences::GetBool("media.eme.adobe-access.enabled", false) &&
IsVistaOrLater() && // Win Vista and later only.
(!aInitDataType.WasPassed() || aInitDataType.Value().EqualsLiteral("cenc")) &&
(!aContentType.WasPassed() || IsPlayableMP4Type(aContentType.Value())) &&
HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
NS_LITERAL_CSTRING("eme-decrypt")) &&
HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
NS_LITERAL_CSTRING("decode-video"),
NS_LITERAL_CSTRING("h264")) &&
HaveGMPFor(NS_LITERAL_CSTRING("com.adobe.access"),
NS_LITERAL_CSTRING("decode-audio"),
NS_LITERAL_CSTRING("aac"))) {
return true;
}
#endif
return false;
}
/* static */
@ -128,8 +206,16 @@ MediaKeys::IsTypeSupported(const GlobalObject& aGlobal,
{
// TODO: Should really get spec changed to this is async, so we can wait
// for user to consent to running plugin.
return IsSupportedKeySystem(aKeySystem) ? IsTypeSupportedResult::Maybe
: IsTypeSupportedResult::_empty;
bool supported = IsTypeSupported(aKeySystem, aInitDataType, aContentType);
EME_LOG("MediaKeys::IsTypeSupported keySystem='%s' initDataType='%s' contentType='%s' supported=%d",
NS_ConvertUTF16toUTF8(aKeySystem).get(),
(aInitDataType.WasPassed() ? NS_ConvertUTF16toUTF8(aInitDataType.Value()).get() : ""),
(aContentType.WasPassed() ? NS_ConvertUTF16toUTF8(aContentType.Value()).get() : ""),
supported);
return supported ? IsTypeSupportedResult::Probably
: IsTypeSupportedResult::_empty;
}
already_AddRefed<Promise>
@ -242,7 +328,7 @@ MediaKeys::Init(ErrorResult& aRv)
return nullptr;
}
if (!IsSupportedKeySystem(mKeySystem)) {
if (!IsTypeSupported(mKeySystem)) {
promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return promise.forget();
}
@ -271,7 +357,7 @@ MediaKeys::Init(ErrorResult& aRv)
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
mTopLevelPrincipal = top->GetExtantDoc()->NodePrincipal();
if (!mPrincipal || !mTopLevelPrincipal) {

View File

@ -124,6 +124,10 @@ public:
private:
static bool IsTypeSupported(const nsAString& aKeySystem,
const Optional<nsAString>& aInitDataType = Optional<nsAString>(),
const Optional<nsAString>& aContentType = Optional<nsAString>());
bool IsInPrivateBrowsing();
already_AddRefed<Promise> Init(ErrorResult& aRv);

View File

@ -109,7 +109,7 @@ public:
// with a U and V plane that are half the size of the Y plane, i.e 8 bit,
// 2x2 subsampled. Have the data pointers of each frame point to the
// first plane, they'll always be zero'd memory anyway.
uint8_t* frame = new uint8_t[mFrameWidth * mFrameHeight];
nsAutoArrayPtr<uint8_t> frame(new uint8_t[mFrameWidth * mFrameHeight]);
memset(frame, 0, mFrameWidth * mFrameHeight);
VideoData::YCbCrBuffer buffer;

View File

@ -92,7 +92,7 @@ private:
bool IsSupportedAudioMimeType(const char* aMimeType);
void NotifyResourcesStatusChanged();
bool IsWaitingOnCodecResource();
bool IsWaitingOnCDMResource();
virtual bool IsWaitingOnCDMResource() MOZ_OVERRIDE;
nsAutoPtr<mp4_demuxer::MP4Demuxer> mDemuxer;
nsAutoPtr<PlatformDecoderModule> mPlatform;

View File

@ -61,6 +61,7 @@ PlatformDecoderModule::Init()
#endif
}
#ifdef MOZ_EME
class CreateTaskQueueTask : public nsRunnable {
public:
NS_IMETHOD Run() {
@ -81,7 +82,6 @@ CreateTaskQueue()
return t->mTaskQueue.forget();
}
#ifdef MOZ_EME
/* static */
PlatformDecoderModule*
PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy,

View File

@ -31,6 +31,7 @@ namespace gmp {
GMPAudioDecoderParent::GMPAudioDecoderParent(GMPParent* aPlugin)
: mIsOpen(false)
, mShuttingDown(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
{
@ -161,17 +162,19 @@ GMPAudioDecoderParent::Shutdown()
LOGD(("%s: %p", __FUNCTION__, this));
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (mShuttingDown) {
return NS_OK;
}
mShuttingDown = true;
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
mCallback = nullptr;
}
if (mIsOpen) {
// Don't send DecodingComplete if we died
mIsOpen = false;
unused << SendDecodingComplete();
}
mIsOpen = false;
unused << SendDecodingComplete();
return NS_OK;
}

View File

@ -53,6 +53,7 @@ private:
virtual bool Recv__delete__() MOZ_OVERRIDE;
bool mIsOpen;
bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin;
GMPAudioDecoderProxyCallback* mCallback;
};

View File

@ -13,6 +13,7 @@ namespace gmp {
GMPDecryptorParent::GMPDecryptorParent(GMPParent* aPlugin)
: mIsOpen(false)
, mShuttingDown(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
{
@ -328,16 +329,19 @@ GMPDecryptorParent::Shutdown()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (mShuttingDown) {
return;
}
mShuttingDown = true;
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
mCallback = nullptr;
}
if (mIsOpen) {
mIsOpen = false;
unused << SendDecryptingComplete();
}
mIsOpen = false;
unused << SendDecryptingComplete();
}
// Note: Keep this sync'd up with Shutdown

View File

@ -106,6 +106,7 @@ private:
virtual bool Recv__delete__() MOZ_OVERRIDE;
bool mIsOpen;
bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin;
GMPDecryptorProxyCallback* mCallback;
};

View File

@ -143,6 +143,7 @@ GeckoMediaPluginService::GeckoMediaPluginService()
: mMutex("GeckoMediaPluginService::mMutex")
, mShuttingDown(false)
, mShuttingDownOnGMPThread(false)
, mScannedPluginOnDisk(false)
, mWaitingForPluginsAsyncShutdown(false)
{
MOZ_ASSERT(NS_IsMainThread());
@ -590,7 +591,7 @@ GeckoMediaPluginService::UnloadPlugins()
MutexAutoLock lock(mMutex);
// Note: CloseActive is async; it will actually finish
// shutting down when all the plugins have unloaded.
for (uint32_t i = 0; i < mPlugins.Length(); i++) {
for (size_t i = 0; i < mPlugins.Length(); i++) {
mPlugins[i]->CloseActive(true);
}
mPlugins.Clear();
@ -619,7 +620,7 @@ GeckoMediaPluginService::CrashPlugins()
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPlugins.Length(); i++) {
for (size_t i = 0; i < mPlugins.Length(); i++) {
mPlugins[i]->Crash();
}
}
@ -652,6 +653,8 @@ GeckoMediaPluginService::LoadFromEnvironment()
pos = next + 1;
}
}
mScannedPluginOnDisk = true;
}
NS_IMETHODIMP
@ -693,47 +696,88 @@ GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory)
return NS_OK;
}
class DummyRunnable : public nsRunnable {
public:
NS_IMETHOD Run() { return NS_OK; }
};
NS_IMETHODIMP
GeckoMediaPluginService::HasPluginForAPI(const nsACString& aNodeId,
const nsACString& aAPI,
GeckoMediaPluginService::HasPluginForAPI(const nsACString& aAPI,
nsTArray<nsCString>* aTags,
bool* aResult)
{
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
NS_ENSURE_ARG(aResult);
nsCString temp(aAPI);
GMPParent *parent = SelectPluginForAPI(aNodeId, temp, *aTags, false);
*aResult = !!parent;
const char* env = nullptr;
if (!mScannedPluginOnDisk && (env = PR_GetEnv("MOZ_GMP_PATH")) && *env) {
// We have a MOZ_GMP_PATH environment variable which may specify the
// location of plugins to load, and we haven't yet scanned the disk to
// see if there are plugins there. Get the GMP thread, which will
// cause an event to be dispatched to which scans for plugins. We
// dispatch a sync event to the GMP thread here in order to wait until
// after the GMP thread has scanned any paths in MOZ_GMP_PATH.
nsCOMPtr<nsIThread> thread;
nsresult rv = GetThread(getter_AddRefs(thread));
if (NS_FAILED(rv)) {
return rv;
}
thread->Dispatch(new DummyRunnable(), NS_DISPATCH_SYNC);
MOZ_ASSERT(mScannedPluginOnDisk, "Should have scanned MOZ_GMP_PATH by now");
}
{
MutexAutoLock lock(mMutex);
nsCString api(aAPI);
GMPParent* gmp = FindPluginForAPIFrom(0, api, *aTags, nullptr);
*aResult = (gmp != nullptr);
}
return NS_OK;
}
GMPParent*
GeckoMediaPluginService::FindPluginForAPIFrom(size_t aSearchStartIndex,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
size_t* aOutPluginIndex)
{
mMutex.AssertCurrentThreadOwns();
for (size_t i = aSearchStartIndex; i < mPlugins.Length(); i++) {
GMPParent* gmp = mPlugins[i];
bool supportsAllTags = true;
for (size_t t = 0; t < aTags.Length(); t++) {
const nsCString& tag = aTags.ElementAt(t);
if (!gmp->SupportsAPI(aAPI, tag)) {
supportsAllTags = false;
break;
}
}
if (!supportsAllTags) {
continue;
}
if (aOutPluginIndex) {
*aOutPluginIndex = i;
}
return gmp;
}
return nullptr;
}
GMPParent*
GeckoMediaPluginService::SelectPluginForAPI(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
bool aCloneCrossNodeIds)
const nsTArray<nsCString>& aTags)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread || !aCloneCrossNodeIds,
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread,
"Can't clone GMP plugins on non-GMP threads.");
GMPParent* gmpToClone = nullptr;
{
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPlugins.Length(); i++) {
GMPParent* gmp = mPlugins[i];
bool supportsAllTags = true;
for (uint32_t t = 0; t < aTags.Length(); t++) {
const nsCString& tag = aTags[t];
if (!gmp->SupportsAPI(aAPI, tag)) {
supportsAllTags = false;
break;
}
}
if (!supportsAllTags) {
continue;
}
size_t index = 0;
GMPParent* gmp = nullptr;
while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) {
if (aNodeId.IsEmpty()) {
if (gmp->CanBeSharedCrossNodeIds()) {
return gmp;
@ -744,15 +788,17 @@ GeckoMediaPluginService::SelectPluginForAPI(const nsACString& aNodeId,
return gmp;
}
// This GMP has the correct type but has the wrong origin; hold on to it
// This GMP has the correct type but has the wrong nodeId; hold on to it
// in case we need to clone it.
gmpToClone = gmp;
// Loop around and try the next plugin; it may be usable from aNodeId.
index++;
}
}
// Plugin exists, but we can't use it due to cross-origin separation. Create a
// new one.
if (aCloneCrossNodeIds && gmpToClone) {
if (gmpToClone) {
GMPParent* clone = ClonePlugin(gmpToClone);
if (!aNodeId.IsEmpty()) {
clone->SetNodeId(aNodeId);
@ -847,7 +893,7 @@ GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)
}
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPlugins.Length(); ++i) {
for (size_t i = 0; i < mPlugins.Length(); ++i) {
nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory();
bool equals;
if (NS_SUCCEEDED(directory->Equals(pluginpath, &equals)) && equals) {

View File

@ -19,6 +19,7 @@
#include "nsITimer.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "mozilla/Atomics.h"
template <class> struct already_AddRefed;
@ -49,8 +50,11 @@ private:
GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
bool aCloneCrossNodeIds = true);
const nsTArray<nsCString>& aTags);
GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags,
size_t* aOutPluginIndex);
void UnloadPlugins();
void CrashPlugins();
@ -94,6 +98,10 @@ private:
bool mShuttingDown;
bool mShuttingDownOnGMPThread;
// True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any
// plugins found there into mPlugins.
Atomic<bool> mScannedPluginOnDisk;
template<typename T>
class MainThreadOnly {
public:

View File

@ -45,6 +45,7 @@ namespace gmp {
GMPVideoDecoderParent::GMPVideoDecoderParent(GMPParent* aPlugin)
: GMPSharedMemManager(aPlugin)
, mIsOpen(false)
, mShuttingDown(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
, mVideoHost(MOZ_THIS_IN_INITIALIZER_LIST())
@ -187,6 +188,11 @@ GMPVideoDecoderParent::Shutdown()
LOGD(("%s: %p", __FUNCTION__, this));
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (mShuttingDown) {
return NS_OK;
}
mShuttingDown = true;
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
@ -194,11 +200,8 @@ GMPVideoDecoderParent::Shutdown()
}
mVideoHost.DoneWithAPI();
if (mIsOpen) {
// Don't send DecodingComplete if we died
mIsOpen = false;
unused << SendDecodingComplete();
}
mIsOpen = false;
unused << SendDecodingComplete();
return NS_OK;
}

View File

@ -77,6 +77,7 @@ private:
virtual bool Recv__delete__() MOZ_OVERRIDE;
bool mIsOpen;
bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin;
GMPVideoDecoderCallbackProxy* mCallback;
GMPVideoHostImpl mVideoHost;

View File

@ -52,6 +52,7 @@ namespace gmp {
GMPVideoEncoderParent::GMPVideoEncoderParent(GMPParent *aPlugin)
: GMPSharedMemManager(aPlugin),
mIsOpen(false),
mShuttingDown(false),
mPlugin(aPlugin),
mCallback(nullptr),
mVideoHost(MOZ_THIS_IN_INITIALIZER_LIST())
@ -220,17 +221,20 @@ GMPVideoEncoderParent::Shutdown()
LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
if (mShuttingDown) {
return;
}
mShuttingDown = true;
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
mCallback = nullptr;
}
mVideoHost.DoneWithAPI();
if (mIsOpen) {
// Don't send EncodingComplete if we died
mIsOpen = false;
unused << SendEncodingComplete();
}
mIsOpen = false;
unused << SendEncodingComplete();
}
static void

View File

@ -74,6 +74,7 @@ private:
virtual bool Recv__delete__() MOZ_OVERRIDE;
bool mIsOpen;
bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin;
GMPVideoEncoderCallbackProxy* mCallback;
GMPVideoHostImpl mVideoHost;

View File

@ -26,7 +26,7 @@ class GMPVideoHost;
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
[scriptable, uuid(b350d3b6-00c9-4602-bdfe-84c2be8d1e7a)]
[scriptable, uuid(657443a4-6b5d-4181-98b0-56997b35bd57)]
interface mozIGeckoMediaPluginService : nsISupports
{
@ -40,9 +40,7 @@ interface mozIGeckoMediaPluginService : nsISupports
* Callable on any thread
*/
[noscript]
boolean hasPluginForAPI([optional] in ACString nodeId,
in ACString api,
in TagArray tags);
boolean hasPluginForAPI(in ACString api, in TagArray tags);
/**
* Get a video decoder that supports the specified tags.

View File

@ -0,0 +1,123 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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 "gtest/gtest.h"
#include "mozilla/StaticPtr.h"
#include "GMPVideoDecoderProxy.h"
#include "GMPVideoEncoderProxy.h"
#include "GMPService.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
using namespace mozilla;
using namespace mozilla::gmp;
struct GMPTestRunner
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner)
void DoTest(void (GMPTestRunner::*aTestMethod)());
void RunTestGMPTestCodec();
void RunTestGMPCrossOrigin();
private:
~GMPTestRunner() { }
};
void
GMPTestRunner::RunTestGMPTestCodec()
{
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
GMPVideoHost* host = nullptr;
GMPVideoDecoderProxy* decoder = nullptr;
GMPVideoDecoderProxy* decoder2 = nullptr;
GMPVideoEncoderProxy* encoder = nullptr;
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("o"), &host, &decoder2);
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING(""), &host, &decoder);
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING(""), &host, &encoder);
EXPECT_TRUE(host);
EXPECT_TRUE(decoder);
EXPECT_TRUE(decoder2);
EXPECT_TRUE(encoder);
if (decoder) decoder->Close();
if (decoder2) decoder2->Close();
if (encoder) encoder->Close();
}
void
GMPTestRunner::RunTestGMPCrossOrigin()
{
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
GMPVideoHost* host = nullptr;
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
GMPVideoDecoderProxy* decoder1 = nullptr;
GMPVideoDecoderProxy* decoder2 = nullptr;
GMPVideoEncoderProxy* encoder1 = nullptr;
GMPVideoEncoderProxy* encoder2 = nullptr;
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder1);
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &decoder2);
EXPECT_TRUE(!!decoder1 && !!decoder2 &&
decoder1->ParentID() != decoder2->ParentID());
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder1);
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &encoder2);
EXPECT_TRUE(!!encoder1 && !!encoder2 &&
encoder1->ParentID() != encoder2->ParentID());
if (decoder2) decoder2->Close();
if (encoder2) encoder2->Close();
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder2);
EXPECT_TRUE(!!decoder1 && !!decoder2 &&
decoder1->ParentID() == decoder2->ParentID());
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder2);
EXPECT_TRUE(!!encoder1 && !!encoder2 &&
encoder1->ParentID() == encoder2->ParentID());
if (decoder1) decoder1->Close();
if (decoder2) decoder2->Close();
if (encoder1) encoder1->Close();
if (encoder2) encoder2->Close();
}
void
GMPTestRunner::DoTest(void (GMPTestRunner::*aTestMethod)())
{
nsRefPtr<GeckoMediaPluginService> service =
GeckoMediaPluginService::GetGeckoMediaPluginService();
nsCOMPtr<nsIThread> thread;
service->GetThread(getter_AddRefs(thread));
thread->Dispatch(NS_NewRunnableMethod(this, aTestMethod), NS_DISPATCH_SYNC);
}
TEST(GeckoMediaPlugins, GMPTestCodec) {
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec);
}
TEST(GeckoMediaPlugins, GMPCrossOrigin) {
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin);
}

View File

@ -6,6 +6,7 @@
UNIFIED_SOURCES += [
'TestAudioCompactor.cpp',
'TestGMPCrossOrigin.cpp',
'TestTrackEncoder.cpp',
'TestVideoSegment.cpp',
'TestWebMBuffered.cpp'
@ -25,6 +26,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [
'/content/media/encoder',
'/content/media/gmp',
]
FINAL_LIBRARY = 'xul-gtest'

View File

@ -187,4 +187,17 @@ MediaSourceDecoder::PrepareReaderInitialization()
mReader->PrepareInitialization();
}
#ifdef MOZ_EME
nsresult
MediaSourceDecoder::SetCDMProxy(CDMProxy* aProxy)
{
nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
NS_ENSURE_SUCCESS(rv, rv);
rv = mReader->SetCDMProxy(aProxy);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
#endif
} // namespace mozilla

View File

@ -63,6 +63,10 @@ public:
// registered TrackBuffers essential for initialization.
void PrepareReaderInitialization();
#ifdef MOZ_EME
virtual nsresult SetCDMProxy(CDMProxy* aProxy) MOZ_OVERRIDE;
#endif
private:
// The owning MediaSource holds a strong reference to this decoder, and
// calls Attach/DetachMediaSource on this decoder to set and clear

View File

@ -329,6 +329,9 @@ MediaSourceReader::CreateSubDecoder(const nsACString& aType)
MSE_DEBUG("MediaSourceReader(%p)::CreateSubDecoder subdecoder %p subreader %p",
this, decoder.get(), reader.get());
decoder->SetReader(reader);
#ifdef MOZ_EME
decoder->SetCDMProxy(mCDMProxy);
#endif
return decoder.forget();
}
@ -515,4 +518,20 @@ MediaSourceReader::IsEnded()
return mEnded;
}
#ifdef MOZ_EME
nsresult
MediaSourceReader::SetCDMProxy(CDMProxy* aProxy)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mCDMProxy = aProxy;
for (size_t i = 0; i < mTrackBuffers.Length(); i++) {
nsresult rv = mTrackBuffers[i]->SetCDMProxy(aProxy);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
#endif
} // namespace mozilla

View File

@ -101,6 +101,10 @@ public:
// Return true if the Ended method has been called
bool IsEnded();
#ifdef MOZ_EME
nsresult SetCDMProxy(CDMProxy* aProxy);
#endif
private:
bool SwitchAudioReader(int64_t aTarget);
bool SwitchVideoReader(int64_t aTarget);
@ -123,6 +127,10 @@ private:
nsRefPtr<TrackBuffer> mAudioTrack;
nsRefPtr<TrackBuffer> mVideoTrack;
#ifdef MOZ_EME
nsRefPtr<CDMProxy> mCDMProxy;
#endif
// These are read and written on the decode task queue threads.
int64_t mLastAudioTime;
int64_t mLastVideoTime;

View File

@ -11,6 +11,9 @@
#include "MediaDecoderReader.h"
#include "SourceBufferResource.h"
#include "mozilla/Attributes.h"
#ifdef MOZ_EME
#include "mozilla/CDMProxy.h"
#endif
#include "mozilla/ReentrantMonitor.h"
namespace mozilla {
@ -81,6 +84,23 @@ public:
mTaskQueue = aTaskQueue;
}
#ifdef MOZ_EME
virtual nsresult SetCDMProxy(CDMProxy* aProxy)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mCDMProxy = aProxy;
return NS_OK;
}
virtual CDMProxy* GetCDMProxy() MOZ_OVERRIDE
{
MOZ_ASSERT(OnDecodeThread() || NS_IsMainThread());
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
return mCDMProxy;
}
#endif
// Given a time convert it into an approximate byte offset from the
// cached data. Returns -1 if no such value is computable.
int64_t ConvertToByteOffset(double aTime);
@ -96,6 +116,10 @@ private:
AbstractMediaDecoder* mParentDecoder;
nsRefPtr<MediaDecoderReader> mReader;
int64_t mMediaDuration;
#ifdef MOZ_EME
nsRefPtr<CDMProxy> mCDMProxy;
#endif
};
} // namespace mozilla

View File

@ -237,6 +237,7 @@ TrackBuffer::NewDecoder()
mLastStartTimestamp = 0;
mLastEndTimestamp = 0;
decoder->SetTaskQueue(mTaskQueue);
return QueueInitializeDecoder(decoder);
}
@ -247,7 +248,6 @@ TrackBuffer::QueueInitializeDecoder(SourceBufferDecoder* aDecoder)
NS_NewRunnableMethodWithArg<SourceBufferDecoder*>(this,
&TrackBuffer::InitializeDecoder,
aDecoder);
aDecoder->SetTaskQueue(mTaskQueue);
if (NS_FAILED(mTaskQueue->Dispatch(task))) {
MSE_DEBUG("MediaSourceReader(%p): Failed to enqueue decoder initialization task", this);
RemoveDecoder(aDecoder);
@ -272,8 +272,16 @@ TrackBuffer::InitializeDecoder(SourceBufferDecoder* aDecoder)
MediaInfo mi;
nsAutoPtr<MetadataTags> tags; // TODO: Handle metadata.
nsresult rv = reader->ReadMetadata(&mi, getter_Transfers(tags));
aDecoder->SetTaskQueue(nullptr);
reader->SetIdle();
if (NS_SUCCEEDED(rv) && reader->IsWaitingOnCDMResource()) {
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
mWaitingDecoders.AppendElement(aDecoder);
return;
}
aDecoder->SetTaskQueue(nullptr);
if (NS_FAILED(rv) || (!mi.HasVideo() && !mi.HasAudio())) {
// XXX: Need to signal error back to owning SourceBuffer.
MSE_DEBUG("TrackBuffer(%p): Reader %p failed to initialize rv=%x audio=%d video=%d",
@ -415,6 +423,31 @@ TrackBuffer::Decoders()
return mInitializedDecoders;
}
#ifdef MOZ_EME
nsresult
TrackBuffer::SetCDMProxy(CDMProxy* aProxy)
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
nsresult rv = mDecoders[i]->SetCDMProxy(aProxy);
NS_ENSURE_SUCCESS(rv, rv);
}
for (uint32_t i = 0; i < mWaitingDecoders.Length(); ++i) {
CDMCaps::AutoLock caps(aProxy->Capabilites());
caps.CallOnMainThreadWhenCapsAvailable(
NS_NewRunnableMethodWithArg<SourceBufferDecoder*>(this,
&TrackBuffer::QueueInitializeDecoder,
mWaitingDecoders[i]));
}
mWaitingDecoders.Clear();
return NS_OK;
}
#endif
#if defined(DEBUG)
void
TrackBuffer::Dump(const char* aPath)

View File

@ -73,6 +73,10 @@ public:
// TODO: Refactor to a cleaner interface between TrackBuffer and MediaSourceReader.
const nsTArray<nsRefPtr<SourceBufferDecoder>>& Decoders();
#ifdef MOZ_EME
nsresult SetCDMProxy(CDMProxy* aProxy);
#endif
#if defined(DEBUG)
void Dump(const char* aPath);
#endif
@ -127,6 +131,10 @@ private:
// Access protected by mParentDecoder's monitor.
nsTArray<nsRefPtr<SourceBufferDecoder>> mInitializedDecoders;
// Decoders which are waiting on a Content Decryption Module to be able to
// finish ReadMetadata.
nsTArray<nsRefPtr<SourceBufferDecoder>> mWaitingDecoders;
// The decoder that the owning SourceBuffer is currently appending data to.
nsRefPtr<SourceBufferDecoder> mCurrentDecoder;

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This XML file describes the encryption applied to |gizmo-frag-cenc*|. To
generate the gizmo-frag-cenc files, run the following commands:
Encrypt gizmo.mp4 with the keys specified in this file, and output to |gizmo-cenc.mp4|
MP4Box -crypt gizmo-frag-cenc.xml -out gizmo-cenc.mp4 gizmo.mp4
Fragment |gizmo-cenc.mp4| into 1000ms segments:
MP4Box -dash 1000 -rap -segment-name gizmo-frag-cenc -subsegs-per-sidx 5 -rem 2 gizmo-cenc.mp4
The above command will generate a set of fragments in |gizmo-frag-cenc*.m4s|
and a single |gizmo-frag-cencinit.mp4| containing just the init segment.
To cut down the duration, we throw out all but the first two segments:
rm gizmo-frag-cenc[^12].m4s
-->
<GPACDRM type="CENC AES-CTR">
<DRMInfo type="pssh" version="1">
<!--
SystemID specified in
https://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/cenc-format.html
-->
<BS ID128="1077efecc0b24d02ace33c1e52e2fb4b" />
<!-- Number of KeyIDs = 2 -->
<BS bits="32" value="2" />
<!-- KeyID -->
<BS ID128="0x7e571d037e571d037e571d037e571d03" />
<BS ID128="0x7e571d047e571d047e571d047e571d04" />
</DRMInfo>
<CrypTrack trackID="1" isEncrypted="1" IV_size="16" saiSavedBox="senc"
first_IV="0x00000000000000000000000000000000">
<key KID="0x7e571d037e571d037e571d037e571d03"
value="0x7e5733337e5733337e5733337e573333" />
</CrypTrack>
<CrypTrack trackID="2" isEncrypted="1" IV_size="16" saiSavedBox="senc"
first_IV="0x00000000000000000000000000000000">
<key KID="0x7e571d047e571d047e571d047e571d04"
value="0x7e5744447e5744447e5744447e574444" />
</CrypTrack>
</GPACDRM>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -640,14 +640,28 @@ var gMetadataTests = [
var gEMETests = [
{
name:"short-cenc.mp4",
type:"video/mp4",
type:"video/mp4; codecs=\"avc1.64000d,mp4a.40.2\"",
keys: {
// "keyid" : "key"
"7e571d017e571d017e571d017e571d01" : "7e5711117e5711117e5711117e571111",
"7e571d027e571d027e571d027e571d02" : "7e5722227e5722227e5722227e572222",
},
sessionType:"temporary",
duration:0.47
},
// XXX Bug 1082239
//{
// name:"gizmo-frag-cencinit.mp4",
// fragments: [ "gizmo-frag-cencinit.mp4", "gizmo-frag-cenc1.m4s", "gizmo-frag-cenc2.m4s" ],
// type:"video/mp4; codecs=\"avc1.64000d,mp4a.40.2\"",
// keys: {
// // "keyid" : "key"
// "7e571d037e571d037e571d037e571d03" : "7e5733337e5733337e5733337e573333",
// "7e571d047e571d047e571d047e571d04" : "7e5744447e5744447e5744447e574444",
// },
// sessionType:"temporary",
// duration:2.00,
//},
];
function checkMetadata(msg, e, test) {

View File

@ -140,6 +140,9 @@ support-files =
dirac.ogg^headers^
dynamic_redirect.sjs
dynamic_resource.sjs
gizmo-frag-cenc1.m4s
gizmo-frag-cenc2.m4s
gizmo-frag-cencinit.mp4
file_access_controls.html
fragment_noplay.js
fragment_play.js
@ -319,7 +322,6 @@ skip-if = buildapp == 'mulet' || os == 'win' # bug 894922
[test_bug686942.html]
[test_bug726904.html]
[test_bug874897.html]
[test_bug879717.html]
[test_bug883173.html]
[test_bug895091.html]
[test_bug895305.html]

View File

@ -1,65 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for bug 879717, check that a video element can be drawn into a canvas directly on 'play' event</title>
<script type="text/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>
<video id="v1" autoplay />
<video id="v2" autoplay />
<canvas id="c1" />
<canvas id="c2" />
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var media = getPlayableVideo(gSmallTests);
var checkDrawImage = function(video, canvas, name) {
var exception = null;
var exceptionName = "nothing";
try {
var ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
} catch (e) {
exception = e;
exceptionName = e.name;
}
ok(exception === null || video.ended,
"drawImage shouldn't throw an exception on play of " + name + ", got " + exceptionName);
};
if (media == null) {
todo(false, "No media supported.");
SimpleTest.finish();
} else {
v1.src = media.name;
v2.mozSrcObject = v1.mozCaptureStream();
var v1Tested = false;
var v2Tested = false;
v1.addEventListener('play', function() {
checkDrawImage(v1, c1, media.name);
v1Tested = true;
if (v2Tested) {
SimpleTest.finish();
}
});
v2.addEventListener('play', function() {
checkDrawImage(v2, c2, "stream of " + media.name);
v2Tested = true;
if (v1Tested) {
SimpleTest.finish();
}
});
}
</script>
</pre>
</body>
</html>

View File

@ -104,46 +104,131 @@ function UpdateSessionFunc(test) {
}
}
function PlayFragmented(test, elem)
{
var ms = new MediaSource();
elem.src = URL.createObjectURL(ms);
var sb;
var curFragment = 0;
function addNextFragment() {
if (curFragment >= test.fragments.length) {
ms.endOfStream();
elem.play();
return;
}
var fragmentFile = test.fragments[curFragment++];
var req = new XMLHttpRequest();
req.open("GET", fragmentFile);
req.responseType = "arraybuffer";
req.addEventListener("load", function() {
sb.appendBuffer(new Uint8Array(req.response));
});
info("fetching resource " + fragmentFile);
req.send(null);
}
ms.addEventListener("sourceopen", function () {
sb = ms.addSourceBuffer(test.type);
sb.addEventListener("updateend", addNextFragment);
addNextFragment();
});
}
function PlayTest(test, elem)
{
if (test.fragments) {
PlayFragmented(test, elem);
return;
}
// This file isn't fragmented; set the media source normally.
elem.src = test.name;
elem.play();
}
function startTest(test, token)
{
manager.started(test._token);
var v = document.createElement("video");
manager.started(token);
var gotEncrypted = false;
var gotPlaying = false;
v.addEventListener("encrypted", function(ev) {
info("got encrypted event");
gotEncrypted = true;
info(token + " got encrypted event");
ok(MediaKeys.isTypeSupported(KEYSYSTEM_TYPE, ev.initDataType, test.type),
"MediaKeys should support this keysystem");
token + " MediaKeys should support this keysystem");
MediaKeys.create(KEYSYSTEM_TYPE).then(function(mediaKeys) {
info("created MediaKeys object ok");
info(token + " created MediaKeys object ok");
return v.setMediaKeys(mediaKeys);
}, bail("failed to create MediaKeys object")).then(function() {
info("set MediaKeys on <video> element ok");
info(token + " set MediaKeys on <video> element ok");
ok(MediaKeys.isTypeSupported(KEYSYSTEM_TYPE, ev.initDataType, test.type),
"MediaKeys should still support keysystem after CDM created...");
var session = v.mediaKeys.createSession(test.sessionType);
session.addEventListener("message", UpdateSessionFunc(test));
session.generateRequest(ev.initDataType, ev.initData).then(function() {
}, bail("Failed to initialise MediaKeySession"));
}, bail(token + " Failed to initialise MediaKeySession"));
}, bail("Failed to set MediaKeys on <video> element"));
}, bail(token + " Failed to set MediaKeys on <video> element"));
});
v.addEventListener("playing", function () { gotPlaying = true; });
v.addEventListener("ended", function(ev) {
ok(true, "got ended event");
SimpleTest.finish();
ok(true, token + " got ended event");
manager.finished(test._token);
ok(gotEncrypted, token + " encrypted event should have fired");
ok(gotPlaying, token + " playing event should have fired");
ok(Math.abs(test.duration - v.duration) < 0.1,
token + " Duration of video should be corrrect");
ok(Math.abs(test.duration - v.currentTime) < 0.1,
token + " Current time should be same as duration");
});
v.addEventListener("error", bail("got error event"));
v.addEventListener("error", bail(token + " got error event"));
v.src = test.name;
v.play();
PlayTest(test, v);
}
function testIsTypeSupported()
{
var t = MediaKeys.isTypeSupported;
const clearkey = "org.w3.clearkey";
ok(!t("bogus", "bogon", "video/bogus"), "Invalid type.");
ok(t(clearkey), "ClearKey supported.");
ok(!t(clearkey, "bogus"), "ClearKey bogus initDataType not supported.");
ok(t(clearkey, "cenc"), "ClearKey/cenc should be supported.");
ok(!t(clearkey, "cenc", "bogus"), "ClearKey/cenc bogus content type should be supported.");
ok(t(clearkey, "cenc", 'video/mp4'), "ClearKey/cenc video/mp4 supported.");
ok(t(clearkey, "cenc", 'video/mp4; codecs="avc1.4d4015,mp4a.40.2"'), "ClearKey/cenc H.264/AAC supported.");
ok(t(clearkey, "cenc", 'audio/mp4'), "ClearKey/cenc audio/mp4 supported.");
ok(t(clearkey, "cenc", 'audio/mp4; codecs="mp4a.40.2"'), "ClearKey/cenc AAC LC supported.");
}
function beginTest() {
testIsTypeSupported();
manager.runTests(gEMETests, startTest);
}
var prefs = [ ];
var prefs = [
[ "media.mediasource.enabled", true ],
[ "media.mediasource.ignore_codecs", true ],
];
if (/Linux/.test(navigator.userAgent) ||
!document.createElement('video').canPlayType("video/mp4")) {

View File

@ -19,8 +19,6 @@ using namespace mozilla::dom;
namespace mozilla {
static const TrackID TRACK_VIDEO = 2;
void
FakeMediaStreamGraph::DispatchToMainThreadAfterStreamStateUpdate(already_AddRefed<nsIRunnable> aRunnable)
{
@ -34,7 +32,6 @@ CameraPreviewMediaStream::CameraPreviewMediaStream(DOMMediaStream* aWrapper)
, mInvalidatePending(0)
, mDiscardedFrames(0)
, mRateLimit(false)
, mTrackCreated(false)
{
SetGraphImpl(MediaStreamGraph::GetInstance());
mFakeMediaStreamGraph = new FakeMediaStreamGraph();
@ -114,22 +111,6 @@ CameraPreviewMediaStream::RemoveListener(MediaStreamListener* aListener)
listener->NotifyEvent(mFakeMediaStreamGraph, MediaStreamListener::EVENT_REMOVED);
}
void
CameraPreviewMediaStream::OnPreviewStateChange(bool aActive)
{
MutexAutoLock lock(mMutex);
if (!mTrackCreated && aActive) {
mTrackCreated = true;
VideoSegment tmpSegment;
uint32_t trackEvent = aActive ? MediaStreamListener::TRACK_EVENT_CREATED
: MediaStreamListener::TRACK_EVENT_ENDED;
for (uint32_t j = 0; j < mListeners.Length(); ++j) {
MediaStreamListener* l = mListeners[j];
l->NotifyQueuedTrackChanges(mFakeMediaStreamGraph, TRACK_VIDEO, 0, 0, trackEvent, tmpSegment);
}
}
}
void
CameraPreviewMediaStream::Destroy()
{

View File

@ -51,7 +51,6 @@ public:
virtual void AddListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
virtual void RemoveListener(MediaStreamListener* aListener) MOZ_OVERRIDE;
virtual void Destroy();
void OnPreviewStateChange(bool aActive);
void Invalidate();
@ -68,7 +67,6 @@ protected:
int32_t mInvalidatePending;
uint32_t mDiscardedFrames;
bool mRateLimit;
bool mTrackCreated;
nsRefPtr<FakeMediaStreamGraph> mFakeMediaStreamGraph;
};

View File

@ -218,8 +218,7 @@ nsDOMCameraControl::nsDOMCameraControl(uint32_t aCameraId,
mCurrentConfiguration = initialConfig.forget();
// Attach our DOM-facing media stream to our viewfinder stream.
SetHintContents(HINT_CONTENTS_VIDEO);
InitStreamCommon(mInput);
mStream = mInput;
MOZ_ASSERT(mWindow, "Shouldn't be created with a null window!");
if (mWindow->GetExtantDoc()) {
CombineWithPrincipal(mWindow->GetExtantDoc()->NodePrincipal());

View File

@ -137,7 +137,6 @@ DOMCameraControlListener::OnPreviewStateChange(PreviewState aState)
MOZ_ASSERT_UNREACHABLE("Invalid preview state");
return;
}
mStream->OnPreviewStateChange(aState == kPreviewStarted);
NS_DispatchToMainThread(new Callback(mDOMCameraControl, aState));
}

View File

@ -109,26 +109,18 @@ var Camera = {
var blob = e.data;
var img = new Image();
var test = this._currentTest;
var onPreviewStateChange = function(e) {
if (e.newState === 'started') {
ok(true, "viewfinder is ready and playing after resume");
Camera.cameraObj.removeEventListener('previewstatechange', onPreviewStateChange);
Camera._testsCompleted++;
if(Camera._testsCompleted == Camera._tests.length) {
ok(true, "test finishing");
SimpleTest.finish();
} else {
Camera.runTests();
}
}
}
Camera.cameraObj.addEventListener('previewstatechange', onPreviewStateChange);
img.onload = function Imgsize() {
ok(this.width == test.pictureSize.width, "The image taken has the width " +
this.width + " pictureSize width = " + test.pictureSize.width);
ok(this.height == test.pictureSize.height, "The image taken has the height " +
this.height + " picturesize height = " + test.pictureSize.height);
Camera.cameraObj.resumePreview();
Camera._testsCompleted++;
if(Camera._testsCompleted == Camera._tests.length) {
ok(true, "test finishing");
SimpleTest.finish();
} else {
Camera.runTests();
}
}
ok(blob.size > 100 , "Blob Size Gathered = " + blob.size);
ok("image/" + test.fileFormat == blob.type, "Blob Type = " + blob.type);

View File

@ -248,7 +248,6 @@ private:
bool ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth,
const char* info);
};
} // namespace mozilla

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGL2Context.h"
#include "WebGLContextUtils.h"
#include "GLContext.h"
using namespace mozilla;
@ -115,14 +116,9 @@ WebGL2Context::ValidateTexStorage(GLenum target, GLsizei levels, GLenum internal
if (depth < 1) { ErrorInvalidValue("%s: depth is < 1", info); return false; }
if (levels < 1) { ErrorInvalidValue("%s: levels is < 1", info); return false; }
// The following check via FloorLog2 only requires a depth value if target is TEXTURE_3D.
bool is3D = (target != LOCAL_GL_TEXTURE_3D);
if (!is3D)
depth = 1;
// GL_INVALID_OPERATION is generated if levels is greater than floor(log2(max(width, height, depth)))+1.
if (FloorLog2(std::max(std::max(width, height), depth))+1 < levels) {
ErrorInvalidOperation("%s: levels > floor(log2(max(width, height%s)))+1", info, is3D ? ", depth" : "");
if (FloorLog2(std::max(std::max(width, height), depth)) + 1 < levels) {
ErrorInvalidOperation("%s: too many levels for given texture dimensions", info);
return false;
}
@ -140,7 +136,7 @@ WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
if (target != LOCAL_GL_TEXTURE_2D && target != LOCAL_GL_TEXTURE_CUBE_MAP)
return ErrorInvalidEnum("texStorage2D: target is not TEXTURE_2D or TEXTURE_CUBE_MAP.");
return ErrorInvalidEnum("texStorage2D: target is not TEXTURE_2D or TEXTURE_CUBE_MAP");
if (!ValidateTexStorage(target, levels, internalformat, width, height, 1, "texStorage2D"))
return;
@ -154,12 +150,12 @@ WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat
for (size_t l = 0; l < size_t(levels); l++) {
for (size_t f = 0; f < facesCount; f++) {
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, f),
l, w, h,
l, w, h, 1,
internalformat,
WebGLImageDataStatus::UninitializedImageData);
}
w = std::max(1, w/2);
h = std::max(1, h/2);
w = std::max(1, w / 2);
h = std::max(1, h / 2);
}
gl->fTexStorage2D(target, levels, internalformat, width, height);
@ -169,17 +165,131 @@ void
WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth)
{
MOZ_CRASH("Not Implemented.");
if (IsContextLost())
return;
// GL_INVALID_ENUM is generated if target is not one of the accepted target enumerants.
if (target != LOCAL_GL_TEXTURE_3D)
return ErrorInvalidEnum("texStorage3D: target is not TEXTURE_3D");
if (!ValidateTexStorage(target, levels, internalformat, width, height, depth, "texStorage3D"))
return;
WebGLTexture* tex = activeBoundTextureForTarget(target);
tex->SetImmutable();
GLsizei w = width;
GLsizei h = height;
GLsizei d = depth;
for (size_t l = 0; l < size_t(levels); l++) {
tex->SetImageInfo(TexImageTargetForTargetAndFace(target, 0),
l, w, h, d,
internalformat,
WebGLImageDataStatus::UninitializedImageData);
w = std::max(1, w >> 1);
h = std::max(1, h >> 1);
d = std::max(1, d >> 1);
}
gl->fTexStorage3D(target, levels, internalformat, width, height, depth);
}
void
WebGL2Context::TexSubImage3D(GLenum target, GLint level,
WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const Nullable<dom::ArrayBufferView>& pixels,
ErrorResult& rv)
{
MOZ_CRASH("Not Implemented.");
if (IsContextLost())
return;
if (pixels.IsNull())
return ErrorInvalidValue("texSubImage3D: pixels must not be null!");
const ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
if (!ValidateTexImageTarget(rawTarget, func, dims))
return;
TexImageTarget texImageTarget(rawTarget);
WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
if (!tex) {
return ErrorInvalidOperation("texSubImage3D: no texture bound on active texture unit");
}
if (!tex->HasImageInfoAt(texImageTarget, level)) {
return ErrorInvalidOperation("texSubImage3D: no previously defined texture image");
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
TexInternalFormat existingUnsizedInternalFormat = LOCAL_GL_NONE;
TexType existingType = LOCAL_GL_NONE;
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(existingEffectiveInternalFormat,
&existingUnsizedInternalFormat,
&existingType);
if (!ValidateTexImage(texImageTarget, level, existingEffectiveInternalFormat.get(),
xoffset, yoffset, zoffset,
width, height, depth,
0, format, type, func, dims))
{
return;
}
if (type != existingType) {
return ErrorInvalidOperation("texSubImage3D: type differs from that of the existing image");
}
js::Scalar::Type jsArrayType = JS_GetArrayBufferViewType(view.Obj());
void* data = view.Data();
size_t dataLength = view.Length();
if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
const size_t bitsPerTexel = GetBitsPerTexel(existingEffectiveInternalFormat);
MOZ_ASSERT((bitsPerTexel % 8) == 0); // should not have compressed formats here.
size_t srcTexelSize = bitsPerTexel / 8;
if (width == 0 || height == 0 || depth == 0)
return; // no effect, we better return right now
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (dataLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, dataLength);
if (imageInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
DriverFormatsFromEffectiveInternalFormat(gl,
existingEffectiveInternalFormat,
&driverInternalFormat,
&driverFormat,
&driverType);
MakeContextCurrent();
gl->fTexSubImage3D(texImageTarget.get(), level,
xoffset, yoffset, zoffset,
width, height, depth,
driverFormat, driverType, data);
}
void

View File

@ -345,6 +345,7 @@ WebGLContext::DestroyResourcesAndContext()
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBound3DTextures.Clear();
mBoundArrayBuffer = nullptr;
mBoundTransformFeedbackBuffer = nullptr;
mCurrentProgram = nullptr;
@ -1772,8 +1773,11 @@ bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
type = LOCAL_GL_HALF_FLOAT;
}
if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
if (!ValidateTexImageFormatAndType(format, type,
WebGLTexImageFunc::TexImage, WebGLTexDimensions::Tex2D))
{
return false;
}
HTMLVideoElement* video = HTMLVideoElement::FromContentOrNull(&elt);
if (!video) {
@ -1825,7 +1829,7 @@ bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
TexInternalFormat effectiveinternalformat =
EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
MOZ_ASSERT(effectiveinternalformat != LOCAL_GL_NONE);
tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width, srcImage->GetSize().height,
tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width, srcImage->GetSize().height, 1,
effectiveinternalformat, WebGLImageDataStatus::InitializedImageData);
tex->Bind(TexImageTargetToTexTarget(texImageTarget));
}
@ -1869,6 +1873,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
mExtensions,
mBound2DTextures,
mBoundCubeMapTextures,
mBound3DTextures,
mBoundArrayBuffer,
mBoundTransformFeedbackBuffer,
mCurrentProgram,

View File

@ -228,8 +228,16 @@ public:
void DummyFramebufferOperation(const char *info);
WebGLTexture* activeBoundTextureForTarget(const TexTarget texTarget) const {
return texTarget == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
: mBoundCubeMapTextures[mActiveTexture];
switch (texTarget.get()) {
case LOCAL_GL_TEXTURE_2D:
return mBound2DTextures[mActiveTexture];
case LOCAL_GL_TEXTURE_CUBE_MAP:
return mBoundCubeMapTextures[mActiveTexture];
case LOCAL_GL_TEXTURE_3D:
return mBound3DTextures[mActiveTexture];
default:
MOZ_CRASH("bad target");
}
}
/* Use this function when you have the texture image target, for example:
@ -483,10 +491,12 @@ public:
if (IsContextLost())
return;
auto dims = 2;
if (!ValidateTexImageTarget(dims, rawTexImgTarget, WebGLTexImageFunc::TexImage))
if (!ValidateTexImageTarget(rawTexImgTarget,
WebGLTexImageFunc::TexImage,
WebGLTexDimensions::Tex2D))
{
return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImgTarget);
}
const TexImageTarget texImageTarget(rawTexImgTarget);
@ -520,7 +530,7 @@ public:
return TexImage2D_base(texImageTarget, level, internalformat,
size.width, size.height, data->Stride(),
0, format, type, data->GetData(), byteLength,
-1, srcFormat, mPixelStorePremultiplyAlpha);
js::Scalar::TypeMax, srcFormat, mPixelStorePremultiplyAlpha);
}
void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
@ -552,8 +562,12 @@ public:
if (IsContextLost())
return;
if (!ValidateTexImageTarget(2, rawTexImageTarget, WebGLTexImageFunc::TexSubImage))
if (!ValidateTexImageTarget(rawTexImageTarget,
WebGLTexImageFunc::TexSubImage,
WebGLTexDimensions::Tex2D))
{
return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
}
const TexImageTarget texImageTarget(rawTexImageTarget);
@ -592,7 +606,7 @@ public:
size.width, size.height,
data->Stride(), format, type,
data->GetData(), byteLength,
-1, srcFormat, mPixelStorePremultiplyAlpha);
js::Scalar::TypeMax, srcFormat, mPixelStorePremultiplyAlpha);
}
@ -836,6 +850,7 @@ private:
public:
void Disable(GLenum cap);
void Enable(GLenum cap);
bool GetStencilBits(GLint* out_stencilBits);
JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
void GetParameter(JSContext* cx, GLenum pname,
JS::MutableHandle<JS::Value> retval, ErrorResult& rv) {
@ -971,6 +986,7 @@ protected:
static CheckedUint32 GetImageSize(GLsizei height,
GLsizei width,
GLsizei depth,
uint32_t pixelSize,
uint32_t alignment);
@ -1092,7 +1108,10 @@ protected:
bool ValidateComparisonEnum(GLenum target, const char *info);
bool ValidateStencilOpEnum(GLenum action, const char *info);
bool ValidateFaceEnum(GLenum face, const char *info);
bool ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFunc func);
bool ValidateTexInputData(GLenum type,
js::Scalar::Type jsArrayType,
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateDrawModeEnum(GLenum mode, const char *info);
bool ValidateAttribIndex(GLuint index, const char *info);
bool ValidateStencilParamsForDrawCall();
@ -1102,40 +1121,56 @@ protected:
bool ValidateGLSLString(const nsAString& string, const char *info);
bool ValidateCopyTexImage(GLenum internalformat,
WebGLTexImageFunc func);
bool ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImage(TexImageTarget texImageTarget,
GLint level, GLenum internalFormat,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLint border, GLenum format, GLenum type,
WebGLTexImageFunc func);
bool ValidateTexImageTarget(GLuint dims, GLenum target, WebGLTexImageFunc func);
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImageTarget(GLenum target,
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImageFormat(GLenum internalformat,
WebGLTexImageFunc func);
bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func);
bool ValidateTexImageFormatAndType(GLenum format, GLenum type, WebGLTexImageFunc func);
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImageType(GLenum type,
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImageFormatAndType(GLenum format,
GLenum type,
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateCompTexImageInternalFormat(GLenum format,
WebGLTexImageFunc func);
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateCopyTexImageInternalFormat(GLenum format,
WebGLTexImageFunc func);
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexImageSize(TexImageTarget target, GLint level,
GLint width, GLint height, GLint depth,
WebGLTexImageFunc func);
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateTexSubImageSize(GLint x, GLint y, GLint z,
GLsizei width, GLsizei height, GLsizei depth,
GLsizei baseWidth, GLsizei baseHeight, GLsizei baseDepth,
WebGLTexImageFunc func);
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateCompTexImageSize(GLint level,
GLenum internalformat,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLsizei levelWidth, GLsizei levelHeight,
WebGLTexImageFunc func);
WebGLTexImageFunc func,
WebGLTexDimensions dims);
bool ValidateCompTexImageDataSize(GLint level,
GLenum internalformat,
GLsizei width, GLsizei height,
uint32_t byteLength, WebGLTexImageFunc func);
uint32_t byteLength,
WebGLTexImageFunc func,
WebGLTexDimensions dims);
void Invalidate();
void DestroyResourcesAndContext();
@ -1143,6 +1178,7 @@ protected:
void MakeContextCurrent() const;
// helpers
void TexImage2D_base(TexImageTarget target,
GLint level,
GLenum internalformat,
@ -1150,7 +1186,7 @@ protected:
GLenum format,
GLenum type,
void *data, uint32_t byteLength,
int jsArrayType,
js::Scalar::Type jsArrayType, // special value TypeMax used to mean no array
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexSubImage2D_base(TexImageTarget target, GLint level,
GLint xoffset, GLint yoffset,
@ -1158,7 +1194,7 @@ protected:
GLenum format,
GLenum type,
void *pixels, uint32_t byteLength,
int jsArrayType,
js::Scalar::Type jsArrayType, // special value TypeMax used to mean no array
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexParameter_base(GLenum target, GLenum pname,
GLint *intParamPtr, GLfloat *floatParamPtr);
@ -1255,6 +1291,7 @@ protected:
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound3DTextures;
WebGLRefPtr<WebGLProgram> mCurrentProgram;

View File

@ -48,6 +48,7 @@
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/Endian.h"
#include "mozilla/fallible.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -233,6 +234,12 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture *newTex)
case LOCAL_GL_TEXTURE_CUBE_MAP:
currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
break;
case LOCAL_GL_TEXTURE_3D:
if (!IsWebGL2()) {
return ErrorInvalidEnum("bindTexture: target TEXTURE_3D is only available in WebGL version 2.0 or newer");
}
currentTexPtr = &mBound3DTextures[mActiveTexture];
break;
default:
return ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
}
@ -367,22 +374,25 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
GLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
const char* info = sub ? "copyTexSubImage2D" : "copyTexImage2D";
WebGLTexImageFunc func = sub ? WebGLTexImageFunc::CopyTexSubImage : WebGLTexImageFunc::CopyTexImage;
WebGLTexImageFunc func = sub
? WebGLTexImageFunc::CopyTexSubImage
: WebGLTexImageFunc::CopyTexImage;
WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
const char* info = InfoFrom(func, dims);
// TODO: This changes with color_buffer_float. Reassess when the
// patch lands.
if (!ValidateTexImage(2, texImageTarget, level, internalformat.get(),
if (!ValidateTexImage(texImageTarget, level, internalformat.get(),
xoffset, yoffset, 0,
width, height, 0,
0,
LOCAL_GL_NONE, LOCAL_GL_NONE,
func))
func, dims))
{
return;
}
if (!ValidateCopyTexImage(internalformat.get(), func))
if (!ValidateCopyTexImage(internalformat.get(), func, dims))
return;
if (!mBoundFramebuffer)
@ -440,7 +450,7 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
// first, we initialize the texture as black
if (!sub) {
tex->SetImageInfo(texImageTarget, level, width, height,
tex->SetImageInfo(texImageTarget, level, width, height, 1,
effectiveInternalFormat,
WebGLImageDataStatus::UninitializedImageData);
tex->DoDeferredImageInitialization(texImageTarget, level);
@ -478,7 +488,7 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
}
if (!sub) {
tex->SetImageInfo(texImageTarget, level, width, height,
tex->SetImageInfo(texImageTarget, level, width, height, 1,
effectiveInternalFormat,
WebGLImageDataStatus::InitializedImageData);
}
@ -499,20 +509,21 @@ WebGLContext::CopyTexImage2D(GLenum rawTexImgTarget,
// copyTexImage2D only generates textures with type = UNSIGNED_BYTE
const WebGLTexImageFunc func = WebGLTexImageFunc::CopyTexImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CopyTexImage))
if (!ValidateTexImageTarget(rawTexImgTarget, func, dims))
return;
if (!ValidateTexImage(2, rawTexImgTarget, level, internalformat,
if (!ValidateTexImage(rawTexImgTarget, level, internalformat,
0, 0, 0,
width, height, 0,
border, LOCAL_GL_NONE, LOCAL_GL_NONE,
func))
func, dims))
{
return;
}
if (!ValidateCopyTexImage(internalformat, func))
if (!ValidateCopyTexImage(internalformat, func, dims))
return;
if (!mBoundFramebuffer)
@ -698,7 +709,8 @@ WebGLContext::DeleteTexture(WebGLTexture *tex)
GLuint activeTexture = mActiveTexture;
for (int32_t i = 0; i < mGLMaxTextureUnits; i++) {
if ((mBound2DTextures[i] == tex && tex->Target() == LOCAL_GL_TEXTURE_2D) ||
(mBoundCubeMapTextures[i] == tex && tex->Target() == LOCAL_GL_TEXTURE_CUBE_MAP))
(mBoundCubeMapTextures[i] == tex && tex->Target() == LOCAL_GL_TEXTURE_CUBE_MAP) ||
(mBound3DTextures[i] == tex && tex->Target() == LOCAL_GL_TEXTURE_3D))
{
ActiveTexture(LOCAL_GL_TEXTURE0 + i);
BindTexture(tex->Target().get(), static_cast<WebGLTexture*>(nullptr));
@ -2144,7 +2156,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
// Check the pixels param size
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, bytesPerPixel, mPixelStorePackAlignment);
GetImageSize(height, width, 1, bytesPerPixel, mPixelStorePackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * bytesPerPixel;
@ -3309,15 +3321,16 @@ WebGLContext::CompressedTexImage2D(GLenum rawTexImgTarget,
return;
const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CompTexImage))
if (!ValidateTexImageTarget(rawTexImgTarget, func, dims))
return;
if (!ValidateTexImage(2, rawTexImgTarget, level, internalformat,
if (!ValidateTexImage(rawTexImgTarget, level, internalformat,
0, 0, 0, width, height, 0,
border, LOCAL_GL_NONE,
LOCAL_GL_NONE,
func))
func, dims))
{
return;
}
@ -3325,11 +3338,11 @@ WebGLContext::CompressedTexImage2D(GLenum rawTexImgTarget,
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func)) {
if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func, dims)) {
return;
}
if (!ValidateCompTexImageSize(level, internalformat, 0, 0, width, height, width, height, func))
if (!ValidateCompTexImageSize(level, internalformat, 0, 0, width, height, width, height, func, dims))
{
return;
}
@ -3347,7 +3360,7 @@ WebGLContext::CompressedTexImage2D(GLenum rawTexImgTarget,
MakeContextCurrent();
gl->fCompressedTexImage2D(texImageTarget.get(), level, internalformat, width, height, border, byteLength, view.Data());
tex->SetImageInfo(texImageTarget, level, width, height, internalformat,
tex->SetImageInfo(texImageTarget, level, width, height, 1, internalformat,
WebGLImageDataStatus::InitializedImageData);
}
@ -3361,16 +3374,17 @@ WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint
return;
const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexSubImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CompTexSubImage))
if (!ValidateTexImageTarget(rawTexImgTarget, func, dims))
return;
if (!ValidateTexImage(2, rawTexImgTarget,
if (!ValidateTexImage(rawTexImgTarget,
level, internalformat,
xoffset, yoffset, 0,
width, height, 0,
0, LOCAL_GL_NONE, LOCAL_GL_NONE,
func))
func, dims))
{
return;
}
@ -3388,14 +3402,14 @@ WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func))
if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func, dims))
return;
if (!ValidateCompTexImageSize(level, internalformat,
xoffset, yoffset,
width, height,
levelInfo.Width(), levelInfo.Height(),
func))
func, dims))
{
return;
}
@ -3647,19 +3661,20 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
GLenum format,
GLenum type,
void* data, uint32_t byteLength,
int jsArrayType, // a TypedArray format enum, or -1 if not relevant
js::Scalar::Type jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
if (type == LOCAL_GL_HALF_FLOAT_OES) {
type = LOCAL_GL_HALF_FLOAT;
}
if (!ValidateTexImage(2, texImageTarget, level, internalformat,
if (!ValidateTexImage(texImageTarget, level, internalformat,
0, 0, 0,
width, height, 0,
border, format, type, func))
border, format, type, func, dims))
{
return;
}
@ -3675,7 +3690,7 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
"level must be zero");
}
if (!ValidateTexInputData(type, jsArrayType, func))
if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
TexInternalFormat effectiveInternalFormat =
@ -3701,7 +3716,7 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
}
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
GetImageSize(height, width, 1, srcTexelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
CheckedUint32 checked_alignedRowSize =
@ -3755,7 +3770,12 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
else
{
size_t convertedDataSize = height * dstStride;
convertedData = new uint8_t[convertedDataSize];
convertedData = (uint8_t*)moz_malloc(convertedDataSize);
if (!convertedData) {
ErrorOutOfMemory("texImage2D: Ran out of memory when allocating"
" a buffer for doing format conversion.");
return;
}
if (!ConvertImage(width, height, srcStride, dstStride,
static_cast<uint8_t*>(data), convertedData,
actualSrcFormat, srcPremultiplied,
@ -3781,7 +3801,7 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
// have NoImageData at this point.
MOZ_ASSERT(imageInfoStatusIfSuccess != WebGLImageDataStatus::NoImageData);
tex->SetImageInfo(texImageTarget, level, width, height,
tex->SetImageInfo(texImageTarget, level, width, height, 1,
effectiveInternalFormat, imageInfoStatusIfSuccess);
}
@ -3796,21 +3816,21 @@ WebGLContext::TexImage2D(GLenum rawTarget, GLint level,
void* data;
uint32_t length;
int jsArrayType;
js::Scalar::Type jsArrayType;
if (pixels.IsNull()) {
data = nullptr;
length = 0;
jsArrayType = -1;
jsArrayType = js::Scalar::TypeMax;
} else {
const ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
data = view.Data();
length = view.Length();
jsArrayType = int(JS_GetArrayBufferViewType(view.Obj()));
jsArrayType = JS_GetArrayBufferViewType(view.Obj());
}
if (!ValidateTexImageTarget(2, rawTarget, WebGLTexImageFunc::TexImage))
if (!ValidateTexImageTarget(rawTarget, WebGLTexImageFunc::TexImage, WebGLTexDimensions::Tex2D))
return;
return TexImage2D_base(rawTarget, level, internalformat, width, height, 0, border, format, type,
@ -3839,12 +3859,12 @@ WebGLContext::TexImage2D(GLenum rawTarget, GLint level,
void* pixelData = arr.Data();
const uint32_t pixelDataLength = arr.Length();
if (!ValidateTexImageTarget(2, rawTarget, WebGLTexImageFunc::TexImage))
if (!ValidateTexImageTarget(rawTarget, WebGLTexImageFunc::TexImage, WebGLTexDimensions::Tex2D))
return;
return TexImage2D_base(rawTarget, level, internalformat, pixels->Width(),
pixels->Height(), 4*pixels->Width(), 0,
format, type, pixelData, pixelDataLength, -1,
format, type, pixelData, pixelDataLength, js::Scalar::TypeMax,
WebGLTexelFormat::RGBA8, false);
}
@ -3855,10 +3875,11 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
GLenum format, GLenum type,
void* data, uint32_t byteLength,
int jsArrayType,
js::Scalar::Type jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
if (type == LOCAL_GL_HALF_FLOAT_OES) {
type = LOCAL_GL_HALF_FLOAT;
@ -3876,16 +3897,16 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
if (!ValidateTexImage(2, texImageTarget, level,
if (!ValidateTexImage(texImageTarget, level,
existingEffectiveInternalFormat.get(),
xoffset, yoffset, 0,
width, height, 0,
0, format, type, func))
0, format, type, func, dims))
{
return;
}
if (!ValidateTexInputData(type, jsArrayType, func))
if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
if (type != TypeFromInternalFormat(existingEffectiveInternalFormat)) {
@ -3905,7 +3926,7 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
return; // ES 2.0 says it has no effect, we better return right now
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
GetImageSize(height, width, 1, srcTexelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
@ -3945,7 +3966,12 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
if (!noConversion) {
size_t convertedDataSize = height * dstStride;
convertedData = new uint8_t[convertedDataSize];
convertedData = (uint8_t*)moz_malloc(convertedDataSize);
if (!convertedData) {
ErrorOutOfMemory("texImage2D: Ran out of memory when allocating"
" a buffer for doing format conversion.");
return;
}
if (!ConvertImage(width, height, srcStride, dstStride,
static_cast<const uint8_t*>(data), convertedData,
actualSrcFormat, srcPremultiplied,
@ -3985,7 +4011,7 @@ WebGLContext::TexSubImage2D(GLenum rawTarget, GLint level,
const ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
if (!ValidateTexImageTarget(2, rawTarget, WebGLTexImageFunc::TexSubImage))
if (!ValidateTexImageTarget(rawTarget, WebGLTexImageFunc::TexSubImage, WebGLTexDimensions::Tex2D))
return;
return TexSubImage2D_base(rawTarget, level, xoffset, yoffset,
@ -4016,7 +4042,7 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
pixels->Width(), pixels->Height(),
4*pixels->Width(), format, type,
arr.Data(), arr.Length(),
-1,
js::Scalar::TypeMax,
WebGLTexelFormat::RGBA8, false);
}

View File

@ -70,6 +70,29 @@ StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
return JS::StringValue(str);
}
bool
WebGLContext::GetStencilBits(GLint* out_stencilBits)
{
*out_stencilBits = 0;
if (mBoundFramebuffer) {
if (mBoundFramebuffer->HasDepthStencilConflict()) {
// Error, we don't know which stencil buffer's bits to use
ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
return false;
}
if (mBoundFramebuffer->StencilAttachment().IsDefined() ||
mBoundFramebuffer->DepthStencilAttachment().IsDefined())
{
*out_stencilBits = 8;
}
} else if (mOptions.stencil) {
*out_stencilBits = 8;
}
return true;
}
JS::Value
WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
{
@ -241,9 +264,26 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
return JS::NumberValue(uint32_t(i));
}
// int
case LOCAL_GL_STENCIL_CLEAR_VALUE:
case LOCAL_GL_STENCIL_REF:
case LOCAL_GL_STENCIL_BACK_REF:
case LOCAL_GL_STENCIL_BACK_REF: {
GLint stencilBits = 0;
if (!GetStencilBits(&stencilBits))
return JS::NullValue();
// Assuming stencils have 8 bits
const GLint stencilMask = (1 << stencilBits) - 1;
GLint refValue = 0;
gl->fGetIntegerv(pname, &refValue);
return JS::Int32Value(refValue & stencilMask);
}
case LOCAL_GL_STENCIL_BITS: {
GLint stencilBits = 0;
GetStencilBits(&stencilBits);
return JS::Int32Value(stencilBits);
}
case LOCAL_GL_STENCIL_CLEAR_VALUE:
case LOCAL_GL_UNPACK_ALIGNMENT:
case LOCAL_GL_PACK_ALIGNMENT:
case LOCAL_GL_SUBPIXEL_BITS:
@ -257,8 +297,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
case LOCAL_GL_GREEN_BITS:
case LOCAL_GL_BLUE_BITS:
case LOCAL_GL_ALPHA_BITS:
case LOCAL_GL_DEPTH_BITS:
case LOCAL_GL_STENCIL_BITS: {
case LOCAL_GL_DEPTH_BITS: {
GLint i = 0;
gl->fGetIntegerv(pname, &i);
return JS::Int32Value(i);

View File

@ -60,7 +60,8 @@ TexImageTargetToTexTarget(TexImageTarget texImageTarget)
{
switch (texImageTarget.get()) {
case LOCAL_GL_TEXTURE_2D:
return LOCAL_GL_TEXTURE_2D;
case LOCAL_GL_TEXTURE_3D:
return texImageTarget.get();
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
@ -69,7 +70,7 @@ TexImageTargetToTexTarget(TexImageTarget texImageTarget)
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
return LOCAL_GL_TEXTURE_CUBE_MAP;
default:
MOZ_ASSERT(false, "Bad texture conversion");
MOZ_ASSERT(false, "Bad texture target");
// Should be caught by the constructor for TexTarget
return LOCAL_GL_NONE;
}
@ -448,6 +449,7 @@ WebGLContext::ShouldGenerateWarnings() const
CheckedUint32
WebGLContext::GetImageSize(GLsizei height,
GLsizei width,
GLsizei depth,
uint32_t pixelSize,
uint32_t packOrUnpackAlignment)
{
@ -457,10 +459,12 @@ WebGLContext::GetImageSize(GLsizei height,
CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
// if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
CheckedUint32 checked_neededByteLength
CheckedUint32 checked_2dImageSize
= height <= 0 ? 0 : (height-1) * checked_alignedRowSize + checked_plainRowSize;
return checked_neededByteLength;
// FIXME - we should honor UNPACK_IMAGE_HEIGHT
CheckedUint32 checked_imageSize = checked_2dImageSize * depth;
return checked_imageSize;
}
void
@ -705,6 +709,22 @@ AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow)
MOZ_ASSERT(false, "Bad cached value.");
}
}
void
AssertMaskedUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint mask, GLuint shadow)
{
GLuint val = 0;
gl->GetUIntegerv(pname, &val);
const GLuint valMasked = val & mask;
const GLuint shadowMasked = shadow & mask;
if (valMasked != shadowMasked) {
printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
pname, shadowMasked, shadowMasked, valMasked, valMasked);
MOZ_ASSERT(false, "Bad cached value.");
}
}
#else
void
AssertUintParamCorrect(gl::GLContext*, GLenum, GLuint)
@ -802,8 +822,12 @@ WebGLContext::AssertCachedState()
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_CLEAR_VALUE, mStencilClearValue);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, mStencilRefFront);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, mStencilRefBack);
GLint stencilBits = 0;
gl->fGetIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
const GLuint stencilRefMask = (1 << stencilBits) - 1;
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, stencilRefMask, mStencilRefFront);
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, stencilRefMask, mStencilRefBack);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront);
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack);
@ -826,4 +850,32 @@ WebGLContext::AssertCachedState()
#endif
}
const char*
InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims)
{
switch (dims) {
case WebGLTexDimensions::Tex2D:
switch (func) {
case WebGLTexImageFunc::TexImage: return "texImage2D";
case WebGLTexImageFunc::TexSubImage: return "texSubImage2D";
case WebGLTexImageFunc::CopyTexImage: return "copyTexImage2D";
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage2D";
case WebGLTexImageFunc::CompTexImage: return "compressedTexImage2D";
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage2D";
default:
MOZ_CRASH();
}
case WebGLTexDimensions::Tex3D:
switch (func) {
case WebGLTexImageFunc::TexSubImage: return "texSubImage3D";
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage3D";
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage3D";
default:
MOZ_CRASH();
}
default:
MOZ_CRASH();
}
}
} // namespace mozilla

View File

@ -106,6 +106,13 @@ WebGLContext::WebGLObjectAsJSObject(JSContext *cx, const WebGLObjectType *object
return &v.toObject();
}
/**
* Return the displayable name for the texture function that is the
* source for validation.
*/
const char*
InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims);
} // namespace mozilla
#endif // WEBGLCONTEXTUTILS_H_

View File

@ -61,27 +61,6 @@ BlockSizeFor(GLenum format, GLint* blockWidth, GLint* blockHeight)
}
}
/**
* Return the displayable name for the texture function that is the
* source for validation.
*/
static const char*
InfoFrom(WebGLTexImageFunc func)
{
// TODO: Account for dimensions (WebGL 2)
switch (func) {
case WebGLTexImageFunc::TexImage: return "texImage2D";
case WebGLTexImageFunc::TexSubImage: return "texSubImage2D";
case WebGLTexImageFunc::CopyTexImage: return "copyTexImage2D";
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage2D";
case WebGLTexImageFunc::CompTexImage: return "compressedTexImage2D";
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage2D";
default:
MOZ_ASSERT(false, "Missing case for WebGLTexImageSource");
return "(error)";
}
}
static bool
IsCompressedFunc(WebGLTexImageFunc func)
{
@ -94,13 +73,13 @@ IsCompressedFunc(WebGLTexImageFunc func)
* name for \a glenum.
*/
static void
ErrorInvalidEnumWithName(WebGLContext* ctx, const char* msg, GLenum glenum, WebGLTexImageFunc func)
ErrorInvalidEnumWithName(WebGLContext* ctx, const char* msg, GLenum glenum, WebGLTexImageFunc func, WebGLTexDimensions dims)
{
const char* name = WebGLContext::EnumName(glenum);
if (name)
ctx->ErrorInvalidEnum("%s: %s %s", InfoFrom(func), msg, name);
ctx->ErrorInvalidEnum("%s: %s %s", InfoFrom(func, dims), msg, name);
else
ctx->ErrorInvalidEnum("%s: %s 0x%04X", InfoFrom(func), msg, glenum);
ctx->ErrorInvalidEnum("%s: %s 0x%04X", InfoFrom(func, dims), msg, glenum);
}
/**
@ -386,7 +365,7 @@ WebGLContext::ValidateFramebufferAttachment(GLenum attachment, const char* funcN
* taking into account enabled WebGL extensions.
*/
bool
WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebGLTexDimensions dims)
{
/* Core WebGL texture formats */
if (format == LOCAL_GL_ALPHA ||
@ -409,7 +388,7 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
bool valid = IsWebGL2();
if (!valid) {
ErrorInvalidEnum("%s: invalid format %s: requires WebGL version 2.0 or newer",
InfoFrom(func), EnumName(format));
InfoFrom(func, dims), EnumName(format));
}
return valid;
}
@ -420,7 +399,7 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
{
if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture)) {
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_depth_texture enabled",
InfoFrom(func), EnumName(format));
InfoFrom(func, dims), EnumName(format));
return false;
}
@ -431,7 +410,7 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
func == WebGLTexImageFunc::CopyTexImage ||
func == WebGLTexImageFunc::CopyTexSubImage)
{
ErrorInvalidOperation("%s: format %s is not supported", InfoFrom(func), EnumName(format));
ErrorInvalidOperation("%s: format %s is not supported", InfoFrom(func, dims), EnumName(format));
return false;
}
@ -443,7 +422,7 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
/* Only core formats are valid for CopyTex(Sub)?Image */
// TODO: Revisit this once color_buffer_(half_)?float lands
if (IsCopyFunc(func)) {
ErrorInvalidEnumWithName(this, "invalid format", format, func);
ErrorInvalidEnumWithName(this, "invalid format", format, func, dims);
return false;
}
@ -454,11 +433,11 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
bool validFormat = IsExtensionEnabled(WebGLExtensionID::EXT_sRGB);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need EXT_sRGB enabled",
InfoFrom(func), WebGLContext::EnumName(format));
InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
ErrorInvalidEnumWithName(this, "invalid format", format, func);
ErrorInvalidEnumWithName(this, "invalid format", format, func, dims);
return false;
}
@ -467,19 +446,27 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
* Check if the given texture target is valid for TexImage.
*/
bool
WebGLContext::ValidateTexImageTarget(GLuint dims,
GLenum target,
WebGLTexImageFunc func)
WebGLContext::ValidateTexImageTarget(GLenum target,
WebGLTexImageFunc func, WebGLTexDimensions dims)
{
switch (dims) {
case 2:
case WebGLTexDimensions::Tex2D:
if (target == LOCAL_GL_TEXTURE_2D ||
IsTexImageCubemapTarget(target))
{
return true;
}
ErrorInvalidEnumWithName(this, "invalid target", target, func);
ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
return false;
case WebGLTexDimensions::Tex3D:
if (target == LOCAL_GL_TEXTURE_3D)
{
return true;
}
ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
return false;
default:
@ -495,7 +482,8 @@ WebGLContext::ValidateTexImageTarget(GLuint dims,
*/
bool
WebGLContext::ValidateTexImageType(GLenum type,
WebGLTexImageFunc func)
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
/* Core WebGL texture types */
if (type == LOCAL_GL_UNSIGNED_BYTE ||
@ -518,7 +506,7 @@ WebGLContext::ValidateTexImageType(GLenum type,
bool validType = IsWebGL2();
if (!validType) {
ErrorInvalidEnum("%s: invalid type %s: requires WebGL version 2.0 or newer",
InfoFrom(func), WebGLContext::EnumName(type));
InfoFrom(func, dims), WebGLContext::EnumName(type));
}
return validType;
}
@ -528,7 +516,7 @@ WebGLContext::ValidateTexImageType(GLenum type,
bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_float);
if (!validType)
ErrorInvalidEnum("%s: invalid type %s: need OES_texture_float enabled",
InfoFrom(func), WebGLContext::EnumName(type));
InfoFrom(func, dims), WebGLContext::EnumName(type));
return validType;
}
@ -537,7 +525,7 @@ WebGLContext::ValidateTexImageType(GLenum type,
bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float);
if (!validType)
ErrorInvalidEnum("%s: invalid type %s: need OES_texture_half_float enabled",
InfoFrom(func), WebGLContext::EnumName(type));
InfoFrom(func, dims), WebGLContext::EnumName(type));
return validType;
}
@ -549,11 +537,11 @@ WebGLContext::ValidateTexImageType(GLenum type,
bool validType = IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture);
if (!validType)
ErrorInvalidEnum("%s: invalid type %s: need WEBGL_depth_texture enabled",
InfoFrom(func), WebGLContext::EnumName(type));
InfoFrom(func, dims), WebGLContext::EnumName(type));
return validType;
}
ErrorInvalidEnumWithName(this, "invalid type", type, func);
ErrorInvalidEnumWithName(this, "invalid type", type, func, dims);
return false;
}
@ -568,19 +556,20 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLsizei levelWidth, GLsizei levelHeight,
WebGLTexImageFunc func)
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
// Negative parameters must already have been handled above
MOZ_ASSERT(xoffset >= 0 && yoffset >= 0 &&
width >= 0 && height >= 0);
if (xoffset + width > (GLint) levelWidth) {
ErrorInvalidValue("%s: xoffset + width must be <= levelWidth", InfoFrom(func));
ErrorInvalidValue("%s: xoffset + width must be <= levelWidth", InfoFrom(func, dims));
return false;
}
if (yoffset + height > (GLint) levelHeight) {
ErrorInvalidValue("%s: yoffset + height must be <= levelHeight", InfoFrom(func));
ErrorInvalidValue("%s: yoffset + height must be <= levelHeight", InfoFrom(func, dims));
return false;
}
@ -596,13 +585,13 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
/* offsets must be multiple of block size */
if (xoffset % blockWidth != 0) {
ErrorInvalidOperation("%s: xoffset must be multiple of %d",
InfoFrom(func), blockWidth);
InfoFrom(func, dims), blockWidth);
return false;
}
if (yoffset % blockHeight != 0) {
ErrorInvalidOperation("%s: yoffset must be multiple of %d",
InfoFrom(func), blockHeight);
InfoFrom(func, dims), blockHeight);
return false;
}
@ -618,13 +607,13 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
if (level == 0) {
if (width % blockWidth != 0) {
ErrorInvalidOperation("%s: width of level 0 must be multple of %d",
InfoFrom(func), blockWidth);
InfoFrom(func, dims), blockWidth);
return false;
}
if (height % blockHeight != 0) {
ErrorInvalidOperation("%s: height of level 0 must be multipel of %d",
InfoFrom(func), blockHeight);
InfoFrom(func, dims), blockHeight);
return false;
}
}
@ -632,14 +621,14 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
if (width % blockWidth != 0 && width > 2) {
ErrorInvalidOperation("%s: width of level %d must be multiple"
" of %d or 0, 1, 2",
InfoFrom(func), level, blockWidth);
InfoFrom(func, dims), level, blockWidth);
return false;
}
if (height % blockHeight != 0 && height > 2) {
ErrorInvalidOperation("%s: height of level %d must be multiple"
" of %d or 0, 1, 2",
InfoFrom(func), level, blockHeight);
InfoFrom(func, dims), level, blockHeight);
return false;
}
}
@ -647,13 +636,13 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
if (IsSubFunc(func)) {
if ((xoffset % blockWidth) != 0) {
ErrorInvalidOperation("%s: xoffset must be multiple of %d",
InfoFrom(func), blockWidth);
InfoFrom(func, dims), blockWidth);
return false;
}
if (yoffset % blockHeight != 0) {
ErrorInvalidOperation("%s: yoffset must be multiple of %d",
InfoFrom(func), blockHeight);
InfoFrom(func, dims), blockHeight);
return false;
}
}
@ -668,7 +657,7 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
!is_pot_assuming_nonnegative(height))
{
ErrorInvalidValue("%s: width and height must be powers of two",
InfoFrom(func));
InfoFrom(func, dims));
return false;
}
}
@ -683,7 +672,9 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
bool
WebGLContext::ValidateCompTexImageDataSize(GLint level, GLenum format,
GLsizei width, GLsizei height,
uint32_t byteLength, WebGLTexImageFunc func)
uint32_t byteLength,
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
// negative width and height must already have been handled above
MOZ_ASSERT(width >= 0 && height >= 0);
@ -722,7 +713,7 @@ WebGLContext::ValidateCompTexImageDataSize(GLint level, GLenum format,
}
if (!required_byteLength.isValid() || required_byteLength.value() != byteLength) {
ErrorInvalidValue("%s: data size does not match dimensions", InfoFrom(func));
ErrorInvalidValue("%s: data size does not match dimensions", InfoFrom(func, dims));
return false;
}
@ -738,7 +729,7 @@ WebGLContext::ValidateCompTexImageDataSize(GLint level, GLenum format,
bool
WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
GLint width, GLint height, GLint depth,
WebGLTexImageFunc func)
WebGLTexImageFunc func, WebGLTexDimensions dims)
{
MOZ_ASSERT(level >= 0, "level should already be validated");
@ -766,7 +757,7 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
* INVALID_VALUE is generated if the width and height
* parameters are not equal."
*/
ErrorInvalidValue("%s: for cube map, width must equal height", InfoFrom(func));
ErrorInvalidValue("%s: for cube map, width must equal height", InfoFrom(func, dims));
return false;
}
@ -778,12 +769,12 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
* INVALID_VALUE is generated."
*/
if (width < 0) {
ErrorInvalidValue("%s: width must be >= 0", InfoFrom(func));
ErrorInvalidValue("%s: width must be >= 0", InfoFrom(func, dims));
return false;
}
if (height < 0) {
ErrorInvalidValue("%s: height must be >= 0", InfoFrom(func));
ErrorInvalidValue("%s: height must be >= 0", InfoFrom(func, dims));
return false;
}
@ -799,13 +790,13 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
*/
if (width > (int) maxTexImageSize) {
ErrorInvalidValue("%s: the maximum width for level %d is %u",
InfoFrom(func), level, maxTexImageSize);
InfoFrom(func, dims), level, maxTexImageSize);
return false;
}
if (height > (int) maxTexImageSize) {
ErrorInvalidValue("%s: tex maximum height for level %d is %u",
InfoFrom(func), level, maxTexImageSize);
InfoFrom(func, dims), level, maxTexImageSize);
return false;
}
@ -817,13 +808,13 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
if (level > 0) {
if (!is_pot_assuming_nonnegative(width)) {
ErrorInvalidValue("%s: level >= 0, width of %d must be a power of two.",
InfoFrom(func), width);
InfoFrom(func, dims), width);
return false;
}
if (!is_pot_assuming_nonnegative(height)) {
ErrorInvalidValue("%s: level >= 0, height of %d must be a power of two.",
InfoFrom(func), height);
InfoFrom(func, dims), height);
return false;
}
}
@ -832,13 +823,13 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
// TODO: WebGL 2
if (texImageTarget == LOCAL_GL_TEXTURE_3D) {
if (depth < 0) {
ErrorInvalidValue("%s: depth must be >= 0", InfoFrom(func));
ErrorInvalidValue("%s: depth must be >= 0", InfoFrom(func, dims));
return false;
}
if (!is_pot_assuming_nonnegative(depth)) {
if (depth > 0 && !is_pot_assuming_nonnegative(depth)) {
ErrorInvalidValue("%s: level >= 0, depth of %d must be a power of two.",
InfoFrom(func), depth);
InfoFrom(func, dims), depth);
return false;
}
}
@ -854,7 +845,7 @@ bool
WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoffset*/,
GLsizei width, GLsizei height, GLsizei /*depth*/,
GLsizei baseWidth, GLsizei baseHeight, GLsizei /*baseDepth*/,
WebGLTexImageFunc func)
WebGLTexImageFunc func, WebGLTexDimensions dims)
{
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
* "Taking wt and ht to be the specified width and height of the
@ -868,17 +859,17 @@ WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoff
*/
if (xoffset < 0) {
ErrorInvalidValue("%s: xoffset must be >= 0", InfoFrom(func));
ErrorInvalidValue("%s: xoffset must be >= 0", InfoFrom(func, dims));
return false;
}
if (yoffset < 0) {
ErrorInvalidValue("%s: yoffset must be >= 0", InfoFrom(func));
ErrorInvalidValue("%s: yoffset must be >= 0", InfoFrom(func, dims));
return false;
}
if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, baseWidth, baseHeight)) {
ErrorInvalidValue("%s: subtexture rectangle out-of-bounds", InfoFrom(func));
ErrorInvalidValue("%s: subtexture rectangle out-of-bounds", InfoFrom(func, dims));
return false;
}
@ -891,15 +882,17 @@ WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoff
*/
bool
WebGLContext::ValidateTexImageFormatAndType(GLenum format,
GLenum type, WebGLTexImageFunc func)
GLenum type,
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
if (IsCompressedFunc(func) || IsCopyFunc(func))
{
MOZ_ASSERT(type == LOCAL_GL_NONE && format == LOCAL_GL_NONE);
return true;
}
if (!ValidateTexImageFormat(format, func) ||
!ValidateTexImageType(type, func))
if (!ValidateTexImageFormat(format, func, dims) ||
!ValidateTexImageType(type, func, dims))
{
return false;
}
@ -913,18 +906,19 @@ WebGLContext::ValidateTexImageFormatAndType(GLenum format,
if (!validCombo)
ErrorInvalidOperation("%s: invalid combination of format %s and type %s",
InfoFrom(func), WebGLContext::EnumName(format), WebGLContext::EnumName(type));
InfoFrom(func, dims), WebGLContext::EnumName(format), WebGLContext::EnumName(type));
return validCombo;
}
bool
WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
WebGLTexImageFunc func)
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
if (!IsCompressedTextureFormat(format)) {
ErrorInvalidEnum("%s: invalid compressed texture format: %s",
InfoFrom(func), WebGLContext::EnumName(format));
InfoFrom(func, dims), WebGLContext::EnumName(format));
return false;
}
@ -936,7 +930,7 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_atc);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_atc enabled",
InfoFrom(func), WebGLContext::EnumName(format));
InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
@ -945,7 +939,7 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_etc1);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_etc1 enabled",
InfoFrom(func), WebGLContext::EnumName(format));
InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
@ -958,7 +952,7 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_pvrtc);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_pvrtc enabled",
InfoFrom(func), WebGLContext::EnumName(format));
InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
@ -971,7 +965,7 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_s3tc);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_s3tc enabled",
InfoFrom(func), WebGLContext::EnumName(format));
InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
@ -980,7 +974,8 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
bool
WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format,
WebGLTexImageFunc func)
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
bool valid = format == LOCAL_GL_RGBA ||
format == LOCAL_GL_RGB ||
@ -994,7 +989,7 @@ WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format,
// in CopyTexSubImage, the internalformat is part of existing state,
// so this is an INVALID_OPERATION error.
GenerateWarning("%s: invalid texture internal format: %s",
InfoFrom(func), WebGLContext::EnumName(format));
InfoFrom(func, dims), WebGLContext::EnumName(format));
SynthesizeGLError(func == WebGLTexImageFunc::CopyTexImage
? LOCAL_GL_INVALID_ENUM
: LOCAL_GL_INVALID_OPERATION);
@ -1009,19 +1004,28 @@ WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format,
* It is assumed that type has previously been validated.
*/
bool
WebGLContext::ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFunc func)
WebGLContext::ValidateTexInputData(GLenum type,
js::Scalar::Type jsArrayType,
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
bool validInput = false;
const char invalidTypedArray[] = "%s: invalid typed array type for given texture data type";
// We're using js::Scalar::TypeMax as dummy value when the tex source wasn't a
// typed array.
if (jsArrayType == js::Scalar::TypeMax) {
return true;
}
// First, we check for packed types
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Uint8);
validInput = jsArrayType == js::Scalar::Uint8;
break;
case LOCAL_GL_BYTE:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Int8);
validInput = jsArrayType == js::Scalar::Int8;
break;
case LOCAL_GL_HALF_FLOAT:
@ -1029,11 +1033,11 @@ WebGLContext::ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFu
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Uint16);
validInput = jsArrayType == js::Scalar::Uint16;
break;
case LOCAL_GL_SHORT:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Int16);
validInput = jsArrayType == js::Scalar::Int16;
break;
case LOCAL_GL_UNSIGNED_INT:
@ -1041,15 +1045,15 @@ WebGLContext::ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFu
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Uint32);
validInput = jsArrayType == js::Scalar::Uint32;
break;
case LOCAL_GL_INT:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Int32);
validInput = jsArrayType == js::Scalar::Int32;
break;
case LOCAL_GL_FLOAT:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Float32);
validInput = jsArrayType == js::Scalar::Float32;
break;
default:
@ -1057,7 +1061,7 @@ WebGLContext::ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFu
}
if (!validInput)
ErrorInvalidOperation(invalidTypedArray, InfoFrom(func));
ErrorInvalidOperation(invalidTypedArray, InfoFrom(func, dims));
return validInput;
}
@ -1070,7 +1074,8 @@ WebGLContext::ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFu
*/
bool
WebGLContext::ValidateCopyTexImage(GLenum format,
WebGLTexImageFunc func)
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
MOZ_ASSERT(IsCopyFunc(func));
@ -1079,14 +1084,14 @@ WebGLContext::ValidateCopyTexImage(GLenum format,
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", InfoFrom(func));
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", InfoFrom(func, dims));
return false;
}
GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
ErrorInvalidOperation("%s: Read source attachment doesn't have the"
" correct color/depth/stencil type.", InfoFrom(func));
" correct color/depth/stencil type.", InfoFrom(func, dims));
return false;
}
@ -1101,7 +1106,7 @@ WebGLContext::ValidateCopyTexImage(GLenum format,
const GLComponents fboComps = GLComponents(fboFormat);
if (!formatComps.IsSubsetOf(fboComps)) {
ErrorInvalidOperation("%s: format %s is not a subset of the current framebuffer format, which is %s.",
InfoFrom(func), EnumName(format), EnumName(fboFormat));
InfoFrom(func, dims), EnumName(format), EnumName(fboFormat));
return false;
}
@ -1114,7 +1119,7 @@ WebGLContext::ValidateCopyTexImage(GLenum format,
*/
// TODO: Texture dims is here for future expansion in WebGL 2.0
bool
WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
WebGLContext::ValidateTexImage(TexImageTarget texImageTarget,
GLint level,
GLenum internalFormat,
GLint xoffset, GLint yoffset, GLint zoffset,
@ -1122,9 +1127,10 @@ WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
GLint border,
GLenum format,
GLenum type,
WebGLTexImageFunc func)
WebGLTexImageFunc func,
WebGLTexDimensions dims)
{
const char* info = InfoFrom(func);
const char* info = InfoFrom(func, dims);
/* Check level */
if (level < 0) {
@ -1139,7 +1145,7 @@ WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
}
/* Check incoming image format and type */
if (!ValidateTexImageFormatAndType(format, type, func))
if (!ValidateTexImageFormatAndType(format, type, func, dims))
return false;
if (!TexInternalFormat::IsValueLegal(internalFormat)) {
@ -1150,11 +1156,11 @@ WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
UnsizedInternalFormatFromInternalFormat(internalFormat);
if (IsCompressedFunc(func)) {
if (!ValidateCompTexImageInternalFormat(internalFormat, func)) {
if (!ValidateCompTexImageInternalFormat(internalFormat, func, dims)) {
return false;
}
} else if (IsCopyFunc(func)) {
if (!ValidateCopyTexImageInternalFormat(unsizedInternalFormat.get(), func)) {
if (!ValidateCopyTexImageInternalFormat(unsizedInternalFormat.get(), func, dims)) {
return false;
}
} else if (format != unsizedInternalFormat) {
@ -1189,7 +1195,7 @@ WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
}
/* Check texture image size */
if (!ValidateTexImageSize(texImageTarget, level, width, height, 0, func))
if (!ValidateTexImageSize(texImageTarget, level, width, height, 0, func, dims))
return false;
/* 5.14.8 Texture objects - WebGL Spec.
@ -1216,7 +1222,7 @@ WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset,
width, height, depth,
imageInfo.Width(), imageInfo.Height(), 0,
func))
func, dims))
{
return false;
}
@ -1502,6 +1508,7 @@ WebGLContext::InitAndValidateGL()
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBound3DTextures.Clear();
mBoundArrayBuffer = nullptr;
mBoundTransformFeedbackBuffer = nullptr;
@ -1542,6 +1549,7 @@ WebGLContext::InitAndValidateGL()
mBound2DTextures.SetLength(mGLMaxTextureUnits);
mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
mBound3DTextures.SetLength(mGLMaxTextureUnits);
if (MinCapabilityMode()) {
mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;

View File

@ -48,25 +48,32 @@ WebGLTexture::Delete() {
LinkedListElement<WebGLTexture>::removeFrom(mContext->mTextures);
}
int64_t
size_t
WebGLTexture::ImageInfo::MemoryUsage() const {
if (mImageDataStatus == WebGLImageDataStatus::NoImageData)
return 0;
int64_t bitsPerTexel = GetBitsPerTexel(mEffectiveInternalFormat);
return int64_t(mWidth) * int64_t(mHeight) * bitsPerTexel/8;
size_t bitsPerTexel = GetBitsPerTexel(mEffectiveInternalFormat);
return size_t(mWidth) * size_t(mHeight) * size_t(mDepth) * bitsPerTexel / 8;
}
int64_t
size_t
WebGLTexture::MemoryUsage() const {
if (IsDeleted())
return 0;
int64_t result = 0;
size_t result = 0;
for(size_t face = 0; face < mFacesCount; face++) {
if (mHaveGeneratedMipmap) {
// Each mipmap level is 1/4 the size of the previous level
size_t level0MemoryUsage = ImageInfoAtFace(face, 0).MemoryUsage();
// Each mipmap level is 1/(2^d) the size of the previous level,
// where d is 2 or 3 depending on whether the images are 2D or 3D
// 1 + x + x^2 + ... = 1/(1-x)
// for x = 1/4, we get 1/(1-1/4) = 4/3
result += ImageInfoAtFace(face, 0).MemoryUsage() * 4 / 3;
// for x = 1/(2^2), we get 1/(1-1/4) = 4/3
// for x = 1/(2^3), we get 1/(1-1/8) = 8/7
size_t allLevelsMemoryUsage =
mTarget == LOCAL_GL_TEXTURE_3D
? level0MemoryUsage * 8 / 7
: level0MemoryUsage * 4 / 3;
result += allLevelsMemoryUsage;
} else {
for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++)
result += ImageInfoAtFace(face, level).MemoryUsage();
@ -76,7 +83,8 @@ WebGLTexture::MemoryUsage() const {
}
bool
WebGLTexture::DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const {
WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const
{
if (mHaveGeneratedMipmap)
return true;
@ -89,13 +97,18 @@ WebGLTexture::DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget
const ImageInfo& actual = ImageInfoAt(texImageTarget, level);
if (actual != expected)
return false;
expected.mWidth = std::max(1, expected.mWidth >> 1);
expected.mHeight = std::max(1, expected.mHeight >> 1);
expected.mWidth = std::max(1, expected.mWidth / 2);
expected.mHeight = std::max(1, expected.mHeight / 2);
expected.mDepth = std::max(1, expected.mDepth / 2);
// if the current level has size 1x1, we can stop here: the spec doesn't seem to forbid the existence
// of extra useless levels.
if (actual.mWidth == 1 && actual.mHeight == 1)
if (actual.mWidth == 1 &&
actual.mHeight == 1 &&
actual.mDepth == 1)
{
return true;
}
}
// if we're here, we've exhausted all levels without finding a 1x1 image
@ -123,7 +136,7 @@ WebGLTexture::Bind(TexTarget aTexTarget) {
mContext->gl->fBindTexture(aTexTarget.get(), name);
if (firstTimeThisTextureIsBound) {
mFacesCount = (aTexTarget == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
mFacesCount = (aTexTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? 6 : 1;
EnsureMaxLevelWithCustomImagesAtLeast(0);
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
@ -137,16 +150,15 @@ WebGLTexture::Bind(TexTarget aTexTarget) {
void
WebGLTexture::SetImageInfo(TexImageTarget aTexImageTarget, GLint aLevel,
GLsizei aWidth, GLsizei aHeight,
GLsizei aWidth, GLsizei aHeight, GLsizei aDepth,
TexInternalFormat aEffectiveInternalFormat, WebGLImageDataStatus aStatus)
{
MOZ_ASSERT(aDepth == 1 || aTexImageTarget == LOCAL_GL_TEXTURE_3D);
MOZ_ASSERT(TexImageTargetToTexTarget(aTexImageTarget) == mTarget);
if (TexImageTargetToTexTarget(aTexImageTarget) != mTarget)
return;
EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aEffectiveInternalFormat, aStatus);
ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aDepth, aEffectiveInternalFormat, aStatus);
if (aLevel > 0)
SetCustomMipmap();
@ -176,7 +188,7 @@ WebGLTexture::SetCustomMipmap() {
ImageInfo imageInfo = ImageInfoAtFace(0, 0);
NS_ASSERTION(imageInfo.IsPowerOfTwo(), "this texture is NPOT, so how could GenerateMipmap() ever accept it?");
GLsizei size = std::max(imageInfo.mWidth, imageInfo.mHeight);
GLsizei size = std::max(std::max(imageInfo.mWidth, imageInfo.mHeight), imageInfo.mDepth);
// so, the size is a power of two, let's find its log in base 2.
size_t maxLevel = 0;
@ -187,8 +199,9 @@ WebGLTexture::SetCustomMipmap() {
for (size_t level = 1; level <= maxLevel; ++level) {
// again, since the sizes are powers of two, no need for any max(1,x) computation
imageInfo.mWidth >>= 1;
imageInfo.mHeight >>= 1;
imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1);
imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1);
imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1);
for(size_t face = 0; face < mFacesCount; ++face)
ImageInfoAtFace(face, level) = imageInfo;
}
@ -206,20 +219,21 @@ WebGLTexture::AreAllLevel0ImageInfosEqual() const {
}
bool
WebGLTexture::IsMipmapTexture2DComplete() const {
if (mTarget != LOCAL_GL_TEXTURE_2D)
return false;
if (!ImageInfoAt(LOCAL_GL_TEXTURE_2D, 0).IsPositive())
WebGLTexture::IsMipmapComplete() const {
MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_2D ||
mTarget == LOCAL_GL_TEXTURE_3D);
if (!ImageInfoAtFace(0, 0).IsPositive())
return false;
if (mHaveGeneratedMipmap)
return true;
return DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(LOCAL_GL_TEXTURE_2D);
return DoesMipmapHaveAllLevelsConsistentlyDefined(LOCAL_GL_TEXTURE_2D);
}
bool
WebGLTexture::IsCubeComplete() const {
if (mTarget != LOCAL_GL_TEXTURE_CUBE_MAP)
return false;
MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_CUBE_MAP);
const ImageInfo &first = ImageInfoAt(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
if (!first.IsPositive() || !first.IsSquare())
return false;
@ -232,7 +246,7 @@ WebGLTexture::IsMipmapCubeComplete() const {
return false;
for (int i = 0; i < 6; i++) {
const TexImageTarget face = TexImageTargetForTargetAndFace(LOCAL_GL_TEXTURE_CUBE_MAP, i);
if (!DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(face))
if (!DoesMipmapHaveAllLevelsConsistentlyDefined(face))
return false;
}
return true;
@ -260,18 +274,20 @@ WebGLTexture::ResolvedFakeBlackStatus() {
= "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, "
"because it";
if (mTarget == LOCAL_GL_TEXTURE_2D)
if (mTarget == LOCAL_GL_TEXTURE_2D ||
mTarget == LOCAL_GL_TEXTURE_3D)
{
int dim = mTarget == LOCAL_GL_TEXTURE_2D ? 2 : 3;
if (DoesMinFilterRequireMipmap())
{
if (!IsMipmapTexture2DComplete()) {
if (!IsMipmapComplete()) {
mContext->GenerateWarning
("%s is a 2D texture, with a minification filter requiring a mipmap, "
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
("%s is a %dD texture, with a minification filter requiring a mipmap, "
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black, dim);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
} else if (!ImageInfoBase().IsPowerOfTwo()) {
mContext->GenerateWarning
("%s is a 2D texture, with a minification filter requiring a mipmap, "
("%s is a %dD texture, with a minification filter requiring a mipmap, "
"and either its width or height is not a power of two.", msg_rendering_as_black);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
}
@ -280,14 +296,14 @@ WebGLTexture::ResolvedFakeBlackStatus() {
{
if (!ImageInfoBase().IsPositive()) {
mContext->GenerateWarning
("%s is a 2D texture and its width or height is equal to zero.",
msg_rendering_as_black);
("%s is a %dD texture and its width or height is equal to zero.",
msg_rendering_as_black, dim);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoBase().IsPowerOfTwo()) {
mContext->GenerateWarning
("%s is a 2D texture, with a minification filter not requiring a mipmap, "
("%s is a %dD texture, with a minification filter not requiring a mipmap, "
"with its width or height not a power of two, and with a wrap mode "
"different from CLAMP_TO_EDGE.", msg_rendering_as_black);
"different from CLAMP_TO_EDGE.", msg_rendering_as_black, dim);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
}
}
@ -455,8 +471,7 @@ ClearWithTempFB(WebGLContext* context, GLuint tex,
TexInternalFormat baseInternalFormat,
GLsizei width, GLsizei height)
{
if (texImageTarget != LOCAL_GL_TEXTURE_2D)
return false;
MOZ_ASSERT(texImageTarget == LOCAL_GL_TEXTURE_2D);
gl::GLContext* gl = context->GL();
MOZ_ASSERT(gl->IsCurrent());
@ -536,13 +551,15 @@ WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint le
// Try to clear with glCLear.
bool cleared = ClearWithTempFB(mContext, GLName(),
imageTarget, level,
imageInfo.mEffectiveInternalFormat,
imageInfo.mHeight, imageInfo.mWidth);
if (cleared) {
SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
return;
if (imageTarget == LOCAL_GL_TEXTURE_2D) {
bool cleared = ClearWithTempFB(mContext, GLName(),
imageTarget, level,
imageInfo.mEffectiveInternalFormat,
imageInfo.mHeight, imageInfo.mWidth);
if (cleared) {
SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
return;
}
}
// That didn't work. Try uploading zeros then.
@ -556,6 +573,7 @@ WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint le
= WebGLContext::GetImageSize(
imageInfo.mHeight,
imageInfo.mWidth,
imageInfo.mDepth,
bytespertexel,
mContext->mPixelStoreUnpackAlignment);
MOZ_ASSERT(checked_byteLength.isValid()); // should have been checked earlier
@ -570,16 +588,24 @@ WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint le
&driverInternalFormat, &driverFormat, &driverType);
mContext->GetAndFlushUnderlyingGLErrors();
if (mImmutable) {
gl->fTexSubImage2D(imageTarget.get(), level, 0, 0,
imageInfo.mWidth, imageInfo.mHeight,
driverFormat, driverType,
zeros);
} else {
gl->fTexImage2D(imageTarget.get(), level, driverInternalFormat,
imageInfo.mWidth, imageInfo.mHeight,
0, driverFormat, driverType,
if (imageTarget == LOCAL_GL_TEXTURE_3D) {
MOZ_ASSERT(mImmutable, "Shouldn't be possible to have non-immutable-format 3D textures in WebGL");
gl->fTexSubImage3D(imageTarget.get(), level, 0, 0, 0,
imageInfo.mWidth, imageInfo.mHeight, imageInfo.mDepth,
driverFormat, driverType,
zeros);
} else {
if (mImmutable) {
gl->fTexSubImage2D(imageTarget.get(), level, 0, 0,
imageInfo.mWidth, imageInfo.mHeight,
driverFormat, driverType,
zeros);
} else {
gl->fTexImage2D(imageTarget.get(), level, driverInternalFormat,
imageInfo.mWidth, imageInfo.mHeight,
0, driverFormat, driverType,
zeros);
}
}
GLenum error = mContext->GetAndFlushUnderlyingGLErrors();
if (error) {

View File

@ -15,6 +15,7 @@
#include "mozilla/CheckedInt.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Assertions.h"
#include <algorithm>
namespace mozilla {
@ -68,15 +69,18 @@ public:
public:
ImageInfo()
: mEffectiveInternalFormat(LOCAL_GL_NONE)
, mDepth(0)
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
{}
ImageInfo(GLsizei width,
GLsizei height,
GLsizei depth,
TexInternalFormat effectiveInternalFormat,
WebGLImageDataStatus status)
: WebGLRectangleObject(width, height)
, mEffectiveInternalFormat(effectiveInternalFormat)
, mDepth(depth)
, mImageDataStatus(status)
{
// shouldn't use this constructor to construct a null ImageInfo
@ -87,6 +91,7 @@ public:
return mImageDataStatus == a.mImageDataStatus &&
mWidth == a.mWidth &&
mHeight == a.mHeight &&
mDepth == a.mDepth &&
mEffectiveInternalFormat == a.mEffectiveInternalFormat;
}
bool operator!=(const ImageInfo& a) const {
@ -96,7 +101,7 @@ public:
return mWidth == mHeight;
}
bool IsPositive() const {
return mWidth > 0 && mHeight > 0;
return mWidth > 0 && mHeight > 0 && mDepth > 0;
}
bool IsPowerOfTwo() const {
return is_pot_assuming_nonnegative(mWidth) &&
@ -105,7 +110,7 @@ public:
bool HasUninitializedImageData() const {
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
}
int64_t MemoryUsage() const;
size_t MemoryUsage() const;
TexInternalFormat EffectiveInternalFormat() const { return mEffectiveInternalFormat; }
@ -117,6 +122,14 @@ public:
*/
TexInternalFormat mEffectiveInternalFormat;
/*
* Used only for 3D textures.
* Note that mWidth and mHeight are inherited from WebGLRectangleObject.
* It's a pity to store a useless mDepth on non-3D texture images, but
* the size of GLsizei is negligible compared to the typical size of a texture image.
*/
GLsizei mDepth;
WebGLImageDataStatus mImageDataStatus;
friend class WebGLTexture;
@ -124,14 +137,16 @@ public:
private:
static size_t FaceForTarget(TexImageTarget texImageTarget) {
if (texImageTarget == LOCAL_GL_TEXTURE_2D)
if (texImageTarget == LOCAL_GL_TEXTURE_2D ||
texImageTarget == LOCAL_GL_TEXTURE_3D)
{
return 0;
}
return texImageTarget.get() - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
}
ImageInfo& ImageInfoAtFace(size_t face, GLint level) {
MOZ_ASSERT(face < mFacesCount, "wrong face index, must be 0 for TEXTURE_2D and at most 5 for cube maps");
MOZ_ASSERT(face < mFacesCount, "wrong face index, must be 0 for TEXTURE_2D or TEXTURE_3D, and at most 5 for cube maps");
// no need to check level as a wrong value would be caught by ElementAt().
return mImageInfos.ElementAt(level * mFacesCount + face);
@ -169,7 +184,7 @@ public:
return ImageInfoAtFace(0, 0);
}
int64_t MemoryUsage() const;
size_t MemoryUsage() const;
void SetImageDataStatus(TexImageTarget imageTarget, GLint level, WebGLImageDataStatus newStatus) {
MOZ_ASSERT(HasImageInfoAt(imageTarget, level));
@ -214,14 +229,14 @@ protected:
return mWrapS == LOCAL_GL_CLAMP_TO_EDGE && mWrapT == LOCAL_GL_CLAMP_TO_EDGE;
}
bool DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const;
bool DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const;
public:
void Bind(TexTarget aTexTarget);
void SetImageInfo(TexImageTarget aTarget, GLint aLevel,
GLsizei aWidth, GLsizei aHeight,
GLsizei aWidth, GLsizei aHeight, GLsizei aDepth,
TexInternalFormat aFormat, WebGLImageDataStatus aStatus);
void SetMinFilter(TexMinFilter aMinFilter) {
@ -256,7 +271,7 @@ public:
bool AreAllLevel0ImageInfosEqual() const;
bool IsMipmapTexture2DComplete() const;
bool IsMipmapComplete() const;
bool IsCubeComplete() const;
@ -277,9 +292,17 @@ public:
inline TexImageTarget
TexImageTargetForTargetAndFace(TexTarget target, size_t face)
{
return target == LOCAL_GL_TEXTURE_2D
? LOCAL_GL_TEXTURE_2D
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
switch (target.get()) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_3D:
MOZ_ASSERT(face == 0);
return target.get();
case LOCAL_GL_TEXTURE_CUBE_MAP:
MOZ_ASSERT(face < 6);
return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
default:
MOZ_CRASH();
}
}
} // namespace mozilla

View File

@ -46,13 +46,13 @@ namespace mozilla {
* reason why it needs to be faked (incomplete texture vs. uninitialized image data),
* whereas the WebGL context can only know whether _any_ faking is currently needed at all.
*/
MOZ_BEGIN_ENUM_CLASS(WebGLContextFakeBlackStatus, int)
MOZ_BEGIN_ENUM_CLASS(WebGLContextFakeBlackStatus, uint8_t)
Unknown,
NotNeeded,
Needed
MOZ_END_ENUM_CLASS(WebGLContextFakeBlackStatus)
MOZ_BEGIN_ENUM_CLASS(WebGLTextureFakeBlackStatus, int)
MOZ_BEGIN_ENUM_CLASS(WebGLTextureFakeBlackStatus, uint8_t)
Unknown,
NotNeeded,
IncompleteTexture,
@ -65,7 +65,7 @@ MOZ_END_ENUM_CLASS(WebGLTextureFakeBlackStatus)
* OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
* desktop OpenGL does not allow that.
*/
MOZ_BEGIN_ENUM_CLASS(WebGLVertexAttrib0Status, int)
MOZ_BEGIN_ENUM_CLASS(WebGLVertexAttrib0Status, uint8_t)
Default, // default status - no emulation needed
EmulatedUninitializedArray, // need an artificial attrib 0 array, but contents may be left uninitialized
EmulatedInitializedArray // need an artificial attrib 0 array, and contents must be initialized
@ -81,7 +81,7 @@ MOZ_END_ENUM_CLASS(WebGLVertexAttrib0Status)
* initialized. It is the state that renderbuffers are in after a renderbufferStorage call,
* and it is the state that texture images are in after a texImage2D call with null data.
*/
MOZ_BEGIN_ENUM_CLASS(WebGLImageDataStatus, int)
MOZ_BEGIN_ENUM_CLASS(WebGLImageDataStatus, uint8_t)
NoImageData,
UninitializedImageData,
InitializedImageData
@ -95,7 +95,7 @@ MOZ_END_ENUM_CLASS(WebGLImageDataStatus)
* - additional source formats, depending on browser details, used when uploading
* textures from DOM elements. See gfxImageSurface::Format().
*/
MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, int)
MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, uint8_t)
// returned by SurfaceFromElementResultToImageSurface to indicate absence of image data
None,
// common value for formats for which format conversions are not supported
@ -130,7 +130,7 @@ MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, int)
RGBA32F // OES_texture_float
MOZ_END_ENUM_CLASS(WebGLTexelFormat)
MOZ_BEGIN_ENUM_CLASS(WebGLTexImageFunc, int)
MOZ_BEGIN_ENUM_CLASS(WebGLTexImageFunc, uint8_t)
TexImage,
TexSubImage,
CopyTexImage,
@ -139,6 +139,11 @@ MOZ_BEGIN_ENUM_CLASS(WebGLTexImageFunc, int)
CompTexSubImage,
MOZ_END_ENUM_CLASS(WebGLTexImageFunc)
MOZ_BEGIN_ENUM_CLASS(WebGLTexDimensions, uint8_t)
Tex2D,
Tex3D
MOZ_END_ENUM_CLASS(WebGLTexDimensions)
// Please keep extensions in alphabetic order.
MOZ_BEGIN_ENUM_CLASS(WebGLExtensionID, uint8_t)
ANGLE_instanced_arrays,

View File

@ -180,6 +180,7 @@ ScopedBindTexture::Init(GLenum aTarget)
mTarget = aTarget;
mOldTex = 0;
GLenum bindingTarget = (aTarget == LOCAL_GL_TEXTURE_2D) ? LOCAL_GL_TEXTURE_BINDING_2D
: (aTarget == LOCAL_GL_TEXTURE_3D) ? LOCAL_GL_TEXTURE_BINDING_3D
: (aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) ? LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB
: (aTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? LOCAL_GL_TEXTURE_BINDING_CUBE_MAP
: (aTarget == LOCAL_GL_TEXTURE_EXTERNAL) ? LOCAL_GL_TEXTURE_BINDING_EXTERNAL

View File

@ -174,6 +174,7 @@ else
LIBXUL_DIST="$MOZ_BUILD_ROOT/dist"
AC_DEFINE(JS_STANDALONE)
fi
AC_SUBST(JS_STANDALONE)
BUILDING_JS=1
AC_SUBST(autoconfmk)

View File

@ -20,7 +20,11 @@ function logProxy(object) {
return {proxy, log};
}
for (var property of ["string-property", Symbol("symbol-property")]) {
var properties = ["string-property"];
if (typeof Symbol === 'function')
properties.push(Symbol("symbol-property"));
for (var property of properties) {
// Test 1: property is not present on object
var {proxy, log} = logProxy({});
var result = Object.prototype.propertyIsEnumerable.call(proxy, property);

View File

View File

@ -273,7 +273,7 @@ nsTableFrame::RegisterPositionedTablePart(nsIFrame* aFrame)
// the potential to break sites that apply 'position: relative' to those
// parts, expecting nothing to happen. We warn at the console to make tracking
// down the issue easy.
if (nsGkAtoms::tableCellFrame != aFrame->GetType()) {
if (!IS_TABLE_CELL(aFrame->GetType())) {
nsIContent* content = aFrame->GetContent();
nsPresContext* presContext = aFrame->PresContext();
if (content && !presContext->HasWarnedAboutPositionedTableParts()) {

View File

@ -376,9 +376,6 @@ ClearKeyDecryptor::ClearKeyDecryptor(GMPDecryptorCallback* aCallback,
ClearKeyDecryptor::~ClearKeyDecryptor()
{
CK_LOGD("ClearKeyDecryptor dtor; key ID = %08x...", *(uint32_t*)&mKey[0]);
if (mThread) {
mThread->Join();
}
}
uint32_t
@ -390,13 +387,15 @@ ClearKeyDecryptor::AddRef()
uint32_t
ClearKeyDecryptor::Release()
{
if (!--mRefCnt) {
uint32_t newCount = --mRefCnt;
if (!newCount) {
if (mThread) {
mThread->Post(new DestroyTask(this));
mThread->Join();
} else {
delete this;
}
}
return mRefCnt;
return newCount;
}

View File

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <algorithm>
#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
@ -62,7 +63,9 @@ ClearKeyUtils::DecryptAES(const vector<uint8_t>& aKey,
vector<uint8_t> enc(encLen);
oaes_encrypt(aes, &aIV[0], CLEARKEY_KEY_LEN, &enc[0], &encLen);
for (size_t j = 0; j < CLEARKEY_KEY_LEN; j++) {
assert(encLen >= 2 * OAES_BLOCK_SIZE + CLEARKEY_KEY_LEN);
size_t blockLen = std::min(aData.size() - i, CLEARKEY_KEY_LEN);
for (size_t j = 0; j < blockLen; j++) {
aData[i + j] ^= enc[2 * OAES_BLOCK_SIZE + j];
}
IncrementIV(aIV);

View File

@ -9,7 +9,7 @@
#include <string>
#include <vector>
#define CLEARKEY_KEY_LEN 16
#define CLEARKEY_KEY_LEN ((size_t)16)
#if 0
void CK_Log(const char* aFmt, ...);

View File

@ -10,4 +10,6 @@ CLEARKEY_CDM_FILES = \
clearkey.info \
$(NULL)
MOZ_GLUE_LDFLAGS =
include $(topsrcdir)/config/rules.mk

View File

@ -20,4 +20,6 @@ LOCAL_INCLUDES += [
]
USE_STATIC_LIBS = True
USE_LIBS += [ 'mozalloc' ]
DISABLE_STL_WRAPPING = True
DEFINES['MOZ_NO_MOZALLOC'] = True

View File

@ -155,6 +155,16 @@ private:
Vector<Sample> mCurrentSamples;
MPEG4Extractor::TrackExtends mTrackExtends;
// XXX hack -- demuxer expects a track's trun to be seen before saio or
// saiz. Here we store saiz/saio box offsets for parsing *after* the trun
// has been parsed.
struct AuxRange {
off64_t mStart;
off64_t mSize;
};
Vector<AuxRange> mDeferredSaiz;
Vector<AuxRange> mDeferredSaio;
MPEG4Source(const MPEG4Source &);
MPEG4Source &operator=(const MPEG4Source &);
};
@ -2606,16 +2616,20 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
case FOURCC('s', 'a', 'i', 'z'): {
status_t err;
if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
return err;
if (mLastParsedTrackId == mTrackId) {
if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
return err;
}
}
*offset += chunk_size;
break;
}
case FOURCC('s', 'a', 'i', 'o'): {
status_t err;
if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
return err;
if (mLastParsedTrackId == mTrackId) {
if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
return err;
}
}
*offset += chunk_size;
break;
@ -2640,6 +2654,18 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) {
ALOGV("parseSampleAuxiliaryInformationSizes");
// 14496-12 8.7.12
if (mCurrentSamples.isEmpty()) {
// XXX hack -- we haven't seen trun yet; defer parsing this box until
// after trun.
ALOGW("deferring processing of saiz box");
AuxRange range;
range.mStart = offset;
range.mSize = size;
mDeferredSaiz.add(range);
return OK;
}
uint8_t version;
if (mDataSource->readAt(
offset, &version, sizeof(version))
@ -2702,6 +2728,18 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64
status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) {
ALOGV("parseSampleAuxiliaryInformationOffsets");
// 14496-12 8.7.13
if (mCurrentSamples.isEmpty()) {
// XXX hack -- we haven't seen trun yet; defer parsing this box until
// after trun.
ALOGW("deferring processing of saio box");
AuxRange range;
range.mStart = offset;
range.mSize = size;
mDeferredSaio.add(range);
return OK;
}
uint8_t version;
if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
return ERROR_IO;
@ -2714,6 +2752,11 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off
}
offset += 3;
if (flags & 1) {
// Skip uint32s aux_info_type and aux_info_type_parameter
offset += 8;
}
uint32_t entrycount;
if (!mDataSource->getUInt32(offset, &entrycount)) {
return ERROR_IO;
@ -3096,6 +3139,13 @@ status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
for (size_t i = 0; i < mDeferredSaio.size() && i < mDeferredSaiz.size(); i++) {
const auto& saio = mDeferredSaio[i];
const auto& saiz = mDeferredSaiz[i];
parseSampleAuxiliaryInformationSizes(saiz.mStart, saiz.mSize);
parseSampleAuxiliaryInformationOffsets(saio.mStart, saio.mSize);
}
return OK;
}
@ -3538,6 +3588,8 @@ status_t MPEG4Source::fragmentedRead(
}
mCurrentMoofOffset = totalOffset;
mCurrentSamples.clear();
mDeferredSaio.clear();
mDeferredSaiz.clear();
mCurrentSampleIndex = 0;
mTrackFragmentData.mPresent = false;
parseChunk(&totalOffset);
@ -3569,6 +3621,8 @@ status_t MPEG4Source::fragmentedRead(
// move to next fragment
off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
mCurrentSamples.clear();
mDeferredSaio.clear();
mDeferredSaiz.clear();
mCurrentSampleIndex = 0;
mTrackFragmentData.mPresent = false;
uint32_t hdr[2];

View File

@ -203,16 +203,14 @@ int VcmSIPCCBinding::getVideoCodecsGmp()
// H.264 only for now
bool has_gmp;
nsresult rv;
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("encode-video"),
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING("encode-video"),
&tags,
&has_gmp);
if (NS_FAILED(rv) || !has_gmp) {
return 0;
}
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("decode-video"),
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING("decode-video"),
&tags,
&has_gmp);
if (NS_FAILED(rv) || !has_gmp) {

View File

@ -59,13 +59,9 @@
* zone allocator anyways. Jemalloc-specific functions are also left
* unprefixed.
*
* - On Android, both malloc implementation and duplication functions are
* prefixed with "__wrap_". Additionally, C++ allocation functions
* (operator new/delete) are also exported and prefixed with "__wrap_".
* Jemalloc specific functions are left unprefixed.
*
* - On Gonk, all functions are left unprefixed. Additionally, C++ allocation
* functions (operator new/delete) are also exported and unprefixed.
* - On Android and Gonk, all functions are left unprefixed. Additionally,
* C++ allocation functions (operator new/delete) are also exported and
* unprefixed.
*
* - On other systems (mostly Linux), all functions are left unprefixed.
*
@ -79,9 +75,10 @@
*
* All these functions are meant to be called with no prefix from Gecko code.
* In most cases, this is because that's how they are available at runtime.
* However, on Android, "__wrap_" prefixing is left to the build-time linker
* (with -Wl,--wrap), or to the mozmemory.h header for malloc_good_size and
* jemalloc specific functions.
* However, on Android, this relies on faulty.lib (the custom dynamic linker)
* resolving mozglue symbols before libc symbols, which is guaranteed by the
* way faulty.lib works (it respects the DT_NEEDED order, and libc always
* appears after mozglue ; which we double check when building anyways)
*
*
* Within libmozglue (when MOZ_MEMORY_IMPL is defined), all the functions
@ -157,13 +154,6 @@
# endif
# endif
# if defined(MOZ_WIDGET_ANDROID)
# ifndef mozmem_malloc_impl
# define mozmem_malloc_impl(a) __wrap_ ## a
# endif
# define mozmem_dup_impl(a) __wrap_ ## a
# endif
/* All other jemalloc3 functions are prefixed with "je_", except when
* building against an unprefixed system jemalloc library */
# define je_(a) je_ ## a

View File

@ -15,12 +15,8 @@
#include <unistd.h>
#ifdef MOZ_MEMORY
#ifdef MOZ_WIDGET_ANDROID
extern "C" int __wrap_posix_memalign(void** memptr, size_t alignment, size_t size);
#else
extern "C" int posix_memalign(void** memptr, size_t alignment, size_t size);
#endif
#endif
#define MIN_VOLATILE_ALLOC_SIZE 8192
@ -68,11 +64,7 @@ heap_alloc:
}
#ifdef MOZ_MEMORY
#ifdef MOZ_WIDGET_ANDROID
__wrap_posix_memalign(&mBuf, aAlignment, aSize);
#else
posix_memalign(&mBuf, aAlignment, aSize);
#endif
#else
mBuf = memalign(aAlignment, aSize);
#endif

View File

@ -1,2 +0,0 @@
MOZ_GLUE_LDFLAGS = # Don't link against mozglue
WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap

View File

@ -0,0 +1,6 @@
# 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/.
MOZ_GLUE_LDFLAGS = # Don't link against mozglue
WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap

View File

@ -104,7 +104,6 @@
@BINPATH@/blocklist.xml
#ifdef XP_UNIX
@BINPATH@/run-mozilla.sh
@BINPATH@/mozilla-xremote-client
#endif
; [Components]

View File

@ -66,7 +66,6 @@ static std::vector<AtForkFuncs, SpecialAllocator<AtForkFuncs> > atfork;
#ifdef MOZ_WIDGET_GONK
#include "cpuacct.h"
#define WRAP(x) x
#if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
extern "C" NS_EXPORT int
@ -80,12 +79,11 @@ timer_create(clockid_t, struct sigevent*, timer_t*)
#else
#define cpuacct_add(x)
#define WRAP(x) __wrap_##x
#endif
#if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
extern "C" NS_EXPORT int
WRAP(pthread_atfork)(void (*prepare)(void), void (*parent)(void), void (*child)(void))
pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
{
AtForkFuncs funcs;
funcs.prepare = prepare;
@ -100,7 +98,7 @@ WRAP(pthread_atfork)(void (*prepare)(void), void (*parent)(void), void (*child)(
extern "C" NS_EXPORT pid_t __fork(void);
extern "C" NS_EXPORT pid_t
WRAP(fork)(void)
fork(void)
{
pid_t pid;
for (auto it = atfork.rbegin();
@ -127,7 +125,7 @@ WRAP(fork)(void)
#endif
extern "C" NS_EXPORT int
WRAP(raise)(int sig)
raise(int sig)
{
// Bug 741272: Bionic incorrectly uses kill(), which signals the
// process, and thus could signal another thread (and let this one
@ -262,3 +260,20 @@ extern "C" NS_EXPORT size_t __wrap_strspn(const char * a0, const char * a1) { re
extern "C" NS_EXPORT int __wrap_strcoll(const char * a0, const char * a1) { return __real_strcoll(a0, a1); }
extern "C" NS_EXPORT size_t __wrap_strxfrm(char * a0, const char * a1, size_t a2) { return __real_strxfrm(a0, a1, a2); }
#endif
/* Flash plugin uses symbols that are not present in Android >= 4.4 */
#ifndef MOZ_WIDGET_GONK
namespace android {
namespace VectorImpl {
NS_EXPORT void reservedVectorImpl1(void) { }
NS_EXPORT void reservedVectorImpl2(void) { }
NS_EXPORT void reservedVectorImpl3(void) { }
NS_EXPORT void reservedVectorImpl4(void) { }
NS_EXPORT void reservedVectorImpl5(void) { }
NS_EXPORT void reservedVectorImpl6(void) { }
NS_EXPORT void reservedVectorImpl7(void) { }
NS_EXPORT void reservedVectorImpl8(void) { }
}
}
#endif

View File

@ -49,11 +49,6 @@ OS_LDFLAGS += -Wl,-weak_library,$(DEPTH)/memory/replace/dummy/$(DLL_PREFIX)repla
endif
endif
ifeq (android, $(MOZ_WIDGET_TOOLKIT))
# To properly wrap jemalloc's pthread_atfork call.
OS_LDFLAGS += -Wl,--wrap=pthread_atfork
endif
ifdef MOZ_LINKER
ifeq (arm, $(TARGET_CPU))
OS_LDFLAGS += -Wl,-version-script,$(srcdir)/arm-eabi-filter

View File

@ -74,11 +74,6 @@ static int p_flags_to_mprot(Word flags)
((flags & PF_R) ? PROT_READ : 0);
}
void
__void_stub(void)
{
}
} /* anonymous namespace */
/**
@ -330,16 +325,6 @@ CustomElf::GetSymbolPtrInDeps(const char *symbol) const
return FunctionPtr(sigaction);
}
#define MISSING_FLASH_SYMNAME_START "_ZN7android10VectorImpl19reservedVectorImpl"
// Android changed some symbols that Flash depended on in 4.4,
// so stub those out here
if (strncmp(symbol,
MISSING_FLASH_SYMNAME_START,
sizeof(MISSING_FLASH_SYMNAME_START) - 1) == 0) {
return FunctionPtr(__void_stub);
}
void *sym;
unsigned long hash = Hash(symbol);

View File

@ -54,8 +54,12 @@ ArrayBufferInputStream::Available(uint64_t* aCount)
if (mClosed) {
return NS_BASE_STREAM_CLOSED;
}
uint32_t buflen = JS_GetArrayBufferByteLength(mArrayBuffer->get());
*aCount = buflen ? buflen - mPos : 0;
if (mArrayBuffer) {
uint32_t buflen = JS_GetArrayBufferByteLength(mArrayBuffer->get());
*aCount = buflen ? buflen - mPos : 0;
} else {
*aCount = 0;
}
return NS_OK;
}

View File

@ -40,8 +40,8 @@ RtspHandler::GetDefaultPort(int32_t *aDefaultPort)
NS_IMETHODIMP
RtspHandler::GetProtocolFlags(uint32_t *aProtocolFlags)
{
*aProtocolFlags = URI_NORELATIVE | URI_NOAUTH | URI_INHERITS_SECURITY_CONTEXT |
URI_LOADABLE_BY_ANYONE | URI_NON_PERSISTABLE | URI_SYNC_LOAD_IS_OK;
*aProtocolFlags = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE |
URI_NON_PERSISTABLE | URI_SYNC_LOAD_IS_OK;
return NS_OK;
}

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