mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:11:03 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1199885 - Part 2: Add AsyncDragMetrics. r=kats (220a4f445e)
- Bug 1149482 - Localize the 'none' string for APZ in about:support. r=dvander (3e0128f62e)
- Bug 1199885 - Part 3: Add 'apz.drag.enabled' preference for async scrollbars. r=kats (5133061d3f)
- Bug 1199885 - Part 4: Let the hit testing tree know about the scroll thumb. r=kats (26a9a69443)
- Bug 1199885 - Part 5: Make mRootLayerTreeID const to prove that there's no data races. r=kats (88e2eb80f1)
- Bug 1199885 - Part 8: Add FindScrollNode to locate the scrollbar thumb. r=kats (a545ec9569)
- Bug 1199885 - Part 9: Let APZC handle the drag events. r=kats (4cc0f88153)
- Bug 1199885 - Part 9.5: Make the mouse events APZC aware. r=kats (69bd4caf94)
- Bug 1199885 - Part 10: Add APZTeeManager API to start an async scroll. r=kats (e212ee2750)
- Bug 1199885 - Part 12: Add StartScrollbarDrag IPC message. r=kats (705af3b233)
- Bug 1199885 - Part 13: Let nsSliderFrame trigger async scrolling via StartScrollbarDrag. r=kats (d31b5a790d)
- put in gstreamer as of 2015-10-05 Bug 1146482 (7cca45858c)
- pointer style (f8041af438)
- Bug 1197097 - Don't use a context-wide cycle-detection mechanism for detecting cycles during JSON.stringify. This prevents nested (yet separate) JSON.stringify, and it causes that algorithm to be affected by specification-unrelated operations like toSource. r=jonco (09652471c1)
- align to ugly grammaer of 1114782 (c760693693)
- remove space (7158a0c2bf)
- align to FF/TFF (27138a55bb)
- Bug 1205887 - Verify that MOZILLA_VERSION was set correctly, r=glandium (2269e8f31b)
- Bug 1205012 - Allow rust source code in SpiderMonkey; r=mshal (9ebca9ed28)
- Bug 1197281 - Use MOZ_FIND_WINSDK_VERSION for MOZ_WINSDK_MAXVER on mingw. r=glandium (2910b2160e)
- Bug 1207893 - Refactor how build backend execution is summarized. r=gps (56d8fecbc2)
- Bug 1207893 - Allow to create multiple build backends at once. r=gps (d8cba87d2b)
- Bug 1207897 - Add a configure option to build multiple build backends. r=gps (f9c7851d02)
- Bug 1188555 - part 1 - remove write-only configure.in variable NO_LD_ARCHIVE_FLAGS; r=mshal (461958b100)
- Bug 1188555 - part 2 - remove write-only configure.in variables MKSHLIB_{UN,}FORCE_ALL; r=mshal (1813210dda)
- Bug 1207882 - Ensure chrome manifests are created in a directory that exists when processing jar manifests. r=gps (59165a64cb)
- Bug 1204712 - Handle wildcards properly for localized content in jar manifests. r=gps (54dfb632c7)
- Bug 1188551: treat assertion failures as bad mozconfig; r=mshal (e307769de7)
- Bug 1181040 - Set ${var}_IS_SET variables for mk_add_options-defined variables. r=gps (19f169556b)
- Bug 1193015 - Require MOZ_GLX_USE_SURFACE_SHARING to enable WebGL surface sharing on GLX. r=jgilbert (9aa4fa8f41)
- Bug 1211324 (part 1) - Remove BILINEAR and GAUSSIAN filter constants. (3d9290ef02)
- Bug 1211324 (part 2) - Make gfx::FILTER::GOOD convert to GraphicsFilter::FILTER_GOOD. r=mattwoodrow. (16e7607c70)
- Bug 1208365 (part 1) - Remove unused EXTEND_PAD_EDGE. r=Bas. (10920e2bb6)
- Bug 1208365 (part 2) - Remove gfxPattern::Extend(). r=bas. (3703b9748a)
- Bug 1208365 (part 3) - Change gfxPattern::mExtend from a GraphicsExtend to a gfx::ExtendMode. r=bas. (b105d06e91)
- Bug 1208365 (part 4) - Remove gfxPattern::GraphicsExtend. r=bas. (7a16d48995)
- Bug 1211324 (part 3) - Remove GraphicsFilter::FILTER_FAST and replace it with FILTER_BEST. r=mattwoodrow. (b5101e049f)
- Bug 1211324 (part 4) - Replace GraphicsFilter constants with gfx::Filter equivalents. r=mattwoodrow. (c19b6b030e)
- Bug 1190117 - Track mLastProducerID and mLastFrameID explicitly in ImageLayerProperties. r=roc (ed9a5c777f)
- Bug 1211324 (part 5) - Remove GraphicsFilter and gfxGraphicsFilter. r=mattwoodrow. (0bd4ce7160)
- Bug 1194954 - Fix -Wunreachable-code warnings in gfx/layers and gfx/thebes. r=BenWa (1a3d68c490)
- Bug 1180509 - Fix judder of icons in Australis doorhanger menu at the end of its scale-in animation. r=roc (9b4df470fa)
- Bug 1206915 - Make paint dumping to a file e10s-friendly. r=mattwoodrow (87d2e12c2b)
- Bug 1206915 - Handle nested PaintFrame() calls correctly during paint dumping. r=mattwoodrow,BenWa (d30f77fbdd)
- Fix max texture size handling in displayport clamping. (bug 1135907 follow-up, r=kats) (a791894332)
- Fix bogus assertion in nsLayoutUtils::SetDisplayPortMargins. (bug 1156409, r=botond, a=philor) (b635b21c34)
- Bug 1169879 - Use only the critical displayport when computing image visibility. r=tn (9ec91c9527)
- Bug 1169881 - Recompute image visibility when display port margins change. r=tn (35a5bd3a51)
- Bug 1197765 - Compare text content inside frame instead of the content node for ruby autohiding. r=dbaron (00cf5b7674)
- Bug 1173580 - Record content descriptions in APZ test data. r=kats (7a72d1ac0a)
- Bug 1178971 - Changed line snapping behaviour depending on even/odd-ness of stroke width. r=mstange (495b32dc23)
- Bug 1208953: [mp3] Don't parse data we've already parsed. r=cpearce (72eed4309f)
- Bug 1137151: Marked destructor of |android::MediaCodecReader| as protected, r=sotaro (0632b34bc5)
- Bug 1205351 - Replace nsBaseHashtable::Enumerate() calls in dom/media/ with iterators r=cpearce (45976c24c0)
- Bug 1133624 - Add lang-specific ruby rules to ua.css. r=dbaron (46788cc220)
- Bug 1133624 - followup add fuzzy maxdiff on CLOSED TREE (1b6b62aded)
- Bug 1180443 - Consider whitespace collapse when calculating intrinsic isize of ruby. r=dbaron (3862184acd)
- Bug 1153764 - Avoid explicitly doing break before when there is ruby span. r=roc (71b4ec7749)
- add gstreamer parts (7e562556be)
- some preferences aligned to FF (b26d0b389c)
- Bug 1166301 - If APZ is enabled, clip fixed background images at the layer level rather than the display item level. r=mattwoodrow (5644e22090)
- Bug 1144990 - Dump display items with class id and name, r=roc (aa2e227e35)
- Bug 1205087 - Remove LayerManager parameter for ShouldFixToViewport. r=roc (00a1f2e36f)
- Bug 1205087 - Make nsSVGIntegrationUtils paint frame continuations manually since combining them meant that our reference frame wasn't an ancestor of all painted frames. r=roc (e40f6b7b81)
- Bug 1195400 - Check ancestor geometry roots when determining scrollability of a layer. r=mattwoodrow (4699b7e935)
- Bug 1205087 - Cache the AnimatedGeometryRoot on DisplayItem. r=roc (06bba311c3)
- Back out the bits of bug 1205087 that cache the AnimatedGeometryRoot on DisplayItem. r=backout (254057a6b6)
- Bug 1203190 - Don't intersect with the visible rect for fixed background images. r=mattwoodrow (1c5a432459)
- Bug 1208438 - Don't allow layers with scrolling clips to occlusion-cull layers behind them. r=mattwoodrow (c3d77a9846)
- Bug 1205630 - Translate a fixed background display item's clip rect correctly when setting it on the layer. r=mstange (49039f0e2d)
- Bug 1205630 - Reftest. r=mstange (a8db59eaee)
- Bug 1105832 - Also dump inactive layer managers when display list dumping is enabled. r=mattwoodrow (564fe5fcbc)
- Bug 1208661 - Move Dump() up from ContentClient to CompositableClient. r=BenWa (37915312b3)
This commit is contained in:
Vendored
+1
@@ -33,6 +33,7 @@ builtin(include, build/autoconf/ffi.m4)dnl
|
||||
builtin(include, build/autoconf/clang-plugin.m4)dnl
|
||||
builtin(include, build/autoconf/alloc.m4)dnl
|
||||
builtin(include, build/autoconf/jemalloc.m4)dnl
|
||||
builtin(include, build/autoconf/rust.m4)dnl
|
||||
|
||||
MOZ_PROG_CHECKMSYS()
|
||||
|
||||
|
||||
@@ -222,3 +222,15 @@ MOZ_RUN_CONFIG_STATUS()],
|
||||
define([AC_CONFIG_HEADER],
|
||||
[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
|
||||
])
|
||||
|
||||
define([MOZ_BUILD_BACKEND],
|
||||
[
|
||||
BUILD_BACKENDS="RecursiveMake"
|
||||
|
||||
MOZ_ARG_ENABLE_STRING(build-backend,
|
||||
[ --enable-build-backend={AndroidEclipse,CppEclipse,VisualStudio,FasterMake}
|
||||
Enable additional build backends],
|
||||
[ BUILD_BACKENDS="RecursiveMake `echo $enableval | sed 's/,/ /g'`"])
|
||||
|
||||
AC_SUBST_LIST([BUILD_BACKENDS])
|
||||
])
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
dnl This Source Code Form is subject to the terms of the Mozilla Public
|
||||
dnl License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
AC_DEFUN([MOZ_RUST_SUPPORT], [
|
||||
MOZ_PATH_PROG(RUSTC, rustc)
|
||||
if test -n "$RUSTC"; then
|
||||
AC_MSG_CHECKING([rustc version])
|
||||
RUSTC_VERSION=`$RUSTC --version | cut -d ' ' -f 2`
|
||||
# Parse out semversion elements.
|
||||
_RUSTC_MAJOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 1`
|
||||
_RUSTC_MINOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 2`
|
||||
_RUSTC_EXTRA_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 3 | cut -d + -f 1`
|
||||
_RUSTC_PATCH_VERSION=`echo ${_RUSTC_EXTRA_VERSION} | cut -d '-' -f 1`
|
||||
AC_MSG_RESULT([$RUSTC_VERSION (v${_RUSTC_MAJOR_VERSION}.${_RUSTC_MINOR_VERSION}.${_RUSTC_PATCH_VERSION})])
|
||||
fi
|
||||
MOZ_ARG_ENABLE_BOOL([rust],
|
||||
[ --enable-rust Include Rust language sources],
|
||||
[MOZ_RUST=1],
|
||||
[MOZ_RUST= ])
|
||||
if test -z "$RUSTC" -a -n "$MOZ_RUST"; then
|
||||
AC_MSG_ERROR([Rust compiler not found.
|
||||
To compile rust language sources, you must have 'rustc' in your path.
|
||||
See http://www.rust-lang.org/ for more information.])
|
||||
fi
|
||||
if test -n "$MOZ_RUST" && test -z "$_RUSTC_MAJOR_VERSION" -o \
|
||||
"$_RUSTC_MAJOR_VERSION" -lt 1; then
|
||||
AC_MSG_ERROR([Rust compiler ${RUSTC_VERSION} is too old.
|
||||
To compile Rust language sources please install at least
|
||||
version 1.0 of the 'rustc' toolchain and make sure it is
|
||||
first in your path.
|
||||
You can verify this by typing 'rustc --version'.])
|
||||
fi
|
||||
AC_SUBST(MOZ_RUST)
|
||||
])
|
||||
+76
-83
@@ -137,6 +137,8 @@ MOZ_BUILD_ROOT=`pwd -W 2>/dev/null || pwd`
|
||||
|
||||
MOZ_PYTHON
|
||||
|
||||
MOZ_BUILD_BACKEND
|
||||
|
||||
MOZ_DEFAULT_COMPILER
|
||||
|
||||
COMPILE_ENVIRONMENT=1
|
||||
@@ -424,6 +426,8 @@ MOZ_TOOL_VARIABLES
|
||||
|
||||
MOZ_CHECK_COMPILER_WRAPPER
|
||||
|
||||
MOZ_RUST_SUPPORT
|
||||
|
||||
dnl ========================================================
|
||||
dnl Check for MacOS deployment target version
|
||||
dnl ========================================================
|
||||
@@ -448,6 +452,9 @@ esac
|
||||
|
||||
AC_SUBST(MACOSX_DEPLOYMENT_TARGET)
|
||||
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXXCPP
|
||||
|
||||
dnl ========================================================
|
||||
dnl Special win32 checks
|
||||
dnl ========================================================
|
||||
@@ -647,8 +654,6 @@ See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
|
||||
fi
|
||||
CFLAGS="$CFLAGS -D_HAS_EXCEPTIONS=0"
|
||||
CXXFLAGS="$CXXFLAGS -D_HAS_EXCEPTIONS=0"
|
||||
|
||||
MOZ_FIND_WINSDK_VERSION
|
||||
else
|
||||
# Check w32api version
|
||||
_W32API_MAJOR_VERSION=`echo $W32API_VERSION | $AWK -F\. '{ print $1 }'`
|
||||
@@ -700,10 +705,9 @@ See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
|
||||
# strsafe.h on mingw uses macros for function deprecation that pollutes namespace
|
||||
# causing problems with local implementations with the same name.
|
||||
AC_DEFINE(STRSAFE_NO_DEPRECATE)
|
||||
|
||||
MOZ_WINSDK_MAXVER=0x06030000
|
||||
fi # !GNU_CC
|
||||
|
||||
MOZ_FIND_WINSDK_VERSION
|
||||
AC_DEFINE_UNQUOTED(WINVER,0x$WINVER)
|
||||
AC_DEFINE_UNQUOTED(_WIN32_WINNT,0x$WINVER)
|
||||
# Require OS features provided by IE 6.0 SP2 (XP SP2)
|
||||
@@ -727,9 +731,6 @@ See https://developer.mozilla.org/en/Windows_Build_Prerequisites.])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXXCPP
|
||||
|
||||
if test -n "$_WIN32_MSVC"; then
|
||||
SKIP_PATH_CHECKS=1
|
||||
SKIP_COMPILER_CHECKS=1
|
||||
@@ -1648,46 +1649,6 @@ if test "$GCC_MAJOR_VERSION" -ge "6" ; then
|
||||
CXXFLAGS="$CXXFLAGS -fno-delete-null-pointer-checks -fno-lifetime-dse -fno-schedule-insns2"
|
||||
fi
|
||||
|
||||
dnl gcc can come with its own linker so it is better to use the pass-thru calls
|
||||
dnl MKSHLIB_FORCE_ALL is used to force the linker to include all object
|
||||
dnl files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker to
|
||||
dnl normal behavior.
|
||||
dnl ========================================================
|
||||
MKSHLIB_FORCE_ALL=
|
||||
MKSHLIB_UNFORCE_ALL=
|
||||
|
||||
if test "$COMPILE_ENVIRONMENT"; then
|
||||
if test "$GNU_CC"; then
|
||||
AC_MSG_CHECKING(whether ld has archive extraction flags)
|
||||
AC_CACHE_VAL(ac_cv_mkshlib_force_and_unforce,
|
||||
[_SAVE_LDFLAGS=$LDFLAGS; _SAVE_LIBS=$LIBS
|
||||
ac_cv_mkshlib_force_and_unforce="no"
|
||||
exec 3<&0 <<LOOP_INPUT
|
||||
force="-Wl,--whole-archive"; unforce="-Wl,--no-whole-archive"
|
||||
force="-Wl,-z -Wl,allextract"; unforce="-Wl,-z -Wl,defaultextract"
|
||||
force="-Wl,-all"; unforce="-Wl,-none"
|
||||
LOOP_INPUT
|
||||
while read line
|
||||
do
|
||||
eval $line
|
||||
LDFLAGS=$force
|
||||
LIBS=$unforce
|
||||
AC_TRY_LINK(,, ac_cv_mkshlib_force_and_unforce=$line; break)
|
||||
done
|
||||
exec 0<&3 3<&-
|
||||
LDFLAGS=$_SAVE_LDFLAGS; LIBS=$_SAVE_LIBS
|
||||
])
|
||||
if test "$ac_cv_mkshlib_force_and_unforce" = "no"; then
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
eval $ac_cv_mkshlib_force_and_unforce
|
||||
MKSHLIB_FORCE_ALL=$force
|
||||
MKSHLIB_UNFORCE_ALL=$unforce
|
||||
fi
|
||||
fi # GNU_CC
|
||||
fi # COMPILE_ENVIRONMENT
|
||||
|
||||
dnl ========================================================
|
||||
dnl Checking for 64-bit OS
|
||||
dnl ========================================================
|
||||
@@ -1867,6 +1828,9 @@ dnl ==============================================================
|
||||
MOZILLA_VERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir`
|
||||
MOZILLA_UAVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --uaversion`
|
||||
MOZILLA_SYMBOLVERSION=`$PYTHON $srcdir/python/mozbuild/mozbuild/milestone.py --topsrcdir $srcdir --symbolversion`
|
||||
if test -z "$MOZILLA_VERSION"; then
|
||||
AC_MSG_ERROR([failed to read version info from milestone file])
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION")
|
||||
AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION)
|
||||
@@ -2175,9 +2139,7 @@ ia64*-hpux*)
|
||||
IMPORT_LIB_SUFFIX=lib
|
||||
MKSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
|
||||
MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
|
||||
MKSHLIB_FORCE_ALL=
|
||||
MKSHLIB_UNFORCE_ALL=
|
||||
dnl Set subsystem version 6.
|
||||
dnl Set subsystem version 5 for Windows XP.
|
||||
WIN32_SUBSYSTEM_VERSION=5.01
|
||||
if test "$HAVE_64BIT_BUILD"; then
|
||||
WIN32_SUBSYSTEM_VERSION=5.02
|
||||
@@ -2359,8 +2321,6 @@ ia64*-hpux*)
|
||||
DSO_LDOPTS='-shared'
|
||||
fi
|
||||
# This will fail on a.out systems prior to 1.5.1_ALPHA.
|
||||
MKSHLIB_FORCE_ALL='-Wl,--whole-archive'
|
||||
MKSHLIB_UNFORCE_ALL='-Wl,--no-whole-archive'
|
||||
if test "$LIBRUNPATH"; then
|
||||
DSO_LDOPTS="-Wl,-R$LIBRUNPATH $DSO_LDOPTS"
|
||||
fi
|
||||
@@ -2410,8 +2370,6 @@ ia64*-hpux*)
|
||||
MOZ_OPTIMIZE_FLAGS="-xO4"
|
||||
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(DSO_SONAME) -o $@'
|
||||
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_FLAGS) $(DSO_LDOPTS) -h $(DSO_SONAME) -o $@'
|
||||
MKSHLIB_FORCE_ALL='-z allextract'
|
||||
MKSHLIB_UNFORCE_ALL='-z defaultextract'
|
||||
DSO_LDOPTS='-G'
|
||||
AR_LIST="$AR t"
|
||||
AR_EXTRACT="$AR x"
|
||||
@@ -2452,8 +2410,6 @@ ia64*-hpux*)
|
||||
else
|
||||
LDFLAGS="$LDFLAGS -Wl,-z,ignore -Wl,-R,'\$\$ORIGIN:\$\$ORIGIN/..' -Wl,-z,lazyload -Wl,-z,combreloc -Wl,-z,muldefs"
|
||||
LIBS="-lc $LIBS"
|
||||
MKSHLIB_FORCE_ALL='-Wl,-z -Wl,allextract'
|
||||
MKSHLIB_UNFORCE_ALL='-Wl,-z -Wl,defaultextract'
|
||||
ASFLAGS="$ASFLAGS -fPIC"
|
||||
DSO_LDOPTS='-shared'
|
||||
WARNINGS_AS_ERRORS='-Werror'
|
||||
@@ -2503,31 +2459,6 @@ dnl Only one oddball right now (QNX), but this gives us flexibility
|
||||
dnl if any other platforms need to override this in the future.
|
||||
AC_DEFINE_UNQUOTED(D_INO,$DIRENT_INO)
|
||||
|
||||
dnl ========================================================
|
||||
dnl Any platform that doesn't have MKSHLIB_FORCE_ALL defined
|
||||
dnl by now will not have any way to link most binaries (tests
|
||||
dnl as well as viewer, apprunner, etc.), because some symbols
|
||||
dnl will be left out of the "composite" .so's by ld as unneeded.
|
||||
dnl So, by defining NO_LD_ARCHIVE_FLAGS for these platforms,
|
||||
dnl they can link in the static libs that provide the missing
|
||||
dnl symbols.
|
||||
dnl ========================================================
|
||||
NO_LD_ARCHIVE_FLAGS=
|
||||
if test -z "$MKSHLIB_FORCE_ALL" -o -z "$MKSHLIB_UNFORCE_ALL"; then
|
||||
NO_LD_ARCHIVE_FLAGS=1
|
||||
fi
|
||||
case "$target" in
|
||||
*-aix4.3*|*-aix5*)
|
||||
NO_LD_ARCHIVE_FLAGS=
|
||||
;;
|
||||
*-mingw*)
|
||||
if test -z "$GNU_CC"; then
|
||||
NO_LD_ARCHIVE_FLAGS=
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(NO_LD_ARCHIVE_FLAGS)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Flags to strip unused symbols from .so components and
|
||||
dnl = to export jemalloc symbols when linking a program
|
||||
@@ -3740,6 +3671,7 @@ MOZ_WAVE=1
|
||||
MOZ_SAMPLE_TYPE_FLOAT32=
|
||||
MOZ_SAMPLE_TYPE_S16=
|
||||
MOZ_WEBM=1
|
||||
MOZ_GSTREAMER=
|
||||
MOZ_DIRECTSHOW=
|
||||
MOZ_WMF=
|
||||
if test -n "$MOZ_FMP4"; then
|
||||
@@ -5523,6 +5455,69 @@ fi
|
||||
|
||||
AC_SUBST(MOZ_PULSEAUDIO)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable GStreamer
|
||||
dnl ========================================================
|
||||
case "$OS_TARGET" in
|
||||
WINNT|Darwin|Android)
|
||||
;;
|
||||
*)
|
||||
MOZ_GSTREAMER=1
|
||||
GST_API_VERSION=0.10
|
||||
;;
|
||||
esac
|
||||
|
||||
MOZ_ARG_ENABLE_STRING(gstreamer,
|
||||
[ --enable-gstreamer[=0.10] Enable GStreamer support],
|
||||
[ MOZ_GSTREAMER=1
|
||||
# API version, eg 0.10, 1.0 etc
|
||||
if test -z "$enableval" -o "$enableval" = "yes"; then
|
||||
GST_API_VERSION=0.10
|
||||
elif test "$enableval" = "no"; then
|
||||
MOZ_GSTREAMER=
|
||||
else
|
||||
GST_API_VERSION=$enableval
|
||||
fi],
|
||||
)
|
||||
|
||||
if test -n "$MOZ_GSTREAMER"; then
|
||||
# core/base release number
|
||||
if test "$GST_API_VERSION" = "1.0"; then
|
||||
GST_VERSION=1.0
|
||||
else
|
||||
GST_VERSION=0.10.25
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(GSTREAMER,
|
||||
gstreamer-$GST_API_VERSION >= $GST_VERSION
|
||||
gstreamer-app-$GST_API_VERSION
|
||||
gstreamer-plugins-base-$GST_API_VERSION,
|
||||
[_HAVE_GSTREAMER=1],
|
||||
[_HAVE_GSTREAMER=])
|
||||
if test -z "$_HAVE_GSTREAMER"; then
|
||||
AC_MSG_ERROR([gstreamer and gstreamer-plugins-base development packages are needed to build gstreamer backend. Install them or disable gstreamer support with --disable-gstreamer])
|
||||
fi
|
||||
|
||||
_SAVE_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS $GSTREAMER_LIBS -lgstvideo-$GST_API_VERSION"
|
||||
AC_TRY_LINK(,[return 0;],_HAVE_LIBGSTVIDEO=1,_HAVE_LIBGSTVIDEO=)
|
||||
if test -n "$_HAVE_LIBGSTVIDEO" ; then
|
||||
GSTREAMER_LIBS="$GSTREAMER_LIBS -lgstvideo-$GST_API_VERSION"
|
||||
else
|
||||
AC_MSG_ERROR([gstreamer-plugins-base found, but no libgstvideo. Something has gone terribly wrong. Try reinstalling gstreamer-plugins-base; failing that, disable the gstreamer backend with --disable-gstreamer.])
|
||||
fi
|
||||
LDFLAGS=$_SAVE_LDFLAGS
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_GSTREAMER)
|
||||
AC_SUBST(GST_API_VERSION)
|
||||
|
||||
if test -n "$MOZ_GSTREAMER"; then
|
||||
AC_DEFINE(MOZ_GSTREAMER)
|
||||
AC_DEFINE_UNQUOTED(GST_API_VERSION, "$GST_API_VERSION")
|
||||
fi
|
||||
|
||||
|
||||
dnl ========================================================
|
||||
dnl Permissions System
|
||||
dnl ========================================================
|
||||
@@ -8498,8 +8493,6 @@ AC_SUBST(MOZ_CHROME_FILE_FORMAT)
|
||||
AC_SUBST(WRAP_LDFLAGS)
|
||||
AC_SUBST(MKSHLIB)
|
||||
AC_SUBST(MKCSHLIB)
|
||||
AC_SUBST(MKSHLIB_FORCE_ALL)
|
||||
AC_SUBST(MKSHLIB_UNFORCE_ALL)
|
||||
AC_SUBST(DSO_CFLAGS)
|
||||
AC_SUBST(DSO_PIC_CFLAGS)
|
||||
AC_SUBST(DSO_LDOPTS)
|
||||
|
||||
@@ -1350,6 +1350,8 @@ public:
|
||||
* are not converted into newlines. Only textnodes and cdata nodes are
|
||||
* added to the result.
|
||||
*
|
||||
* @see nsLayoutUtils::GetFrameTextContent
|
||||
*
|
||||
* @param aNode Node to get textual contents of.
|
||||
* @param aDeep If true child elements of aNode are recursivly descended
|
||||
* into to find text children.
|
||||
|
||||
@@ -4705,8 +4705,7 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
|
||||
auto result = image.mImgContainer->
|
||||
Draw(context, scaledImageSize,
|
||||
ImageRegion::Create(gfxRect(src.x, src.y, src.width, src.height)),
|
||||
image.mWhichFrame, GraphicsFilter::FILTER_GOOD,
|
||||
Some(svgContext), modifiedFlags);
|
||||
image.mWhichFrame, Filter::GOOD, Some(svgContext), modifiedFlags);
|
||||
|
||||
if (result != DrawResult::SUCCESS) {
|
||||
NS_WARNING("imgIContainer::Draw failed");
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "GraphicsFilter.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
|
||||
|
||||
@@ -60,6 +60,7 @@ using mozilla::CommandInt from "mozilla/EventForwards.h";
|
||||
using mozilla::Modifiers from "mozilla/EventForwards.h";
|
||||
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
|
||||
using mozilla::WritingMode from "mozilla/WritingModes.h";
|
||||
using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
|
||||
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
|
||||
using nsIWidget::TouchPointerState from "nsIWidget.h";
|
||||
using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
|
||||
@@ -537,6 +538,9 @@ parent:
|
||||
prio(high) sync DispatchMouseEvent(WidgetMouseEvent event);
|
||||
prio(high) sync DispatchKeyboardEvent(WidgetKeyboardEvent event);
|
||||
|
||||
// Start an APZ drag on a scrollbar
|
||||
async StartScrollbarDrag(AsyncDragMetrics aDragMetrics);
|
||||
|
||||
InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action,
|
||||
nsCString visualData, uint32_t width, uint32_t height,
|
||||
uint32_t stride, uint8_t format, int32_t dragAreaX, int32_t dragAreaY);
|
||||
@@ -619,7 +623,7 @@ child:
|
||||
* When two consecutive mouse move events would be added to the message queue,
|
||||
* they are 'compressed' by dumping the oldest one.
|
||||
*/
|
||||
RealMouseMoveEvent(WidgetMouseEvent event) compress;
|
||||
RealMouseMoveEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId) compress;
|
||||
/**
|
||||
* Mouse move events with |reason == eSynthesized| are sent via a separate
|
||||
* message because they do not generate DOM 'mousemove' events, and the
|
||||
@@ -627,8 +631,8 @@ child:
|
||||
* |reason == eReal| event being dropped in favour of an |eSynthesized|
|
||||
* event, and thus a DOM 'mousemove' event to be lost.
|
||||
*/
|
||||
SynthMouseMoveEvent(WidgetMouseEvent event);
|
||||
RealMouseButtonEvent(WidgetMouseEvent event);
|
||||
SynthMouseMoveEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
RealMouseButtonEvent(WidgetMouseEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
RealKeyEvent(WidgetKeyboardEvent event, MaybeNativeKeyBinding keyBinding);
|
||||
MouseWheelEvent(WidgetWheelEvent event, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
RealTouchEvent(WidgetTouchEvent aEvent,
|
||||
|
||||
+15
-5
@@ -33,6 +33,7 @@
|
||||
#include "mozilla/layers/CompositorChild.h"
|
||||
#include "mozilla/layers/DoubleTapToZoom.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/layers/InputAPZContext.h"
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
#include "mozilla/layout/RenderFrameChild.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
@@ -1899,20 +1900,29 @@ TabChild::RecvMouseEvent(const nsString& aType,
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& event)
|
||||
TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& event,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId)
|
||||
{
|
||||
return RecvRealMouseButtonEvent(event);
|
||||
return RecvRealMouseButtonEvent(event, aGuid, aInputBlockId);
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvSynthMouseMoveEvent(const WidgetMouseEvent& event)
|
||||
TabChild::RecvSynthMouseMoveEvent(const WidgetMouseEvent& event,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId)
|
||||
{
|
||||
return RecvRealMouseButtonEvent(event);
|
||||
return RecvRealMouseButtonEvent(event, aGuid, aInputBlockId);
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& event)
|
||||
TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& event,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId)
|
||||
{
|
||||
nsEventStatus unused;
|
||||
InputAPZContext context(aGuid, aInputBlockId, unused);
|
||||
|
||||
WidgetMouseEvent localEvent(event);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
|
||||
+9
-3
@@ -331,9 +331,15 @@ public:
|
||||
const int32_t& aClickCount,
|
||||
const int32_t& aModifiers,
|
||||
const bool& aIgnoreRootScrollFrame) override;
|
||||
virtual bool RecvRealMouseMoveEvent(const mozilla::WidgetMouseEvent& event) override;
|
||||
virtual bool RecvSynthMouseMoveEvent(const mozilla::WidgetMouseEvent& event) override;
|
||||
virtual bool RecvRealMouseButtonEvent(const mozilla::WidgetMouseEvent& event) override;
|
||||
virtual bool RecvRealMouseMoveEvent(const mozilla::WidgetMouseEvent& event,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId) override;
|
||||
virtual bool RecvSynthMouseMoveEvent(const mozilla::WidgetMouseEvent& event,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId) override;
|
||||
virtual bool RecvRealMouseButtonEvent(const mozilla::WidgetMouseEvent& event,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
const uint64_t& aInputBlockId) override;
|
||||
virtual bool RecvRealDragEvent(const WidgetDragEvent& aEvent,
|
||||
const uint32_t& aDragAction,
|
||||
const uint32_t& aDropEffect) override;
|
||||
|
||||
+18
-3
@@ -28,6 +28,7 @@
|
||||
#include "mozilla/IMEStateManager.h"
|
||||
#include "mozilla/ipc/DocumentRendererParent.h"
|
||||
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
||||
#include "mozilla/layers/AsyncDragMetrics.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "mozilla/layers/InputAPZContext.h"
|
||||
#include "mozilla/layout/RenderFrameParent.h"
|
||||
@@ -1437,14 +1438,19 @@ bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event)
|
||||
}
|
||||
}
|
||||
|
||||
ScrollableLayerGuid guid;
|
||||
uint64_t blockId;
|
||||
ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
|
||||
|
||||
if (eMouseMove == event.mMessage) {
|
||||
if (event.reason == WidgetMouseEvent::eSynthesized) {
|
||||
return SendSynthMouseMoveEvent(event);
|
||||
return SendSynthMouseMoveEvent(event, guid, blockId);
|
||||
} else {
|
||||
return SendRealMouseMoveEvent(event);
|
||||
return SendRealMouseMoveEvent(event, guid, blockId);
|
||||
}
|
||||
}
|
||||
return SendRealMouseButtonEvent(event);
|
||||
|
||||
return SendRealMouseButtonEvent(event, guid, blockId);
|
||||
}
|
||||
|
||||
LayoutDeviceToCSSScale
|
||||
@@ -2913,6 +2919,15 @@ TabParent::RecvSetTargetAPZC(const uint64_t& aInputBlockId,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
|
||||
{
|
||||
if (RenderFrameParent* rfp = GetRenderFrame()) {
|
||||
rfp->StartScrollbarDrag(aDragMetrics);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
|
||||
nsTArray<TouchBehaviorFlags>&& aFlags)
|
||||
|
||||
@@ -43,6 +43,7 @@ class CpowHolder;
|
||||
} // namespace jsipc
|
||||
|
||||
namespace layers {
|
||||
class AsyncDragMetrics;
|
||||
struct FrameMetrics;
|
||||
struct TextureFactoryIdentifier;
|
||||
} // namespace layers
|
||||
@@ -81,6 +82,7 @@ class TabParent final : public PBrowserParent
|
||||
, public nsAPostRefreshObserver
|
||||
{
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
|
||||
|
||||
virtual ~TabParent();
|
||||
|
||||
@@ -239,6 +241,7 @@ public:
|
||||
virtual bool RecvDispatchWheelEvent(const mozilla::WidgetWheelEvent& aEvent) override;
|
||||
virtual bool RecvDispatchMouseEvent(const mozilla::WidgetMouseEvent& aEvent) override;
|
||||
virtual bool RecvDispatchKeyboardEvent(const mozilla::WidgetKeyboardEvent& aEvent) override;
|
||||
virtual bool RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
|
||||
|
||||
virtual PColorPickerParent*
|
||||
AllocPColorPickerParent(const nsString& aTitle, const nsString& aInitialColor) override;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsString.h"
|
||||
#include "Intervals.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -213,6 +214,24 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class NotifyDataArrivedFilter {
|
||||
public:
|
||||
media::IntervalSet<int64_t> NotifyDataArrived(uint32_t aLength, int64_t aOffset) {
|
||||
media::Interval<int64_t> interval(aOffset, aOffset + aLength);
|
||||
media::IntervalSet<int64_t> newIntervals(interval);
|
||||
newIntervals -= mIntervals;
|
||||
mIntervals += interval;
|
||||
return newIntervals;
|
||||
}
|
||||
|
||||
const media::IntervalSet<int64_t>& GetIntervals() {
|
||||
return mIntervals;
|
||||
}
|
||||
|
||||
private:
|
||||
media::IntervalSet<int64_t> mIntervals;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1478,6 +1478,14 @@ MediaDecoder::IsRtspEnabled()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GSTREAMER
|
||||
bool
|
||||
MediaDecoder::IsGStreamerEnabled()
|
||||
{
|
||||
return Preferences::GetBool("media.gstreamer.enabled");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_OMX_DECODER
|
||||
bool
|
||||
MediaDecoder::IsOmxEnabled()
|
||||
|
||||
@@ -710,6 +710,10 @@ private:
|
||||
static bool IsRtspEnabled();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GSTREAMER
|
||||
static bool IsGStreamerEnabled();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_OMX_DECODER
|
||||
static bool IsOmxEnabled();
|
||||
static bool IsOmxAsyncEnabled();
|
||||
|
||||
@@ -520,20 +520,23 @@ AppleMP3Reader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaByteBuffer> bytes =
|
||||
mDecoder->GetResource()->MediaReadAt(aOffset, aLength);
|
||||
NS_ENSURE_TRUE_VOID(bytes);
|
||||
mMP3FrameParser.Parse(bytes->Elements(), aLength, aOffset);
|
||||
if (!mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
}
|
||||
IntervalSet<int64_t> intervals = mFilter.NotifyDataArrived(aLength, aOffset);
|
||||
for (const auto& interval : intervals) {
|
||||
nsRefPtr<MediaByteBuffer> bytes =
|
||||
mResource.MediaReadAt(interval.mStart, interval.Length());
|
||||
NS_ENSURE_TRUE_VOID(bytes);
|
||||
mMP3FrameParser.Parse(bytes->Elements(), interval.Length(), interval.mStart);
|
||||
if (!mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t duration = mMP3FrameParser.GetDuration();
|
||||
if (duration != mDuration) {
|
||||
LOGD("Updating media duration to %lluus\n", duration);
|
||||
MOZ_ASSERT(mDecoder);
|
||||
mDuration = duration;
|
||||
mDecoder->DispatchUpdateEstimatedMediaDuration(duration);
|
||||
uint64_t duration = mMP3FrameParser.GetDuration();
|
||||
if (duration != mDuration) {
|
||||
LOGD("Updating media duration to %lluus\n", duration);
|
||||
MOZ_ASSERT(mDecoder);
|
||||
mDuration = duration;
|
||||
mDecoder->DispatchUpdateEstimatedMediaDuration(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ private:
|
||||
MP3FrameParser mMP3FrameParser;
|
||||
|
||||
MediaResourceIndex mResource;
|
||||
NotifyDataArrivedFilter mFilter;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -408,18 +408,22 @@ DirectShowReader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset)
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaByteBuffer> bytes = mDecoder->GetResource()->MediaReadAt(aOffset, aLength);
|
||||
NS_ENSURE_TRUE_VOID(bytes);
|
||||
mMP3FrameParser.Parse(bytes->Elements(), aLength, aOffset);
|
||||
if (!mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
}
|
||||
IntervalSet<int64_t> intervals = mFilter.NotifyDataArrived(aLength, aOffset);
|
||||
for (const auto& interval : intervals) {
|
||||
nsRefPtr<MediaByteBuffer> bytes =
|
||||
mDecoder->GetResource()->MediaReadAt(interval.mStart, interval.Length());
|
||||
NS_ENSURE_TRUE_VOID(bytes);
|
||||
mMP3FrameParser.Parse(bytes->Elements(), interval.Length(), interval.mStart);
|
||||
if (!mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t duration = mMP3FrameParser.GetDuration();
|
||||
if (duration != mDuration) {
|
||||
MOZ_ASSERT(mDecoder);
|
||||
mDuration = duration;
|
||||
mDecoder->DispatchUpdateEstimatedMediaDuration(mDuration);
|
||||
int64_t duration = mMP3FrameParser.GetDuration();
|
||||
if (duration != mDuration) {
|
||||
MOZ_ASSERT(mDecoder);
|
||||
mDuration = duration;
|
||||
mDecoder->DispatchUpdateEstimatedMediaDuration(mDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@ private:
|
||||
|
||||
// Duration of the stream, in microseconds.
|
||||
int64_t mDuration;
|
||||
|
||||
NotifyDataArrivedFilter mFilter;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -283,20 +283,16 @@ GMPServiceChild::GetBridgedGMPContentParent(ProcessId aOtherPid,
|
||||
mContentParents.Get(aOtherPid, aGMPContentParent);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FindAndRemoveGMPContentParent(const uint64_t& aKey,
|
||||
nsRefPtr<GMPContentParent>& aData,
|
||||
void* aUserArg)
|
||||
{
|
||||
return aData == aUserArg ?
|
||||
(PLDHashOperator)(PL_DHASH_STOP | PL_DHASH_REMOVE) :
|
||||
PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
GMPServiceChild::RemoveGMPContentParent(GMPContentParent* aGMPContentParent)
|
||||
{
|
||||
mContentParents.Enumerate(FindAndRemoveGMPContentParent, aGMPContentParent);
|
||||
for (auto iter = mContentParents.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsRefPtr<GMPContentParent>& parent = iter.Data();
|
||||
if (parent == aGMPContentParent) {
|
||||
iter.Remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "GStreamerAllocator.h"
|
||||
|
||||
#include <gst/video/video.h>
|
||||
#include <gst/video/gstvideometa.h>
|
||||
|
||||
#include "GStreamerLoader.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstAllocator parent;
|
||||
GStreamerReader *reader;
|
||||
} MozGfxMemoryAllocator;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstAllocatorClass parent;
|
||||
} MozGfxMemoryAllocatorClass;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstMemory memory;
|
||||
PlanarYCbCrImage* image;
|
||||
guint8* data;
|
||||
} MozGfxMemory;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstMeta meta;
|
||||
} MozGfxMeta;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstVideoBufferPoolClass parent_class;
|
||||
} MozGfxBufferPoolClass;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstVideoBufferPool pool;
|
||||
} MozGfxBufferPool;
|
||||
|
||||
// working around GTK+ bug https://bugzilla.gnome.org/show_bug.cgi?id=723899
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
G_DEFINE_TYPE(MozGfxMemoryAllocator, moz_gfx_memory_allocator, GST_TYPE_ALLOCATOR);
|
||||
G_DEFINE_TYPE(MozGfxBufferPool, moz_gfx_buffer_pool, GST_TYPE_VIDEO_BUFFER_POOL);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
void
|
||||
moz_gfx_memory_reset(MozGfxMemory *mem)
|
||||
{
|
||||
if (mem->image)
|
||||
mem->image->Release();
|
||||
|
||||
ImageContainer* container = ((MozGfxMemoryAllocator*) mem->memory.allocator)->reader->GetImageContainer();
|
||||
mem->image = reinterpret_cast<PlanarYCbCrImage*>(container->CreateImage(ImageFormat::PLANAR_YCBCR).take());
|
||||
mem->data = mem->image->AllocateAndGetNewBuffer(mem->memory.size);
|
||||
}
|
||||
|
||||
static GstMemory*
|
||||
moz_gfx_memory_allocator_alloc(GstAllocator* aAllocator, gsize aSize,
|
||||
GstAllocationParams* aParams)
|
||||
{
|
||||
MozGfxMemory* mem = g_slice_new (MozGfxMemory);
|
||||
gsize maxsize = aSize + aParams->prefix + aParams->padding;
|
||||
gst_memory_init(GST_MEMORY_CAST (mem),
|
||||
(GstMemoryFlags)aParams->flags,
|
||||
aAllocator, NULL, maxsize, aParams->align,
|
||||
aParams->prefix, aSize);
|
||||
mem->image = NULL;
|
||||
moz_gfx_memory_reset(mem);
|
||||
|
||||
return (GstMemory *) mem;
|
||||
}
|
||||
|
||||
static void
|
||||
moz_gfx_memory_allocator_free (GstAllocator * allocator, GstMemory * gmem)
|
||||
{
|
||||
MozGfxMemory *mem = (MozGfxMemory *) gmem;
|
||||
|
||||
if (mem->memory.parent)
|
||||
goto sub_mem;
|
||||
|
||||
if (mem->image)
|
||||
mem->image->Release();
|
||||
|
||||
sub_mem:
|
||||
g_slice_free (MozGfxMemory, mem);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
moz_gfx_memory_map (MozGfxMemory * mem, gsize maxsize, GstMapFlags flags)
|
||||
{
|
||||
// check that the allocation didn't fail
|
||||
if (mem->data == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return mem->data + mem->memory.offset;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
moz_gfx_memory_unmap (MozGfxMemory * mem)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MozGfxMemory *
|
||||
moz_gfx_memory_share (MozGfxMemory * mem, gssize offset, gsize size)
|
||||
{
|
||||
MozGfxMemory *sub;
|
||||
GstMemory *parent;
|
||||
|
||||
/* find the real parent */
|
||||
if ((parent = mem->memory.parent) == NULL)
|
||||
parent = (GstMemory *) mem;
|
||||
|
||||
if (size == (gsize) -1)
|
||||
size = mem->memory.size - offset;
|
||||
|
||||
/* the shared memory is always readonly */
|
||||
sub = g_slice_new (MozGfxMemory);
|
||||
|
||||
gst_memory_init (GST_MEMORY_CAST (sub),
|
||||
(GstMemoryFlags) (GST_MINI_OBJECT_FLAGS (parent) | GST_MINI_OBJECT_FLAG_LOCK_READONLY),
|
||||
mem->memory.allocator, &mem->memory, mem->memory.maxsize, mem->memory.align,
|
||||
mem->memory.offset + offset, size);
|
||||
|
||||
sub->image = mem->image;
|
||||
sub->data = mem->data;
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
static void
|
||||
moz_gfx_memory_allocator_class_init (MozGfxMemoryAllocatorClass * klass)
|
||||
{
|
||||
GstAllocatorClass *allocator_class;
|
||||
|
||||
allocator_class = (GstAllocatorClass *) klass;
|
||||
|
||||
allocator_class->alloc = moz_gfx_memory_allocator_alloc;
|
||||
allocator_class->free = moz_gfx_memory_allocator_free;
|
||||
}
|
||||
|
||||
static void
|
||||
moz_gfx_memory_allocator_init (MozGfxMemoryAllocator * allocator)
|
||||
{
|
||||
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
|
||||
|
||||
alloc->mem_type = "moz-gfx-image";
|
||||
alloc->mem_map = (GstMemoryMapFunction) moz_gfx_memory_map;
|
||||
alloc->mem_unmap = (GstMemoryUnmapFunction) moz_gfx_memory_unmap;
|
||||
alloc->mem_share = (GstMemoryShareFunction) moz_gfx_memory_share;
|
||||
/* fallback copy and is_span */
|
||||
}
|
||||
|
||||
void
|
||||
moz_gfx_memory_allocator_set_reader(GstAllocator* aAllocator, GStreamerReader* aReader)
|
||||
{
|
||||
MozGfxMemoryAllocator *allocator = (MozGfxMemoryAllocator *) aAllocator;
|
||||
allocator->reader = aReader;
|
||||
}
|
||||
|
||||
nsRefPtr<PlanarYCbCrImage>
|
||||
moz_gfx_memory_get_image(GstMemory *aMemory)
|
||||
{
|
||||
NS_ASSERTION(GST_IS_MOZ_GFX_MEMORY_ALLOCATOR(aMemory->allocator), "Should be a gfx image");
|
||||
|
||||
return ((MozGfxMemory *) aMemory)->image;
|
||||
}
|
||||
|
||||
void
|
||||
moz_gfx_buffer_pool_reset_buffer (GstBufferPool* aPool, GstBuffer* aBuffer)
|
||||
{
|
||||
GstMemory* mem = gst_buffer_peek_memory(aBuffer, 0);
|
||||
|
||||
NS_ASSERTION(GST_IS_MOZ_GFX_MEMORY_ALLOCATOR(mem->allocator), "Should be a gfx image");
|
||||
moz_gfx_memory_reset((MozGfxMemory *) mem);
|
||||
GST_BUFFER_POOL_CLASS(moz_gfx_buffer_pool_parent_class)->reset_buffer(aPool, aBuffer);
|
||||
}
|
||||
|
||||
static void
|
||||
moz_gfx_buffer_pool_class_init (MozGfxBufferPoolClass * klass)
|
||||
{
|
||||
GstBufferPoolClass *pool_class = (GstBufferPoolClass *) klass;
|
||||
pool_class->reset_buffer = moz_gfx_buffer_pool_reset_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
moz_gfx_buffer_pool_init (MozGfxBufferPool * pool)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,25 @@
|
||||
/* 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/. */
|
||||
|
||||
#if !defined(GStreamerAllocator_h_)
|
||||
#define GStreamerAllocator_h_
|
||||
|
||||
#include "GStreamerReader.h"
|
||||
|
||||
#define GST_TYPE_MOZ_GFX_MEMORY_ALLOCATOR (moz_gfx_memory_allocator_get_type())
|
||||
#define GST_IS_MOZ_GFX_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_GFX_MEMORY_ALLOCATOR))
|
||||
#define GST_TYPE_MOZ_GFX_BUFFER_POOL (moz_gfx_buffer_pool_get_type())
|
||||
#define GST_IS_MOZ_GFX_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_GFX_BUFFER_POOL))
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
GType moz_gfx_memory_allocator_get_type();
|
||||
void moz_gfx_memory_allocator_set_reader(GstAllocator *aAllocator, GStreamerReader* aReader);
|
||||
nsRefPtr<layers::PlanarYCbCrImage> moz_gfx_memory_get_image(GstMemory *aMemory);
|
||||
|
||||
GType moz_gfx_buffer_pool_get_type();
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "MediaDecoderStateMachine.h"
|
||||
#include "GStreamerReader.h"
|
||||
#include "GStreamerDecoder.h"
|
||||
#include "GStreamerFormatHelper.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
MediaDecoderStateMachine* GStreamerDecoder::CreateStateMachine()
|
||||
{
|
||||
return new MediaDecoderStateMachine(this, new GStreamerReader(this));
|
||||
}
|
||||
|
||||
bool
|
||||
GStreamerDecoder::CanHandleMediaType(const nsACString& aMIMEType,
|
||||
const nsAString* aCodecs)
|
||||
{
|
||||
return MediaDecoder::IsGStreamerEnabled() &&
|
||||
GStreamerFormatHelper::Instance()->CanHandleMediaType(aMIMEType, aCodecs);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#if !defined(GStreamerDecoder_h_)
|
||||
#define GStreamerDecoder_h_
|
||||
|
||||
#include "MediaDecoder.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GStreamerDecoder : public MediaDecoder
|
||||
{
|
||||
public:
|
||||
virtual MediaDecoder* Clone() { return new GStreamerDecoder(); }
|
||||
virtual MediaDecoderStateMachine* CreateStateMachine();
|
||||
static bool CanHandleMediaType(const nsACString& aMIMEType, const nsAString* aCodecs);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,373 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "GStreamerFormatHelper.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsString.h"
|
||||
#include "GStreamerLoader.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#define ENTRY_FORMAT(entry) entry[0]
|
||||
#define ENTRY_CAPS(entry) entry[1]
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
extern PRLogModuleInfo* gMediaDecoderLog;
|
||||
#define LOG(msg, ...) \
|
||||
MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, ("GStreamerFormatHelper " msg, ##__VA_ARGS__))
|
||||
|
||||
GStreamerFormatHelper* GStreamerFormatHelper::gInstance = nullptr;
|
||||
bool GStreamerFormatHelper::sLoadOK = false;
|
||||
|
||||
GStreamerFormatHelper* GStreamerFormatHelper::Instance() {
|
||||
if (!gInstance) {
|
||||
if ((sLoadOK = load_gstreamer())) {
|
||||
gst_init(nullptr, nullptr);
|
||||
}
|
||||
|
||||
gInstance = new GStreamerFormatHelper();
|
||||
}
|
||||
|
||||
return gInstance;
|
||||
}
|
||||
|
||||
void GStreamerFormatHelper::Shutdown() {
|
||||
delete gInstance;
|
||||
gInstance = nullptr;
|
||||
}
|
||||
|
||||
static char const *const sContainers[][2] = {
|
||||
{"video/mp4", "video/quicktime"},
|
||||
{"video/x-m4v", "video/quicktime"},
|
||||
{"video/quicktime", "video/quicktime"},
|
||||
{"audio/mp4", "audio/x-m4a"},
|
||||
{"audio/x-m4a", "audio/x-m4a"},
|
||||
{"audio/mpeg", "audio/mpeg, mpegversion=(int)1"},
|
||||
{"audio/mp3", "audio/mpeg, mpegversion=(int)1"},
|
||||
};
|
||||
|
||||
static char const *const sCodecs[9][2] = {
|
||||
{"avc1.42E01E", "video/x-h264"},
|
||||
{"avc1.42001E", "video/x-h264"},
|
||||
{"avc1.58A01E", "video/x-h264"},
|
||||
{"avc1.4D401E", "video/x-h264"},
|
||||
{"avc1.64001E", "video/x-h264"},
|
||||
{"avc1.64001F", "video/x-h264"},
|
||||
{"mp4v.20.3", "video/3gpp"},
|
||||
{"mp4a.40.2", "audio/mpeg, mpegversion=(int)4"},
|
||||
{"mp3", "audio/mpeg, mpegversion=(int)1"},
|
||||
};
|
||||
|
||||
static char const * const sDefaultCodecCaps[][2] = {
|
||||
{"video/mp4", "video/x-h264"},
|
||||
{"video/x-m4v", "video/x-h264"},
|
||||
{"video/quicktime", "video/x-h264"},
|
||||
{"audio/mp4", "audio/mpeg, mpegversion=(int)4"},
|
||||
{"audio/x-m4a", "audio/mpeg, mpegversion=(int)4"},
|
||||
{"audio/mp3", "audio/mpeg, layer=(int)3"},
|
||||
{"audio/mpeg", "audio/mpeg, layer=(int)3"}
|
||||
};
|
||||
|
||||
static char const * const sPluginBlacklist[] = {
|
||||
"flump3dec",
|
||||
"h264parse",
|
||||
};
|
||||
|
||||
GStreamerFormatHelper::GStreamerFormatHelper()
|
||||
: mFactories(nullptr),
|
||||
mCookie(static_cast<uint32_t>(-1))
|
||||
{
|
||||
if (!sLoadOK) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSupportedContainerCaps = gst_caps_new_empty();
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS(sContainers); i++) {
|
||||
const char* capsString = sContainers[i][1];
|
||||
GstCaps* caps = gst_caps_from_string(capsString);
|
||||
gst_caps_append(mSupportedContainerCaps, caps);
|
||||
}
|
||||
|
||||
mSupportedCodecCaps = gst_caps_new_empty();
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS(sCodecs); i++) {
|
||||
const char* capsString = sCodecs[i][1];
|
||||
GstCaps* caps = gst_caps_from_string(capsString);
|
||||
gst_caps_append(mSupportedCodecCaps, caps);
|
||||
}
|
||||
}
|
||||
|
||||
GStreamerFormatHelper::~GStreamerFormatHelper() {
|
||||
if (!sLoadOK) {
|
||||
return;
|
||||
}
|
||||
|
||||
gst_caps_unref(mSupportedContainerCaps);
|
||||
gst_caps_unref(mSupportedCodecCaps);
|
||||
|
||||
if (mFactories)
|
||||
g_list_free(mFactories);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
GetContainerCapsFromMIMEType(const char *aType) {
|
||||
/* convert aMIMEType to gst container caps */
|
||||
const char* capsString = nullptr;
|
||||
for (uint32_t i = 0; i < G_N_ELEMENTS(sContainers); i++) {
|
||||
if (!strcmp(ENTRY_FORMAT(sContainers[i]), aType)) {
|
||||
capsString = ENTRY_CAPS(sContainers[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!capsString) {
|
||||
/* we couldn't find any matching caps */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return gst_caps_from_string(capsString);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
GetDefaultCapsFromMIMEType(const char *aType) {
|
||||
GstCaps *caps = GetContainerCapsFromMIMEType(aType);
|
||||
|
||||
for (uint32_t i = 0; i < G_N_ELEMENTS(sDefaultCodecCaps); i++) {
|
||||
if (!strcmp(sDefaultCodecCaps[i][0], aType)) {
|
||||
GstCaps *tmp = gst_caps_from_string(sDefaultCodecCaps[i][1]);
|
||||
|
||||
gst_caps_append(caps, tmp);
|
||||
return caps;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool GStreamerFormatHelper::CanHandleMediaType(const nsACString& aMIMEType,
|
||||
const nsAString* aCodecs) {
|
||||
if (!sLoadOK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *type;
|
||||
NS_CStringGetData(aMIMEType, &type, nullptr);
|
||||
|
||||
GstCaps *caps;
|
||||
if (aCodecs && !aCodecs->IsEmpty()) {
|
||||
caps = ConvertFormatsToCaps(type, aCodecs);
|
||||
} else {
|
||||
// Get a minimal set of codec caps for this MIME type we should support so
|
||||
// that we don't overreport MIME types we are able to play.
|
||||
caps = GetDefaultCapsFromMIMEType(type);
|
||||
}
|
||||
|
||||
if (!caps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = HaveElementsToProcessCaps(caps);
|
||||
gst_caps_unref(caps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstCaps* GStreamerFormatHelper::ConvertFormatsToCaps(const char* aMIMEType,
|
||||
const nsAString* aCodecs) {
|
||||
NS_ASSERTION(sLoadOK, "GStreamer library not linked");
|
||||
|
||||
unsigned int i;
|
||||
|
||||
GstCaps *caps = GetContainerCapsFromMIMEType(aMIMEType);
|
||||
if (!caps) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* container only */
|
||||
if (!aCodecs) {
|
||||
return caps;
|
||||
}
|
||||
|
||||
nsCharSeparatedTokenizer tokenizer(*aCodecs, ',');
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsSubstring& codec = tokenizer.nextToken();
|
||||
const char *capsString = nullptr;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(sCodecs); i++) {
|
||||
if (codec.EqualsASCII(ENTRY_FORMAT(sCodecs[i]))) {
|
||||
capsString = ENTRY_CAPS(sCodecs[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!capsString) {
|
||||
gst_caps_unref(caps);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GstCaps* tmp = gst_caps_from_string(capsString);
|
||||
/* appends and frees tmp */
|
||||
gst_caps_append(caps, tmp);
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
GStreamerFormatHelper::IsBlacklistEnabled()
|
||||
{
|
||||
static bool sBlacklistEnabled;
|
||||
static bool sBlacklistEnabledCached = false;
|
||||
|
||||
if (!sBlacklistEnabledCached) {
|
||||
Preferences::AddBoolVarCache(&sBlacklistEnabled,
|
||||
"media.gstreamer.enable-blacklist", true);
|
||||
sBlacklistEnabledCached = true;
|
||||
}
|
||||
|
||||
return sBlacklistEnabled;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
GStreamerFormatHelper::IsPluginFeatureBlacklisted(GstPluginFeature *aFeature)
|
||||
{
|
||||
if (!IsBlacklistEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const gchar *factoryName =
|
||||
gst_plugin_feature_get_name(aFeature);
|
||||
|
||||
for (unsigned int i = 0; i < G_N_ELEMENTS(sPluginBlacklist); i++) {
|
||||
if (!strcmp(factoryName, sPluginBlacklist[i])) {
|
||||
LOG("rejecting disabled plugin %s", factoryName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static gboolean FactoryFilter(GstPluginFeature *aFeature, gpointer)
|
||||
{
|
||||
if (!GST_IS_ELEMENT_FACTORY(aFeature)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const gchar *className =
|
||||
gst_element_factory_get_klass(GST_ELEMENT_FACTORY_CAST(aFeature));
|
||||
|
||||
// NB: We skip filtering parsers here, because adding them to
|
||||
// the list can give false decoder positives to canPlayType().
|
||||
if (!strstr(className, "Decoder") && !strstr(className, "Demux")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return
|
||||
gst_plugin_feature_get_rank(aFeature) >= GST_RANK_MARGINAL &&
|
||||
!GStreamerFormatHelper::IsPluginFeatureBlacklisted(aFeature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any |aFactory| caps intersect with |aCaps|
|
||||
*/
|
||||
static bool SupportsCaps(GstElementFactory *aFactory, GstCaps *aCaps)
|
||||
{
|
||||
for (const GList *iter = gst_element_factory_get_static_pad_templates(aFactory); iter; iter = iter->next) {
|
||||
GstStaticPadTemplate *templ = static_cast<GstStaticPadTemplate *>(iter->data);
|
||||
|
||||
if (templ->direction == GST_PAD_SRC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GstCaps *caps = gst_static_caps_get(&templ->static_caps);
|
||||
if (!caps) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool supported = gst_caps_can_intersect(caps, aCaps);
|
||||
|
||||
gst_caps_unref(caps);
|
||||
|
||||
if (supported) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GStreamerFormatHelper::HaveElementsToProcessCaps(GstCaps* aCaps) {
|
||||
NS_ASSERTION(sLoadOK, "GStreamer library not linked");
|
||||
|
||||
GList* factories = GetFactories();
|
||||
|
||||
/* here aCaps contains [containerCaps, [codecCaps1, [codecCaps2, ...]]] so process
|
||||
* caps structures individually as we want one element for _each_
|
||||
* structure */
|
||||
for (unsigned int i = 0; i < gst_caps_get_size(aCaps); i++) {
|
||||
GstStructure* s = gst_caps_get_structure(aCaps, i);
|
||||
GstCaps* caps = gst_caps_new_full(gst_structure_copy(s), nullptr);
|
||||
|
||||
bool found = false;
|
||||
for (GList *elem = factories; elem; elem = elem->next) {
|
||||
if (SupportsCaps(GST_ELEMENT_FACTORY_CAST(elem->data), caps)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gst_caps_unref(caps);
|
||||
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GStreamerFormatHelper::CanHandleContainerCaps(GstCaps* aCaps)
|
||||
{
|
||||
NS_ASSERTION(sLoadOK, "GStreamer library not linked");
|
||||
|
||||
return gst_caps_can_intersect(aCaps, mSupportedContainerCaps);
|
||||
}
|
||||
|
||||
bool GStreamerFormatHelper::CanHandleCodecCaps(GstCaps* aCaps)
|
||||
{
|
||||
NS_ASSERTION(sLoadOK, "GStreamer library not linked");
|
||||
|
||||
return gst_caps_can_intersect(aCaps, mSupportedCodecCaps);
|
||||
}
|
||||
|
||||
GList* GStreamerFormatHelper::GetFactories() {
|
||||
NS_ASSERTION(sLoadOK, "GStreamer library not linked");
|
||||
|
||||
#if GST_VERSION_MAJOR >= 1
|
||||
uint32_t cookie = gst_registry_get_feature_list_cookie(gst_registry_get());
|
||||
#else
|
||||
uint32_t cookie = gst_default_registry_get_feature_list_cookie();
|
||||
#endif
|
||||
if (cookie != mCookie) {
|
||||
g_list_free(mFactories);
|
||||
#if GST_VERSION_MAJOR >= 1
|
||||
mFactories =
|
||||
gst_registry_feature_filter(gst_registry_get(),
|
||||
(GstPluginFeatureFilter)FactoryFilter,
|
||||
false, nullptr);
|
||||
#else
|
||||
mFactories =
|
||||
gst_default_registry_feature_filter((GstPluginFeatureFilter)FactoryFilter,
|
||||
false, nullptr);
|
||||
#endif
|
||||
mCookie = cookie;
|
||||
}
|
||||
|
||||
return mFactories;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,81 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#if !defined(GStreamerFormatHelper_h_)
|
||||
#define GStreamerFormatHelper_h_
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <mozilla/Types.h>
|
||||
#include "nsXPCOMStrings.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class GStreamerFormatHelper {
|
||||
/* This class can be used to query the GStreamer registry for the required
|
||||
* demuxers/decoders from nsHTMLMediaElement::CanPlayType.
|
||||
* It implements looking at the GstRegistry to check if elements to
|
||||
* demux/decode the formats passed to CanPlayType() are actually installed.
|
||||
*/
|
||||
public:
|
||||
static GStreamerFormatHelper* Instance();
|
||||
~GStreamerFormatHelper();
|
||||
|
||||
bool CanHandleMediaType(const nsACString& aMIMEType,
|
||||
const nsAString* aCodecs);
|
||||
|
||||
bool CanHandleContainerCaps(GstCaps* aCaps);
|
||||
bool CanHandleCodecCaps(GstCaps* aCaps);
|
||||
|
||||
static bool IsBlacklistEnabled();
|
||||
static bool IsPluginFeatureBlacklisted(GstPluginFeature *aFeature);
|
||||
|
||||
static GstCaps* ConvertFormatsToCaps(const char* aMIMEType,
|
||||
const nsAString* aCodecs);
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
GStreamerFormatHelper();
|
||||
char* const *CodecListFromCaps(GstCaps* aCaps);
|
||||
bool HaveElementsToProcessCaps(GstCaps* aCaps);
|
||||
GList* GetFactories();
|
||||
|
||||
static GStreamerFormatHelper* gInstance;
|
||||
|
||||
/* table to convert from container MIME types to GStreamer caps */
|
||||
static char const *const mContainers[6][2];
|
||||
|
||||
/* table to convert from codec MIME types to GStreamer caps */
|
||||
static char const *const mCodecs[9][2];
|
||||
|
||||
/*
|
||||
* True iff we were able to find the proper GStreamer libs and the functions
|
||||
* we need.
|
||||
*/
|
||||
static bool sLoadOK;
|
||||
|
||||
/* whitelist of supported container/codec gst caps */
|
||||
GstCaps* mSupportedContainerCaps;
|
||||
GstCaps* mSupportedCodecCaps;
|
||||
|
||||
/* list of GStreamer element factories
|
||||
* Element factories are the basic types retrieved from the GStreamer
|
||||
* registry, they describe all plugins and elements that GStreamer can
|
||||
* create.
|
||||
* This means that element factories are useful for automated element
|
||||
* instancing, such as what autopluggers do,
|
||||
* and for creating lists of available elements. */
|
||||
GList* mFactories;
|
||||
|
||||
/* Storage for the default registrys feature list cookie.
|
||||
* It changes every time a feature is added to or removed from the
|
||||
* GStreamer registry. */
|
||||
uint32_t mCookie;
|
||||
};
|
||||
|
||||
} //namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
/*
|
||||
* List of symbol names we need to dlsym from the gstreamer library.
|
||||
*/
|
||||
GST_FUNC(LIBGSTAPP, gst_app_sink_get_type)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_sink_set_callbacks)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_end_of_stream)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_get_size)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_get_type)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_push_buffer)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_set_callbacks)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_set_caps)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_set_size)
|
||||
GST_FUNC(LIBGSTAPP, gst_app_src_set_stream_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_bin_get_by_name)
|
||||
GST_FUNC(LIBGSTREAMER, gst_bin_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_bin_iterate_recurse)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_new)
|
||||
GST_FUNC(LIBGSTREAMER, gst_bus_set_sync_handler)
|
||||
GST_FUNC(LIBGSTREAMER, gst_bus_timed_pop_filtered)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_append)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_can_intersect)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_from_string)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_get_size)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_get_structure)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_new_any)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_new_empty)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_new_full)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_new_simple)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_set_simple)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_factory_get_static_pad_templates)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_factory_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_factory_make)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_get_factory)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_get_static_pad)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_query_convert)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_query_duration)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_seek_simple)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_set_state)
|
||||
GST_FUNC(LIBGSTREAMER, gst_flow_get_name)
|
||||
GST_FUNC(LIBGSTREAMER, gst_init)
|
||||
GST_FUNC(LIBGSTREAMER, gst_init_check)
|
||||
GST_FUNC(LIBGSTREAMER, gst_iterator_free)
|
||||
GST_FUNC(LIBGSTREAMER, gst_iterator_next)
|
||||
GST_FUNC(LIBGSTREAMER, gst_message_parse_error)
|
||||
GST_FUNC(LIBGSTREAMER, gst_message_type_get_name)
|
||||
GST_FUNC(LIBGSTREAMER, gst_mini_object_ref)
|
||||
GST_FUNC(LIBGSTREAMER, gst_mini_object_unref)
|
||||
GST_FUNC(LIBGSTREAMER, gst_object_get_name)
|
||||
GST_FUNC(LIBGSTREAMER, gst_object_get_parent)
|
||||
GST_FUNC(LIBGSTREAMER, gst_object_unref)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_get_element_private)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_set_element_private)
|
||||
GST_FUNC(LIBGSTREAMER, gst_parse_bin_from_description)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pipeline_get_bus)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pipeline_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_plugin_feature_get_rank)
|
||||
GST_FUNC(LIBGSTREAMER, gst_plugin_feature_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_registry_feature_filter)
|
||||
GST_FUNC(LIBGSTREAMER, gst_registry_get_feature_list_cookie)
|
||||
GST_FUNC(LIBGSTREAMER, gst_segment_init)
|
||||
GST_FUNC(LIBGSTREAMER, gst_segment_to_stream_time)
|
||||
GST_FUNC(LIBGSTREAMER, gst_static_caps_get)
|
||||
GST_FUNC(LIBGSTREAMER, gst_structure_copy)
|
||||
GST_FUNC(LIBGSTREAMER, gst_structure_get_fraction)
|
||||
GST_FUNC(LIBGSTREAMER, gst_structure_get_int)
|
||||
GST_FUNC(LIBGSTREAMER, gst_structure_get_value)
|
||||
GST_FUNC(LIBGSTREAMER, gst_structure_new)
|
||||
GST_FUNC(LIBGSTREAMER, gst_util_uint64_scale)
|
||||
|
||||
#if GST_VERSION_MAJOR == 0
|
||||
GST_FUNC(LIBGSTAPP, gst_app_sink_pull_buffer)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_copy_metadata)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_new_and_alloc)
|
||||
GST_FUNC(LIBGSTREAMER, gst_caps_unref)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_factory_get_klass)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_get_pad)
|
||||
GST_FUNC(LIBGSTREAMER, gst_event_parse_new_segment)
|
||||
GST_FUNC(LIBGSTREAMER, gst_mini_object_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_mini_object_new)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_add_event_probe)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_alloc_buffer)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_get_negotiated_caps)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_set_bufferalloc_function)
|
||||
GST_FUNC(LIBGSTREAMER, gst_plugin_feature_get_name)
|
||||
GST_FUNC(LIBGSTREAMER, gst_registry_get_default)
|
||||
GST_FUNC(LIBGSTREAMER, gst_segment_set_newsegment)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_format_get_component_height)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_format_get_component_offset)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_format_get_component_width)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_format_get_pixel_stride)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_format_get_row_stride)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_format_parse_caps)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_parse_caps_pixel_aspect_ratio)
|
||||
#else
|
||||
|
||||
GST_FUNC(LIBGSTAPP, gst_app_sink_pull_sample)
|
||||
GST_FUNC(LIBGSTREAMER, _gst_caps_any)
|
||||
GST_FUNC(LIBGSTREAMER, gst_allocator_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_copy_into)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_extract)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_get_meta)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_get_size)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_map)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_new_allocate)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_n_memory)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_peek_memory)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_acquire_buffer)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_config_set_allocator)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_config_set_params)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_get_config)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_is_active)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_set_active)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_pool_set_config)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_set_size)
|
||||
GST_FUNC(LIBGSTREAMER, gst_buffer_unmap)
|
||||
GST_FUNC(LIBGSTREAMER, gst_element_factory_get_metadata)
|
||||
GST_FUNC(LIBGSTREAMER, gst_event_parse_segment)
|
||||
GST_FUNC(LIBGSTREAMER, gst_event_type_get_name)
|
||||
GST_FUNC(LIBGSTREAMER, gst_memory_init)
|
||||
GST_FUNC(LIBGSTREAMER, gst_memory_map)
|
||||
GST_FUNC(LIBGSTREAMER, gst_memory_unmap)
|
||||
GST_FUNC(LIBGSTREAMER, gst_object_get_type)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_add_probe)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_get_current_caps)
|
||||
GST_FUNC(LIBGSTREAMER, gst_pad_probe_info_get_query)
|
||||
GST_FUNC(LIBGSTREAMER, gst_query_add_allocation_meta)
|
||||
GST_FUNC(LIBGSTREAMER, gst_query_add_allocation_param)
|
||||
GST_FUNC(LIBGSTREAMER, gst_query_add_allocation_pool)
|
||||
GST_FUNC(LIBGSTREAMER, gst_query_parse_allocation)
|
||||
GST_FUNC(LIBGSTREAMER, gst_registry_get)
|
||||
GST_FUNC(LIBGSTREAMER, gst_sample_get_buffer)
|
||||
GST_FUNC(LIBGSTREAMER, gst_segment_copy_into)
|
||||
GST_FUNC(LIBGSTREAMER, gst_structure_free)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_buffer_pool_config_get_video_alignment)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_buffer_pool_has_option)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_buffer_pool_get_type)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_frame_map)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_frame_unmap)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_info_align)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_info_from_caps)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_info_init)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_meta_api_get_type)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_meta_map)
|
||||
GST_FUNC(LIBGSTVIDEO, gst_video_meta_unmap)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions that have been defined in the header file. We replace them so that
|
||||
* they don't try to use the global gstreamer functions.
|
||||
*/
|
||||
#ifdef REPLACE_FUNC
|
||||
REPLACE_FUNC(gst_buffer_ref);
|
||||
REPLACE_FUNC(gst_buffer_unref);
|
||||
REPLACE_FUNC(gst_message_unref);
|
||||
|
||||
#if GST_VERSION_MAJOR == 1
|
||||
REPLACE_FUNC(gst_caps_unref);
|
||||
REPLACE_FUNC(gst_sample_unref);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // !defined(__APPLE__)
|
||||
@@ -0,0 +1,145 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nsDebug.h"
|
||||
|
||||
#include "GStreamerLoader.h"
|
||||
|
||||
#define LIBGSTREAMER 0
|
||||
#define LIBGSTAPP 1
|
||||
#define LIBGSTVIDEO 2
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define LIB_GST_SUFFIX ".so"
|
||||
#else
|
||||
#define LIB_GST_SUFFIX ".so.0"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* Declare our function pointers using the types from the global gstreamer
|
||||
* definitions.
|
||||
*/
|
||||
#define GST_FUNC(_, func) typeof(::func)* func;
|
||||
#define REPLACE_FUNC(func) GST_FUNC(-1, func)
|
||||
#include "GStreamerFunctionList.h"
|
||||
#undef GST_FUNC
|
||||
#undef REPLACE_FUNC
|
||||
|
||||
/*
|
||||
* Redefinitions of functions that have been defined in the gstreamer headers to
|
||||
* stop them calling the gstreamer functions in global scope.
|
||||
*/
|
||||
GstBuffer * gst_buffer_ref_impl(GstBuffer *buf);
|
||||
void gst_buffer_unref_impl(GstBuffer *buf);
|
||||
void gst_message_unref_impl(GstMessage *msg);
|
||||
void gst_caps_unref_impl(GstCaps *caps);
|
||||
|
||||
#if GST_VERSION_MAJOR == 1
|
||||
void gst_sample_unref_impl(GstSample *sample);
|
||||
#endif
|
||||
|
||||
bool
|
||||
load_gstreamer()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return true;
|
||||
#endif
|
||||
static bool loaded = false;
|
||||
|
||||
if (loaded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void *gstreamerLib = nullptr;
|
||||
guint major = 0;
|
||||
guint minor = 0;
|
||||
guint micro, nano;
|
||||
|
||||
typedef typeof(::gst_version) VersionFuncType;
|
||||
if (VersionFuncType *versionFunc = (VersionFuncType*)dlsym(RTLD_DEFAULT, "gst_version")) {
|
||||
versionFunc(&major, &minor, µ, &nano);
|
||||
}
|
||||
|
||||
if (major == GST_VERSION_MAJOR && minor == GST_VERSION_MINOR) {
|
||||
gstreamerLib = RTLD_DEFAULT;
|
||||
} else {
|
||||
gstreamerLib = dlopen("libgstreamer-" GST_API_VERSION LIB_GST_SUFFIX, RTLD_NOW | RTLD_LOCAL);
|
||||
}
|
||||
|
||||
void *handles[3] = {
|
||||
gstreamerLib,
|
||||
dlopen("libgstapp-" GST_API_VERSION LIB_GST_SUFFIX, RTLD_NOW | RTLD_LOCAL),
|
||||
dlopen("libgstvideo-" GST_API_VERSION LIB_GST_SUFFIX, RTLD_NOW | RTLD_LOCAL)
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(handles) / sizeof(handles[0]); i++) {
|
||||
if (!handles[i]) {
|
||||
NS_WARNING("Couldn't link gstreamer libraries");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
#define GST_FUNC(lib, symbol) \
|
||||
if (!(symbol = (typeof(symbol))dlsym(handles[lib], #symbol))) { \
|
||||
NS_WARNING("Couldn't link symbol " #symbol); \
|
||||
goto fail; \
|
||||
}
|
||||
#define REPLACE_FUNC(symbol) symbol = symbol##_impl;
|
||||
#include "GStreamerFunctionList.h"
|
||||
#undef GST_FUNC
|
||||
#undef REPLACE_FUNC
|
||||
|
||||
loaded = true;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
|
||||
for (size_t i = 0; i < sizeof(handles) / sizeof(handles[0]); i++) {
|
||||
if (handles[i] && handles[i] != RTLD_DEFAULT) {
|
||||
dlclose(handles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GstBuffer *
|
||||
gst_buffer_ref_impl(GstBuffer *buf)
|
||||
{
|
||||
return (GstBuffer *)gst_mini_object_ref(GST_MINI_OBJECT_CAST(buf));
|
||||
}
|
||||
|
||||
void
|
||||
gst_buffer_unref_impl(GstBuffer *buf)
|
||||
{
|
||||
gst_mini_object_unref(GST_MINI_OBJECT_CAST(buf));
|
||||
}
|
||||
|
||||
void
|
||||
gst_message_unref_impl(GstMessage *msg)
|
||||
{
|
||||
gst_mini_object_unref(GST_MINI_OBJECT_CAST(msg));
|
||||
}
|
||||
|
||||
#if GST_VERSION_MAJOR == 1
|
||||
void
|
||||
gst_sample_unref_impl(GstSample *sample)
|
||||
{
|
||||
gst_mini_object_unref(GST_MINI_OBJECT_CAST(sample));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
gst_caps_unref_impl(GstCaps *caps)
|
||||
{
|
||||
gst_mini_object_unref(GST_MINI_OBJECT_CAST(caps));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GStreamerLoader_h_
|
||||
#define GStreamerLoader_h_
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/gstbuffer.h>
|
||||
#include <gst/gstelementfactory.h>
|
||||
#include <gst/gststructure.h>
|
||||
#include <gst/app/gstappsrc.h>
|
||||
#include <gst/app/gstappsink.h>
|
||||
// This include trips -Wreserved-user-defined-literal on clang. Ignoring it
|
||||
// trips -Wpragmas on GCC (unknown warning), but ignoring that trips
|
||||
// -Wunknown-pragmas on clang (unknown pragma).
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wreserved-user-defined-literal"
|
||||
#include <gst/video/video.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#if GST_VERSION_MAJOR == 1
|
||||
#include <gst/video/gstvideometa.h>
|
||||
#include <gst/video/gstvideopool.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* dlopens the required libraries and dlsyms the functions we need.
|
||||
* Returns true on success, false otherwise.
|
||||
*/
|
||||
bool load_gstreamer();
|
||||
|
||||
/*
|
||||
* Declare our extern function pointers using the types from the global
|
||||
* gstreamer definitions.
|
||||
*/
|
||||
#define GST_FUNC(_, func) extern typeof(::func)* func;
|
||||
#define REPLACE_FUNC(func) GST_FUNC(-1, func)
|
||||
#include "GStreamerFunctionList.h"
|
||||
#undef GST_FUNC
|
||||
#undef REPLACE_FUNC
|
||||
|
||||
}
|
||||
|
||||
#undef GST_CAPS_ANY
|
||||
#define GST_CAPS_ANY (*_gst_caps_any)
|
||||
|
||||
#endif // GStreamerLoader_h_
|
||||
@@ -0,0 +1,123 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 <string.h>
|
||||
#include "GStreamerReader.h"
|
||||
#include "GStreamerMozVideoBuffer.h"
|
||||
#include "ImageContainer.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static GstMozVideoBuffer *gst_moz_video_buffer_copy(GstMozVideoBuffer* self);
|
||||
static void gst_moz_video_buffer_finalize(GstMozVideoBuffer* self);
|
||||
|
||||
// working around GTK+ bug https://bugzilla.gnome.org/show_bug.cgi?id=723899
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
G_DEFINE_TYPE(GstMozVideoBuffer, gst_moz_video_buffer, GST_TYPE_BUFFER);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
static void
|
||||
gst_moz_video_buffer_class_init(GstMozVideoBufferClass* klass)
|
||||
{
|
||||
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER_CLASS(klass));
|
||||
|
||||
GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS(klass);
|
||||
|
||||
mo_class->copy =(GstMiniObjectCopyFunction)gst_moz_video_buffer_copy;
|
||||
mo_class->finalize =(GstMiniObjectFinalizeFunction)gst_moz_video_buffer_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_moz_video_buffer_init(GstMozVideoBuffer* self)
|
||||
{
|
||||
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
|
||||
}
|
||||
|
||||
static void
|
||||
gst_moz_video_buffer_finalize(GstMozVideoBuffer* self)
|
||||
{
|
||||
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
|
||||
|
||||
if(self->data)
|
||||
g_boxed_free(GST_TYPE_MOZ_VIDEO_BUFFER_DATA, self->data);
|
||||
|
||||
GST_MINI_OBJECT_CLASS(gst_moz_video_buffer_parent_class)->finalize(GST_MINI_OBJECT(self));
|
||||
}
|
||||
|
||||
static GstMozVideoBuffer*
|
||||
gst_moz_video_buffer_copy(GstMozVideoBuffer* self)
|
||||
{
|
||||
GstMozVideoBuffer* copy;
|
||||
|
||||
g_return_val_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self), nullptr);
|
||||
|
||||
copy = gst_moz_video_buffer_new();
|
||||
|
||||
/* we simply copy everything from our parent */
|
||||
GST_BUFFER_DATA(GST_BUFFER_CAST(copy)) =
|
||||
(guint8*)g_memdup(GST_BUFFER_DATA(GST_BUFFER_CAST(self)), GST_BUFFER_SIZE(GST_BUFFER_CAST(self)));
|
||||
|
||||
/* make sure it gets freed(even if the parent is subclassed, we return a
|
||||
normal buffer) */
|
||||
GST_BUFFER_MALLOCDATA(GST_BUFFER_CAST(copy)) = GST_BUFFER_DATA(GST_BUFFER_CAST(copy));
|
||||
GST_BUFFER_SIZE(GST_BUFFER_CAST(copy)) = GST_BUFFER_SIZE(GST_BUFFER_CAST(self));
|
||||
|
||||
/* copy metadata */
|
||||
gst_buffer_copy_metadata(GST_BUFFER_CAST(copy),
|
||||
GST_BUFFER_CAST(self),
|
||||
(GstBufferCopyFlags)GST_BUFFER_COPY_ALL);
|
||||
/* copy videobuffer */
|
||||
if(self->data)
|
||||
copy->data = (GstMozVideoBufferData*)g_boxed_copy(GST_TYPE_MOZ_VIDEO_BUFFER_DATA, self->data);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
GstMozVideoBuffer*
|
||||
gst_moz_video_buffer_new(void)
|
||||
{
|
||||
GstMozVideoBuffer *self;
|
||||
|
||||
self =(GstMozVideoBuffer*)gst_mini_object_new(GST_TYPE_MOZ_VIDEO_BUFFER);
|
||||
self->data = nullptr;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gst_moz_video_buffer_set_data(GstMozVideoBuffer* self, GstMozVideoBufferData* data)
|
||||
{
|
||||
g_return_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self));
|
||||
|
||||
self->data = data;
|
||||
}
|
||||
|
||||
GstMozVideoBufferData*
|
||||
gst_moz_video_buffer_get_data(const GstMozVideoBuffer* self)
|
||||
{
|
||||
g_return_val_if_fail(GST_IS_MOZ_VIDEO_BUFFER(self), nullptr);
|
||||
|
||||
return self->data;
|
||||
}
|
||||
|
||||
GType
|
||||
gst_moz_video_buffer_data_get_type(void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if(g_once_init_enter(&g_define_type_id__volatile)) {
|
||||
GType g_define_type_id =
|
||||
g_boxed_type_register_static(g_intern_static_string("GstMozVideoBufferData"),
|
||||
(GBoxedCopyFunc)GstMozVideoBufferData::Copy,
|
||||
(GBoxedFreeFunc)GstMozVideoBufferData::Free);
|
||||
g_once_init_leave(&g_define_type_id__volatile, g_define_type_id);
|
||||
}
|
||||
|
||||
return g_define_type_id__volatile;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __GST_MOZ_VIDEO_BUFFER_H__
|
||||
#define __GST_MOZ_VIDEO_BUFFER_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include "GStreamerLoader.h"
|
||||
#include "MediaDecoderReader.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#define GST_TYPE_MOZ_VIDEO_BUFFER_DATA (gst_moz_video_buffer_data_get_type())
|
||||
#define GST_IS_MOZ_VIDEO_BUFFER_DATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_VIDEO_BUFFER_DATA))
|
||||
|
||||
#define GST_TYPE_MOZ_VIDEO_BUFFER (gst_moz_video_buffer_get_type())
|
||||
#define GST_IS_MOZ_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MOZ_VIDEO_BUFFER))
|
||||
#define GST_IS_MOZ_VIDEO_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MOZ_VIDEO_BUFFER))
|
||||
#define GST_MOZ_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MOZ_VIDEO_BUFFER, GstMozVideoBuffer))
|
||||
|
||||
typedef struct _GstMozVideoBuffer GstMozVideoBuffer;
|
||||
typedef struct _GstMozVideoBufferClass GstMozVideoBufferClass;
|
||||
|
||||
class GstMozVideoBufferData;
|
||||
|
||||
struct _GstMozVideoBuffer {
|
||||
GstBuffer buffer;
|
||||
GstMozVideoBufferData* data;
|
||||
};
|
||||
|
||||
struct _GstMozVideoBufferClass {
|
||||
GstBufferClass buffer_class;
|
||||
};
|
||||
|
||||
GType gst_moz_video_buffer_get_type(void);
|
||||
GstMozVideoBuffer* gst_moz_video_buffer_new(void);
|
||||
void gst_moz_video_buffer_set_data(GstMozVideoBuffer* buf, GstMozVideoBufferData* data);
|
||||
GstMozVideoBufferData* gst_moz_video_buffer_get_data(const GstMozVideoBuffer* buf);
|
||||
|
||||
class GstMozVideoBufferData {
|
||||
public:
|
||||
explicit GstMozVideoBufferData(layers::PlanarYCbCrImage* aImage) : mImage(aImage) {}
|
||||
|
||||
static void* Copy(void* aData) {
|
||||
return new GstMozVideoBufferData(reinterpret_cast<GstMozVideoBufferData*>(aData)->mImage);
|
||||
}
|
||||
|
||||
static void Free(void* aData) {
|
||||
delete reinterpret_cast<GstMozVideoBufferData*>(aData);
|
||||
}
|
||||
|
||||
nsRefPtr<layers::PlanarYCbCrImage> mImage;
|
||||
};
|
||||
|
||||
GType gst_moz_video_buffer_data_get_type (void);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* __GST_MOZ_VIDEO_BUFFER_H__ */
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
#include "nsError.h"
|
||||
#include "MediaDecoderStateMachine.h"
|
||||
#include "AbstractMediaDecoder.h"
|
||||
#include "MediaResource.h"
|
||||
#include "GStreamerReader.h"
|
||||
#include "GStreamerMozVideoBuffer.h"
|
||||
#include "GStreamerFormatHelper.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using mozilla::layers::PlanarYCbCrImage;
|
||||
using mozilla::layers::ImageContainer;
|
||||
|
||||
GstFlowReturn GStreamerReader::AllocateVideoBufferCb(GstPad* aPad,
|
||||
guint64 aOffset,
|
||||
guint aSize,
|
||||
GstCaps* aCaps,
|
||||
GstBuffer** aBuf)
|
||||
{
|
||||
GStreamerReader* reader = reinterpret_cast<GStreamerReader*>(gst_pad_get_element_private(aPad));
|
||||
return reader->AllocateVideoBuffer(aPad, aOffset, aSize, aCaps, aBuf);
|
||||
}
|
||||
|
||||
GstFlowReturn GStreamerReader::AllocateVideoBuffer(GstPad* aPad,
|
||||
guint64 aOffset,
|
||||
guint aSize,
|
||||
GstCaps* aCaps,
|
||||
GstBuffer** aBuf)
|
||||
{
|
||||
nsRefPtr<PlanarYCbCrImage> image;
|
||||
return AllocateVideoBufferFull(aPad, aOffset, aSize, aCaps, aBuf, image);
|
||||
}
|
||||
|
||||
GstFlowReturn GStreamerReader::AllocateVideoBufferFull(GstPad* aPad,
|
||||
guint64 aOffset,
|
||||
guint aSize,
|
||||
GstCaps* aCaps,
|
||||
GstBuffer** aBuf,
|
||||
nsRefPtr<PlanarYCbCrImage>& aImage)
|
||||
{
|
||||
/* allocate an image using the container */
|
||||
ImageContainer* container = mDecoder->GetImageContainer();
|
||||
if (container == nullptr) {
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
nsRefPtr<PlanarYCbCrImage> image =
|
||||
container->CreateImage(ImageFormat::PLANAR_YCBCR).downcast<PlanarYCbCrImage>();
|
||||
|
||||
/* prepare a GstBuffer pointing to the underlying PlanarYCbCrImage buffer */
|
||||
GstBuffer* buf = GST_BUFFER(gst_moz_video_buffer_new());
|
||||
GST_BUFFER_SIZE(buf) = aSize;
|
||||
/* allocate the actual YUV buffer */
|
||||
GST_BUFFER_DATA(buf) = image->AllocateAndGetNewBuffer(aSize);
|
||||
|
||||
aImage = image;
|
||||
|
||||
/* create a GstMozVideoBufferData to hold the image */
|
||||
GstMozVideoBufferData* bufferdata = new GstMozVideoBufferData(image);
|
||||
|
||||
/* Attach bufferdata to our GstMozVideoBuffer, it will take care to free it */
|
||||
gst_moz_video_buffer_set_data(GST_MOZ_VIDEO_BUFFER(buf), bufferdata);
|
||||
|
||||
*aBuf = buf;
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
gboolean GStreamerReader::EventProbe(GstPad* aPad, GstEvent* aEvent)
|
||||
{
|
||||
GstElement* parent = GST_ELEMENT(gst_pad_get_parent(aPad));
|
||||
switch(GST_EVENT_TYPE(aEvent)) {
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
{
|
||||
gboolean update;
|
||||
gdouble rate;
|
||||
GstFormat format;
|
||||
gint64 start, stop, position;
|
||||
GstSegment* segment;
|
||||
|
||||
/* Store the segments so we can convert timestamps to stream time, which
|
||||
* is what the upper layers sync on.
|
||||
*/
|
||||
ReentrantMonitorAutoEnter mon(mGstThreadsMonitor);
|
||||
gst_event_parse_new_segment(aEvent, &update, &rate, &format,
|
||||
&start, &stop, &position);
|
||||
if (parent == GST_ELEMENT(mVideoAppSink))
|
||||
segment = &mVideoSegment;
|
||||
else
|
||||
segment = &mAudioSegment;
|
||||
gst_segment_set_newsegment(segment, update, rate, format,
|
||||
start, stop, position);
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
/* Reset on seeks */
|
||||
ResetDecode();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gst_object_unref(parent);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean GStreamerReader::EventProbeCb(GstPad* aPad,
|
||||
GstEvent* aEvent,
|
||||
gpointer aUserData)
|
||||
{
|
||||
GStreamerReader* reader = reinterpret_cast<GStreamerReader*>(aUserData);
|
||||
return reader->EventProbe(aPad, aEvent);
|
||||
}
|
||||
|
||||
nsRefPtr<PlanarYCbCrImage> GStreamerReader::GetImageFromBuffer(GstBuffer* aBuffer)
|
||||
{
|
||||
if (!GST_IS_MOZ_VIDEO_BUFFER (aBuffer))
|
||||
return nullptr;
|
||||
|
||||
nsRefPtr<PlanarYCbCrImage> image;
|
||||
GstMozVideoBufferData* bufferdata = reinterpret_cast<GstMozVideoBufferData*>(gst_moz_video_buffer_get_data(GST_MOZ_VIDEO_BUFFER(aBuffer)));
|
||||
image = bufferdata->mImage;
|
||||
|
||||
PlanarYCbCrImage::Data data;
|
||||
data.mPicX = data.mPicY = 0;
|
||||
data.mPicSize = gfx::IntSize(mPicture.width, mPicture.height);
|
||||
data.mStereoMode = StereoMode::MONO;
|
||||
|
||||
data.mYChannel = GST_BUFFER_DATA(aBuffer);
|
||||
data.mYStride = gst_video_format_get_row_stride(mFormat, 0, mPicture.width);
|
||||
data.mYSize = gfx::IntSize(gst_video_format_get_component_width(mFormat, 0, mPicture.width),
|
||||
gst_video_format_get_component_height(mFormat, 0, mPicture.height));
|
||||
data.mYSkip = 0;
|
||||
data.mCbCrStride = gst_video_format_get_row_stride(mFormat, 1, mPicture.width);
|
||||
data.mCbCrSize = gfx::IntSize(gst_video_format_get_component_width(mFormat, 1, mPicture.width),
|
||||
gst_video_format_get_component_height(mFormat, 1, mPicture.height));
|
||||
data.mCbChannel = data.mYChannel + gst_video_format_get_component_offset(mFormat, 1,
|
||||
mPicture.width, mPicture.height);
|
||||
data.mCrChannel = data.mYChannel + gst_video_format_get_component_offset(mFormat, 2,
|
||||
mPicture.width, mPicture.height);
|
||||
data.mCbSkip = 0;
|
||||
data.mCrSkip = 0;
|
||||
|
||||
image->SetDataNoCopy(data);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void GStreamerReader::CopyIntoImageBuffer(GstBuffer* aBuffer,
|
||||
GstBuffer** aOutBuffer,
|
||||
nsRefPtr<PlanarYCbCrImage> &aImage)
|
||||
{
|
||||
AllocateVideoBufferFull(nullptr, GST_BUFFER_OFFSET(aBuffer),
|
||||
GST_BUFFER_SIZE(aBuffer), nullptr, aOutBuffer, aImage);
|
||||
|
||||
gst_buffer_copy_metadata(*aOutBuffer, aBuffer, (GstBufferCopyFlags)GST_BUFFER_COPY_ALL);
|
||||
memcpy(GST_BUFFER_DATA(*aOutBuffer), GST_BUFFER_DATA(aBuffer), GST_BUFFER_SIZE(*aOutBuffer));
|
||||
|
||||
aImage = GetImageFromBuffer(*aOutBuffer);
|
||||
}
|
||||
|
||||
GstCaps* GStreamerReader::BuildAudioSinkCaps()
|
||||
{
|
||||
GstCaps* caps;
|
||||
|
||||
#if MOZ_LITTLE_ENDIAN
|
||||
int endianness = 1234;
|
||||
#else
|
||||
int endianness = 4321;
|
||||
#endif
|
||||
|
||||
gint width;
|
||||
|
||||
#ifdef MOZ_SAMPLE_TYPE_FLOAT32
|
||||
caps = gst_caps_from_string("audio/x-raw-float, channels={1,2}");
|
||||
width = 32;
|
||||
#else /* !MOZ_SAMPLE_TYPE_FLOAT32 */
|
||||
caps = gst_caps_from_string("audio/x-raw-int, channels={1,2}");
|
||||
width = 16;
|
||||
#endif
|
||||
|
||||
gst_caps_set_simple(caps,
|
||||
"width", G_TYPE_INT, width,
|
||||
"endianness", G_TYPE_INT, endianness,
|
||||
nullptr);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
void GStreamerReader::InstallPadCallbacks()
|
||||
{
|
||||
GstPad* sinkpad = gst_element_get_static_pad(GST_ELEMENT(mVideoAppSink), "sink");
|
||||
gst_pad_add_event_probe(sinkpad,
|
||||
G_CALLBACK(&GStreamerReader::EventProbeCb), this);
|
||||
|
||||
gst_pad_set_bufferalloc_function(sinkpad, GStreamerReader::AllocateVideoBufferCb);
|
||||
gst_pad_set_element_private(sinkpad, this);
|
||||
gst_object_unref(sinkpad);
|
||||
|
||||
sinkpad = gst_element_get_static_pad(GST_ELEMENT(mAudioAppSink), "sink");
|
||||
gst_pad_add_event_probe(sinkpad,
|
||||
G_CALLBACK(&GStreamerReader::EventProbeCb), this);
|
||||
gst_object_unref(sinkpad);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,273 @@
|
||||
/* 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/. */
|
||||
|
||||
#if !defined(GStreamerReader_h_)
|
||||
#define GStreamerReader_h_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsrc.h>
|
||||
#include <gst/app/gstappsink.h>
|
||||
// This include trips -Wreserved-user-defined-literal on clang. Ignoring it
|
||||
// trips -Wpragmas on GCC (unknown warning), but ignoring that trips
|
||||
// -Wunknown-pragmas on clang (unknown pragma).
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wreserved-user-defined-literal"
|
||||
#include <gst/video/video.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "MediaResource.h"
|
||||
#include "MP3FrameParser.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
struct GstURIDecodeBin;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AbstractMediaDecoder;
|
||||
|
||||
class GStreamerReader : public MediaDecoderReader
|
||||
{
|
||||
typedef gfx::IntRect IntRect;
|
||||
|
||||
public:
|
||||
explicit GStreamerReader(AbstractMediaDecoder* aDecoder);
|
||||
virtual ~GStreamerReader();
|
||||
|
||||
virtual nsresult Init(MediaDecoderReader* aCloneDonor) override;
|
||||
virtual nsRefPtr<ShutdownPromise> Shutdown() override;
|
||||
virtual nsresult ResetDecode() override;
|
||||
virtual bool DecodeAudioData() override;
|
||||
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
int64_t aTimeThreshold) override;
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags) override;
|
||||
virtual nsRefPtr<SeekPromise>
|
||||
Seek(int64_t aTime, int64_t aEndTime) override;
|
||||
virtual media::TimeIntervals GetBuffered() override;
|
||||
|
||||
protected:
|
||||
virtual void NotifyDataArrivedInternal(uint32_t aLength,
|
||||
int64_t aOffset) override;
|
||||
public:
|
||||
|
||||
virtual bool HasAudio() override {
|
||||
return mInfo.HasAudio();
|
||||
}
|
||||
|
||||
virtual bool HasVideo() override {
|
||||
return mInfo.HasVideo();
|
||||
}
|
||||
|
||||
layers::ImageContainer* GetImageContainer() { return mDecoder->GetImageContainer(); }
|
||||
|
||||
virtual bool IsMediaSeekable() override;
|
||||
|
||||
private:
|
||||
|
||||
void ReadAndPushData(guint aLength);
|
||||
nsRefPtr<layers::PlanarYCbCrImage> GetImageFromBuffer(GstBuffer* aBuffer);
|
||||
void CopyIntoImageBuffer(GstBuffer *aBuffer, GstBuffer** aOutBuffer, nsRefPtr<layers::PlanarYCbCrImage> &image);
|
||||
GstCaps* BuildAudioSinkCaps();
|
||||
void InstallPadCallbacks();
|
||||
|
||||
#if GST_VERSION_MAJOR >= 1
|
||||
void ImageDataFromVideoFrame(GstVideoFrame *aFrame, layers::PlanarYCbCrImage::Data *aData);
|
||||
#endif
|
||||
|
||||
/* Called once the pipeline is setup to check that the stream only contains
|
||||
* supported formats
|
||||
*/
|
||||
nsresult CheckSupportedFormats();
|
||||
|
||||
/* Gst callbacks */
|
||||
|
||||
static GstBusSyncReply ErrorCb(GstBus *aBus, GstMessage *aMessage, gpointer aUserData);
|
||||
GstBusSyncReply Error(GstBus *aBus, GstMessage *aMessage);
|
||||
|
||||
/*
|
||||
* We attach this callback to playbin so that when uridecodebin is
|
||||
* constructed, we can then list for its autoplug-sort signal to blacklist
|
||||
* the elements it can construct.
|
||||
*/
|
||||
static void ElementAddedCb(GstBin *aPlayBin,
|
||||
GstElement *aElement,
|
||||
gpointer aUserData);
|
||||
|
||||
/*
|
||||
* Called on the autoplug-sort signal emitted by uridecodebin for filtering
|
||||
* the elements it uses.
|
||||
*/
|
||||
static GValueArray *ElementFilterCb(GstURIDecodeBin *aBin,
|
||||
GstPad *aPad,
|
||||
GstCaps *aCaps,
|
||||
GValueArray *aFactories,
|
||||
gpointer aUserData);
|
||||
|
||||
GValueArray *ElementFilter(GstURIDecodeBin *aBin,
|
||||
GstPad *aPad,
|
||||
GstCaps *aCaps,
|
||||
GValueArray *aFactories);
|
||||
|
||||
/* Called on the source-setup signal emitted by playbin. Used to
|
||||
* configure appsrc .
|
||||
*/
|
||||
static void PlayBinSourceSetupCb(GstElement* aPlayBin,
|
||||
GParamSpec* pspec,
|
||||
gpointer aUserData);
|
||||
void PlayBinSourceSetup(GstAppSrc* aSource);
|
||||
|
||||
/* Called from appsrc when we need to read more data from the resource */
|
||||
static void NeedDataCb(GstAppSrc* aSrc, guint aLength, gpointer aUserData);
|
||||
void NeedData(GstAppSrc* aSrc, guint aLength);
|
||||
|
||||
/* Called when appsrc has enough data and we can stop reading */
|
||||
static void EnoughDataCb(GstAppSrc* aSrc, gpointer aUserData);
|
||||
void EnoughData(GstAppSrc* aSrc);
|
||||
|
||||
/* Called when a seek is issued on the pipeline */
|
||||
static gboolean SeekDataCb(GstAppSrc* aSrc,
|
||||
guint64 aOffset,
|
||||
gpointer aUserData);
|
||||
gboolean SeekData(GstAppSrc* aSrc, guint64 aOffset);
|
||||
|
||||
/* Called when events reach the sinks. See inline comments */
|
||||
#if GST_VERSION_MAJOR == 1
|
||||
static GstPadProbeReturn EventProbeCb(GstPad *aPad, GstPadProbeInfo *aInfo, gpointer aUserData);
|
||||
GstPadProbeReturn EventProbe(GstPad *aPad, GstEvent *aEvent);
|
||||
#else
|
||||
static gboolean EventProbeCb(GstPad* aPad, GstEvent* aEvent, gpointer aUserData);
|
||||
gboolean EventProbe(GstPad* aPad, GstEvent* aEvent);
|
||||
#endif
|
||||
|
||||
/* Called when the video part of the pipeline allocates buffers. Used to
|
||||
* provide PlanarYCbCrImage backed GstBuffers to the pipeline so that a memory
|
||||
* copy can be avoided when handling YUV buffers from the pipeline to the gfx
|
||||
* side.
|
||||
*/
|
||||
#if GST_VERSION_MAJOR == 1
|
||||
static GstPadProbeReturn QueryProbeCb(GstPad *aPad, GstPadProbeInfo *aInfo, gpointer aUserData);
|
||||
GstPadProbeReturn QueryProbe(GstPad *aPad, GstPadProbeInfo *aInfo, gpointer aUserData);
|
||||
#else
|
||||
static GstFlowReturn AllocateVideoBufferCb(GstPad* aPad, guint64 aOffset, guint aSize,
|
||||
GstCaps* aCaps, GstBuffer** aBuf);
|
||||
GstFlowReturn AllocateVideoBufferFull(GstPad* aPad, guint64 aOffset, guint aSize,
|
||||
GstCaps* aCaps, GstBuffer** aBuf, nsRefPtr<layers::PlanarYCbCrImage>& aImage);
|
||||
GstFlowReturn AllocateVideoBuffer(GstPad* aPad, guint64 aOffset, guint aSize,
|
||||
GstCaps* aCaps, GstBuffer** aBuf);
|
||||
#endif
|
||||
|
||||
|
||||
/* Called when the pipeline is prerolled, that is when at start or after a
|
||||
* seek, the first audio and video buffers are queued in the sinks.
|
||||
*/
|
||||
static GstFlowReturn NewPrerollCb(GstAppSink* aSink, gpointer aUserData);
|
||||
void VideoPreroll();
|
||||
void AudioPreroll();
|
||||
|
||||
/* Called when buffers reach the sinks */
|
||||
static GstFlowReturn NewBufferCb(GstAppSink* aSink, gpointer aUserData);
|
||||
void NewVideoBuffer();
|
||||
void NewAudioBuffer();
|
||||
|
||||
/* Called at end of stream, when decoding has finished */
|
||||
static void EosCb(GstAppSink* aSink, gpointer aUserData);
|
||||
/* Notifies that a sink will no longer receive any more data. If nullptr
|
||||
* is passed to this, we'll assume all streams have reached EOS (for example
|
||||
* an error has occurred). */
|
||||
void Eos(GstAppSink* aSink = nullptr);
|
||||
|
||||
/* Called when an element is added inside playbin. We use it to find the
|
||||
* decodebin instance.
|
||||
*/
|
||||
static void PlayElementAddedCb(GstBin *aBin, GstElement *aElement,
|
||||
gpointer *aUserData);
|
||||
|
||||
/* Called during decoding, to decide whether a (sub)stream should be decoded or
|
||||
* ignored */
|
||||
static bool ShouldAutoplugFactory(GstElementFactory* aFactory, GstCaps* aCaps);
|
||||
|
||||
/* Called by decodebin during autoplugging. We use it to apply our
|
||||
* container/codec blacklist.
|
||||
*/
|
||||
static GValueArray* AutoplugSortCb(GstElement* aElement,
|
||||
GstPad* aPad, GstCaps* aCaps,
|
||||
GValueArray* aFactories);
|
||||
|
||||
// Try to find MP3 headers in this stream using our MP3 frame parser.
|
||||
nsresult ParseMP3Headers();
|
||||
|
||||
// Get the length of the stream, excluding any metadata we have ignored at the
|
||||
// start of the stream: ID3 headers, for example.
|
||||
int64_t GetDataLength();
|
||||
|
||||
// Use our own MP3 parser here, largely for consistency with other platforms.
|
||||
MP3FrameParser mMP3FrameParser;
|
||||
|
||||
// The byte position in the stream where the actual media (ignoring, for
|
||||
// example, ID3 tags) starts.
|
||||
uint64_t mDataOffset;
|
||||
|
||||
// We want to be able to decide in |ReadMetadata| whether or not we use the
|
||||
// duration from the MP3 frame parser, as this backend supports more than just
|
||||
// MP3. But |NotifyDataArrived| can update the duration and is often called
|
||||
// _before_ |ReadMetadata|. This flag stops the former from using the parser
|
||||
// duration until we are sure we want to.
|
||||
bool mUseParserDuration;
|
||||
int64_t mLastParserDuration;
|
||||
|
||||
#if GST_VERSION_MAJOR >= 1
|
||||
GstAllocator *mAllocator;
|
||||
GstBufferPool *mBufferPool;
|
||||
GstVideoInfo mVideoInfo;
|
||||
#endif
|
||||
GstElement* mPlayBin;
|
||||
GstBus* mBus;
|
||||
GstAppSrc* mSource;
|
||||
/* video sink bin */
|
||||
GstElement* mVideoSink;
|
||||
/* the actual video app sink */
|
||||
GstAppSink* mVideoAppSink;
|
||||
/* audio sink bin */
|
||||
GstElement* mAudioSink;
|
||||
/* the actual audio app sink */
|
||||
GstAppSink* mAudioAppSink;
|
||||
GstVideoFormat mFormat;
|
||||
IntRect mPicture;
|
||||
int mVideoSinkBufferCount;
|
||||
int mAudioSinkBufferCount;
|
||||
GstAppSrcCallbacks mSrcCallbacks;
|
||||
GstAppSinkCallbacks mSinkCallbacks;
|
||||
/* monitor used to synchronize access to shared state between gstreamer
|
||||
* threads and other gecko threads */
|
||||
ReentrantMonitor mGstThreadsMonitor;
|
||||
/* video and audio segments we use to convert absolute timestamps to [0,
|
||||
* stream_duration]. They're set when the pipeline is started or after a seek.
|
||||
* Concurrent access guarded with mGstThreadsMonitor.
|
||||
*/
|
||||
GstSegment mVideoSegment;
|
||||
GstSegment mAudioSegment;
|
||||
/* bool used to signal when gst has detected the end of stream and
|
||||
* DecodeAudioData and DecodeVideoFrame should not expect any more data
|
||||
*/
|
||||
bool mReachedAudioEos;
|
||||
bool mReachedVideoEos;
|
||||
#if GST_VERSION_MAJOR >= 1
|
||||
bool mConfigureAlignment;
|
||||
#endif
|
||||
int fpsNum;
|
||||
int fpsDen;
|
||||
|
||||
MediaResourceIndex mResource;
|
||||
NotifyDataArrivedFilter mFilter;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS += [
|
||||
'GStreamerDecoder.h',
|
||||
'GStreamerFormatHelper.h',
|
||||
'GStreamerLoader.h',
|
||||
'GStreamerReader.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'GStreamerDecoder.cpp',
|
||||
'GStreamerFormatHelper.cpp',
|
||||
'GStreamerLoader.cpp',
|
||||
'GStreamerReader.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['GST_API_VERSION'] == '1.0':
|
||||
SOURCES += [
|
||||
'GStreamerAllocator.cpp',
|
||||
]
|
||||
else:
|
||||
SOURCES += [
|
||||
'GStreamerMozVideoBuffer.cpp',
|
||||
'GStreamerReader-0.10.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/dom/html',
|
||||
]
|
||||
|
||||
CFLAGS += CONFIG['GSTREAMER_CFLAGS']
|
||||
CXXFLAGS += CONFIG['GSTREAMER_CFLAGS']
|
||||
@@ -46,6 +46,9 @@ if CONFIG['MOZ_WAVE']:
|
||||
if CONFIG['MOZ_WEBM']:
|
||||
DIRS += ['webm']
|
||||
|
||||
if CONFIG['MOZ_GSTREAMER']:
|
||||
DIRS += ['gstreamer']
|
||||
|
||||
if CONFIG['MOZ_DIRECTSHOW']:
|
||||
DIRS += ['directshow']
|
||||
|
||||
|
||||
@@ -526,27 +526,28 @@ void
|
||||
MediaCodecReader::NotifyDataArrivedInternal(uint32_t aLength,
|
||||
int64_t aOffset)
|
||||
{
|
||||
nsRefPtr<MediaByteBuffer> bytes =
|
||||
mDecoder->GetResource()->MediaReadAt(aOffset, aLength);
|
||||
NS_ENSURE_TRUE_VOID(bytes);
|
||||
|
||||
MonitorAutoLock monLock(mParserMonitor);
|
||||
if (mNextParserPosition == mParsedDataLength &&
|
||||
mNextParserPosition >= aOffset &&
|
||||
mNextParserPosition <= aOffset + aLength) {
|
||||
// No pending parsing runnable currently. And available data are adjacent to
|
||||
// parsed data.
|
||||
int64_t shift = mNextParserPosition - aOffset;
|
||||
const char* buffer = reinterpret_cast<const char*>(bytes->Elements()) + shift;
|
||||
uint32_t length = aLength - shift;
|
||||
int64_t offset = mNextParserPosition;
|
||||
if (length > 0) {
|
||||
MonitorAutoUnlock monUnlock(mParserMonitor);
|
||||
ParseDataSegment(buffer, length, offset);
|
||||
IntervalSet<int64_t> intervals = mFilter.NotifyDataArrived(aLength, aOffset);
|
||||
for (const auto& interval : intervals) {
|
||||
nsRefPtr<MediaByteBuffer> bytes =
|
||||
mDecoder->GetResource()->MediaReadAt(interval.mStart, interval.Length());
|
||||
MonitorAutoLock monLock(mParserMonitor);
|
||||
if (mNextParserPosition == mParsedDataLength &&
|
||||
mNextParserPosition >= interval.mStart &&
|
||||
mNextParserPosition <= interval.mEnd) {
|
||||
// No pending parsing runnable currently. And available data are adjacent to
|
||||
// parsed data.
|
||||
int64_t shift = mNextParserPosition - interval.mStart;
|
||||
const char* buffer = reinterpret_cast<const char*>(bytes->Elements()) + shift;
|
||||
uint32_t length = interval.Length() - shift;
|
||||
int64_t offset = mNextParserPosition;
|
||||
if (length > 0) {
|
||||
MonitorAutoUnlock monUnlock(mParserMonitor);
|
||||
ParseDataSegment(buffer, length, offset);
|
||||
}
|
||||
mParseDataFromCache = false;
|
||||
mParsedDataLength = offset + length;
|
||||
mNextParserPosition = mParsedDataLength;
|
||||
}
|
||||
mParseDataFromCache = false;
|
||||
mParsedDataLength = offset + length;
|
||||
mNextParserPosition = mParsedDataLength;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,32 +848,6 @@ MediaCodecReader::WaitFenceAndReleaseOutputBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
MediaCodecReader::ReleaseTextureClient(TextureClient* aClient,
|
||||
size_t& aIndex,
|
||||
void* aUserArg)
|
||||
{
|
||||
nsRefPtr<MediaCodecReader> reader = static_cast<MediaCodecReader*>(aUserArg);
|
||||
MOZ_ASSERT(reader, "reader should not be nullptr in ReleaseTextureClient()");
|
||||
|
||||
return reader->ReleaseTextureClient(aClient, aIndex);
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
MediaCodecReader::ReleaseTextureClient(TextureClient* aClient,
|
||||
size_t& aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aClient, "TextureClient should be a valid pointer");
|
||||
|
||||
aClient->ClearRecycleCallback();
|
||||
|
||||
if (mVideoTrack.mCodec != nullptr) {
|
||||
mVideoTrack.mCodec->releaseOutputBuffer(aIndex);
|
||||
}
|
||||
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
MediaCodecReader::ReleaseAllTextureClients()
|
||||
{
|
||||
@@ -884,7 +859,17 @@ MediaCodecReader::ReleaseAllTextureClients()
|
||||
}
|
||||
printf_stderr("All TextureClients should be released already");
|
||||
|
||||
mTextureClientIndexes.Enumerate(MediaCodecReader::ReleaseTextureClient, this);
|
||||
for (auto iter = mTextureClientIndexes.Iter(); !iter.Done(); iter.Next()) {
|
||||
TextureClient* client = iter.Key();
|
||||
size_t& index = iter.Data();
|
||||
|
||||
client->ClearRecycleCallback();
|
||||
|
||||
if (mVideoTrack.mCodec != nullptr) {
|
||||
mVideoTrack.mCodec->releaseOutputBuffer(index);
|
||||
}
|
||||
iter.Remove();
|
||||
}
|
||||
mTextureClientIndexes.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <ui/Fence.h>
|
||||
#endif
|
||||
|
||||
#include "MP3FrameParser.h"
|
||||
|
||||
namespace android {
|
||||
struct ALooper;
|
||||
struct AMessage;
|
||||
@@ -264,10 +266,12 @@ private:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SignalObject)
|
||||
|
||||
SignalObject(const char* aName);
|
||||
~SignalObject();
|
||||
void Wait();
|
||||
void Signal();
|
||||
|
||||
protected:
|
||||
~SignalObject();
|
||||
|
||||
private:
|
||||
// Forbidden
|
||||
SignalObject() = delete;
|
||||
@@ -395,11 +399,6 @@ private:
|
||||
void WaitFenceAndReleaseOutputBuffer();
|
||||
|
||||
void ReleaseRecycledTextureClients();
|
||||
static PLDHashOperator ReleaseTextureClient(TextureClient* aClient,
|
||||
size_t& aIndex,
|
||||
void* aUserArg);
|
||||
PLDHashOperator ReleaseTextureClient(TextureClient* aClient,
|
||||
size_t& aIndex);
|
||||
|
||||
void ReleaseAllTextureClients();
|
||||
|
||||
@@ -439,6 +438,8 @@ private:
|
||||
FenceHandle mReleaseFence;
|
||||
};
|
||||
nsTArray<ReleaseItem> mPendingReleaseItems;
|
||||
|
||||
NotifyDataArrivedFilter mFilter;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -474,18 +474,21 @@ void MediaOmxReader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaByteBuffer> bytes =
|
||||
mDecoder->GetResource()->MediaReadAt(aOffset, aLength);
|
||||
NS_ENSURE_TRUE_VOID(bytes);
|
||||
mMP3FrameParser.Parse(bytes->Elements(), aLength, aOffset);
|
||||
if (!mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
}
|
||||
IntervalSet<int64_t> intervals = mFilter.NotifyDataArrived(aLength, aOffset);
|
||||
for (const auto& interval : intervals) {
|
||||
nsRefPtr<MediaByteBuffer> bytes =
|
||||
mDecoder->GetResource()->MediaReadAt(interval.mStart, interval.Length());
|
||||
NS_ENSURE_TRUE_VOID(bytes);
|
||||
mMP3FrameParser.Parse(bytes->Elements(), interval.Length(), interval.mStart);
|
||||
if (!mMP3FrameParser.IsMP3()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t duration = mMP3FrameParser.GetDuration();
|
||||
if (duration != mLastParserDuration) {
|
||||
mLastParserDuration = duration;
|
||||
decoder->DispatchUpdateEstimatedMediaDuration(mLastParserDuration);
|
||||
int64_t duration = mMP3FrameParser.GetDuration();
|
||||
if (duration != mLastParserDuration) {
|
||||
mLastParserDuration = duration;
|
||||
decoder->DispatchUpdateEstimatedMediaDuration(mLastParserDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -128,6 +128,8 @@ private:
|
||||
int64_t ProcessCachedData(int64_t aOffset);
|
||||
|
||||
already_AddRefed<AbstractMediaDecoder> SafeGetDecoder();
|
||||
|
||||
NotifyDataArrivedFilter mFilter;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -83,26 +83,21 @@ class OriginKeyStore : public nsISupports
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
HashCleaner(const nsACString& aOrigin, nsAutoPtr<OriginKey>& aOriginKey,
|
||||
void *aUserArg)
|
||||
{
|
||||
OriginKey* since = static_cast<OriginKey*>(aUserArg);
|
||||
|
||||
LOG((((aOriginKey->mSecondsStamp >= since->mSecondsStamp)?
|
||||
"%s: REMOVE %lld >= %lld" :
|
||||
"%s: KEEP %lld < %lld"),
|
||||
__FUNCTION__, aOriginKey->mSecondsStamp, since->mSecondsStamp));
|
||||
|
||||
return (aOriginKey->mSecondsStamp >= since->mSecondsStamp)?
|
||||
PL_DHASH_REMOVE : PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void Clear(int64_t aSinceWhen)
|
||||
{
|
||||
// Avoid int64_t* <-> void* casting offset
|
||||
OriginKey since(nsCString(), aSinceWhen / PR_USEC_PER_SEC);
|
||||
mKeys.Enumerate(HashCleaner, &since);
|
||||
for (auto iter = mKeys.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoPtr<OriginKey>& originKey = iter.Data();
|
||||
LOG((((originKey->mSecondsStamp >= since.mSecondsStamp)?
|
||||
"%s: REMOVE %lld >= %lld" :
|
||||
"%s: KEEP %lld < %lld"),
|
||||
__FUNCTION__, originKey->mSecondsStamp, since.mSecondsStamp));
|
||||
|
||||
if (originKey->mSecondsStamp >= since.mSecondsStamp) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
mPersistCount = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,25 +141,6 @@ MediaSystemResourceService::ReleaseResource(media::MediaSystemResourceManagerPar
|
||||
UpdateRequests(aResourceType);
|
||||
}
|
||||
|
||||
struct ReleaseResourceData
|
||||
{
|
||||
MediaSystemResourceService* mSelf;
|
||||
media::MediaSystemResourceManagerParent* mParent;
|
||||
};
|
||||
|
||||
/*static*/PLDHashOperator
|
||||
MediaSystemResourceService::ReleaseResourceForKey(const uint32_t& aKey,
|
||||
nsAutoPtr<MediaSystemResource>& aData,
|
||||
void* aClosure)
|
||||
{
|
||||
ReleaseResourceData* closure = static_cast<ReleaseResourceData*>(aClosure);
|
||||
|
||||
closure->mSelf->RemoveRequests(closure->mParent, static_cast<MediaSystemResourceType>(aKey));
|
||||
closure->mSelf->UpdateRequests(static_cast<MediaSystemResourceType>(aKey));
|
||||
|
||||
return PLDHashOperator::PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
MediaSystemResourceService::ReleaseResource(media::MediaSystemResourceManagerParent* aParent)
|
||||
{
|
||||
@@ -169,8 +150,11 @@ MediaSystemResourceService::ReleaseResource(media::MediaSystemResourceManagerPar
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseResourceData data = { this, aParent };
|
||||
mResources.Enumerate(ReleaseResourceForKey, &data);
|
||||
for (auto iter = mResources.Iter(); !iter.Done(); iter.Next()) {
|
||||
const uint32_t& key = iter.Key();
|
||||
RemoveRequests(aParent, static_cast<MediaSystemResourceType>(key));
|
||||
UpdateRequests(static_cast<MediaSystemResourceType>(key));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -77,10 +77,6 @@ private:
|
||||
|
||||
void UpdateRequests(MediaSystemResourceType aResourceType);
|
||||
|
||||
static PLDHashOperator ReleaseResourceForKey(const uint32_t& aKey,
|
||||
nsAutoPtr<MediaSystemResource>& aData,
|
||||
void* aClosure);
|
||||
|
||||
bool mDestroyed;
|
||||
|
||||
nsClassHashtable<nsUint32HashKey, MediaSystemResource> mResources;
|
||||
|
||||
@@ -495,40 +495,8 @@ nsPicoService::GetServiceType(SpeechServiceType* aServiceType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct VoiceTraverserData
|
||||
{
|
||||
nsPicoService* mService;
|
||||
nsSynthVoiceRegistry* mRegistry;
|
||||
};
|
||||
|
||||
// private methods
|
||||
|
||||
static PLDHashOperator
|
||||
PicoAddVoiceTraverser(const nsAString& aUri,
|
||||
nsRefPtr<PicoVoice>& aVoice,
|
||||
void* aUserArg)
|
||||
{
|
||||
// If we are missing either a language or a voice resource, it is invalid.
|
||||
if (aVoice->mTaFile.IsEmpty() || aVoice->mSgFile.IsEmpty()) {
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
VoiceTraverserData* data = static_cast<VoiceTraverserData*>(aUserArg);
|
||||
|
||||
nsAutoString name;
|
||||
name.AssignLiteral("Pico ");
|
||||
name.Append(aVoice->mLanguage);
|
||||
|
||||
// This service is multi-threaded and can handle more than one utterance at a
|
||||
// time before previous utterances end. So, aQueuesUtterances == false
|
||||
DebugOnly<nsresult> rv =
|
||||
data->mRegistry->AddVoice(
|
||||
data->mService, aUri, name, aVoice->mLanguage, true, false);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to add voice");
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsPicoService::Init()
|
||||
{
|
||||
@@ -608,8 +576,28 @@ nsPicoService::Init()
|
||||
void
|
||||
nsPicoService::RegisterVoices()
|
||||
{
|
||||
VoiceTraverserData data = { this, nsSynthVoiceRegistry::GetInstance() };
|
||||
mVoices.Enumerate(PicoAddVoiceTraverser, &data);
|
||||
nsSynthVoiceRegistry* registry = nsSynthVoiceRegistry::GetInstance();
|
||||
|
||||
for (auto iter = mVoices.Iter(); !iter.Done(); iter.Next()) {
|
||||
const nsAString& uri = iter.Key();
|
||||
nsRefPtr<PicoVoice>& voice = iter.Data();
|
||||
|
||||
// If we are missing either a language or a voice resource, it is invalid.
|
||||
if (voice->mTaFile.IsEmpty() || voice->mSgFile.IsEmpty()) {
|
||||
iter.Remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString name;
|
||||
name.AssignLiteral("Pico ");
|
||||
name.Append(voice->mLanguage);
|
||||
|
||||
// This service is multi-threaded and can handle more than one utterance at a
|
||||
// time before previous utterances end. So, aQueuesUtterances == false
|
||||
DebugOnly<nsresult> rv =
|
||||
registry->AddVoice(this, uri, name, voice->mLanguage, true, false);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to add voice");
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ SVGFEImageElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
|
||||
Matrix TM = viewBoxTM;
|
||||
TM.PostTranslate(aFilterSubregion.x, aFilterSubregion.y);
|
||||
|
||||
Filter filter = ToFilter(nsLayoutUtils::GetGraphicsFilterForFrame(frame));
|
||||
Filter filter = nsLayoutUtils::GetGraphicsFilterForFrame(frame);
|
||||
|
||||
FilterPrimitiveDescription descr(PrimitiveType::Image);
|
||||
descr.Attributes().Set(eImageFilter, (uint32_t)filter);
|
||||
|
||||
@@ -119,6 +119,8 @@ GfxFilterToCairoFilter(Filter filter)
|
||||
return CAIRO_FILTER_BILINEAR;
|
||||
case Filter::POINT:
|
||||
return CAIRO_FILTER_NEAREST;
|
||||
default:
|
||||
MOZ_CRASH("bad filter");
|
||||
}
|
||||
|
||||
return CAIRO_FILTER_BILINEAR;
|
||||
|
||||
+25
-13
@@ -184,7 +184,8 @@ AppendEllipseToPath(PathBuilder* aPathBuilder,
|
||||
|
||||
bool
|
||||
SnapLineToDevicePixelsForStroking(Point& aP1, Point& aP2,
|
||||
const DrawTarget& aDrawTarget)
|
||||
const DrawTarget& aDrawTarget,
|
||||
Float aLineWidth)
|
||||
{
|
||||
Matrix mat = aDrawTarget.GetTransform();
|
||||
if (mat.HasNonTranslation()) {
|
||||
@@ -199,14 +200,21 @@ SnapLineToDevicePixelsForStroking(Point& aP1, Point& aP2,
|
||||
p2.Round();
|
||||
p1 -= mat.GetTranslation(); // back into user space
|
||||
p2 -= mat.GetTranslation();
|
||||
if (aP1.x == aP2.x) {
|
||||
// snap vertical line, adding 0.5 to align it to be mid-pixel:
|
||||
aP1 = p1 + Point(0.5, 0);
|
||||
aP2 = p2 + Point(0.5, 0);
|
||||
} else {
|
||||
// snap horizontal line, adding 0.5 to align it to be mid-pixel:
|
||||
aP1 = p1 + Point(0, 0.5);
|
||||
aP2 = p2 + Point(0, 0.5);
|
||||
|
||||
aP1 = p1;
|
||||
aP2 = p2;
|
||||
|
||||
bool lineWidthIsOdd = (int(aLineWidth) % 2) == 1;
|
||||
if (lineWidthIsOdd) {
|
||||
if (aP1.x == aP2.x) {
|
||||
// snap vertical line, adding 0.5 to align it to be mid-pixel:
|
||||
aP1 += Point(0.5, 0);
|
||||
aP2 += Point(0.5, 0);
|
||||
} else {
|
||||
// snap horizontal line, adding 0.5 to align it to be mid-pixel:
|
||||
aP1 += Point(0, 0.5);
|
||||
aP2 += Point(0, 0.5);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -222,22 +230,26 @@ StrokeSnappedEdgesOfRect(const Rect& aRect, DrawTarget& aDrawTarget,
|
||||
|
||||
Point p1 = aRect.TopLeft();
|
||||
Point p2 = aRect.BottomLeft();
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget);
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget,
|
||||
aStrokeOptions.mLineWidth);
|
||||
aDrawTarget.StrokeLine(p1, p2, aColor, aStrokeOptions);
|
||||
|
||||
p1 = aRect.BottomLeft();
|
||||
p2 = aRect.BottomRight();
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget);
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget,
|
||||
aStrokeOptions.mLineWidth);
|
||||
aDrawTarget.StrokeLine(p1, p2, aColor, aStrokeOptions);
|
||||
|
||||
p1 = aRect.TopLeft();
|
||||
p2 = aRect.TopRight();
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget);
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget,
|
||||
aStrokeOptions.mLineWidth);
|
||||
aDrawTarget.StrokeLine(p1, p2, aColor, aStrokeOptions);
|
||||
|
||||
p1 = aRect.TopRight();
|
||||
p2 = aRect.BottomRight();
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget);
|
||||
SnapLineToDevicePixelsForStroking(p1, p2, aDrawTarget,
|
||||
aStrokeOptions.mLineWidth);
|
||||
aDrawTarget.StrokeLine(p1, p2, aColor, aStrokeOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -300,7 +300,8 @@ inline already_AddRefed<Path> MakePathForEllipse(const DrawTarget& aDrawTarget,
|
||||
* false.
|
||||
*/
|
||||
GFX2D_API bool SnapLineToDevicePixelsForStroking(Point& aP1, Point& aP2,
|
||||
const DrawTarget& aDrawTarget);
|
||||
const DrawTarget& aDrawTarget,
|
||||
Float aLineWidth);
|
||||
|
||||
/**
|
||||
* This function paints each edge of aRect separately, snapping the edges using
|
||||
|
||||
+2
-1
@@ -192,7 +192,8 @@ enum class AntialiasMode : int8_t {
|
||||
enum class Filter : int8_t {
|
||||
GOOD,
|
||||
LINEAR,
|
||||
POINT
|
||||
POINT,
|
||||
SENTINEL // one past the last valid value
|
||||
};
|
||||
|
||||
enum class PatternType : int8_t {
|
||||
|
||||
@@ -270,7 +270,7 @@ TextureImage::TextureImage(const gfx::IntSize& aSize,
|
||||
: mSize(aSize)
|
||||
, mWrapMode(aWrapMode)
|
||||
, mContentType(aContentType)
|
||||
, mFilter(GraphicsFilter::FILTER_GOOD)
|
||||
, mFilter(Filter::GOOD)
|
||||
, mFlags(aFlags)
|
||||
{}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "nsTArray.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GraphicsFilter.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
@@ -199,7 +198,7 @@ public:
|
||||
virtual bool InUpdate() const = 0;
|
||||
GLenum GetWrapMode() const { return mWrapMode; }
|
||||
|
||||
void SetFilter(GraphicsFilter aFilter) { mFilter = aFilter; }
|
||||
void SetFilter(gfx::Filter aFilter) { mFilter = aFilter; }
|
||||
|
||||
protected:
|
||||
friend class GLContext;
|
||||
@@ -224,7 +223,7 @@ protected:
|
||||
GLenum mWrapMode;
|
||||
ContentType mContentType;
|
||||
gfx::SurfaceFormat mTextureFormat;
|
||||
GraphicsFilter mFilter;
|
||||
gfx::Filter mFilter;
|
||||
Flags mFlags;
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef XID GLXContextID;
|
||||
typedef XID GLXWindow;
|
||||
typedef XID GLXPbuffer;
|
||||
// end of stuff from glx.h
|
||||
#include "prenv.h"
|
||||
|
||||
struct PRLibrary;
|
||||
class gfxASurface;
|
||||
@@ -108,6 +109,12 @@ public:
|
||||
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
|
||||
bool IsATI() { return mIsATI; }
|
||||
bool GLXVersionCheck(int aMajor, int aMinor);
|
||||
bool UseSurfaceSharing() {
|
||||
// Disable surface sharing due to issues with compatible FBConfigs on
|
||||
// NVIDIA drivers as described in bug 1193015.
|
||||
static bool useSharing = PR_GetEnv("MOZ_GLX_USE_SURFACE_SHARING");
|
||||
return mUseTextureFromPixmap && useSharing;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "GraphicsFilter.h"
|
||||
#include "gfxPoint.h"
|
||||
#include "gfxRect.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsRegion.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "mozilla/layers/AsyncDragMetrics.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "FrameMetrics.h"
|
||||
@@ -33,7 +33,6 @@
|
||||
namespace mozilla {
|
||||
|
||||
typedef gfxImageFormat PixelFormat;
|
||||
typedef ::GraphicsFilter GraphicsFilterType;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -206,11 +205,11 @@ struct ParamTraits<gfxSurfaceType>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::GraphicsFilterType>
|
||||
struct ParamTraits<mozilla::gfx::Filter>
|
||||
: public ContiguousEnumSerializer<
|
||||
mozilla::GraphicsFilterType,
|
||||
GraphicsFilter::FILTER_FAST,
|
||||
GraphicsFilter::FILTER_SENTINEL>
|
||||
mozilla::gfx::Filter,
|
||||
mozilla::gfx::Filter::GOOD,
|
||||
mozilla::gfx::Filter::SENTINEL>
|
||||
{};
|
||||
|
||||
template <>
|
||||
@@ -1098,6 +1097,40 @@ struct ParamTraits<mozilla::layers::EventRegionsOverride>
|
||||
mozilla::layers::EventRegionsOverride::ALL_BITS>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::layers::AsyncDragMetrics::DragDirection>
|
||||
: public ContiguousEnumSerializer<
|
||||
mozilla::layers::AsyncDragMetrics::DragDirection,
|
||||
mozilla::layers::AsyncDragMetrics::DragDirection::NONE,
|
||||
mozilla::layers::AsyncDragMetrics::DragDirection::SENTINEL>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::layers::AsyncDragMetrics>
|
||||
{
|
||||
typedef mozilla::layers::AsyncDragMetrics paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mViewId);
|
||||
WriteParam(aMsg, aParam.mPresShellId);
|
||||
WriteParam(aMsg, aParam.mDragStartSequenceNumber);
|
||||
WriteParam(aMsg, aParam.mScrollbarDragOffset);
|
||||
WriteParam(aMsg, aParam.mScrollTrack);
|
||||
WriteParam(aMsg, aParam.mDirection);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return (ReadParam(aMsg, aIter, &aResult->mViewId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDragStartSequenceNumber) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollbarDragOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollTrack) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDirection));
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace IPC */
|
||||
|
||||
#endif /* __GFXMESSAGEUTILS_H__ */
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
ImageLayer::ImageLayer(LayerManager* aManager, void* aImplData)
|
||||
: Layer(aManager, aImplData), mFilter(GraphicsFilter::FILTER_GOOD)
|
||||
: Layer(aManager, aImplData), mFilter(gfx::Filter::GOOD)
|
||||
, mScaleMode(ScaleMode::SCALE_NONE), mDisallowBigImage(false)
|
||||
{}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#define GFX_IMAGELAYER_H
|
||||
|
||||
#include "Layers.h" // for Layer, etc
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
@@ -39,7 +38,7 @@ public:
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set the filter used to resample this image if necessary.
|
||||
*/
|
||||
void SetFilter(GraphicsFilter aFilter)
|
||||
void SetFilter(gfx::Filter aFilter)
|
||||
{
|
||||
if (mFilter != aFilter) {
|
||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) Filter", this));
|
||||
@@ -63,7 +62,7 @@ public:
|
||||
|
||||
|
||||
ImageContainer* GetContainer() { return mContainer; }
|
||||
GraphicsFilter GetFilter() { return mFilter; }
|
||||
gfx::Filter GetFilter() { return mFilter; }
|
||||
const gfx::IntSize& GetScaleToSize() { return mScaleToSize; }
|
||||
ScaleMode GetScaleMode() { return mScaleMode; }
|
||||
|
||||
@@ -95,7 +94,7 @@ protected:
|
||||
virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override;
|
||||
|
||||
nsRefPtr<ImageContainer> mContainer;
|
||||
GraphicsFilter mFilter;
|
||||
gfx::Filter mFilter;
|
||||
gfx::IntSize mScaleToSize;
|
||||
ScaleMode mScaleMode;
|
||||
bool mDisallowBigImage;
|
||||
|
||||
@@ -364,6 +364,29 @@ public:
|
||||
return EventRegionsOverride::NoOverride;
|
||||
}
|
||||
|
||||
Layer::ScrollDirection GetScrollbarDirection() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
return mLayer->GetScrollbarDirection();
|
||||
}
|
||||
|
||||
FrameMetrics::ViewID GetScrollbarTargetContainerId() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
return mLayer->GetScrollbarTargetContainerId();
|
||||
}
|
||||
|
||||
int32_t GetScrollbarSize() const
|
||||
{
|
||||
if (GetScrollbarDirection() == Layer::VERTICAL) {
|
||||
return mLayer->GetVisibleRegion().GetBounds().height;
|
||||
} else {
|
||||
return mLayer->GetVisibleRegion().GetBounds().width;
|
||||
}
|
||||
}
|
||||
|
||||
// Expose an opaque pointer to the layer. Mostly used for printf
|
||||
// purposes. This is not intended to be a general-purpose accessor
|
||||
// for the underlying layer.
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "ImageLayers.h" // for ImageLayer, etc
|
||||
#include "Layers.h" // for Layer, ContainerLayer, etc
|
||||
#include "Units.h" // for ParentLayerIntRect
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfxUtils.h" // for gfxUtils
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
@@ -403,9 +402,14 @@ struct ImageLayerProperties : public LayerPropertiesBase
|
||||
, mFilter(aImage->GetFilter())
|
||||
, mScaleToSize(aImage->GetScaleToSize())
|
||||
, mScaleMode(aImage->GetScaleMode())
|
||||
, mLastProducerID(-1)
|
||||
, mLastFrameID(-1)
|
||||
, mIsMask(aIsMask)
|
||||
{
|
||||
mFrameID = mImageHost ? mImageHost->GetFrameID() : -1;
|
||||
if (mImageHost) {
|
||||
mLastProducerID = mImageHost->GetLastProducerID();
|
||||
mLastFrameID = mImageHost->GetLastFrameID();
|
||||
}
|
||||
}
|
||||
|
||||
virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback,
|
||||
@@ -427,7 +431,8 @@ struct ImageLayerProperties : public LayerPropertiesBase
|
||||
mScaleToSize != imageLayer->GetScaleToSize() ||
|
||||
mScaleMode != imageLayer->GetScaleMode() ||
|
||||
host != mImageHost ||
|
||||
(host && host->GetFrameID() != mFrameID)) {
|
||||
(host && host->GetProducerID() != mLastProducerID) ||
|
||||
(host && host->GetFrameID() != mLastFrameID)) {
|
||||
aGeometryChanged = true;
|
||||
|
||||
if (mIsMask) {
|
||||
@@ -451,10 +456,11 @@ struct ImageLayerProperties : public LayerPropertiesBase
|
||||
|
||||
nsRefPtr<ImageContainer> mContainer;
|
||||
nsRefPtr<ImageHost> mImageHost;
|
||||
GraphicsFilter mFilter;
|
||||
Filter mFilter;
|
||||
gfx::IntSize mScaleToSize;
|
||||
int32_t mFrameID;
|
||||
ScaleMode mScaleMode;
|
||||
int32_t mLastProducerID;
|
||||
int32_t mLastFrameID;
|
||||
bool mIsMask;
|
||||
};
|
||||
|
||||
@@ -475,11 +481,15 @@ CloneLayerTreePropertiesInternal(Layer* aRoot, bool aIsMask /* = false */)
|
||||
return MakeUnique<ColorLayerProperties>(static_cast<ColorLayer*>(aRoot));
|
||||
case Layer::TYPE_IMAGE:
|
||||
return MakeUnique<ImageLayerProperties>(static_cast<ImageLayer*>(aRoot), aIsMask);
|
||||
default:
|
||||
case Layer::TYPE_CANVAS:
|
||||
case Layer::TYPE_READBACK:
|
||||
case Layer::TYPE_SHADOW:
|
||||
case Layer::TYPE_PAINTED:
|
||||
return MakeUnique<LayerPropertiesBase>(aRoot);
|
||||
}
|
||||
|
||||
return UniquePtr<LayerPropertiesBase>(nullptr);
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected root layer type");
|
||||
return MakeUnique<LayerPropertiesBase>(aRoot);
|
||||
}
|
||||
|
||||
/* static */ UniquePtr<LayerProperties>
|
||||
|
||||
+8
-17
@@ -2111,7 +2111,7 @@ void
|
||||
CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||
{
|
||||
Layer::PrintInfo(aStream, aPrefix);
|
||||
if (mFilter != GraphicsFilter::FILTER_GOOD) {
|
||||
if (mFilter != Filter::GOOD) {
|
||||
AppendToString(aStream, mFilter, " [filter=", "]");
|
||||
}
|
||||
}
|
||||
@@ -2119,27 +2119,18 @@ CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||
// This help function is used to assign the correct enum value
|
||||
// to the packet
|
||||
static void
|
||||
DumpFilter(layerscope::LayersPacket::Layer* aLayer, const GraphicsFilter& aFilter)
|
||||
DumpFilter(layerscope::LayersPacket::Layer* aLayer, const Filter& aFilter)
|
||||
{
|
||||
using namespace layerscope;
|
||||
switch (aFilter) {
|
||||
case GraphicsFilter::FILTER_FAST:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_FAST);
|
||||
break;
|
||||
case GraphicsFilter::FILTER_GOOD:
|
||||
case Filter::GOOD:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_GOOD);
|
||||
break;
|
||||
case GraphicsFilter::FILTER_BEST:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_BEST);
|
||||
case Filter::LINEAR:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_LINEAR);
|
||||
break;
|
||||
case GraphicsFilter::FILTER_NEAREST:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_NEAREST);
|
||||
break;
|
||||
case GraphicsFilter::FILTER_BILINEAR:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_BILINEAR);
|
||||
break;
|
||||
case GraphicsFilter::FILTER_GAUSSIAN:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_GAUSSIAN);
|
||||
case Filter::POINT:
|
||||
aLayer->set_filter(LayersPacket::Layer::FILTER_POINT);
|
||||
break;
|
||||
default:
|
||||
// ignore it
|
||||
@@ -2162,7 +2153,7 @@ void
|
||||
ImageLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||
{
|
||||
Layer::PrintInfo(aStream, aPrefix);
|
||||
if (mFilter != GraphicsFilter::FILTER_GOOD) {
|
||||
if (mFilter != Filter::GOOD) {
|
||||
AppendToString(aStream, mFilter, " [filter=", "]");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -13,7 +13,6 @@
|
||||
#include "Units.h" // for LayerMargin, LayerPoint, ParentLayerIntRect
|
||||
#include "gfxContext.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "gfxPoint.h" // for gfxPoint
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
#include "gfx2DGlue.h"
|
||||
@@ -2372,7 +2371,7 @@ public:
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set the filter used to resample this image (if necessary).
|
||||
*/
|
||||
void SetFilter(GraphicsFilter aFilter)
|
||||
void SetFilter(gfx::Filter aFilter)
|
||||
{
|
||||
if (mFilter != aFilter) {
|
||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) Filter", this));
|
||||
@@ -2380,7 +2379,7 @@ public:
|
||||
Mutated();
|
||||
}
|
||||
}
|
||||
GraphicsFilter GetFilter() const { return mFilter; }
|
||||
gfx::Filter GetFilter() const { return mFilter; }
|
||||
|
||||
MOZ_LAYER_DECL_NAME("CanvasLayer", TYPE_CANVAS)
|
||||
|
||||
@@ -2404,7 +2403,7 @@ protected:
|
||||
, mPreTransCallbackData(nullptr)
|
||||
, mPostTransCallback(nullptr)
|
||||
, mPostTransCallbackData(nullptr)
|
||||
, mFilter(GraphicsFilter::FILTER_GOOD)
|
||||
, mFilter(gfx::Filter::GOOD)
|
||||
, mDirty(false)
|
||||
{}
|
||||
|
||||
@@ -2427,7 +2426,7 @@ protected:
|
||||
void* mPreTransCallbackData;
|
||||
DidTransactionCallback mPostTransCallback;
|
||||
void* mPostTransCallbackData;
|
||||
GraphicsFilter mFilter;
|
||||
gfx::Filter mFilter;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -28,25 +28,6 @@ AppendToString(std::stringstream& aStream, const void* p,
|
||||
aStream << sfx;
|
||||
}
|
||||
|
||||
void
|
||||
AppendToString(std::stringstream& aStream, const GraphicsFilter& f,
|
||||
const char* pfx, const char* sfx)
|
||||
{
|
||||
aStream << pfx;
|
||||
switch (f) {
|
||||
case GraphicsFilter::FILTER_FAST: aStream << "fast"; break;
|
||||
case GraphicsFilter::FILTER_GOOD: aStream << "good"; break;
|
||||
case GraphicsFilter::FILTER_BEST: aStream << "best"; break;
|
||||
case GraphicsFilter::FILTER_NEAREST: aStream << "nearest"; break;
|
||||
case GraphicsFilter::FILTER_BILINEAR: aStream << "bilinear"; break;
|
||||
case GraphicsFilter::FILTER_GAUSSIAN: aStream << "gaussian"; break;
|
||||
default:
|
||||
NS_ERROR("unknown filter type");
|
||||
aStream << "???";
|
||||
}
|
||||
aStream << sfx;
|
||||
}
|
||||
|
||||
void
|
||||
AppendToString(std::stringstream& aStream, FrameMetrics::ViewID n,
|
||||
const char* pfx, const char* sfx)
|
||||
@@ -276,7 +257,6 @@ AppendToString(std::stringstream& aStream, const Matrix5x4& m,
|
||||
aStream << sfx;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AppendToString(std::stringstream& aStream, const Filter filter,
|
||||
const char* pfx, const char* sfx)
|
||||
@@ -287,6 +267,9 @@ AppendToString(std::stringstream& aStream, const Filter filter,
|
||||
case Filter::GOOD: aStream << "Filter::GOOD"; break;
|
||||
case Filter::LINEAR: aStream << "Filter::LINEAR"; break;
|
||||
case Filter::POINT: aStream << "Filter::POINT"; break;
|
||||
default:
|
||||
NS_ERROR("unknown filter type");
|
||||
aStream << "???";
|
||||
}
|
||||
aStream << sfx;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#define GFX_LAYERSLOGGING_H
|
||||
|
||||
#include "FrameMetrics.h" // for FrameMetrics, etc
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "mozilla/gfx/Point.h" // for IntSize, etc
|
||||
#include "mozilla/gfx/Types.h" // for Filter, SurfaceFormat
|
||||
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags
|
||||
@@ -30,10 +29,6 @@ void
|
||||
AppendToString(std::stringstream& aStream, const void* p,
|
||||
const char* pfx="", const char* sfx="");
|
||||
|
||||
void
|
||||
AppendToString(std::stringstream& aStream, const GraphicsFilter& f,
|
||||
const char* pfx="", const char* sfx="");
|
||||
|
||||
void
|
||||
AppendToString(std::stringstream& aStream, FrameMetrics::ViewID n,
|
||||
const char* pfx="", const char* sfx="");
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "mozilla/gfx/Point.h" // for Point
|
||||
#include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread, etc
|
||||
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
|
||||
#include "mozilla/layers/AsyncDragMetrics.h" // for AsyncDragMetrics
|
||||
#include "mozilla/layers/CompositorParent.h" // for CompositorParent, etc
|
||||
#include "mozilla/layers/LayerMetricsWrapper.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
@@ -324,6 +325,21 @@ GetEventRegionsOverride(HitTestingTreeNode* aParent,
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::StartScrollbarDrag(const ScrollableLayerGuid& aGuid,
|
||||
const AsyncDragMetrics& aDragMetrics)
|
||||
{
|
||||
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (!apzc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO Confirm the input block
|
||||
//uint64_t inputBlockId = aDragMetrics.mDragStartSequenceNumber;
|
||||
//mInputQueue->SetConfirmedMouseBlock(inputBlockId, apzc, aDragMetrics);
|
||||
}
|
||||
|
||||
HitTestingTreeNode*
|
||||
APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
|
||||
const FrameMetrics& aMetrics,
|
||||
@@ -352,6 +368,9 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
|
||||
node->SetHitTestData(GetEventRegions(aLayer), aLayer.GetTransform(),
|
||||
aLayer.GetClipRect() ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) : Nothing(),
|
||||
GetEventRegionsOverride(aParent, aLayer));
|
||||
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
|
||||
aLayer.GetScrollbarDirection(),
|
||||
aLayer.GetScrollbarSize());
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -522,6 +541,9 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
|
||||
GetEventRegionsOverride(aParent, aLayer));
|
||||
}
|
||||
|
||||
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
|
||||
aLayer.GetScrollbarDirection(),
|
||||
aLayer.GetScrollbarSize());
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -590,6 +612,18 @@ WillHandleWheelEvent(WidgetWheelEvent* aEvent)
|
||||
!EventStateManager::WheelEventNeedsDeltaMultipliers(aEvent);
|
||||
}
|
||||
|
||||
static bool
|
||||
WillHandleMouseEvent(const WidgetMouseEventBase& aEvent)
|
||||
{
|
||||
if (!gfxPrefs::APZDragEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return aEvent.mMessage == eMouseMove ||
|
||||
aEvent.mMessage == eMouseDown ||
|
||||
aEvent.mMessage == eMouseUp;
|
||||
}
|
||||
|
||||
template<typename PanGestureOrScrollWheelInput>
|
||||
static bool
|
||||
WillHandleInput(const PanGestureOrScrollWheelInput& aPanInput)
|
||||
@@ -635,6 +669,28 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
MultiTouchInput& touchInput = aEvent.AsMultiTouchInput();
|
||||
result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId);
|
||||
break;
|
||||
} case MOUSE_INPUT: {
|
||||
MouseInput& mouseInput = aEvent.AsMouseInput();
|
||||
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(mouseInput.mOrigin,
|
||||
&hitResult);
|
||||
if (apzc) {
|
||||
result = mInputQueue->ReceiveInputEvent(
|
||||
apzc,
|
||||
/* aTargetConfirmed = */ false,
|
||||
mouseInput, aOutInputBlockId);
|
||||
|
||||
// Update the out-parameters so they are what the caller expects.
|
||||
apzc->GetGuid(aOutTargetGuid);
|
||||
|
||||
// TODO Dagging on a scrollbar probably behaves differently from
|
||||
// the other input types in that the gecko coordinates are the same
|
||||
// as the screen coordinates even though the async transform on the APZC
|
||||
// is changing. I'm not really sure at this point and it'll take some
|
||||
// though to figure out properly.
|
||||
//mouseInput.mOrigin = untransformedOrigin;
|
||||
}
|
||||
break;
|
||||
} case SCROLLWHEEL_INPUT: {
|
||||
FlushRepaintsToClearScreenToGeckoTransform();
|
||||
|
||||
@@ -951,6 +1007,21 @@ APZCTreeManager::ProcessEvent(WidgetInputEvent& aEvent,
|
||||
return result;
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
APZCTreeManager::ProcessMouseEvent(WidgetMouseEventBase& aEvent,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId)
|
||||
{
|
||||
MouseInput input(aEvent);
|
||||
input.mOrigin = ScreenPoint(aEvent.refPoint.x, aEvent.refPoint.y);
|
||||
|
||||
nsEventStatus status = ReceiveInputEvent(input, aOutTargetGuid, aOutInputBlockId);
|
||||
|
||||
aEvent.refPoint.x = input.mOrigin.x;
|
||||
aEvent.refPoint.y = input.mOrigin.y;
|
||||
return status;
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
APZCTreeManager::ProcessWheelEvent(WidgetWheelEvent& aEvent,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
@@ -997,6 +1068,13 @@ APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent,
|
||||
}
|
||||
|
||||
switch (aEvent.mClass) {
|
||||
case eMouseEventClass: {
|
||||
WidgetMouseEventBase& mouseEvent = *aEvent.AsMouseEventBase();
|
||||
if (WillHandleMouseEvent(mouseEvent)) {
|
||||
return ProcessMouseEvent(mouseEvent, aOutTargetGuid, aOutInputBlockId);
|
||||
}
|
||||
return ProcessEvent(aEvent, aOutTargetGuid, aOutInputBlockId);
|
||||
}
|
||||
case eTouchEventClass: {
|
||||
WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent();
|
||||
MultiTouchInput touchInput(touchEvent);
|
||||
@@ -1528,6 +1606,34 @@ APZCTreeManager::FindTargetNode(HitTestingTreeNode* aNode,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<HitTestingTreeNode>
|
||||
APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics)
|
||||
{
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
|
||||
return FindScrollNode(mRootNode, aDragMetrics);
|
||||
}
|
||||
|
||||
HitTestingTreeNode*
|
||||
APZCTreeManager::FindScrollNode(HitTestingTreeNode* aNode,
|
||||
const AsyncDragMetrics& aDragMetrics)
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
|
||||
for (HitTestingTreeNode* node = aNode; node; node = node->GetPrevSibling()) {
|
||||
if (node->MatchesScrollDragMetrics(aDragMetrics)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
HitTestingTreeNode* match = FindScrollNode(node->GetLastChild(), aDragMetrics);
|
||||
if (match) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
|
||||
const ParentLayerPoint& aHitTestPoint,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "mozilla/layers/APZUtils.h" // for HitTestResult
|
||||
#include "mozilla/layers/TouchCounter.h"// for TouchCounter
|
||||
#include "mozilla/Monitor.h" // for Monitor
|
||||
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
|
||||
#include "mozilla/Vector.h" // for mozilla::Vector
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
@@ -41,6 +42,7 @@ enum AllowedTouchBehavior {
|
||||
};
|
||||
|
||||
class Layer;
|
||||
class AsyncDragMetrics;
|
||||
class AsyncPanZoomController;
|
||||
class CompositorParent;
|
||||
class OverscrollHandoffChain;
|
||||
@@ -96,6 +98,7 @@ class APZCTreeManager {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZCTreeManager)
|
||||
|
||||
typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior;
|
||||
typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
|
||||
|
||||
// Helper struct to hold some state while we build the hit-testing tree. The
|
||||
// sole purpose of this struct is to shorten the argument list to
|
||||
@@ -294,6 +297,12 @@ public:
|
||||
*/
|
||||
static float GetDPI() { return sDPI; }
|
||||
|
||||
/**
|
||||
* Find the hit testing node for the scrollbar thumb that matches these
|
||||
* drag metrics.
|
||||
*/
|
||||
nsRefPtr<HitTestingTreeNode> FindScrollNode(const AsyncDragMetrics& aDragMetrics);
|
||||
|
||||
/**
|
||||
* Sets allowed touch behavior values for current touch-session for specific
|
||||
* input block (determined by aInputBlock).
|
||||
@@ -385,6 +394,9 @@ public:
|
||||
nsRefPtr<const OverscrollHandoffChain> aOverscrollHandoffChain,
|
||||
bool aHandoff);
|
||||
|
||||
void StartScrollbarDrag(const ScrollableLayerGuid& aGuid,
|
||||
const AsyncDragMetrics& aDragMetrics);
|
||||
|
||||
/*
|
||||
* Build the chain of APZCs that will handle overscroll for a pan starting at |aInitialTarget|.
|
||||
*/
|
||||
@@ -427,6 +439,8 @@ private:
|
||||
HitTestingTreeNode* FindTargetNode(HitTestingTreeNode* aNode,
|
||||
const ScrollableLayerGuid& aGuid,
|
||||
GuidComparator aComparator);
|
||||
HitTestingTreeNode* FindScrollNode(HitTestingTreeNode* aNode,
|
||||
const AsyncDragMetrics& aDragMetrics);
|
||||
AsyncPanZoomController* GetAPZCAtPoint(HitTestingTreeNode* aNode,
|
||||
const ParentLayerPoint& aHitTestPoint,
|
||||
HitTestResult* aOutHitResult);
|
||||
@@ -445,6 +459,9 @@ private:
|
||||
nsEventStatus ProcessEvent(WidgetInputEvent& inputEvent,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId);
|
||||
nsEventStatus ProcessMouseEvent(WidgetMouseEventBase& aInput,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId);
|
||||
void UpdateWheelTransaction(WidgetInputEvent& aEvent);
|
||||
void UpdateZoomConstraintsRecursively(HitTestingTreeNode* aNode,
|
||||
const ZoomConstraints& aConstraints);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_layers_DragMetrics_h
|
||||
#define mozilla_layers_DragMetrics_h
|
||||
|
||||
#include "FrameMetrics.h"
|
||||
|
||||
namespace IPC {
|
||||
template <typename T> struct ParamTraits;
|
||||
} // namespace IPC
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
|
||||
class AsyncDragMetrics {
|
||||
friend struct IPC::ParamTraits<mozilla::layers::AsyncDragMetrics>;
|
||||
|
||||
public:
|
||||
enum DragDirection {
|
||||
NONE,
|
||||
VERTICAL,
|
||||
HORIZONTAL,
|
||||
SENTINEL,
|
||||
};
|
||||
|
||||
// IPC constructor
|
||||
AsyncDragMetrics()
|
||||
: mViewId(0)
|
||||
, mPresShellId(0)
|
||||
, mDragStartSequenceNumber(0)
|
||||
, mScrollbarDragOffset(0)
|
||||
, mDirection(NONE)
|
||||
{}
|
||||
|
||||
AsyncDragMetrics(const FrameMetrics::ViewID& aViewId,
|
||||
uint32_t aPresShellId,
|
||||
uint64_t aDragStartSequenceNumber,
|
||||
CSSIntCoord aScrollbarDragOffset,
|
||||
const CSSIntRect& aScrollTrack,
|
||||
DragDirection aDirection)
|
||||
: mViewId(aViewId)
|
||||
, mPresShellId(aPresShellId)
|
||||
, mDragStartSequenceNumber(aDragStartSequenceNumber)
|
||||
, mScrollbarDragOffset(aScrollbarDragOffset)
|
||||
, mScrollTrack(aScrollTrack)
|
||||
, mDirection(aDirection)
|
||||
{}
|
||||
|
||||
FrameMetrics::ViewID mViewId;
|
||||
uint32_t mPresShellId;
|
||||
uint64_t mDragStartSequenceNumber;
|
||||
CSSIntCoord mScrollbarDragOffset;
|
||||
CSSIntRect mScrollTrack;
|
||||
DragDirection mDirection;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Compositor.h" // for Compositor
|
||||
#include "FrameMetrics.h" // for FrameMetrics, etc
|
||||
#include "GestureEventListener.h" // for GestureEventListener
|
||||
#include "HitTestingTreeNode.h" // for HitTestingTreeNode
|
||||
#include "InputData.h" // for MultiTouchInput, etc
|
||||
#include "InputBlockState.h" // for InputBlockState, TouchBlockState
|
||||
#include "InputQueue.h" // for InputQueue
|
||||
@@ -952,6 +953,95 @@ AsyncPanZoomController::ArePointerEventsConsumable(TouchBlockState* aBlock, uint
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static float GetAxisStart(AsyncDragMetrics::DragDirection aDir, T aValue) {
|
||||
if (aDir == AsyncDragMetrics::HORIZONTAL) {
|
||||
return aValue.x;
|
||||
} else {
|
||||
return aValue.y;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static float GetAxisEnd(AsyncDragMetrics::DragDirection aDir, T aValue) {
|
||||
if (aDir == AsyncDragMetrics::HORIZONTAL) {
|
||||
return aValue.x + aValue.width;
|
||||
} else {
|
||||
return aValue.y + aValue.height;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static float GetAxisSize(AsyncDragMetrics::DragDirection aDir, T aValue) {
|
||||
if (aDir == AsyncDragMetrics::HORIZONTAL) {
|
||||
return aValue.width;
|
||||
} else {
|
||||
return aValue.height;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static float GetAxisScale(AsyncDragMetrics::DragDirection aDir, T aValue) {
|
||||
if (aDir == AsyncDragMetrics::HORIZONTAL) {
|
||||
return aValue.xScale;
|
||||
} else {
|
||||
return aValue.yScale;
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent,
|
||||
const AsyncDragMetrics& aDragMetrics)
|
||||
{
|
||||
nsRefPtr<HitTestingTreeNode> node =
|
||||
GetApzcTreeManager()->FindScrollNode(aDragMetrics);
|
||||
if (!node) {
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
CSSPoint scrollFramePoint = aEvent.mLocalOrigin / GetFrameMetrics().GetZoom();
|
||||
// The scrollbar can be transformed with the frame but the pres shell
|
||||
// resolution is only applied to the scroll frame.
|
||||
CSSPoint scrollbarPoint = scrollFramePoint * GetFrameMetrics().GetPresShellResolution();
|
||||
CSSRect cssCompositionBound = GetFrameMetrics().GetCompositionBounds() / GetFrameMetrics().GetZoom();
|
||||
|
||||
float mousePosition = GetAxisStart(aDragMetrics.mDirection, scrollbarPoint) -
|
||||
aDragMetrics.mScrollbarDragOffset -
|
||||
GetAxisStart(aDragMetrics.mDirection, cssCompositionBound) -
|
||||
GetAxisStart(aDragMetrics.mDirection, aDragMetrics.mScrollTrack);
|
||||
|
||||
float scrollMax = GetAxisEnd(aDragMetrics.mDirection, aDragMetrics.mScrollTrack);
|
||||
scrollMax -= node->GetScrollSize() /
|
||||
GetAxisScale(aDragMetrics.mDirection, GetFrameMetrics().GetZoom()) *
|
||||
GetFrameMetrics().GetPresShellResolution();
|
||||
|
||||
float scrollPercent = mousePosition / scrollMax;
|
||||
|
||||
float minScrollPosition =
|
||||
GetAxisStart(aDragMetrics.mDirection, GetFrameMetrics().GetScrollableRect().TopLeft());
|
||||
float maxScrollPosition =
|
||||
GetAxisSize(aDragMetrics.mDirection, GetFrameMetrics().GetScrollableRect()) -
|
||||
GetAxisSize(aDragMetrics.mDirection, GetFrameMetrics().GetCompositionBounds());
|
||||
float scrollPosition = scrollPercent * maxScrollPosition;
|
||||
|
||||
scrollPosition = std::max(scrollPosition, minScrollPosition);
|
||||
scrollPosition = std::min(scrollPosition, maxScrollPosition);
|
||||
|
||||
CSSPoint scrollOffset;
|
||||
if (aDragMetrics.mDirection == AsyncDragMetrics::HORIZONTAL) {
|
||||
scrollOffset = CSSPoint(scrollPosition, 0);
|
||||
} else {
|
||||
scrollOffset = CSSPoint(0, scrollPosition);
|
||||
}
|
||||
mFrameMetrics.SetScrollOffset(scrollOffset);
|
||||
ScheduleCompositeAndMaybeRepaint();
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
|
||||
// Here we consume the events. This means that the content scrollbars
|
||||
// will only see the initial mouse down and the final mouse up.
|
||||
// APZ will still update the scroll position.
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent,
|
||||
const Matrix4x4& aTransformToApzc) {
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
@@ -961,7 +1051,7 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent,
|
||||
switch (aEvent.mInputType) {
|
||||
case MULTITOUCH_INPUT: {
|
||||
MultiTouchInput multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
if (!multiTouchInput.TransformToLocal(aTransformToApzc)) {
|
||||
if (!multiTouchInput.TransformToLocal(aTransformToApzc)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1001,6 +1091,16 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MOUSE_INPUT: {
|
||||
ScrollWheelInput scrollInput = aEvent.AsScrollWheelInput();
|
||||
if (!scrollInput.TransformToLocal(aTransformToApzc)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// TODO Need to implement blocks to properly handle this.
|
||||
//rv = HandleDragEvent(scrollInput, dragMetrics);
|
||||
break;
|
||||
}
|
||||
case SCROLLWHEEL_INPUT: {
|
||||
ScrollWheelInput scrollInput = aEvent.AsScrollWheelInput();
|
||||
if (!scrollInput.TransformToLocal(aTransformToApzc)) {
|
||||
@@ -2950,6 +3050,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
|
||||
bool smoothScrollRequested = aLayerMetrics.GetDoSmoothScroll()
|
||||
&& (aLayerMetrics.GetScrollGeneration() != mFrameMetrics.GetScrollGeneration());
|
||||
|
||||
// TODO if we're in a drag and scrollOffsetUpdated is set then we want to
|
||||
// ignore it
|
||||
|
||||
if (aIsFirstPaint || isDefault) {
|
||||
// Initialize our internal state to something sane when the content
|
||||
// that was just painted is something we knew nothing about previously
|
||||
|
||||
@@ -40,6 +40,7 @@ class SharedMemoryBasic;
|
||||
|
||||
namespace layers {
|
||||
|
||||
class AsyncDragMetrics;
|
||||
struct ScrollableLayerGuid;
|
||||
class CompositorParent;
|
||||
class GestureEventListener;
|
||||
@@ -266,6 +267,9 @@ public:
|
||||
*/
|
||||
void SendAsyncScrollEvent();
|
||||
|
||||
nsEventStatus HandleDragEvent(const MouseInput& aEvent,
|
||||
const AsyncDragMetrics& aDragMetrics);
|
||||
|
||||
/**
|
||||
* Handler for events which should not be intercepted by the touch listener.
|
||||
*/
|
||||
|
||||
@@ -86,6 +86,30 @@ HitTestingTreeNode::SetLastChild(HitTestingTreeNode* aChild)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HitTestingTreeNode::SetScrollbarData(FrameMetrics::ViewID aScrollViewId, Layer::ScrollDirection aDir, int32_t aScrollSize)
|
||||
{
|
||||
mScrollViewId = aScrollViewId;
|
||||
mScrollDir = aDir;
|
||||
mScrollSize = aScrollSize;;
|
||||
}
|
||||
|
||||
bool
|
||||
HitTestingTreeNode::MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const
|
||||
{
|
||||
return ((mScrollDir == Layer::HORIZONTAL &&
|
||||
aDragMetrics.mDirection == AsyncDragMetrics::HORIZONTAL) ||
|
||||
(mScrollDir == Layer::VERTICAL &&
|
||||
aDragMetrics.mDirection == AsyncDragMetrics::VERTICAL)) &&
|
||||
mScrollViewId == aDragMetrics.mViewId;
|
||||
}
|
||||
|
||||
int32_t
|
||||
HitTestingTreeNode::GetScrollSize() const
|
||||
{
|
||||
return mScrollSize;
|
||||
}
|
||||
|
||||
void
|
||||
HitTestingTreeNode::SetPrevSibling(HitTestingTreeNode* aSibling)
|
||||
{
|
||||
|
||||
@@ -9,14 +9,16 @@
|
||||
|
||||
#include "APZUtils.h" // for HitTestResult
|
||||
#include "FrameMetrics.h" // for ScrollableLayerGuid
|
||||
#include "Layers.h"
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
||||
#include "mozilla/layers/LayersTypes.h" // for EventRegions
|
||||
#include "mozilla/Maybe.h" // for Maybe
|
||||
#include "mozilla/nsRefPtr.h" // for nsRefPtr
|
||||
#include "mozilla/nsRefPtr.h" // for nsRefPtr
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class AsyncDragMetrics;
|
||||
class AsyncPanZoomController;
|
||||
|
||||
/**
|
||||
@@ -87,6 +89,13 @@ public:
|
||||
const Maybe<ParentLayerIntRegion>& aClipRegion,
|
||||
const EventRegionsOverride& aOverride);
|
||||
bool IsOutsideClip(const ParentLayerPoint& aPoint) const;
|
||||
|
||||
/* Scrollbar info */
|
||||
|
||||
void SetScrollbarData(FrameMetrics::ViewID aScrollViewId, Layer::ScrollDirection aDir, int32_t aScrollSize);
|
||||
bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
|
||||
int32_t GetScrollSize() const;
|
||||
|
||||
/* Convert aPoint into the LayerPixel space for the layer corresponding to
|
||||
* this node. */
|
||||
Maybe<LayerPoint> Untransform(const ParentLayerPoint& aPoint) const;
|
||||
@@ -111,6 +120,10 @@ private:
|
||||
|
||||
uint64_t mLayersId;
|
||||
|
||||
FrameMetrics::ViewID mScrollViewId;
|
||||
Layer::ScrollDirection mScrollDir;
|
||||
int32_t mScrollSize;
|
||||
|
||||
/* Let {L,M} be the {layer, scrollable metrics} pair that this node
|
||||
* corresponds to in the layer tree. mEventRegions contains the event regions
|
||||
* from L, in the case where event-regions are enabled. If event-regions are
|
||||
|
||||
@@ -52,7 +52,7 @@ BasicCanvasLayer::Paint(DrawTarget* aDT,
|
||||
|
||||
FillRectWithMask(aDT, aDeviceOffset,
|
||||
Rect(0, 0, mBounds.width, mBounds.height),
|
||||
mSurface, ToFilter(mFilter),
|
||||
mSurface, mFilter,
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
aMaskLayer);
|
||||
|
||||
|
||||
@@ -85,8 +85,8 @@ BasicImageLayer::Paint(DrawTarget* aDT,
|
||||
}
|
||||
|
||||
gfx::IntSize size = mSize = surface->GetSize();
|
||||
FillRectWithMask(aDT, aDeviceOffset, Rect(0, 0, size.width, size.height),
|
||||
surface, ToFilter(mFilter),
|
||||
FillRectWithMask(aDT, aDeviceOffset, Rect(0, 0, size.width, size.height),
|
||||
surface, mFilter,
|
||||
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
|
||||
aMaskLayer);
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ ClientCanvasLayer::Initialize(const Data& aData)
|
||||
#elif defined(MOZ_WIDGET_GONK)
|
||||
factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, forwarder, mFlags);
|
||||
#elif defined(GL_PROVIDER_GLX)
|
||||
if (sGLXLibrary.UseTextureFromPixmap())
|
||||
if (sGLXLibrary.UseSurfaceSharing())
|
||||
factory = SurfaceFactory_GLXDrawable::Create(mGLContext, caps, forwarder, mFlags);
|
||||
#else
|
||||
if (mGLContext->GetContextType() == GLContextType::EGL) {
|
||||
|
||||
@@ -127,6 +127,10 @@ public:
|
||||
|
||||
explicit CompositableClient(CompositableForwarder* aForwarder, TextureFlags aFlags = TextureFlags::NO_FLAGS);
|
||||
|
||||
virtual void Dump(std::stringstream& aStream,
|
||||
const char* aPrefix="",
|
||||
bool aDumpHtml=false) {};
|
||||
|
||||
virtual TextureInfo GetTextureInfo() const = 0;
|
||||
|
||||
LayersBackend GetCompositorBackendType() const;
|
||||
|
||||
@@ -88,10 +88,6 @@ public:
|
||||
|
||||
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
|
||||
|
||||
virtual void Dump(std::stringstream& aStream,
|
||||
const char* aPrefix="",
|
||||
bool aDumpHtml=false) {};
|
||||
|
||||
virtual void Clear() = 0;
|
||||
virtual RotatedContentBuffer::PaintState BeginPaintBuffer(PaintedLayer* aLayer,
|
||||
uint32_t aFlags) = 0;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "CanvasLayerComposite.h"
|
||||
#include "composite/CompositableHost.h" // for CompositableHost
|
||||
#include "gfx2DGlue.h" // for ToFilter
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "gfxUtils.h" // for gfxUtils, etc
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
||||
#include "mozilla/gfx/Point.h" // for Point
|
||||
@@ -129,7 +128,7 @@ CanvasLayerComposite::CleanupResources()
|
||||
gfx::Filter
|
||||
CanvasLayerComposite::GetEffectFilter()
|
||||
{
|
||||
GraphicsFilter filter = mFilter;
|
||||
gfx::Filter filter = mFilter;
|
||||
#ifdef ANDROID
|
||||
// Bug 691354
|
||||
// Using the LINEAR filter we get unexplained artifacts.
|
||||
@@ -137,10 +136,10 @@ CanvasLayerComposite::GetEffectFilter()
|
||||
Matrix matrix;
|
||||
bool is2D = GetEffectiveTransform().Is2D(&matrix);
|
||||
if (is2D && !ThebesMatrix(matrix).HasNonTranslationOrFlip()) {
|
||||
filter = GraphicsFilter::FILTER_NEAREST;
|
||||
filter = Filter::POINT;
|
||||
}
|
||||
#endif
|
||||
return gfx::ToFilter(filter);
|
||||
return filter;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -91,6 +91,15 @@ public:
|
||||
return img ? img->mFrameID : -1;
|
||||
}
|
||||
|
||||
int32_t GetProducerID()
|
||||
{
|
||||
const TimedImage* img = ChooseImage();
|
||||
return img ? img->mProducerID : -1;
|
||||
}
|
||||
|
||||
int32_t GetLastFrameID() const { return mLastFrameID; }
|
||||
int32_t GetLastProducerID() const { return mLastProducerID; }
|
||||
|
||||
enum Bias {
|
||||
// Don't apply bias to frame times
|
||||
BIAS_NONE,
|
||||
|
||||
@@ -166,7 +166,7 @@ ImageLayerComposite::CleanupResources()
|
||||
gfx::Filter
|
||||
ImageLayerComposite::GetEffectFilter()
|
||||
{
|
||||
return gfx::ToFilter(mFilter);
|
||||
return mFilter;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -544,6 +544,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
|
||||
, mEGLSurfaceSize(aSurfaceWidth, aSurfaceHeight)
|
||||
, mPauseCompositionMonitor("PauseCompositionMonitor")
|
||||
, mResumeCompositionMonitor("ResumeCompositionMonitor")
|
||||
, mRootLayerTreeID(AllocateLayerTreeId())
|
||||
, mOverrideComposeReadiness(false)
|
||||
, mForceCompositionTask(nullptr)
|
||||
, mCompositorThreadHolder(sCompositorThreadHolder)
|
||||
@@ -563,7 +564,6 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
|
||||
|
||||
CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(SetThreadPriority));
|
||||
|
||||
mRootLayerTreeID = AllocateLayerTreeId();
|
||||
|
||||
{ // scope lock
|
||||
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
||||
|
||||
@@ -459,7 +459,7 @@ protected:
|
||||
mozilla::Monitor mResumeCompositionMonitor;
|
||||
|
||||
uint64_t mCompositorID;
|
||||
uint64_t mRootLayerTreeID;
|
||||
const uint64_t mRootLayerTreeID;
|
||||
|
||||
bool mOverrideComposeReadiness;
|
||||
CancelableTask* mForceCompositionTask;
|
||||
|
||||
@@ -17,7 +17,7 @@ include "gfxipc/ShadowLayerUtils.h";
|
||||
include "mozilla/GfxMessageUtils.h";
|
||||
include "ImageLayers.h";
|
||||
|
||||
using mozilla::GraphicsFilterType from "mozilla/GfxMessageUtils.h";
|
||||
using mozilla::gfx::Filter from "mozilla/gfx/2D.h";
|
||||
using struct mozilla::gfx::Color from "mozilla/gfx/2D.h";
|
||||
using struct mozilla::gfx::Point3D from "mozilla/gfx/Point.h";
|
||||
using mozilla::gfx::IntPoint from "mozilla/gfx/Point.h";
|
||||
@@ -252,14 +252,14 @@ struct ContainerLayerAttributes {
|
||||
uint64_t hmdInfo;
|
||||
};
|
||||
struct ColorLayerAttributes { LayerColor color; IntRect bounds; };
|
||||
struct CanvasLayerAttributes { GraphicsFilterType filter; IntRect bounds; };
|
||||
struct CanvasLayerAttributes { Filter filter; IntRect bounds; };
|
||||
struct RefLayerAttributes {
|
||||
int64_t id;
|
||||
// TODO: Once bug 1132895 is fixed we shouldn't need to propagate the override
|
||||
// explicitly here.
|
||||
EventRegionsOverride eventRegionsOverride;
|
||||
};
|
||||
struct ImageLayerAttributes { GraphicsFilterType filter; IntSize scaleToSize; ScaleMode scaleMode; };
|
||||
struct ImageLayerAttributes { Filter filter; IntSize scaleToSize; ScaleMode scaleMode; };
|
||||
|
||||
union SpecificLayerAttributes {
|
||||
null_t;
|
||||
|
||||
@@ -94,6 +94,7 @@ EXPORTS.mozilla.layers += [
|
||||
# proper interface for the code there
|
||||
'apz/src/APZCTreeManager.h',
|
||||
'apz/src/APZUtils.h',
|
||||
'apz/src/AsyncDragMetrics.h',
|
||||
'apz/src/AsyncPanZoomAnimation.h',
|
||||
'apz/src/TouchCounter.h',
|
||||
'apz/testutil/APZTestData.h',
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "Layers.h" // for WriteSnapshotToDumpFile
|
||||
#include "LayerScope.h" // for LayerScope
|
||||
#include "gfx2DGlue.h" // for ThebesFilter
|
||||
#include "gfxCrashReporterUtils.h" // for ScopedGfxFeatureReporter
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "gfxPrefs.h" // for gfxPrefs
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "Layers.h" // for WriteSnapshotToDumpFile
|
||||
#include "LayerScope.h" // for LayerScope
|
||||
#include "gfx2DGlue.h" // for ThebesFilter
|
||||
#include "gfxCrashReporterUtils.h" // for ScopedGfxFeatureReporter
|
||||
#include "gfxMatrix.h" // for gfxMatrix
|
||||
#include "GraphicsFilter.h" // for GraphicsFilter
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "gfxPrefs.h" // for gfxPrefs
|
||||
#include "gfxRect.h" // for gfxRect
|
||||
|
||||
@@ -1186,16 +1186,10 @@ bool LayersPacket_Layer_Filter_IsValid(int value) {
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_FAST;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_GOOD;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_BEST;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_NEAREST;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_BILINEAR;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_GAUSSIAN;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_LINEAR;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_POINT;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::FILTER_SENTINEL;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::Filter_MIN;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer::Filter_MAX;
|
||||
const int LayersPacket_Layer::Filter_ARRAYSIZE;
|
||||
#endif // _MSC_VER
|
||||
#ifndef _MSC_VER
|
||||
const int LayersPacket_Layer_Size::kWFieldNumber;
|
||||
|
||||
@@ -76,18 +76,12 @@ const LayersPacket_Layer_ScrollingDirect LayersPacket_Layer_ScrollingDirect_Scro
|
||||
const int LayersPacket_Layer_ScrollingDirect_ScrollingDirect_ARRAYSIZE = LayersPacket_Layer_ScrollingDirect_ScrollingDirect_MAX + 1;
|
||||
|
||||
enum LayersPacket_Layer_Filter {
|
||||
LayersPacket_Layer_Filter_FILTER_FAST = 0,
|
||||
LayersPacket_Layer_Filter_FILTER_GOOD = 1,
|
||||
LayersPacket_Layer_Filter_FILTER_BEST = 2,
|
||||
LayersPacket_Layer_Filter_FILTER_NEAREST = 3,
|
||||
LayersPacket_Layer_Filter_FILTER_BILINEAR = 4,
|
||||
LayersPacket_Layer_Filter_FILTER_GAUSSIAN = 5,
|
||||
LayersPacket_Layer_Filter_FILTER_SENTINEL = 6
|
||||
LayersPacket_Layer_Filter_FILTER_GOOD = 0,
|
||||
LayersPacket_Layer_Filter_FILTER_LINEAR = 1,
|
||||
LayersPacket_Layer_Filter_FILTER_POINT = 2,
|
||||
LayersPacket_Layer_Filter_FILTER_SENTINEL = 3
|
||||
};
|
||||
bool LayersPacket_Layer_Filter_IsValid(int value);
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer_Filter_Filter_MIN = LayersPacket_Layer_Filter_FILTER_FAST;
|
||||
const LayersPacket_Layer_Filter LayersPacket_Layer_Filter_Filter_MAX = LayersPacket_Layer_Filter_FILTER_SENTINEL;
|
||||
const int LayersPacket_Layer_Filter_Filter_ARRAYSIZE = LayersPacket_Layer_Filter_Filter_MAX + 1;
|
||||
|
||||
enum Packet_DataType {
|
||||
Packet_DataType_FRAMESTART = 1,
|
||||
@@ -1159,22 +1153,13 @@ class LayersPacket_Layer : public ::google::protobuf::MessageLite {
|
||||
LayersPacket_Layer_ScrollingDirect_ScrollingDirect_ARRAYSIZE;
|
||||
|
||||
typedef LayersPacket_Layer_Filter Filter;
|
||||
static const Filter FILTER_FAST = LayersPacket_Layer_Filter_FILTER_FAST;
|
||||
static const Filter FILTER_GOOD = LayersPacket_Layer_Filter_FILTER_GOOD;
|
||||
static const Filter FILTER_BEST = LayersPacket_Layer_Filter_FILTER_BEST;
|
||||
static const Filter FILTER_NEAREST = LayersPacket_Layer_Filter_FILTER_NEAREST;
|
||||
static const Filter FILTER_BILINEAR = LayersPacket_Layer_Filter_FILTER_BILINEAR;
|
||||
static const Filter FILTER_GAUSSIAN = LayersPacket_Layer_Filter_FILTER_GAUSSIAN;
|
||||
static const Filter FILTER_LINEAR = LayersPacket_Layer_Filter_FILTER_LINEAR;
|
||||
static const Filter FILTER_POINT = LayersPacket_Layer_Filter_FILTER_POINT;
|
||||
static const Filter FILTER_SENTINEL = LayersPacket_Layer_Filter_FILTER_SENTINEL;
|
||||
static inline bool Filter_IsValid(int value) {
|
||||
return LayersPacket_Layer_Filter_IsValid(value);
|
||||
}
|
||||
static const Filter Filter_MIN =
|
||||
LayersPacket_Layer_Filter_Filter_MIN;
|
||||
static const Filter Filter_MAX =
|
||||
LayersPacket_Layer_Filter_Filter_MAX;
|
||||
static const int Filter_ARRAYSIZE =
|
||||
LayersPacket_Layer_Filter_Filter_ARRAYSIZE;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GraphicsFilter_h
|
||||
#define GraphicsFilter_h
|
||||
|
||||
enum class GraphicsFilter : int {
|
||||
FILTER_FAST,
|
||||
FILTER_GOOD,
|
||||
FILTER_BEST,
|
||||
FILTER_NEAREST,
|
||||
FILTER_BILINEAR,
|
||||
FILTER_GAUSSIAN,
|
||||
FILTER_SENTINEL
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+2
-47
@@ -1,3 +1,5 @@
|
||||
/* -*- 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/. */
|
||||
@@ -5,7 +7,6 @@
|
||||
#ifndef GFX_2D_GLUE_H
|
||||
#define GFX_2D_GLUE_H
|
||||
|
||||
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxRect.h"
|
||||
#include "gfxMatrix.h"
|
||||
@@ -60,52 +61,6 @@ inline Size ToSize(const gfxSize &aSize)
|
||||
return Size(Float(aSize.width), Float(aSize.height));
|
||||
}
|
||||
|
||||
inline Filter ToFilter(GraphicsFilter aFilter)
|
||||
{
|
||||
switch (aFilter) {
|
||||
case GraphicsFilter::FILTER_NEAREST:
|
||||
return Filter::POINT;
|
||||
case GraphicsFilter::FILTER_GOOD:
|
||||
return Filter::GOOD;
|
||||
default:
|
||||
return Filter::LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
inline GraphicsFilter ThebesFilter(Filter aFilter)
|
||||
{
|
||||
switch (aFilter) {
|
||||
case Filter::POINT:
|
||||
return GraphicsFilter::FILTER_NEAREST;
|
||||
default:
|
||||
return GraphicsFilter::FILTER_BEST;
|
||||
}
|
||||
}
|
||||
|
||||
inline ExtendMode ToExtendMode(gfxPattern::GraphicsExtend aExtend)
|
||||
{
|
||||
switch (aExtend) {
|
||||
case gfxPattern::EXTEND_REPEAT:
|
||||
return ExtendMode::REPEAT;
|
||||
case gfxPattern::EXTEND_REFLECT:
|
||||
return ExtendMode::REFLECT;
|
||||
default:
|
||||
return ExtendMode::CLAMP;
|
||||
}
|
||||
}
|
||||
|
||||
inline gfxPattern::GraphicsExtend ThebesExtend(ExtendMode aExtend)
|
||||
{
|
||||
switch (aExtend) {
|
||||
case ExtendMode::REPEAT:
|
||||
return gfxPattern::EXTEND_REPEAT;
|
||||
case ExtendMode::REFLECT:
|
||||
return gfxPattern::EXTEND_REFLECT;
|
||||
default:
|
||||
return gfxPattern::EXTEND_PAD;
|
||||
}
|
||||
}
|
||||
|
||||
inline gfxPoint ThebesPoint(const Point &aPoint)
|
||||
{
|
||||
return gfxPoint(aPoint.x, aPoint.y);
|
||||
|
||||
@@ -34,7 +34,7 @@ gfxSurfaceDrawable::DrawWithSamplingRect(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const gfxRect& aSamplingRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
gfxFloat aOpacity)
|
||||
{
|
||||
if (!mSourceSurface) {
|
||||
@@ -60,7 +60,7 @@ bool
|
||||
gfxSurfaceDrawable::Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
gfxFloat aOpacity,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
@@ -77,7 +77,7 @@ gfxSurfaceDrawable::DrawInternal(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const IntRect& aSamplingRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
gfxFloat aOpacity,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
@@ -91,7 +91,7 @@ gfxSurfaceDrawable::DrawInternal(gfxContext* aContext,
|
||||
patternTransform.Invert();
|
||||
|
||||
SurfacePattern pattern(mSourceSurface, extend,
|
||||
patternTransform, ToFilter(aFilter), aSamplingRect);
|
||||
patternTransform, aFilter, aSamplingRect);
|
||||
|
||||
Rect fillRect = ToRect(aFillRect);
|
||||
DrawTarget* dt = aContext->GetDrawTarget();
|
||||
@@ -116,7 +116,7 @@ gfxCallbackDrawable::gfxCallbackDrawable(gfxDrawingCallback* aCallback,
|
||||
}
|
||||
|
||||
already_AddRefed<gfxSurfaceDrawable>
|
||||
gfxCallbackDrawable::MakeSurfaceDrawable(const GraphicsFilter aFilter)
|
||||
gfxCallbackDrawable::MakeSurfaceDrawable(const Filter aFilter)
|
||||
{
|
||||
SurfaceFormat format =
|
||||
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(gfxContentType::COLOR_ALPHA);
|
||||
@@ -141,7 +141,7 @@ bool
|
||||
gfxCallbackDrawable::Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
gfxFloat aOpacity,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
|
||||
virtual bool operator()(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix())
|
||||
{
|
||||
return mDrawable->Draw(aContext, aFillRect, false, aFilter, 1.0,
|
||||
@@ -205,7 +205,7 @@ bool
|
||||
gfxPatternDrawable::Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
gfxFloat aOpacity,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
|
||||
+19
-20
@@ -9,7 +9,6 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "gfxRect.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "GraphicsFilter.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
class gfxContext;
|
||||
@@ -36,14 +35,14 @@ public:
|
||||
virtual bool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
gfxFloat aOpacity = 1.0,
|
||||
const gfxMatrix& aTransform = gfxMatrix()) = 0;
|
||||
virtual bool DrawWithSamplingRect(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const gfxRect& aSamplingRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
gfxFloat aOpacity = 1.0)
|
||||
{
|
||||
return false;
|
||||
@@ -71,14 +70,14 @@ public:
|
||||
virtual bool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
gfxFloat aOpacity = 1.0,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
virtual bool DrawWithSamplingRect(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const gfxRect& aSamplingRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
gfxFloat aOpacity = 1.0);
|
||||
|
||||
protected:
|
||||
@@ -86,7 +85,7 @@ protected:
|
||||
const gfxRect& aFillRect,
|
||||
const mozilla::gfx::IntRect& aSamplingRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
gfxFloat aOpacity,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
|
||||
@@ -113,9 +112,9 @@ public:
|
||||
* @return whether drawing was successful
|
||||
*/
|
||||
virtual bool operator()(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const GraphicsFilter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix()) = 0;
|
||||
const gfxRect& aFillRect,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
const gfxMatrix& aTransform = gfxMatrix()) = 0;
|
||||
|
||||
};
|
||||
|
||||
@@ -129,14 +128,14 @@ public:
|
||||
virtual ~gfxCallbackDrawable() {}
|
||||
|
||||
virtual bool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
gfxFloat aOpacity = 1.0,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
gfxFloat aOpacity = 1.0,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
|
||||
protected:
|
||||
already_AddRefed<gfxSurfaceDrawable> MakeSurfaceDrawable(const GraphicsFilter aFilter = GraphicsFilter::FILTER_FAST);
|
||||
already_AddRefed<gfxSurfaceDrawable> MakeSurfaceDrawable(mozilla::gfx::Filter aFilter = mozilla::gfx::Filter::LINEAR);
|
||||
|
||||
nsRefPtr<gfxDrawingCallback> mCallback;
|
||||
nsRefPtr<gfxSurfaceDrawable> mSurfaceDrawable;
|
||||
@@ -153,11 +152,11 @@ public:
|
||||
virtual ~gfxPatternDrawable();
|
||||
|
||||
virtual bool Draw(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const GraphicsFilter& aFilter,
|
||||
gfxFloat aOpacity = 1.0,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
const gfxRect& aFillRect,
|
||||
bool aRepeat,
|
||||
const mozilla::gfx::Filter& aFilter,
|
||||
gfxFloat aOpacity = 1.0,
|
||||
const gfxMatrix& aTransform = gfxMatrix());
|
||||
|
||||
protected:
|
||||
already_AddRefed<gfxCallbackDrawable> MakeCallbackDrawable();
|
||||
|
||||
+15
-23
@@ -20,14 +20,14 @@
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
gfxPattern::gfxPattern(const Color& aColor)
|
||||
: mExtend(EXTEND_NONE)
|
||||
: mExtend(ExtendMode::CLAMP)
|
||||
{
|
||||
mGfxPattern.InitColorPattern(ToDeviceColor(aColor));
|
||||
}
|
||||
|
||||
// linear
|
||||
gfxPattern::gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1)
|
||||
: mExtend(EXTEND_NONE)
|
||||
: mExtend(ExtendMode::CLAMP)
|
||||
{
|
||||
mGfxPattern.InitLinearGradientPattern(Point(x0, y0), Point(x1, y1), nullptr);
|
||||
}
|
||||
@@ -35,7 +35,7 @@ gfxPattern::gfxPattern(gfxFloat x0, gfxFloat y0, gfxFloat x1, gfxFloat y1)
|
||||
// radial
|
||||
gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
|
||||
gfxFloat cx1, gfxFloat cy1, gfxFloat radius1)
|
||||
: mExtend(EXTEND_NONE)
|
||||
: mExtend(ExtendMode::CLAMP)
|
||||
{
|
||||
mGfxPattern.InitRadialGradientPattern(Point(cx0, cy0), Point(cx1, cy1),
|
||||
radius0, radius1, nullptr);
|
||||
@@ -44,9 +44,9 @@ gfxPattern::gfxPattern(gfxFloat cx0, gfxFloat cy0, gfxFloat radius0,
|
||||
// Azure
|
||||
gfxPattern::gfxPattern(SourceSurface *aSurface, const Matrix &aPatternToUserSpace)
|
||||
: mPatternToUserSpace(aPatternToUserSpace)
|
||||
, mExtend(EXTEND_NONE)
|
||||
, mExtend(ExtendMode::CLAMP)
|
||||
{
|
||||
mGfxPattern.InitSurfacePattern(aSurface, ToExtendMode(mExtend), Matrix(), // matrix is overridden in GetPattern()
|
||||
mGfxPattern.InitSurfacePattern(aSurface, mExtend, Matrix(), // matrix is overridden in GetPattern()
|
||||
mozilla::gfx::Filter::GOOD);
|
||||
}
|
||||
|
||||
@@ -75,8 +75,7 @@ gfxPattern::SetColorStops(GradientStops* aStops)
|
||||
void
|
||||
gfxPattern::CacheColorStops(const DrawTarget *aDT)
|
||||
{
|
||||
mStops = gfxGradientCache::GetOrCreateGradientStops(aDT, mStopsList,
|
||||
ToExtendMode(mExtend));
|
||||
mStops = gfxGradientCache::GetOrCreateGradientStops(aDT, mStopsList, mExtend);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -132,15 +131,14 @@ gfxPattern::GetPattern(const DrawTarget *aTarget,
|
||||
if (!mStops &&
|
||||
!mStopsList.IsEmpty()) {
|
||||
mStops = aTarget->CreateGradientStops(mStopsList.Elements(),
|
||||
mStopsList.Length(),
|
||||
ToExtendMode(mExtend));
|
||||
mStopsList.Length(), mExtend);
|
||||
}
|
||||
|
||||
switch (mGfxPattern.GetPattern()->GetType()) {
|
||||
case PatternType::SURFACE: {
|
||||
SurfacePattern* surfacePattern = static_cast<SurfacePattern*>(mGfxPattern.GetPattern());
|
||||
surfacePattern->mMatrix = patternToUser;
|
||||
surfacePattern->mExtendMode = ToExtendMode(mExtend);
|
||||
surfacePattern->mExtendMode = mExtend;
|
||||
break;
|
||||
}
|
||||
case PatternType::LINEAR_GRADIENT: {
|
||||
@@ -164,9 +162,9 @@ gfxPattern::GetPattern(const DrawTarget *aTarget,
|
||||
}
|
||||
|
||||
void
|
||||
gfxPattern::SetExtend(GraphicsExtend extend)
|
||||
gfxPattern::SetExtend(ExtendMode aExtend)
|
||||
{
|
||||
mExtend = extend;
|
||||
mExtend = aExtend;
|
||||
mStops = nullptr;
|
||||
}
|
||||
|
||||
@@ -183,29 +181,23 @@ gfxPattern::IsOpaque()
|
||||
return false;
|
||||
}
|
||||
|
||||
gfxPattern::GraphicsExtend
|
||||
gfxPattern::Extend() const
|
||||
{
|
||||
return mExtend;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPattern::SetFilter(GraphicsFilter filter)
|
||||
gfxPattern::SetFilter(gfx::Filter filter)
|
||||
{
|
||||
if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
|
||||
return;
|
||||
}
|
||||
|
||||
static_cast<SurfacePattern*>(mGfxPattern.GetPattern())->mFilter = ToFilter(filter);
|
||||
static_cast<SurfacePattern*>(mGfxPattern.GetPattern())->mFilter = filter;
|
||||
}
|
||||
|
||||
GraphicsFilter
|
||||
Filter
|
||||
gfxPattern::Filter() const
|
||||
{
|
||||
if (mGfxPattern.GetPattern()->GetType() != PatternType::SURFACE) {
|
||||
return GraphicsFilter::FILTER_GOOD;
|
||||
return gfx::Filter::GOOD;
|
||||
}
|
||||
return ThebesFilter(static_cast<const SurfacePattern*>(mGfxPattern.GetPattern())->mFilter);
|
||||
return static_cast<const SurfacePattern*>(mGfxPattern.GetPattern())->mFilter;
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
+5
-24
@@ -12,7 +12,6 @@
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/PatternHelpers.h"
|
||||
#include "GraphicsFilter.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTArray.h"
|
||||
@@ -53,31 +52,13 @@ public:
|
||||
mozilla::gfx::Matrix *aOriginalUserToDevice = nullptr);
|
||||
bool IsOpaque();
|
||||
|
||||
enum GraphicsExtend {
|
||||
EXTEND_NONE,
|
||||
EXTEND_REPEAT,
|
||||
EXTEND_REFLECT,
|
||||
EXTEND_PAD,
|
||||
|
||||
// Our own private flag for setting either NONE or PAD,
|
||||
// depending on what the platform does for NONE. This is only
|
||||
// relevant for surface patterns; for all other patterns, it
|
||||
// behaves identical to PAD. On MacOS X, this becomes "NONE",
|
||||
// because Quartz does the thing that we want at image edges;
|
||||
// similarily on the win32 printing surface, since
|
||||
// everything's done with GDI there. On other platforms, it
|
||||
// usually becomes PAD.
|
||||
EXTEND_PAD_EDGE = 1000
|
||||
};
|
||||
|
||||
// none, repeat, reflect
|
||||
void SetExtend(GraphicsExtend extend);
|
||||
GraphicsExtend Extend() const;
|
||||
// clamp, repeat, reflect
|
||||
void SetExtend(mozilla::gfx::ExtendMode aExtend);
|
||||
|
||||
int CairoStatus();
|
||||
|
||||
void SetFilter(GraphicsFilter filter);
|
||||
GraphicsFilter Filter() const;
|
||||
void SetFilter(mozilla::gfx::Filter filter);
|
||||
mozilla::gfx::Filter Filter() const;
|
||||
|
||||
/* returns TRUE if it succeeded */
|
||||
bool GetSolidColor(mozilla::gfx::Color& aColorOut);
|
||||
@@ -91,7 +72,7 @@ private:
|
||||
mozilla::gfx::Matrix mPatternToUserSpace;
|
||||
mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
|
||||
nsTArray<mozilla::gfx::GradientStop> mStopsList;
|
||||
GraphicsExtend mExtend;
|
||||
mozilla::gfx::ExtendMode mExtend;
|
||||
};
|
||||
|
||||
#endif /* GFX_PATTERN_H */
|
||||
|
||||
@@ -2090,26 +2090,19 @@ gfxPlatform::GetLog(eGfxLog aWhichLog)
|
||||
switch (aWhichLog) {
|
||||
case eGfxLog_fontlist:
|
||||
return sFontlistLog;
|
||||
break;
|
||||
case eGfxLog_fontinit:
|
||||
return sFontInitLog;
|
||||
break;
|
||||
case eGfxLog_textrun:
|
||||
return sTextrunLog;
|
||||
break;
|
||||
case eGfxLog_textrunui:
|
||||
return sTextrunuiLog;
|
||||
break;
|
||||
case eGfxLog_cmapdata:
|
||||
return sCmapDataLog;
|
||||
break;
|
||||
case eGfxLog_textperf:
|
||||
return sTextPerfLog;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected log type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -2450,6 +2443,10 @@ gfxPlatform::GetApzSupportInfo(mozilla::widget::InfoObject& aObj)
|
||||
if (SupportsApzTouchInput()) {
|
||||
aObj.DefineProperty("ApzTouchInput", 1);
|
||||
}
|
||||
|
||||
if (SupportsApzDragInput()) {
|
||||
aObj.DefineProperty("ApzDragInput", 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
@@ -2567,3 +2564,9 @@ gfxPlatform::UpdateDeviceInitData()
|
||||
|
||||
SetDeviceInitData(data);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxPlatform::SupportsApzDragInput() const
|
||||
{
|
||||
return gfxPrefs::APZDragEnabled();
|
||||
}
|
||||
|
||||
@@ -632,6 +632,7 @@ public:
|
||||
virtual bool SupportsApzTouchInput() const {
|
||||
return false;
|
||||
}
|
||||
bool SupportsApzDragInput() const;
|
||||
|
||||
virtual void FlushContentDrawing() {}
|
||||
|
||||
|
||||
@@ -150,6 +150,7 @@ private:
|
||||
DECL_GFX_PREF(Live, "apz.cross_slide.enabled", APZCrossSlideEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.danger_zone_x", APZDangerZoneX, int32_t, 50);
|
||||
DECL_GFX_PREF(Live, "apz.danger_zone_y", APZDangerZoneY, int32_t, 100);
|
||||
DECL_GFX_PREF(Live, "apz.drag.enabled", APZDragEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.enlarge_displayport_when_clipped", APZEnlargeDisplayPortWhenClipped, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.fling_accel_base_mult", APZFlingAccelBaseMultiplier, float, 1.0f);
|
||||
DECL_GFX_PREF(Live, "apz.fling_accel_interval_ms", APZFlingAccelInterval, int32_t, 500);
|
||||
|
||||
+13
-13
@@ -447,8 +447,8 @@ CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable,
|
||||
|
||||
nsRefPtr<gfxContext> tmpCtx = new gfxContext(target);
|
||||
tmpCtx->SetOp(OptimalFillOp());
|
||||
aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true,
|
||||
GraphicsFilter::FILTER_FAST, 1.0, gfxMatrix::Translation(needed.TopLeft()));
|
||||
aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true, Filter::LINEAR,
|
||||
1.0, gfxMatrix::Translation(needed.TopLeft()));
|
||||
RefPtr<SourceSurface> surface = target->Snapshot();
|
||||
|
||||
nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(surface, size, gfxMatrix::Translation(-needed.TopLeft()));
|
||||
@@ -536,9 +536,9 @@ DeviceToImageTransform(gfxContext* aContext)
|
||||
|
||||
/* These heuristics are based on Source/WebCore/platform/graphics/skia/ImageSkia.cpp:computeResamplingMode() */
|
||||
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
static GraphicsFilter ReduceResamplingFilter(GraphicsFilter aFilter,
|
||||
int aImgWidth, int aImgHeight,
|
||||
float aSourceWidth, float aSourceHeight)
|
||||
static Filter ReduceResamplingFilter(Filter aFilter,
|
||||
int aImgWidth, int aImgHeight,
|
||||
float aSourceWidth, float aSourceHeight)
|
||||
{
|
||||
// Images smaller than this in either direction are considered "small" and
|
||||
// are not resampled ever (see below).
|
||||
@@ -553,7 +553,7 @@ static GraphicsFilter ReduceResamplingFilter(GraphicsFilter aFilter,
|
||||
|| aImgHeight <= kSmallImageSizeThreshold) {
|
||||
// Never resample small images. These are often used for borders and
|
||||
// rules (think 1x1 images used to make lines).
|
||||
return GraphicsFilter::FILTER_NEAREST;
|
||||
return Filter::POINT;
|
||||
}
|
||||
|
||||
if (aImgHeight * kLargeStretch <= aSourceHeight || aImgWidth * kLargeStretch <= aSourceWidth) {
|
||||
@@ -564,7 +564,7 @@ static GraphicsFilter ReduceResamplingFilter(GraphicsFilter aFilter,
|
||||
// (which might be large) and then is stretching it to fill some part
|
||||
// of the page.
|
||||
if (fabs(aSourceWidth - aImgWidth)/aImgWidth < 0.5 || fabs(aSourceHeight - aImgHeight)/aImgHeight < 0.5)
|
||||
return GraphicsFilter::FILTER_NEAREST;
|
||||
return Filter::POINT;
|
||||
|
||||
// The image is growing a lot and in more than one direction. Resampling
|
||||
// is slow and doesn't give us very much when growing a lot.
|
||||
@@ -592,9 +592,9 @@ static GraphicsFilter ReduceResamplingFilter(GraphicsFilter aFilter,
|
||||
return aFilter;
|
||||
}
|
||||
#else
|
||||
static GraphicsFilter ReduceResamplingFilter(GraphicsFilter aFilter,
|
||||
int aImgWidth, int aImgHeight,
|
||||
int aSourceWidth, int aSourceHeight)
|
||||
static Filter ReduceResamplingFilter(Filter aFilter,
|
||||
int aImgWidth, int aImgHeight,
|
||||
int aSourceWidth, int aSourceHeight)
|
||||
{
|
||||
// Just pass the filter through unchanged
|
||||
return aFilter;
|
||||
@@ -621,7 +621,7 @@ PrescaleAndTileDrawable(gfxDrawable* aDrawable,
|
||||
gfxContext* aContext,
|
||||
const ImageRegion& aRegion,
|
||||
Rect aImageRect,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
const SurfaceFormat aFormat,
|
||||
gfxFloat aOpacity)
|
||||
{
|
||||
@@ -689,7 +689,7 @@ PrescaleAndTileDrawable(gfxDrawable* aDrawable,
|
||||
aContext->CurrentAntialiasMode());
|
||||
|
||||
SurfacePattern scaledImagePattern(scaledImage, ExtendMode::REPEAT,
|
||||
Matrix(), ToFilter(aFilter));
|
||||
Matrix(), aFilter);
|
||||
destDrawTarget->FillRect(scaledNeededRect, scaledImagePattern, drawOptions);
|
||||
}
|
||||
return true;
|
||||
@@ -702,7 +702,7 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
|
||||
const gfxSize& aImageSize,
|
||||
const ImageRegion& aRegion,
|
||||
const SurfaceFormat aFormat,
|
||||
GraphicsFilter aFilter,
|
||||
Filter aFilter,
|
||||
uint32_t aImageFlags,
|
||||
gfxFloat aOpacity)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#define GFX_UTILS_H
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "GraphicsFilter.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
@@ -79,7 +78,7 @@ public:
|
||||
const gfxSize& aImageSize,
|
||||
const ImageRegion& aRegion,
|
||||
const mozilla::gfx::SurfaceFormat aFormat,
|
||||
GraphicsFilter aFilter,
|
||||
mozilla::gfx::Filter aFilter,
|
||||
uint32_t aImageFlags = imgIContainer::FLAG_NONE,
|
||||
gfxFloat aOpacity = 1.0);
|
||||
|
||||
|
||||
@@ -288,9 +288,9 @@ gfxWindowsNativeDrawing::PaintToContext()
|
||||
pat->SetMatrix(m);
|
||||
|
||||
if (mNativeDrawFlags & DO_NEAREST_NEIGHBOR_FILTERING)
|
||||
pat->SetFilter(GraphicsFilter::FILTER_FAST);
|
||||
pat->SetFilter(Filter::LINEAR);
|
||||
|
||||
pat->SetExtend(gfxPattern::EXTEND_PAD);
|
||||
pat->SetExtend(ExtendMode::CLAMP);
|
||||
mContext->SetPattern(pat);
|
||||
mContext->Fill();
|
||||
mContext->Restore();
|
||||
|
||||
@@ -49,7 +49,6 @@ EXPORTS += [
|
||||
'gfxTypes.h',
|
||||
'gfxUserFontSet.h',
|
||||
'gfxUtils.h',
|
||||
'GraphicsFilter.h',
|
||||
'RoundedRect.h',
|
||||
'SoftwareVsyncSource.h',
|
||||
'VsyncSource.h',
|
||||
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
|
||||
virtual bool operator()(gfxContext* aContext,
|
||||
const gfxRect& aFillRect,
|
||||
const GraphicsFilter& aFilter,
|
||||
const Filter& aFilter,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
MOZ_ASSERT(aTransform.IsIdentity(),
|
||||
@@ -266,7 +266,7 @@ ClippedImage::GetFrameInternal(const nsIntSize& aSize,
|
||||
gfxUtils::DrawPixelSnapped(ctx, drawable, aSize,
|
||||
ImageRegion::Create(aSize),
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
GraphicsFilter::FILTER_FAST,
|
||||
Filter::LINEAR,
|
||||
imgIContainer::FLAG_CLAMP);
|
||||
|
||||
// Cache the resulting surface.
|
||||
@@ -323,7 +323,7 @@ ClippedImage::Draw(gfxContext* aContext,
|
||||
const nsIntSize& aSize,
|
||||
const ImageRegion& aRegion,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter,
|
||||
Filter aFilter,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
@@ -381,7 +381,7 @@ ClippedImage::DrawSingleTile(gfxContext* aContext,
|
||||
const nsIntSize& aSize,
|
||||
const ImageRegion& aRegion,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter,
|
||||
Filter aFilter,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
@@ -440,7 +440,7 @@ ClippedImage::GetOrientation()
|
||||
nsIntSize
|
||||
ClippedImage::OptimalImageSizeForDest(const gfxSize& aDest,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter, uint32_t aFlags)
|
||||
Filter aFilter, uint32_t aFlags)
|
||||
{
|
||||
if (!ShouldClip()) {
|
||||
return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aFilter,
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
const nsIntSize& aSize,
|
||||
const ImageRegion& aRegion,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter,
|
||||
gfx::Filter aFilter,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
uint32_t aFlags) override;
|
||||
NS_IMETHOD RequestDiscard() override;
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
override;
|
||||
nsIntSize OptimalImageSizeForDest(const gfxSize& aDest,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter,
|
||||
gfx::Filter aFilter,
|
||||
uint32_t aFlags) override;
|
||||
|
||||
protected:
|
||||
@@ -78,7 +78,7 @@ private:
|
||||
const nsIntSize& aSize,
|
||||
const ImageRegion& aRegion,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter,
|
||||
gfx::Filter aFilter,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
uint32_t aFlags);
|
||||
|
||||
|
||||
@@ -188,8 +188,7 @@ DynamicImage::GetFrameAtSize(const IntSize& aSize,
|
||||
nsRefPtr<gfxContext> context = new gfxContext(dt);
|
||||
|
||||
auto result = Draw(context, aSize, ImageRegion::Create(aSize),
|
||||
aWhichFrame, GraphicsFilter::FILTER_NEAREST,
|
||||
Nothing(), aFlags);
|
||||
aWhichFrame, Filter::POINT, Nothing(), aFlags);
|
||||
|
||||
return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
|
||||
}
|
||||
@@ -219,7 +218,7 @@ DynamicImage::Draw(gfxContext* aContext,
|
||||
const nsIntSize& aSize,
|
||||
const ImageRegion& aRegion,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter,
|
||||
Filter aFilter,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
@@ -325,7 +324,7 @@ DynamicImage::SetAnimationStartTime(const mozilla::TimeStamp& aTime)
|
||||
nsIntSize
|
||||
DynamicImage::OptimalImageSizeForDest(const gfxSize& aDest,
|
||||
uint32_t aWhichFrame,
|
||||
GraphicsFilter aFilter, uint32_t aFlags)
|
||||
Filter aFilter, uint32_t aFlags)
|
||||
{
|
||||
IntSize size(mDrawable->Size());
|
||||
return nsIntSize(size.width, size.height);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user