author | Taras Glek <tglek@mozilla.com> |
Mon, 24 May 2010 15:21:24 -0700 | |
changeset 42636 | 714faf8ec1493fb9d7a3c15bdd513e367f8aff63 |
parent 42635 | d05aa79f947adb5eecc46cb1b6b414a2148513a1 (current diff) |
parent 42634 | 56c19c5c416eec7c8368a8114f5dc2d000d271ad (diff) |
child 42637 | 0c440c656ada5d6e87f694a93663584aea656ae0 |
push id | 13434 |
push user | tglek@mozilla.com |
push date | Mon, 24 May 2010 22:22:07 +0000 |
treeherder | mozilla-central@714faf8ec149 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 537857 |
milestone | 1.9.3a5pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
|
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -176,17 +176,17 @@ pref("general.autoScroll", true); // Whether or not the application should check at startup each time if it // is the default browser. pref("browser.shell.checkDefaultBrowser", true); // 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session // The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore pref("browser.startup.page", 1); -pref("browser.startup.homepage", "resource:/browserconfig.properties"); +pref("browser.startup.homepage", "chrome://branding/locale/browserconfig.properties"); pref("browser.enable_automatic_image_resizing", true); pref("browser.chrome.site_icons", true); pref("browser.chrome.favicons", true); pref("browser.warnOnQuit", true); pref("browser.warnOnRestart", true); pref("browser.fullscreen.autohide", true); pref("browser.fullscreen.animateUp", 1);
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4259,17 +4259,17 @@ var XULBrowserWindow = { }, // simulate all change notifications after switching tabs onUpdateCurrentBrowser: function (aStateFlags, aStatus, aMessage, aTotalProgress) { if (FullZoom.updateBackgroundTabs) FullZoom.onLocationChange(gBrowser.currentURI, true); var nsIWebProgressListener = Components.interfaces.nsIWebProgressListener; var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP; - // use a pseudo-object instead of a (potentially non-existing) channel for getting + // use a pseudo-object instead of a (potentially nonexistent) channel for getting // a correct error message - and make sure that the UI is always either in // loading (STATE_START) or done (STATE_STOP) mode this.onStateChange( gBrowser.webProgress, { URI: gBrowser.currentURI }, loadingDone ? nsIWebProgressListener.STATE_STOP : nsIWebProgressListener.STATE_START, aStatus ); @@ -4770,17 +4770,17 @@ var gHomeButton = { url = gPrefService.getComplexValue(this.prefDomain, Components.interfaces.nsIPrefLocalizedString).data; } catch (e) { } // use this if we can't find the pref if (!url) { var SBS = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService); - var configBundle = SBS.createBundle("resource:/browserconfig.properties"); + var configBundle = SBS.createBundle("chrome://branding/locale/browserconfig.properties"); url = configBundle.GetStringFromName(this.prefDomain); } return url; }, updatePersonalToolbarStyle: function (homeButton) {
--- a/browser/base/content/pageinfo/pageInfo.js +++ b/browser/base/content/pageinfo/pageInfo.js @@ -163,23 +163,29 @@ const COL_IMAGE_BG = 6; const COPYCOL_NONE = -1; const COPYCOL_META_CONTENT = 1; const COPYCOL_IMAGE = COL_IMAGE_ADDRESS; // one nsITreeView for each tree in the window var gMetaView = new pageInfoTreeView(COPYCOL_META_CONTENT); var gImageView = new pageInfoTreeView(COPYCOL_IMAGE); + +var atomSvc = Components.classes["@mozilla.org/atom-service;1"] + .getService(Components.interfaces.nsIAtomService); +gImageView._ltrAtom = atomSvc.getAtom("ltr"); +gImageView._brokenAtom = atomSvc.getAtom("broken"); + gImageView.getCellProperties = function(row, col, props) { - var aserv = Components.classes[ATOM_CONTRACTID] - .getService(Components.interfaces.nsIAtomService); - if (gImageView.data[row][COL_IMAGE_SIZE] == gStrings.unknown && !/^https:/.test(gImageView.data[row][COL_IMAGE_ADDRESS])) - props.AppendElement(aserv.getAtom("broken")); + props.AppendElement(this._brokenAtom); + + if (col.element.id == "image-address") + props.AppendElement(this._ltrAtom); }; var gImageHash = { }; // localized strings (will be filled in when the document is loaded) // this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop var gStrings = { }; var gBundle;
--- a/browser/branding/nightly/locales/Makefile.in +++ b/browser/branding/nightly/locales/Makefile.in @@ -40,16 +40,8 @@ srcdir = @srcdir@ VPATH = @srcdir@ relativesrcdir = browser/branding/nightly/locales include $(DEPTH)/config/autoconf.mk DEFINES += -DAB_CD=$(AB_CD) -DMOZ_DISTRIBUTION_ID_UNQUOTED=$(MOZ_DISTRIBUTION_ID) include $(topsrcdir)/config/rules.mk - -libs:: - @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ - $(srcdir)/browserconfig.properties > $(FINAL_TARGET)/browserconfig.properties - -install:: - @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ - $(srcdir)/browserconfig.properties > $(DESTDIR)$(mozappdir)/browserconfig.properties
--- a/browser/branding/nightly/locales/jar.mn +++ b/browser/branding/nightly/locales/jar.mn @@ -1,7 +1,8 @@ #filter substitution @AB_CD@.jar: % locale branding @AB_CD@ %locale/branding/ # Nightly branding only exists in en-US locale/branding/brand.dtd (en-US/brand.dtd) * locale/branding/brand.properties (en-US/brand.properties) +* locale/branding/browserconfig.properties (browserconfig.properties)
--- a/browser/branding/unofficial/locales/Makefile.in +++ b/browser/branding/unofficial/locales/Makefile.in @@ -40,16 +40,8 @@ srcdir = @srcdir@ VPATH = @srcdir@ relativesrcdir = browser/branding/unofficial/locales include $(DEPTH)/config/autoconf.mk DEFINES += -DAB_CD=$(AB_CD) -DMOZ_DISTRIBUTION_ID_UNQUOTED=$(MOZ_DISTRIBUTION_ID) include $(topsrcdir)/config/rules.mk - -libs:: - @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ - $(srcdir)/browserconfig.properties > $(FINAL_TARGET)/browserconfig.properties - -install:: - @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ - $(srcdir)/browserconfig.properties > $(DESTDIR)$(mozappdir)/browserconfig.properties
--- a/browser/branding/unofficial/locales/jar.mn +++ b/browser/branding/unofficial/locales/jar.mn @@ -1,7 +1,8 @@ #filter substitution @AB_CD@.jar: % locale branding @AB_CD@ %locale/branding/ # Unofficial branding only exists in en-US locale/branding/brand.dtd (en-US/brand.dtd) * locale/branding/brand.properties (en-US/brand.properties) +* locale/branding/browserconfig.properties (browserconfig.properties)
--- a/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js +++ b/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js @@ -104,17 +104,17 @@ var tests = [ } catch (e) { do_throw(" Restore should not have failed"); } } }, { - desc: "JSON restore: nonexisting file should fail", + desc: "JSON restore: nonexistent file should fail", currTopic: NSIOBSERVER_TOPIC_BEGIN, finalTopic: NSIOBSERVER_TOPIC_FAILED, data: NSIOBSERVER_DATA_JSON, folderId: null, run: function () { this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { @@ -158,17 +158,17 @@ var tests = [ } catch (e) { do_throw(" Restore should not have failed"); } } }, { - desc: "HTML restore: nonexisting file should fail", + desc: "HTML restore: nonexistent file should fail", currTopic: NSIOBSERVER_TOPIC_BEGIN, finalTopic: NSIOBSERVER_TOPIC_FAILED, data: NSIOBSERVER_DATA_HTML, folderId: null, run: function () { this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { @@ -212,17 +212,17 @@ var tests = [ } catch (e) { do_throw(" Restore should not have failed"); } } }, { - desc: "HTML initial restore: nonexisting file should fail", + desc: "HTML initial restore: nonexistent file should fail", currTopic: NSIOBSERVER_TOPIC_BEGIN, finalTopic: NSIOBSERVER_TOPIC_FAILED, data: NSIOBSERVER_DATA_HTML_INIT, folderId: null, run: function () { this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); try { @@ -274,17 +274,17 @@ var tests = [ } catch (e) { do_throw(" Restore should not have failed"); } } }, { - desc: "HTML restore into folder: nonexisting file should fail", + desc: "HTML restore into folder: nonexistent file should fail", currTopic: NSIOBSERVER_TOPIC_BEGIN, finalTopic: NSIOBSERVER_TOPIC_FAILED, data: NSIOBSERVER_DATA_HTML, run: function () { this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile); this.file.append("this file doesn't exist because nobody created it"); this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder, "test folder",
--- a/browser/fuel/test/browser_ApplicationPrefs.js +++ b/browser/fuel/test/browser_ApplicationPrefs.js @@ -3,21 +3,21 @@ var testdata = { missing: "fuel.fuel-test-missing", dummy: "fuel.fuel-test", string: "browser.active_color", integer: "permissions.default.image", boolean: "browser.blink_allowed" }; function test() { - // test getting non-existing values + // test getting nonexistent values var itemValue = Application.prefs.getValue(testdata.missing, "default"); - is(itemValue, "default", "Check 'Application.prefs.getValue' for non-existing item"); + is(itemValue, "default", "Check 'Application.prefs.getValue' for nonexistent item"); - is(Application.prefs.get(testdata.missing), null, "Check 'Application.prefs.get' for non-existing item"); + is(Application.prefs.get(testdata.missing), null, "Check 'Application.prefs.get' for nonexistent item"); // test setting and getting a value Application.prefs.setValue(testdata.dummy, "dummy"); itemValue = Application.prefs.getValue(testdata.dummy, "default"); is(itemValue, "dummy", "Check 'Application.prefs.getValue' for existing item"); // test for overwriting an existing value Application.prefs.setValue(testdata.dummy, "smarty");
--- a/browser/fuel/test/browser_ApplicationStorage.js +++ b/browser/fuel/test/browser_ApplicationStorage.js @@ -1,19 +1,19 @@ function test() { // test for existence of values var hasItem = Application.storage.has("fuel-test-missing"); - is(hasItem, false, "Check 'Application.storage.has' for non-existing item"); + is(hasItem, false, "Check 'Application.storage.has' for nonexistent item"); Application.storage.set("fuel-test", "dummy"); hasItem = Application.storage.has("fuel-test"); is(hasItem, true, "Check 'Application.storage.has' for existing item"); - // test getting non-existing and existing values + // test getting nonexistent and existing values var itemValue = Application.storage.get("fuel-test-missing", "default"); - is(itemValue, "default", "Check 'Application.storage.get' for non-existing item"); + is(itemValue, "default", "Check 'Application.storage.get' for nonexistent item"); itemValue = Application.storage.get("fuel-test", "default"); is(itemValue, "dummy", "Check 'Application.storage.get' for existing item"); // test for overwriting an existing value Application.storage.set("fuel-test", "smarty"); itemValue = Application.storage.get("fuel-test", "default"); is(itemValue, "smarty", "Check 'Application.storage.get' for overwritten item");
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -17,17 +17,16 @@ @APPNAME@/Contents/Plug-Ins/ @APPNAME@/Contents/Resources/ #endif [@AB_CD@] @BINPATH@/chrome/@AB_CD@.jar @BINPATH@/chrome/@AB_CD@.manifest @BINPATH@/@PREF_DIR@/firefox-l10n.js -@BINPATH@/browserconfig.properties @BINPATH@/searchplugins/* @BINPATH@/defaults/profile/bookmarks.html @BINPATH@/defaults/profile/localstore.rdf @BINPATH@/defaults/profile/mimeTypes.rdf @BINPATH@/defaults/profile/chrome/* @BINPATH@/update.locale @BINPATH@/updater.ini @BINPATH@/dictionaries/*
--- a/browser/installer/removed-files.in +++ b/browser/installer/removed-files.in @@ -5,16 +5,17 @@ # Inspector files are at the very end. .autoreg @DLL_PREFIX@jsj@DLL_SUFFIX@ @DLL_PREFIX@sqlite3@DLL_SUFFIX@ @DLL_PREFIX@xpcom_compat@DLL_SUFFIX@ @DLL_PREFIX@xpistub@DLL_SUFFIX@ @DLL_PREFIX@zlib@DLL_SUFFIX@ LICENSE +browserconfig.properties chrome.manifest chrome/US.jar chrome/app-chrome.manifest chrome/chrome.rdf chrome/chromelist.txt chrome/classic.jar chrome/classic.manifest chrome/comm.jar
--- a/browser/themes/winstripe/browser/browser-aero.css +++ b/browser/themes/winstripe/browser/browser-aero.css @@ -1,13 +1,12 @@ %define WINSTRIPE_AERO %include browser.css %undef WINSTRIPE_AERO -%if 0 @media all and (-moz-windows-compositor) { #main-window:not(:-moz-lwtheme) { -moz-appearance: -moz-win-glass; background: transparent; } #navigator-toolbox:not(:-moz-lwtheme), #navigator-toolbox > toolbar { @@ -68,17 +67,16 @@ -moz-appearance: -moz-win-glass; -moz-border-radius: 0; border: none; font: normal 1.2em "Segoe UI"; color: black; text-shadow: white -1px -1px .5em, white -1px 1px .5em, white 1px 1px .5em, white 1px -1px .5em; } } -%endif @media not all and (-moz-windows-compositor) { #print-preview-toolbar:not(:-moz-lwtheme) { -moz-appearance: -moz-win-browsertabbar-toolbox; } } @media all and (-moz-windows-default-theme) {
--- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -108,17 +108,16 @@ MOZ_LEAKY = @MOZ_LEAKY@ MOZ_MEMORY = @MOZ_MEMORY@ MOZ_JPROF = @MOZ_JPROF@ MOZ_SHARK = @MOZ_SHARK@ MOZ_CALLGRIND = @MOZ_CALLGRIND@ MOZ_VTUNE = @MOZ_VTUNE@ MOZ_TRACEVIS = @MOZ_TRACEVIS@ DEHYDRA_PATH = @DEHYDRA_PATH@ -MOZ_XPCTOOLS = @MOZ_XPCTOOLS@ NS_TRACE_MALLOC = @NS_TRACE_MALLOC@ USE_ELF_DYNSTR_GC = @USE_ELF_DYNSTR_GC@ INCREMENTAL_LINKER = @INCREMENTAL_LINKER@ MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@ MOZ_MAIL_NEWS = @MOZ_MAIL_NEWS@ MOZ_PLAINTEXT_EDITOR_ONLY = @MOZ_PLAINTEXT_EDITOR_ONLY@ BUILD_STATIC_LIBS = @BUILD_STATIC_LIBS@ MOZ_ENABLE_LIBXUL = @MOZ_ENABLE_LIBXUL@
--- a/config/outofdate.pl +++ b/config/outofdate.pl @@ -36,17 +36,17 @@ # # ***** END LICENSE BLOCK ***** # #Input: [-d dir] foo1.java foo2.java #Compares with: foo1.class foo2.class (if -d specified, checks in 'dir', # otherwise assumes .class files in same directory as .java files) #Returns: list of input arguments which are newer than corresponding class -#files (non-existent class files are considered to be real old :-) +#files (nonexistent class files are considered to be real old :-) # $found = 1; # GLOBALS $SEP = 0; # the paltform independent path separator $CFG = 0; # the value of the -cfg flag
--- a/config/rules.mk +++ b/config/rules.mk @@ -1513,17 +1513,17 @@ SPACE := $(EMPTY) $(EMPTY) # and class paths to be in the DOS form (i.e. e:/builds/...). This function # does the appropriate conversion on Windows, but is a noop on other systems. ifeq (,$(filter-out WINNT WINCE, $(HOST_OS_ARCH))) ifdef CYGWIN_WRAPPER normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p))) else # assume MSYS # We use 'pwd -W' to get DOS form of the path. However, since the given path -# could be a file or a non-existent path, we cannot call 'pwd -W' directly +# could be a file or a nonexistent path, we cannot call 'pwd -W' directly # on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W' # on it, then merge with the rest of the path. root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|") non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|") normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1))) endif else normalizepath = $(1)
--- a/config/system-headers +++ b/config/system-headers @@ -207,16 +207,17 @@ curl/types.h curses.h cxxabi.h DateTimeUtils.h dbus/dbus.h dbus/dbus-glib.h dbus/dbus-glib-lowlevel.h ddeml.h Debug.h +deque dem.h descrip.h Devices.h Dialogs.h direct.h dirent.h DiskInit.h dlfcn.h @@ -269,16 +270,17 @@ freetype/ftcache.h freetype/ftglyph.h freetype/ftsynth.h freetype/ftoutln.h freetype/ttnameid.h freetype/tttables.h freetype/t1tables.h fribidi/fribidi.h FSp_fopen.h +fstream fstream.h ft2build.h fts.h gconf/gconf-client.h Gdiplus.h gdk/gdk.h gdk/gdkkeysyms.h gdk/gdkprivate.h @@ -324,16 +326,17 @@ inttypes.h iodef.h io.h IOKit/IOKitLib.h IOKit/IOMessage.h IOKit/pwr_mgt/IOPMLib.h iomanip iostream iostream.h +iterator jar.h JavaControl.h JavaEmbedding/JavaControl.h JavaVM/jni.h JManager.h JNIEnvTests.h jni.h #if MOZ_NATIVE_JPEG==1 @@ -602,16 +605,17 @@ Process.h proto/dos.h proto/exec.h psap.h Pt.h pthread.h pwd.h Python.h QDOffscreen.h +queue Quickdraw.h QuickDraw.h QuickTimeComponents.h quipu/attr.h rasdlg.h raserror.h ras.h regex.h @@ -636,16 +640,17 @@ seccomon.h sec.h secmod.h secmodt.h secrng.h security.h secutil.h semaphore.h servprov.h +set setjmp.h SFNTLayoutTypes.h SFNTTypes.h share.h shellapi.h shlguid.h shlobj.h sigcontext.h @@ -829,16 +834,17 @@ unixio.h unixlib.h unknwn.h UPrinting.h UQuickTime.h UReanimator.h URegions.h URegistrar.h UResourceMgr.h +utility urlhist.h urlmon.h UScrap.h UScreenPort.h UTCUtils.h UTETextAction.h UTEViewTextAction.h UTextEdit.h
--- a/configure.in +++ b/configure.in @@ -6268,17 +6268,17 @@ if test `echo "$MOZ_EXTENSIONS" | grep - AC_MSG_WARN([spellcheck is no longer an extension.]) MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|spellcheck||g'` fi dnl Remove dupes MOZ_EXTENSIONS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_EXTENSIONS}` dnl Ensure every extension exists, to avoid mostly-inscrutable error messages -dnl when trying to build a non-existent extension. +dnl when trying to build a nonexistent extension. for extension in $MOZ_EXTENSIONS; do if test ! -d "${srcdir}/extensions/${extension}"; then AC_MSG_ERROR([Unrecognized extension provided to --enable-extensions: ${extension}.]) fi done dnl ======================================================== @@ -6523,25 +6523,16 @@ dnl leaky dnl ======================================================== MOZ_ARG_ENABLE_BOOL(leaky, [ --enable-leaky Build leaky memory tool], MOZ_LEAKY=1, MOZ_LEAKY=) dnl ======================================================== -dnl xpctools -dnl ======================================================== -MOZ_ARG_ENABLE_BOOL(xpctools, -[ --enable-xpctools Build JS profiling tool], - MOZ_XPCTOOLS=1, - MOZ_XPCTOOLS= ) - - -dnl ======================================================== dnl build the tests by default dnl ======================================================== MOZ_ARG_DISABLE_BOOL(tests, [ --disable-tests Do not build test libraries & programs], ENABLE_TESTS=, ENABLE_TESTS=1 ) dnl ======================================================== @@ -6929,17 +6920,29 @@ MOZ_ARG_ENABLE_STRING(debug, MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'` _MOZ_DEBUG_FLAGS_SET=1 fi else MOZ_DEBUG= fi ], MOZ_DEBUG=) -MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG -DTRACING" +MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG" + case "${target_os}" in + beos*) + MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${USER}" + ;; + msvc*|mks*|cygwin*|mingw*|os2*|wince*|winmo*) + MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`" + ;; + *) + MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`$WHOAMI`" + ;; + esac +MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DTRACING" MOZ_DEBUG_DISABLE_DEFS="-DNDEBUG -DTRIMMED" if test -n "$MOZ_DEBUG"; then AC_MSG_CHECKING([for valid debug flags]) _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS" AC_TRY_COMPILE([#include <stdio.h>], @@ -8471,17 +8474,16 @@ AC_SUBST(MOZ_IMG_ENCODERS) AC_SUBST(MOZ_JSDEBUGGER) AC_SUBST(MOZ_PLUGINS) AC_SUBST(MOZ_LOG_REFCNT) AC_SUBST(MOZ_LEAKY) AC_SUBST(MOZ_JPROF) AC_SUBST(MOZ_SHARK) AC_SUBST(MOZ_CALLGRIND) AC_SUBST(MOZ_VTUNE) -AC_SUBST(MOZ_XPCTOOLS) AC_SUBST(MOZ_JSLOADER) AC_SUBST(MOZ_USE_NATIVE_UCONV) AC_SUBST(MOZ_QUANTIFY) AC_SUBST(LIBICONV) AC_SUBST(MOZ_PLACES) AC_SUBST(MOZ_PLACES_BOOKMARKS) AC_SUBST(MOZ_STORAGE) AC_SUBST(MOZ_TOOLKIT_SEARCH)
--- a/content/base/src/nsAttrValue.cpp +++ b/content/base/src/nsAttrValue.cpp @@ -1094,16 +1094,33 @@ nsAttrValue::ParseNonNegativeIntValue(co return PR_FALSE; } SetIntValueAndType(originalVal, eInteger, nsnull); return PR_TRUE; } +PRBool +nsAttrValue::ParsePositiveIntValue(const nsAString& aString) +{ + ResetIfSet(); + + PRInt32 ec; + PRBool strict; + PRInt32 originalVal = StringToInteger(aString, &strict, &ec); + if (NS_FAILED(ec) || originalVal <= 0) { + return PR_FALSE; + } + + SetIntValueAndType(originalVal, eInteger, nsnull); + + return PR_TRUE; +} + void nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString) { nsStringBuffer* buf = GetStringBuffer(aString); if (!buf) { return; }
--- a/content/base/src/nsAttrValue.h +++ b/content/base/src/nsAttrValue.h @@ -254,16 +254,31 @@ public: * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers * * @param aString the string to parse * @return whether the value is valid */ PRBool ParseNonNegativeIntValue(const nsAString& aString); /** + * Parse a string value into a positive integer. + * This method follows the rules for parsing non-negative integer from: + * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers + * In addition of these rules, the value has to be greater than zero. + * + * This is generally used for parsing content attributes which reflecting IDL + * attributes are limited to only non-negative numbers greater than zero, see: + * http://dev.w3.org/html5/spec/common-dom-interfaces.html#limited-to-only-non-negative-numbers-greater-than-zero + * + * @param aString the string to parse + * @return whether the value was valid + */ + PRBool ParsePositiveIntValue(const nsAString& aString); + + /** * Parse a string into a color. * * @param aString the string to parse * @param aDocument the document (to find out whether we're in quirks mode) * @return whether the value could be parsed */ PRBool ParseColor(const nsAString& aString, nsIDocument* aDocument);
--- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -427,17 +427,17 @@ nsImageLoadingContent::RemoveObserver(im // splice it out ImageObserver* oldObserver = observer->mNext; observer->mNext = oldObserver->mNext; oldObserver->mNext = nsnull; // so we don't destroy them all delete oldObserver; } #ifdef DEBUG else { - NS_WARNING("Asked to remove non-existent observer"); + NS_WARNING("Asked to remove nonexistent observer"); } #endif return NS_OK; } NS_IMETHODIMP nsImageLoadingContent::GetRequest(PRInt32 aRequestType, imgIRequest** aRequest)
--- a/content/base/test/file_bug416317.xhtml +++ b/content/base/test/file_bug416317.xhtml @@ -660,17 +660,17 @@ t( "Broken Selector", "()" ); t( "Broken Selector", "<>" ); t( "Broken Selector", "{}" ); t( "ID Selector", "#body", ["body"], false ); t( "ID Selector w/ Element", "body#body", ["body"], false ); t( "ID Selector w/ Element", "ul#first", [] ); t( "ID selector with existing ID descendant", "#firstp #simon1", ["simon1"] ); - t( "ID selector with non-existent descendant", "#firstp #foobar", [] ); + t( "ID selector with nonexistent descendant", "#firstp #foobar", [] ); t( "ID selector using UTF8", "#台北Táiběi", ["台北Táiběi"] ); t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", ["台北Táiběi","台北"] ); t( "Descendant ID selector using UTF8", "div #台北", ["台北"] ); t( "Child ID selector using UTF8", "form > #台北", ["台北"] ); t( "Escaped ID", "#foo\\:bar", ["foo:bar"] ); t( "Escaped ID", "#test\\.foo\\[5\\]bar", ["test.foo[5]bar"] ); @@ -681,17 +681,17 @@ t( "ID Selector, child ID present", "#form > #radio1", ["radio1"] ); // bug #267 t( "ID Selector, not an ancestor ID", "#form #first", [] ); t( "ID Selector, not a child ID", "#form > #option1a", [] ); t( "All Children of ID", "#foo > *", ["sndp", "en", "sap"] ); t( "All Children of ID with no children", "#firstUL > *", [] ); - t( "ID selector with non-existent ancestor", "#asdfasdf #foobar", [] ); // bug #986 + t( "ID selector with nonexistent ancestor", "#asdfasdf #foobar", [] ); // bug #986 //t( "body div#form", [], "ID selector within the context of another element" ); t( "Class Selector", ".blog", ["mark","simon"] ); t( "Class Selector", ".blog.link", ["simon"] ); t( "Class Selector w/ Element", "a.blog", ["mark","simon"] ); t( "Parent Class Selector", "p .blog", ["mark","simon"] );
--- a/content/base/test/test_bug390219.html +++ b/content/base/test/test_bug390219.html @@ -16,17 +16,17 @@ https://bugzilla.mozilla.org/show_bug.cg </div> <pre id="test"> <script class="testbody" type="text/javascript"> /** Test for Bug 390219 **/ SimpleTest.waitForExplicitFinish(); xhr = new XMLHttpRequest(); -xhr.open("GET", "non-existing_url", true); +xhr.open("GET", "nonexistent_url", true); xhr.send(null); xhr.abort(); xhr.open("GET", ".", true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { is(xhr.status, 200, "wrong status"); SimpleTest.finish(); }
--- a/content/base/test/test_classList.html +++ b/content/base/test/test_classList.html @@ -64,17 +64,17 @@ function checkModification(e, funcName, is(e.code, expectedException, "wrong exception thrown " + contextMsg); } e.removeEventListener("DOMAttrModified", onAttrModified, false); if (expectedRes !== null) is(res, expectedRes, "wrong return value from " + funcName + " " + contextMsg); var expectedAfter = after; - // XUL returns an empty string when getting a non-existing class attribute. + // XUL returns an empty string when getting a nonexistent class attribute. if (e.namespaceURI == XUL_NS && expectedAfter === null) expectedAfter = ""; is(e.getAttribute("class"), expectedAfter, "wrong class after modification " + contextMsg); var expectedMutation = before != after; is(gMutationEvents.length, expectedMutation ? 1 : 0, "unexpected mutation event count " + contextMsg);
--- a/content/base/test/test_fileapi.html +++ b/content/base/test/test_fileapi.html @@ -249,27 +249,27 @@ r.abort(); is(reuseAbortHasRun, false, "abort() is a no-op unless loading"); r.readAsText(asciiFile); r.readAsText(asciiFile); is(reuseAbortHasRun, true, "abort should fire sync"); r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "reuse-as-abort reading"); expectedTestCount++; -// Test reading from non-existing files +// Test reading from nonexistent files r = new FileReader(); var didThrow = false; try { r.readAsDataURL(nonExistingFile); } catch(ex) { didThrow = true; } // Once this test passes, we shoud test that onerror gets called and // that the FileReader object is in the right state during that call. -todo(!didThrow, "shouldn't throw when opening non-existing file, should fire error instead"); +todo(!didThrow, "shouldn't throw when opening nonexistent file, should fire error instead"); function getLoadHandler(expectedResult, expectedLength, testName) { return function (event) { is(event.target.readyState, FileReader.DONE, "readyState in test " + testName); is(event.target.error, null, "no error in test " + testName);
--- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -2153,23 +2153,22 @@ WebGLContext::DOMElementToImageSurface(n *dst++ = r; *dst++ = g; *dst++ = b; *dst++ = a; } } } else if (surf->Format() == gfxASurface::ImageFormatRGB24) { - PRUint8* src = surf->Data(); PRUint8* dst = surf->Data(); // this wants some SSE love for (int j = 0; j < height; j++) { - src = surf->Data() + j * surf->Stride(); + PRUint8* src = surf->Data() + j * surf->Stride(); // note that dst's stride is always tightly packed for (int i = 0; i < width; i++) { #ifdef IS_LITTLE_ENDIAN PRUint8 b = *src++; PRUint8 g = *src++; PRUint8 r = *src++; src++; #else
--- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -1102,16 +1102,41 @@ NS_NewHTML##_elementName##Element(nsINod } \ NS_IMETHODIMP \ _class::Set##_method(const nsAString& aValue) \ { \ return SetAttrHelper(nsGkAtoms::_atom, aValue); \ } /** + * A macro to implement the getter and setter for a given content + * property that needs to set a positive integer. The method uses + * the generic GetAttr and SetAttr methods. This macro is much like + * the NS_IMPL_NON_NEGATIVE_INT_ATTR macro except the exception is + * thrown also when the value is equal to 0. + */ +#define NS_IMPL_POSITIVE_INT_ATTR(_class, _method, _atom) \ + NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, 1) + +#define NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, _default) \ + NS_IMETHODIMP \ + _class::Get##_method(PRInt32* aValue) \ + { \ + return GetIntAttr(nsGkAtoms::_atom, _default, aValue); \ + } \ + NS_IMETHODIMP \ + _class::Set##_method(PRInt32 aValue) \ + { \ + if (aValue <= 0) { \ + return NS_ERROR_DOM_INDEX_SIZE_ERR; \ + } \ + return SetIntAttr(nsGkAtoms::_atom, aValue); \ + } + +/** * QueryInterface() implementation helper macros */ #define NS_HTML_CONTENT_INTERFACE_TABLE_AMBIGUOUS_BEGIN(_class, _base) \ NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class) \ NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, _base) \ NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMElement, _base) \ NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMHTMLElement, _base)
--- a/content/html/content/src/nsHTMLSelectElement.cpp +++ b/content/html/content/src/nsHTMLSelectElement.cpp @@ -1201,17 +1201,18 @@ nsHTMLSelectElement::SetValue(const nsAS return rv; } NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Autofocus, autofocus) NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Disabled, disabled) NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Multiple, multiple) NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Name, name) -NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, Size, size, 0) +NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, Size, size, + GetDefaultSize()) NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, TabIndex, tabindex, 0) NS_IMETHODIMP nsHTMLSelectElement::Blur() { return nsGenericHTMLElement::Blur(); } @@ -1363,17 +1364,17 @@ nsHTMLSelectElement::DoneAddingChildren( PRBool nsHTMLSelectElement::ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) { if (aAttribute == nsGkAtoms::size && kNameSpaceID_None == aNamespaceID) { - return aResult.ParseIntWithBounds(aValue, 0); + return aResult.ParsePositiveIntValue(aValue); } return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, aResult); } static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
--- a/content/html/content/src/nsHTMLSelectElement.h +++ b/content/html/content/src/nsHTMLSelectElement.h @@ -468,16 +468,24 @@ protected: void VerifyOptionsArray(); #endif virtual PRBool AcceptAutofocus() const { return PR_TRUE; } + /** + * Helper method to get the default size. + */ + PRInt32 GetDefaultSize() const + { + return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ? 4 : 1; + } + /** The options[] array */ nsRefPtr<nsHTMLOptionCollection> mOptions; /** false if the parser is in the middle of adding children. */ PRPackedBool mIsDoneAddingChildren; /** true if our disabled state has changed from the default **/ PRPackedBool mDisabledChanged; /** true if child nodes are being added or removed. * Used by nsSafeOptionListMutation.
--- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -172,12 +172,13 @@ include $(topsrcdir)/config/rules.mk test_bug546995-1.html \ test_bug546995-2.html \ test_bug546995-3.html \ test_bug546995-4.html \ test_bug546995-5.html \ file_bug546995.html \ test_bug377624.html \ test_bug562932.html \ + test_bug551846.html \ $(NULL) libs:: $(_TEST_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644 --- /dev/null +++ b/content/html/content/test/test_bug551846.html @@ -0,0 +1,159 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=551846 +--> +<head> + <title>Test for Bug 551846</title> + <script type="application/javascript" src="/MochiKit/packed.js"></script> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=551846">Mozilla Bug 551846</a> +<p id="display"></p> +<div id="content" style="display: none"> + <select id='s'> + <option>Tulip</option> + <option>Lily</option> + <option>Gagea</option> + <option>Snowflake</option> + <option>Ismene</option> + </select> +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 551846 **/ + +function checkSizeReflection(element, defaultValue) +{ + is(element.size, defaultValue, "Default size should be " + defaultValue); + + element.setAttribute('size', -15); + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), -15, + "The content attribute should containt the previously set value"); + + element.setAttribute('size', 0); + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + + element.setAttribute('size', 2147483647); /* PR_INT32_MAX */ + is(element.size, 2147483647, + "PR_INT32_MAX should be considered as a valid value"); + is(element.getAttribute('size'), 2147483647, + "The content attribute should containt the previously set value"); + + element.setAttribute('size', -2147483648); /* PR_INT32_MIN */ + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), -2147483648, + "The content attribute should containt the previously set value"); + + element.setAttribute('size', 'non-numerical-value'); + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), 'non-numerical-value', + "The content attribute should containt the previously set value"); + + element.setAttribute('size', 4294967294); /* PR_INT32_MAX * 2 */ + is(element.size, defaultValue, + "Value greater than PR_INT32_MAX should be considered as invalid"); + is(element.getAttribute('size'), 4294967294, + "The content attribute should containt the previously set value"); + + element.setAttribute('size', -4294967296); /* PR_INT32_MIN * 2 */ + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + is(element.getAttribute('size'), -4294967296, + "The content attribute should containt the previously set value"); + + element.size = defaultValue + 1; + element.removeAttribute('size'); + is(element.size, defaultValue, + "When the attribute is removed, the size should be the default size"); + + element.setAttribute('size', 'foobar'); + is(element.size, defaultValue, + "The reflecting IDL attribute should return the default value when content attribute value is invalid"); + element.removeAttribute('size'); + is(element.size, defaultValue, + "When the attribute is removed, the size should be the default size"); +} + +function checkSetSizeException(element) +{ + var caught = false; + + try { + element.size = 1; + } catch(e) { + caught = true; + } + ok(!caught, "Setting a valid size shouldn't throw an exception"); + + caught = false; + try { + element.size = 0; + } catch(e) { + caught = true; + } + ok(caught, "Setting an invalid size from the IDL should throw an exception"); + + caught = false; + try { + element.size = -1; + } catch(e) { + caught = true; + } + ok(caught, "Setting an invalid size from the IDL should throw an exception"); + + caught = false; + try { + element.setAttribute('size', -10); + } catch(e) { + caught = true; + } + ok(!caught, "Setting an invalid size in the content attribute shouldn't throw an exception"); + + // reverting to defalut + element.removeAttribute('size'); +} + +function checkSizeWhenChangeMultiple(element) +{ + s.setAttribute('size', -1) + is(s.size, 1, "Size IDL attribute should be 1"); + + s.multiple = true; + is(s.size, 4, "Size IDL attribute should be 4"); + + is(s.getAttribute('size'), -1, "Size content attribute should be -1"); + + s.setAttribute('size', -2); + is(s.size, 4, "Size IDL attribute should be 4"); + + s.multiple = false; + is(s.size, 1, "Size IDL attribute should be 1"); + + is(s.getAttribute('size'), -2, "Size content attribute should be -2"); +} + +var s = document.getElementById('s'); + +checkSizeReflection(s, 1); +checkSetSizeException(s); + +s.setAttribute('multiple', 'true'); +checkSizeReflection(s, 4); +checkSetSizeException(s); +s.removeAttribute('multiple'); + +checkSizeWhenChangeMultiple(s); + +</script> +</pre> +</body> +</html>
--- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -1759,17 +1759,17 @@ HTMLContentSink::BeginContext(PRInt32 aP // Create new context SinkContext* sc = new SinkContext(this); if (!sc) { return NS_ERROR_OUT_OF_MEMORY; } if (!mCurrentContext) { - NS_ERROR("Non-existing context"); + NS_ERROR("Nonexistent context"); return NS_ERROR_FAILURE; } // Flush everything in the current context so that we don't have // to worry about insertions resulting in inconsistent frame creation. mCurrentContext->FlushTags(); @@ -1799,17 +1799,17 @@ HTMLContentSink::BeginContext(PRInt32 aP mContextStack.AppendElement(mCurrentContext); mCurrentContext = sc; return NS_OK; } NS_IMETHODIMP HTMLContentSink::EndContext(PRInt32 aPosition) { - NS_PRECONDITION(mCurrentContext && aPosition > -1, "non-existing context"); + NS_PRECONDITION(mCurrentContext && aPosition > -1, "nonexistent context"); PRUint32 n = mContextStack.Length() - 1; SinkContext* sc = mContextStack.ElementAt(n); const SinkContext::Node &bottom = mCurrentContext->mStack[0]; NS_ASSERTION(sc->mStack[aPosition].mType == bottom.mType, "ending a wrong context");
--- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -2149,17 +2149,17 @@ nsHTMLDocument::Close() FlushPendingNotifications(Flush_Layout); } // Remove the wyciwyg channel request from the document load group // that we added in OpenCommon(). If all other requests between // document.open() and document.close() have completed, then this // method should cause the firing of an onload event. NS_ASSERTION(mWyciwygChannel, "nsHTMLDocument::Close(): Trying to remove " - "non-existent wyciwyg channel!"); + "nonexistent wyciwyg channel!"); RemoveWyciwygChannel(); NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Close(): " "nsIWyciwygChannel could not be removed!"); } return NS_OK; }
--- a/content/media/nsBuiltinDecoderReader.h +++ b/content/media/nsBuiltinDecoderReader.h @@ -51,30 +51,30 @@ class nsBuiltinDecoderStateMachine; // Stores info relevant to presenting media samples. class nsVideoInfo { public: nsVideoInfo() : mFramerate(0.0), - mAspectRatio(1.0), + mPixelAspectRatio(1.0), mCallbackPeriod(1), mAudioRate(0), mAudioChannels(0), mFrame(0,0), mHasAudio(PR_FALSE), mHasVideo(PR_FALSE) {} // Frames per second. float mFramerate; - // Aspect ratio, as stored in the metadata. - float mAspectRatio; + // Pixel aspect ratio, as stored in the metadata. + float mPixelAspectRatio; // Length of a video frame in milliseconds, or the callback period if // there's no audio. PRUint32 mCallbackPeriod; // Samples per second. PRUint32 mAudioRate;
--- a/content/media/nsBuiltinDecoderStateMachine.cpp +++ b/content/media/nsBuiltinDecoderStateMachine.cpp @@ -1025,17 +1025,17 @@ void nsBuiltinDecoderStateMachine::Rende if (aData->mDuplicate) { return; } nsRefPtr<Image> image = aData->mImage; if (image) { const nsVideoInfo& info = mReader->GetInfo(); - mDecoder->SetVideoData(gfxIntSize(info.mPicture.width, info.mPicture.height), info.mAspectRatio, image); + mDecoder->SetVideoData(gfxIntSize(info.mPicture.width, info.mPicture.height), info.mPixelAspectRatio, image); } } PRInt64 nsBuiltinDecoderStateMachine::GetAudioClock() { NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread), "Should be on state machine thread."); if (!mAudioStream || !HasAudio())
--- a/content/media/nsMediaDecoder.cpp +++ b/content/media/nsMediaDecoder.cpp @@ -65,17 +65,17 @@ nsMediaDecoder::nsMediaDecoder() : mElement(0), mRGBWidth(-1), mRGBHeight(-1), mProgressTime(), mDataTime(), mVideoUpdateLock(nsnull), - mAspectRatio(1.0), + mPixelAspectRatio(1.0), mSizeChanged(PR_FALSE), mShuttingDown(PR_FALSE) { MOZ_COUNT_CTOR(nsMediaDecoder); } nsMediaDecoder::~nsMediaDecoder() { @@ -121,24 +121,24 @@ void nsMediaDecoder::Invalidate() nsIFrame* frame = mElement->GetPrimaryFrame(); { nsAutoLock lock(mVideoUpdateLock); if (mSizeChanged) { nsIntSize scaledSize(mRGBWidth, mRGBHeight); // Apply the aspect ratio to produce the intrinsic size we report // to the element. - if (mAspectRatio > 1.0) { + if (mPixelAspectRatio > 1.0) { // Increase the intrinsic width scaledSize.width = - ConditionDimension(mAspectRatio*scaledSize.width, scaledSize.width); + ConditionDimension(mPixelAspectRatio*scaledSize.width, scaledSize.width); } else { // Increase the intrinsic height scaledSize.height = - ConditionDimension(scaledSize.height/mAspectRatio, scaledSize.height); + ConditionDimension(scaledSize.height/mPixelAspectRatio, scaledSize.height); } mElement->UpdateMediaSize(scaledSize); mSizeChanged = PR_FALSE; if (frame) { nsPresContext* presContext = frame->PresContext(); nsIPresShell *presShell = presContext->PresShell(); presShell->FrameNeedsReflow(frame, @@ -208,24 +208,24 @@ nsresult nsMediaDecoder::StopProgress() nsresult rv = mProgressTimer->Cancel(); mProgressTimer = nsnull; return rv; } void nsMediaDecoder::SetVideoData(const gfxIntSize& aSize, - float aAspectRatio, + float aPixelAspectRatio, Image* aImage) { nsAutoLock lock(mVideoUpdateLock); if (mRGBWidth != aSize.width || mRGBHeight != aSize.height || - mAspectRatio != aAspectRatio) { + mPixelAspectRatio != aPixelAspectRatio) { mRGBWidth = aSize.width; mRGBHeight = aSize.height; - mAspectRatio = aAspectRatio; + mPixelAspectRatio = aPixelAspectRatio; mSizeChanged = PR_TRUE; } if (mImageContainer && aImage) { mImageContainer->SetCurrentImage(aImage); } }
--- a/content/media/nsMediaDecoder.h +++ b/content/media/nsMediaDecoder.h @@ -226,17 +226,17 @@ public: // Gets the image container for the media element. Will return null if // the element is not a video element. This can be called from any // thread; ImageContainers can be used from any thread. ImageContainer* GetImageContainer() { return mImageContainer; } // Set the video width, height, pixel aspect ratio, and current image. // Ownership of the image is transferred to the decoder. void SetVideoData(const gfxIntSize& aSize, - float aAspectRatio, + float aPixelAspectRatio, Image* aImage); protected: // Start timer to update download progress information. nsresult StartProgress(); // Stop progress information timer. @@ -278,17 +278,17 @@ protected: // in the midst of being changed. PRLock* mVideoUpdateLock; // Framerate of video being displayed in the element // expressed in numbers of frames per second. float mFramerate; // Pixel aspect ratio (ratio of the pixel width to pixel height) - float mAspectRatio; + float mPixelAspectRatio; // Has our size changed since the last repaint? PRPackedBool mSizeChanged; // True if the decoder is being shutdown. At this point all events that // are currently queued need to return immediately to prevent javascript // being run that operates on the element and decoder during shutdown. // Read/Write from the main thread only.
--- a/content/media/ogg/nsOggCodecState.cpp +++ b/content/media/ogg/nsOggCodecState.cpp @@ -144,17 +144,17 @@ PRBool nsOggCodecState::PageInFromBuffer } nsTheoraState::nsTheoraState(ogg_page* aBosPage) : nsOggCodecState(aBosPage), mSetup(0), mCtx(0), mFrameDuration(0), mFrameRate(0), - mAspectRatio(0) + mPixelAspectRatio(0) { MOZ_COUNT_CTOR(nsTheoraState); th_info_init(&mInfo); th_comment_init(&mComment); } nsTheoraState::~nsTheoraState() { MOZ_COUNT_DTOR(nsTheoraState); @@ -186,17 +186,17 @@ PRBool nsTheoraState::Init() { if (f > PR_UINT32_MAX) { return mActive = PR_FALSE; } mFrameDuration = static_cast<PRUint32>(f); n = mInfo.aspect_numerator; d = mInfo.aspect_denominator; - mAspectRatio = (n == 0 || d == 0) ? + mPixelAspectRatio = (n == 0 || d == 0) ? 1.0f : static_cast<float>(n) / static_cast<float>(d); // Ensure the frame isn't larger than our prescribed maximum. PRUint32 pixels; if (!MulOverflow32(mInfo.pic_width, mInfo.pic_height, pixels) || pixels > MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT || pixels == 0) {
--- a/content/media/ogg/nsOggCodecState.h +++ b/content/media/ogg/nsOggCodecState.h @@ -185,17 +185,17 @@ public: th_dec_ctx* mCtx; // Frame duration in ms. PRUint32 mFrameDuration; // Number of frames per second. float mFrameRate; - float mAspectRatio; + float mPixelAspectRatio; }; class nsSkeletonState : public nsOggCodecState { public: nsSkeletonState(ogg_page* aBosPage); virtual ~nsSkeletonState(); virtual CodecType GetType() { return TYPE_SKELETON; } virtual PRBool DecodeHeader(ogg_packet* aPacket);
--- a/content/media/ogg/nsOggReader.cpp +++ b/content/media/ogg/nsOggReader.cpp @@ -245,26 +245,24 @@ nsresult nsOggReader::ReadMetadata() if (s != mVorbisState && s != mTheoraState) { s->Deactivate(); } } // Initialize the first Theora and Vorbis bitstreams. According to the // Theora spec these can be considered the 'primary' bitstreams for playback. // Extract the metadata needed from these streams. - float aspectRatio = 0; // Set a default callback period for if we have no video data mCallbackPeriod = 1000 / AUDIO_FRAME_RATE; if (mTheoraState) { if (mTheoraState->Init()) { mCallbackPeriod = mTheoraState->mFrameDuration; - aspectRatio = mTheoraState->mAspectRatio; gfxIntSize sz(mTheoraState->mInfo.pic_width, mTheoraState->mInfo.pic_height); - mDecoder->SetVideoData(sz, mTheoraState->mAspectRatio, nsnull); + mDecoder->SetVideoData(sz, mTheoraState->mPixelAspectRatio, nsnull); } else { mTheoraState = nsnull; } } if (mVorbisState) { mVorbisState->Init(); } @@ -272,17 +270,17 @@ nsresult nsOggReader::ReadMetadata() mInfo.mHasVideo = HasVideo(); mInfo.mCallbackPeriod = mCallbackPeriod; if (HasAudio()) { mInfo.mAudioRate = mVorbisState->mInfo.rate; mInfo.mAudioChannels = mVorbisState->mInfo.channels; } if (HasVideo()) { mInfo.mFramerate = mTheoraState->mFrameRate; - mInfo.mAspectRatio = mTheoraState->mAspectRatio; + mInfo.mPixelAspectRatio = mTheoraState->mPixelAspectRatio; mInfo.mPicture.width = mTheoraState->mInfo.pic_width; mInfo.mPicture.height = mTheoraState->mInfo.pic_height; mInfo.mPicture.x = mTheoraState->mInfo.pic_x; mInfo.mPicture.y = mTheoraState->mInfo.pic_y; mInfo.mFrame.width = mTheoraState->mInfo.frame_width; mInfo.mFrame.height = mTheoraState->mInfo.frame_height; } mInfo.mDataOffset = mDataOffset;
--- a/content/svg/content/src/nsSVGAltGlyphElement.cpp +++ b/content/svg/content/src/nsSVGAltGlyphElement.cpp @@ -27,60 +27,54 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsSVGStylableElement.h" #include "nsGkAtoms.h" #include "nsIDOMSVGAltGlyphElement.h" #include "nsIDOMSVGURIReference.h" #include "nsSVGString.h" #include "nsSVGTextPositioningElement.h" -typedef nsSVGStylableElement nsSVGAltGlyphElementBase; +typedef nsSVGTextPositioningElement nsSVGAltGlyphElementBase; -class nsSVGAltGlyphElement : public nsSVGAltGlyphElementBase, +class nsSVGAltGlyphElement : public nsSVGAltGlyphElementBase, // = nsIDOMSVGTextPositioningElement public nsIDOMSVGAltGlyphElement, - public nsIDOMSVGURIReference, - public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement + public nsIDOMSVGURIReference { protected: friend nsresult NS_NewSVGAltGlyphElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsSVGAltGlyphElement(nsINodeInfo* aNodeInfo); - nsresult Init(); public: // interfaces: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGALTGLYPHELEMENT NS_DECL_NSIDOMSVGURIREFERENCE // xxx If xpcom allowed virtual inheritance we wouldn't need to // forward here :-( NS_FORWARD_NSIDOMNODE(nsSVGAltGlyphElementBase::) NS_FORWARD_NSIDOMELEMENT(nsSVGAltGlyphElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAltGlyphElementBase::) - NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::) - NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::) + NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGAltGlyphElementBase::) + NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGAltGlyphElementBase::) // nsIContent interface NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; protected: - virtual nsSVGTextContainerFrame* GetTextContainerFrame() { - return do_QueryFrame(GetPrimaryFrame(Flush_Layout)); - } // nsSVGElement overrides virtual StringAttributesInfo GetStringInfo(); virtual PRBool IsEventName(nsIAtom* aName); enum { HREF }; nsSVGString mStringAttributes[1]; @@ -114,27 +108,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGAlt //---------------------------------------------------------------------- // Implementation nsSVGAltGlyphElement::nsSVGAltGlyphElement(nsINodeInfo *aNodeInfo) : nsSVGAltGlyphElementBase(aNodeInfo) { } -nsresult -nsSVGAltGlyphElement::Init() -{ - nsresult rv = nsSVGAltGlyphElementBase::Init(); - NS_ENSURE_SUCCESS(rv,rv); - - rv = Initialise(this); - NS_ENSURE_SUCCESS(rv,rv); - - return rv; -} //---------------------------------------------------------------------- // nsIDOMNode methods NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGAltGlyphElement) //---------------------------------------------------------------------- // nsIDOMSVGURIReference methods
--- a/content/svg/content/src/nsSVGElement.h +++ b/content/svg/content/src/nsSVGElement.h @@ -189,17 +189,16 @@ protected: virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, const nsAString* aValue, PRBool aNotify); virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult); static nsresult ReportAttributeParseFailure(nsIDocument* aDocument, nsIAtom* aAttribute, const nsAString& aValue); - friend class nsSVGTextPositioningElement; // Hooks for subclasses virtual PRBool IsEventName(nsIAtom* aName); void UpdateContentStyleRule(); #ifdef MOZ_SMIL void UpdateAnimatedContentStyleRule(); nsICSSStyleRule* GetAnimatedContentStyleRule(); #endif // MOZ_SMIL
--- a/content/svg/content/src/nsSVGTSpanElement.cpp +++ b/content/svg/content/src/nsSVGTSpanElement.cpp @@ -31,57 +31,51 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#include "nsSVGStylableElement.h" #include "nsGkAtoms.h" #include "nsIDOMSVGTSpanElement.h" #include "nsSVGSVGElement.h" #include "nsSVGTextPositioningElement.h" -typedef nsSVGStylableElement nsSVGTSpanElementBase; +typedef nsSVGTextPositioningElement nsSVGTSpanElementBase; -class nsSVGTSpanElement : public nsSVGTSpanElementBase, - public nsIDOMSVGTSpanElement, - public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement +class nsSVGTSpanElement : public nsSVGTSpanElementBase, // = nsIDOMSVGTextPositioningElement + public nsIDOMSVGTSpanElement { protected: friend nsresult NS_NewSVGTSpanElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsSVGTSpanElement(nsINodeInfo* aNodeInfo); - nsresult Init(); public: // interfaces: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGTSPANELEMENT // xxx If xpcom allowed virtual inheritance we wouldn't need to // forward here :-( NS_FORWARD_NSIDOMNODE(nsSVGTSpanElementBase::) NS_FORWARD_NSIDOMELEMENT(nsSVGTSpanElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTSpanElementBase::) - NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::) - NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::) + NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTSpanElementBase::) + NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTSpanElementBase::) // nsIContent interface NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; protected: - virtual nsSVGTextContainerFrame* GetTextContainerFrame() { - return do_QueryFrame(GetPrimaryFrame(Flush_Layout)); - } // nsSVGElement overrides virtual PRBool IsEventName(nsIAtom* aName); }; NS_IMPL_NS_NEW_SVG_ELEMENT(TSpan) @@ -107,28 +101,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGTSp nsSVGTSpanElement::nsSVGTSpanElement(nsINodeInfo *aNodeInfo) : nsSVGTSpanElementBase(aNodeInfo) { } -nsresult -nsSVGTSpanElement::Init() -{ - nsresult rv = nsSVGTSpanElementBase::Init(); - NS_ENSURE_SUCCESS(rv,rv); - - rv = Initialise(this); - NS_ENSURE_SUCCESS(rv,rv); - - return rv; -} - //---------------------------------------------------------------------- // nsIDOMNode methods NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTSpanElement) //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGTextContentElement.h +++ b/content/svg/content/src/nsSVGTextContentElement.h @@ -36,19 +36,35 @@ * * ***** END LICENSE BLOCK ***** */ #ifndef __NS_SVGTEXTCONTENTELEMENTBASE_H__ #define __NS_SVGTEXTCONTENTELEMENTBASE_H__ #include "nsIDOMSVGTextContentElement.h" #include "nsSVGTextContainerFrame.h" +#include "nsSVGStylableElement.h" -class nsSVGTextContentElement +typedef nsSVGStylableElement nsSVGTextContentElementBase; + +/** + * Note that nsSVGTextElement does not inherit nsSVGTextPositioningElement, or + * this class - it reimplements us instead (see its documenting comment). The + * upshot is that any changes to this class also need to be made in + * nsSVGTextElement. + */ +class nsSVGTextContentElement : public nsSVGTextContentElementBase { public: NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT protected: - virtual nsSVGTextContainerFrame* GetTextContainerFrame()=0; + + nsSVGTextContentElement(nsINodeInfo *aNodeInfo) + : nsSVGTextContentElementBase(aNodeInfo) + {} + + nsSVGTextContainerFrame* GetTextContainerFrame() { + return do_QueryFrame(GetPrimaryFrame(Flush_Layout)); + } }; #endif
--- a/content/svg/content/src/nsSVGTextElement.cpp +++ b/content/svg/content/src/nsSVGTextElement.cpp @@ -39,53 +39,74 @@ #include "nsSVGGraphicElement.h" #include "nsGkAtoms.h" #include "nsIDOMSVGTextElement.h" #include "nsCOMPtr.h" #include "nsSVGSVGElement.h" #include "nsSVGTextPositioningElement.h" #include "nsIFrame.h" #include "nsDOMError.h" +#include "nsSVGLengthList.h" +#include "nsSVGAnimatedLengthList.h" +#include "nsSVGNumberList.h" +#include "nsSVGAnimatedNumberList.h" typedef nsSVGGraphicElement nsSVGTextElementBase; +/** + * This class does not inherit nsSVGTextPositioningElement - it reimplements it + * instead. + * + * Ideally this class would inherit nsSVGTextPositioningElement in addition to + * nsSVGGraphicElement, but we don't want two instances of nsSVGStylableElement + * and all the classes it inherits. Instead we choose to inherit one of the + * classes (nsSVGGraphicElement) and reimplement the missing pieces from the + * other (nsSVGTextPositioningElement (and thus nsSVGTextContentElement)). Care + * must be taken when making changes to the reimplemented pieces to keep + * nsSVGTextPositioningElement in sync (and vice versa). + */ class nsSVGTextElement : public nsSVGTextElementBase, - public nsIDOMSVGTextElement, - public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement + public nsIDOMSVGTextElement // nsIDOMSVGTextPositioningElement { protected: friend nsresult NS_NewSVGTextElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsSVGTextElement(nsINodeInfo* aNodeInfo); nsresult Init(); public: // interfaces: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGTEXTELEMENT + NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT + NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT // xxx If xpcom allowed virtual inheritance we wouldn't need to // forward here :-( NS_FORWARD_NSIDOMNODE(nsSVGTextElementBase::) NS_FORWARD_NSIDOMELEMENT(nsSVGTextElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextElementBase::) - NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::) - NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::) // nsIContent interface NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; protected: - virtual nsSVGTextContainerFrame* GetTextContainerFrame() { + nsSVGTextContainerFrame* GetTextContainerFrame() { return do_QueryFrame(GetPrimaryFrame(Flush_Layout)); } + // nsIDOMSVGTextPositioning properties: + nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX; + nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY; + nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX; + nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY; + nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate; }; NS_IMPL_NS_NEW_SVG_ELEMENT(Text) //---------------------------------------------------------------------- // nsISupports methods @@ -113,34 +134,280 @@ nsSVGTextElement::nsSVGTextElement(nsINo } nsresult nsSVGTextElement::Init() { nsresult rv = nsSVGTextElementBase::Init(); NS_ENSURE_SUCCESS(rv,rv); - rv = Initialise(this); - NS_ENSURE_SUCCESS(rv,rv); + // DOM property: nsIDOMSVGTextPositioningElement::x, #IMPLIED attrib: x + { + nsCOMPtr<nsIDOMSVGLengthList> lengthList; + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mX), + lengthList); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsGkAtoms::x, mX); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: nsIDOMSVGTextPositioningElement::y, #IMPLIED attrib: y + { + nsCOMPtr<nsIDOMSVGLengthList> lengthList; + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mY), + lengthList); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsGkAtoms::y, mY); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: nsIDOMSVGTextPositioningElement::dx, #IMPLIED attrib: dx + { + nsCOMPtr<nsIDOMSVGLengthList> lengthList; + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdX), + lengthList); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsGkAtoms::dx, mdX); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: nsIDOMSVGTextPositioningElement::dy, #IMPLIED attrib: dy + { + nsCOMPtr<nsIDOMSVGLengthList> lengthList; + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdY), + lengthList); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsGkAtoms::dy, mdY); + NS_ENSURE_SUCCESS(rv,rv); + } + + // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate + { + nsCOMPtr<nsIDOMSVGNumberList> numberList; + rv = NS_NewSVGNumberList(getter_AddRefs(numberList)); + NS_ENSURE_SUCCESS(rv,rv); + rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate), + numberList); + NS_ENSURE_SUCCESS(rv,rv); + rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate); + NS_ENSURE_SUCCESS(rv,rv); + } return rv; } //---------------------------------------------------------------------- // nsIDOMNode methods NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTextElement) //---------------------------------------------------------------------- // nsIDOMSVGTextElement methods // - no methods - + +//---------------------------------------------------------------------- +// nsIDOMSVGTextPositioningElement methods + +/* readonly attribute nsIDOMSVGAnimatedLengthList x; */ +NS_IMETHODIMP +nsSVGTextElement::GetX(nsIDOMSVGAnimatedLengthList * *aX) +{ + *aX = mX; + NS_IF_ADDREF(*aX); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLengthList y; */ +NS_IMETHODIMP +nsSVGTextElement::GetY(nsIDOMSVGAnimatedLengthList * *aY) +{ + *aY = mY; + NS_IF_ADDREF(*aY); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLengthList dx; */ +NS_IMETHODIMP +nsSVGTextElement::GetDx(nsIDOMSVGAnimatedLengthList * *aDx) +{ + *aDx = mdX; + NS_IF_ADDREF(*aDx); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedLengthList dy; */ +NS_IMETHODIMP +nsSVGTextElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy) +{ + *aDy = mdY; + NS_IF_ADDREF(*aDy); + return NS_OK; +} + +/* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */ +NS_IMETHODIMP +nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate) +{ + *aRotate = mRotate; + NS_IF_ADDREF(*aRotate); + return NS_OK; +} + + +//---------------------------------------------------------------------- +// nsIDOMSVGTextContentElement methods + +/* readonly attribute nsIDOMSVGAnimatedLength textLength; */ +NS_IMETHODIMP +nsSVGTextElement::GetTextLength(nsIDOMSVGAnimatedLength * *aTextLength) +{ + NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetTextLength"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* readonly attribute nsIDOMSVGAnimatedEnumeration lengthAdjust; */ +NS_IMETHODIMP +nsSVGTextElement::GetLengthAdjust(nsIDOMSVGAnimatedEnumeration * *aLengthAdjust) +{ + NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetLengthAdjust"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* long getNumberOfChars (); */ +NS_IMETHODIMP +nsSVGTextElement::GetNumberOfChars(PRInt32 *_retval) +{ + *_retval = 0; + + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + if (metrics) + *_retval = metrics->GetNumberOfChars(); + + return NS_OK; +} + +/* float getComputedTextLength (); */ +NS_IMETHODIMP +nsSVGTextElement::GetComputedTextLength(float *_retval) +{ + *_retval = 0.0; + + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + if (metrics) + *_retval = metrics->GetComputedTextLength(); + + return NS_OK; +} + +/* float getSubStringLength (in unsigned long charnum, in unsigned long nchars); */ +NS_IMETHODIMP +nsSVGTextElement::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval) +{ + *_retval = 0.0f; + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + if (!metrics) + return NS_OK; + + PRUint32 charcount = metrics->GetNumberOfChars(); + if (charcount <= charnum || nchars > charcount - charnum) + return NS_ERROR_DOM_INDEX_SIZE_ERR; + + if (nchars == 0) + return NS_OK; + + *_retval = metrics->GetSubStringLength(charnum, nchars); + return NS_OK; +} + +/* nsIDOMSVGPoint getStartPositionOfChar (in unsigned long charnum); */ +NS_IMETHODIMP +nsSVGTextElement::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval) +{ + *_retval = nsnull; + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + + if (!metrics) return NS_ERROR_FAILURE; + + return metrics->GetStartPositionOfChar(charnum, _retval); +} + +/* nsIDOMSVGPoint getEndPositionOfChar (in unsigned long charnum); */ +NS_IMETHODIMP +nsSVGTextElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval) +{ + *_retval = nsnull; + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + + if (!metrics) return NS_ERROR_FAILURE; + + return metrics->GetEndPositionOfChar(charnum, _retval); +} + +/* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */ +NS_IMETHODIMP +nsSVGTextElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval) +{ + *_retval = nsnull; + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + + if (!metrics) return NS_ERROR_FAILURE; + + return metrics->GetExtentOfChar(charnum, _retval); +} + +/* float getRotationOfChar (in unsigned long charnum); */ +NS_IMETHODIMP +nsSVGTextElement::GetRotationOfChar(PRUint32 charnum, float *_retval) +{ + *_retval = 0.0; + + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + + if (!metrics) return NS_ERROR_FAILURE; + + return metrics->GetRotationOfChar(charnum, _retval); +} + +/* long getCharNumAtPosition (in nsIDOMSVGPoint point); */ +NS_IMETHODIMP +nsSVGTextElement::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval) +{ + if (!point) + return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR; + + *_retval = -1; + + nsSVGTextContainerFrame* metrics = GetTextContainerFrame(); + if (metrics) + *_retval = metrics->GetCharNumAtPosition(point); + + return NS_OK; +} + +/* void selectSubString (in unsigned long charnum, in unsigned long nchars); */ +NS_IMETHODIMP +nsSVGTextElement::SelectSubString(PRUint32 charnum, PRUint32 nchars) +{ + NS_NOTYETIMPLEMENTED("nsSVGTextElement::SelectSubString"); + return NS_ERROR_NOT_IMPLEMENTED; +} + + //---------------------------------------------------------------------- // nsIContent methods NS_IMETHODIMP_(PRBool) nsSVGTextElement::IsAttributeMapped(const nsIAtom* name) const { static const MappedAttributeEntry* const map[] = { sTextContentElementsMap,
--- a/content/svg/content/src/nsSVGTextPathElement.h +++ b/content/svg/content/src/nsSVGTextPathElement.h @@ -38,22 +38,21 @@ #ifndef __NS_SVGTEXTPATHELEMENT_H__ #define __NS_SVGTEXTPATHELEMENT_H__ #include "nsSVGEnum.h" #include "nsSVGLength2.h" #include "nsSVGString.h" #include "nsSVGTextContentElement.h" -typedef nsSVGStylableElement nsSVGTextPathElementBase; +typedef nsSVGTextContentElement nsSVGTextPathElementBase; -class nsSVGTextPathElement : public nsSVGTextPathElementBase, +class nsSVGTextPathElement : public nsSVGTextPathElementBase, // = nsIDOMSVGTextContentElement public nsIDOMSVGTextPathElement, - public nsIDOMSVGURIReference, - public nsSVGTextContentElement // = nsIDOMSVGTextContentElement + public nsIDOMSVGURIReference { friend class nsSVGTextPathFrame; protected: friend nsresult NS_NewSVGTextPathElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsSVGTextPathElement(nsINodeInfo* aNodeInfo); @@ -64,29 +63,25 @@ public: NS_DECL_NSIDOMSVGTEXTPATHELEMENT NS_DECL_NSIDOMSVGURIREFERENCE // xxx If xpcom allowed virtual inheritance we wouldn't need to // forward here :-( NS_FORWARD_NSIDOMNODE(nsSVGTextPathElementBase::) NS_FORWARD_NSIDOMELEMENT(nsSVGTextPathElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextPathElementBase::) - NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::) + NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextPathElementBase::) // nsIContent interface NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; protected: - virtual nsSVGTextContainerFrame* GetTextContainerFrame() { - return do_QueryFrame(GetPrimaryFrame(Flush_Layout)); - } - virtual LengthAttributesInfo GetLengthInfo(); virtual EnumAttributesInfo GetEnumInfo(); virtual StringAttributesInfo GetStringInfo(); virtual PRBool IsEventName(nsIAtom* aName); enum { STARTOFFSET }; nsSVGLength2 mLengthAttributes[1];
--- a/content/svg/content/src/nsSVGTextPositioningElement.cpp +++ b/content/svg/content/src/nsSVGTextPositioningElement.cpp @@ -35,78 +35,80 @@ #include "nsSVGTextPositioningElement.h" #include "nsSVGAnimatedLengthList.h" #include "nsSVGAnimatedNumberList.h" #include "nsSVGLengthList.h" #include "nsSVGNumberList.h" nsresult -nsSVGTextPositioningElement::Initialise(nsSVGElement *aSVGElement) +nsSVGTextPositioningElement::Init() { - nsresult rv; + nsresult rv = nsSVGTextPositioningElementBase::Init(); + NS_ENSURE_SUCCESS(rv,rv); + // Create mapped properties: // DOM property: nsIDOMSVGTextPositioningElement::x, #IMPLIED attrib: x { nsCOMPtr<nsIDOMSVGLengthList> lengthList; - rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::X); + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X); NS_ENSURE_SUCCESS(rv,rv); rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mX), lengthList); NS_ENSURE_SUCCESS(rv,rv); - rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::x, mX); + rv = AddMappedSVGValue(nsGkAtoms::x, mX); NS_ENSURE_SUCCESS(rv,rv); } // DOM property: nsIDOMSVGTextPositioningElement::y, #IMPLIED attrib: y { nsCOMPtr<nsIDOMSVGLengthList> lengthList; - rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::Y); + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y); NS_ENSURE_SUCCESS(rv,rv); rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mY), lengthList); NS_ENSURE_SUCCESS(rv,rv); - rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::y, mY); + rv = AddMappedSVGValue(nsGkAtoms::y, mY); NS_ENSURE_SUCCESS(rv,rv); } // DOM property: nsIDOMSVGTextPositioningElement::dx, #IMPLIED attrib: dx { nsCOMPtr<nsIDOMSVGLengthList> lengthList; - rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::X); + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X); NS_ENSURE_SUCCESS(rv,rv); rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdX), lengthList); NS_ENSURE_SUCCESS(rv,rv); - rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::dx, mdX); + rv = AddMappedSVGValue(nsGkAtoms::dx, mdX); NS_ENSURE_SUCCESS(rv,rv); } // DOM property: nsIDOMSVGTextPositioningElement::dy, #IMPLIED attrib: dy { nsCOMPtr<nsIDOMSVGLengthList> lengthList; - rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::Y); + rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y); NS_ENSURE_SUCCESS(rv,rv); rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdY), lengthList); NS_ENSURE_SUCCESS(rv,rv); - rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::dy, mdY); + rv = AddMappedSVGValue(nsGkAtoms::dy, mdY); NS_ENSURE_SUCCESS(rv,rv); } // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate { nsCOMPtr<nsIDOMSVGNumberList> numberList; rv = NS_NewSVGNumberList(getter_AddRefs(numberList)); NS_ENSURE_SUCCESS(rv,rv); rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate), numberList); NS_ENSURE_SUCCESS(rv,rv); - rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::rotate, mRotate); + rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate); NS_ENSURE_SUCCESS(rv,rv); } return rv; } //---------------------------------------------------------------------- // nsIDOMSVGTextPositioningElement methods
--- a/content/svg/content/src/nsSVGTextPositioningElement.h +++ b/content/svg/content/src/nsSVGTextPositioningElement.h @@ -36,23 +36,37 @@ #ifndef __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__ #define __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__ #include "nsIDOMSVGTextPositionElem.h" #include "nsSVGTextContentElement.h" #include "nsIDOMSVGAnimatedLengthList.h" #include "nsIDOMSVGAnimatedNumberList.h" -class nsSVGTextPositioningElement : public nsSVGTextContentElement +class nsSVGElement; + +typedef nsSVGTextContentElement nsSVGTextPositioningElementBase; + +/** + * Note that nsSVGTextElement does not inherit this class - it reimplements it + * instead (see its documenting comment). The upshot is that any changes to + * this class also need to be made in nsSVGTextElement. + */ +class nsSVGTextPositioningElement : public nsSVGTextPositioningElementBase { public: NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT protected: - nsresult Initialise(nsSVGElement *aSVGElement); + + nsSVGTextPositioningElement(nsINodeInfo *aNodeInfo) + : nsSVGTextPositioningElementBase(aNodeInfo) + {} + + nsresult Init(); // nsIDOMSVGTextPositioning properties: nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY; nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate; };
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp +++ b/content/xul/templates/src/nsXULTreeBuilder.cpp @@ -1703,22 +1703,19 @@ nsresult nsXULTreeBuilder::CloseContainer(PRInt32 aIndex) { NS_ASSERTION(aIndex >= 0 && aIndex < mRows.Count(), "bad row"); if (aIndex < 0 || aIndex >= mRows.Count()) return NS_ERROR_INVALID_ARG; nsTreeRows::iterator iter = mRows[aIndex]; - nsTreeRows::Subtree& subtree = *(iter->mSubtree); + if (iter->mSubtree) + RemoveMatchesFor(*iter->mSubtree); - RemoveMatchesFor(subtree); - - // Update the view - iter = mRows[aIndex]; PRInt32 count = mRows.GetSubtreeSizeFor(iter); mRows.RemoveSubtreeFor(iter); iter->mContainerState = nsTreeRows::eContainerState_Closed; if (mBoxObject) { mBoxObject->InvalidateRow(aIndex);
--- a/docshell/resources/content/netError.xhtml +++ b/docshell/resources/content/netError.xhtml @@ -115,17 +115,17 @@ { // Session history has the URL of the page that failed // to load, not the one of the error page. So, just call // reload(), which will also repost POST data correctly. try { location.reload(); } catch (e) { // We probably tried to reload a URI that caused an exception to - // occur; e.g. a non-existent file. + // occur; e.g. a nonexistent file. } buttonEl.disabled = true; } function initPage() { var err = getErrorCode();
--- a/docshell/test/test_bug529119-1.html +++ b/docshell/test/test_bug529119-1.html @@ -6,17 +6,17 @@ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script class="testbody" type="text/javascript"> SimpleTest.waitForExplicitFinish(); var workingURL = "http://mochi.test:8888/tests/docshell/test/bug529119-window.html"; -var faultyURL = "http://some-non-existent-domain-27489274c892748217cn2384.com/"; +var faultyURL = "http://some-nonexistent-domain-27489274c892748217cn2384.com/"; var w = null; var phase = 0; var gotWrongPageOnTryAgainClick = false; function pollForPage(f, w) { // Start with polling after a delay, we might mistakenly take the current page
--- a/docshell/test/test_bug529119-2.html +++ b/docshell/test/test_bug529119-2.html @@ -6,17 +6,17 @@ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script class="testbody" type="text/javascript"> SimpleTest.waitForExplicitFinish(); var workingURL = "http://mochi.test:8888/tests/docshell/test/bug529119-window.html"; -var faultyURL = "http://some-non-existent-domain-27489274c892748217cn2384.com/"; +var faultyURL = "http://some-nonexistent-domain-27489274c892748217cn2384.com/"; var w = null; var phase = 0; function pollForPage(expectErrorPage, f, w) { // Start with polling after a delay, we might mistakenly take the current page // as an expected one.
--- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -1294,17 +1294,17 @@ nsDOMStorage::SetSecure(const nsAString& return gStorageDB->SetSecure(this, aKey, aSecure); } #else return NS_ERROR_NOT_IMPLEMENTED; #endif nsSessionStorageEntry *entry = mItems.GetEntry(aKey); - NS_ASSERTION(entry, "Don't use SetSecure() with non-existing keys!"); + NS_ASSERTION(entry, "Don't use SetSecure() with nonexistent keys!"); if (entry) { entry->mItem->SetSecureInternal(aSecure); } return NS_OK; }
--- a/editor/libeditor/html/nsHTMLAbsPosition.cpp +++ b/editor/libeditor/html/nsHTMLAbsPosition.cpp @@ -495,17 +495,17 @@ nsHTMLEditor::SetFinalPosition(PRInt32 a // keep track of that size mPositionedObjectX = newX; mPositionedObjectY = newY; return RefreshResizers(); } void -nsHTMLEditor::AddPositioningOffet(PRInt32 & aX, PRInt32 & aY) +nsHTMLEditor::AddPositioningOffset(PRInt32 & aX, PRInt32 & aY) { // Get the positioning offset nsresult res; nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &res); PRInt32 positioningOffset = 0; if (NS_SUCCEEDED(res) && prefBranch) { res = prefBranch->GetIntPref("editor.positioning.offset", &positioningOffset); @@ -539,17 +539,17 @@ nsHTMLEditor::AbsolutelyPositionElement( PRInt32 x, y; GetElementOrigin(aElement, x, y); mHTMLCSSUtils->SetCSSProperty(aElement, nsEditProperty::cssPosition, NS_LITERAL_STRING("absolute"), PR_FALSE); - AddPositioningOffet(x, y); + AddPositioningOffset(x, y); SnapToGrid(x, y); SetElementPosition(aElement, x, y); // we may need to create a br if the positioned element is alone in its // container nsCOMPtr<nsIDOMNode> parentNode; res = aElement->GetParentNode(getter_AddRefs(parentNode)); if (NS_FAILED(res)) return res;
--- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -501,17 +501,17 @@ protected: NS_IMETHOD SplitCellIntoColumns(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32 aColIndex, PRInt32 aColSpanLeft, PRInt32 aColSpanRight, nsIDOMElement **aNewCell); NS_IMETHOD SplitCellIntoRows(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32 aColIndex, PRInt32 aRowSpanAbove, PRInt32 aRowSpanBelow, nsIDOMElement **aNewCell); nsresult CopyCellBackgroundColor(nsIDOMElement *destCell, nsIDOMElement *sourceCell); - // Reduce rowspan/colspan when cells span into non-existent rows/columns + // Reduce rowspan/colspan when cells span into nonexistent rows/columns NS_IMETHOD FixBadRowSpan(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32& aNewRowCount); NS_IMETHOD FixBadColSpan(nsIDOMElement *aTable, PRInt32 aColIndex, PRInt32& aNewColCount); // Fallback method: Call this after using ClearSelection() and you // failed to set selection to some other content in the document NS_IMETHOD SetSelectionAtDocumentStart(nsISelection *aSelection); // End of Table Editing utilities @@ -902,17 +902,17 @@ protected: nsCOMPtr<nsIDOMElement> mGrabber; nsCOMPtr<nsIDOMElement> mPositioningShadow; PRInt32 mGridSize; nsresult CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn); nsresult StartMoving(nsIDOMElement * aHandle); nsresult SetFinalPosition(PRInt32 aX, PRInt32 aY); - void AddPositioningOffet(PRInt32 & aX, PRInt32 & aY); + void AddPositioningOffset(PRInt32 & aX, PRInt32 & aY); void SnapToGrid(PRInt32 & newX, PRInt32 & newY); nsresult GrabberClicked(); nsresult EndMoving(); nsresult CheckPositionedElementBGandFG(nsIDOMElement * aElement, nsAString & aReturn); /* INLINE TABLE EDITING */
--- a/editor/libeditor/html/nsWSRunObject.h +++ b/editor/libeditor/html/nsWSRunObject.h @@ -316,22 +316,22 @@ class NS_STACK_CLASS nsWSRunObject // member variables --------------------------------------------------------- nsCOMPtr<nsIDOMNode> mNode; // the node passed to our constructor PRInt32 mOffset; // the offset passed to our contructor // together, the above represent the point at which we are building up ws info. PRBool mPRE; // true if we are in preformatted whitespace context - nsCOMPtr<nsIDOMNode> mStartNode; // node/offet where ws starts + nsCOMPtr<nsIDOMNode> mStartNode; // node/offset where ws starts PRInt32 mStartOffset; // ... PRInt16 mStartReason; // reason why ws starts (eText, eOtherBlock, etc) nsCOMPtr<nsIDOMNode> mStartReasonNode;// the node that implicated by start reason - nsCOMPtr<nsIDOMNode> mEndNode; // node/offet where ws ends + nsCOMPtr<nsIDOMNode> mEndNode; // node/offset where ws ends PRInt32 mEndOffset; // ... PRInt16 mEndReason; // reason why ws ends (eText, eOtherBlock, etc) nsCOMPtr<nsIDOMNode> mEndReasonNode; // the node that implicated by end reason nsCOMPtr<nsIDOMNode> mFirstNBSPNode; // location of first nbsp in ws run, if any PRInt32 mFirstNBSPOffset; // ... nsCOMPtr<nsIDOMNode> mLastNBSPNode; // location of last nbsp in ws run, if any
--- a/editor/libeditor/html/tests/browserscope/lib/browserscope/README +++ b/editor/libeditor/html/tests/browserscope/lib/browserscope/README @@ -13,17 +13,17 @@ http://code.google.com/appengine/downloa For local development, just startup the server: ./pathto/google_appengine/dev_appserver.py --port=8080 browserscope You should then be able to access the local application at: http://localhost:8080/ Note: the first time you hit the homepage it may take a little while - that's because it's trying to read out median times for all -of the tests from a non-existent datastore and write to memcache. +of the tests from a nonexistent datastore and write to memcache. Just be a lil patient. You can run the unit tests at: http://localhost:8080/test CONTRIBUTING ------------------
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp +++ b/embedding/browser/webBrowser/nsWebBrowser.cpp @@ -1661,16 +1661,29 @@ NS_IMETHODIMP nsWebBrowser::EnsureDocShe NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(mDocShellTreeOwner); mDocShellTreeOwner->WebBrowser(this); return NS_OK; } +static void DrawThebesLayer(ThebesLayer* aLayer, + gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + void* aCallbackData) +{ + nscolor* color = static_cast<nscolor*>(aCallbackData); + aContext->NewPath(); + aContext->SetColor(gfxRGBA(*color)); + nsIntRect dirtyRect = aRegionToDraw.GetBounds(); + aContext->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height)); + aContext->Fill(); +} + /* static */ nsEventStatus nsWebBrowser::HandleEvent(nsGUIEvent *aEvent) { nsWebBrowser *browser = nsnull; void *data = nsnull; nsIWidget *widget = aEvent->widget; if (!widget) @@ -1691,29 +1704,17 @@ nsEventStatus nsWebBrowser::HandleEvent( layerManager->BeginTransaction(); nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer(); nsPaintEvent* paintEvent = static_cast<nsPaintEvent*>(aEvent); nsIntRect dirtyRect = paintEvent->region.GetBounds(); if (root) { root->SetVisibleRegion(dirtyRect); layerManager->SetRoot(root); } - layerManager->EndConstruction(); - if (root) { - nsIntRegion toDraw; - gfxContext* ctx = root->BeginDrawing(&toDraw); - if (ctx) { - ctx->NewPath(); - ctx->SetColor(gfxRGBA(browser->mBackgroundColor)); - ctx->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height)); - ctx->Fill(); - } - } - root->EndDrawing(); - layerManager->EndTransaction(); + layerManager->EndTransaction(DrawThebesLayer, &browser->mBackgroundColor); return nsEventStatus_eConsumeDoDefault; } case NS_ACTIVATE: { #if defined(DEBUG_smaug) nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell); nsAutoString documentURI; if (domDocument) {
--- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -117,17 +117,18 @@ class CanvasLayer; * root layer, and each container layer holds a reference to its children. */ class THEBES_API LayerManager { NS_INLINE_DECL_REFCOUNTING(LayerManager) public: enum LayersBackend { LAYERS_BASIC = 0, - LAYERS_OPENGL + LAYERS_OPENGL, + LAYERS_D3D9 }; virtual ~LayerManager() {} /** * Start a new transaction. Nested transactions are not allowed so * there must be no transaction currently in progress. * This transaction will update the state of the window from which @@ -138,24 +139,39 @@ public: * Start a new transaction. Nested transactions are not allowed so * there must be no transaction currently in progress. * This transaction will render the contents of the layer tree to * the given target context. The rendering will be complete when * EndTransaction returns. */ virtual void BeginTransactionWithTarget(gfxContext* aTarget) = 0; /** - * Finish the construction phase of the transaction and enter the - * drawing phase. + * Function called to draw the contents of each ThebesLayer. + * aRegionToDraw contains the region that needs to be drawn. + * This would normally be a subregion of the visible region. Drawing is + * not necessarily clipped to aRegionToDraw. + * The callee must draw all of aRegionToDraw. + * + * aContext must not be used after the call has returned. + * We guarantee that buffered contents in the visible + * region are valid once drawing is complete. */ - virtual void EndConstruction() = 0; + typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer, + gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + void* aCallbackData); /** - * Complete the transaction. + * Finish the construction phase of the transaction, perform the + * drawing phase, and end the transaction. + * During the drawing phase, all ThebesLayers in the tree are + * drawn in tree order, exactly once each, except for those layers + * where it is known that the visible region is empty. */ - virtual void EndTransaction() = 0; + virtual void EndTransaction(DrawThebesLayerCallback aCallback, + void* aCallbackData) = 0; /** * CONSTRUCTION PHASE ONLY * Set the root layer. */ virtual void SetRoot(Layer* aLayer) = 0; /** @@ -192,16 +208,18 @@ public: /** * Type of layer manager his is. This is to be used sparsely in order to * avoid a lot of Layers backend specific code. It should be used only when * Layers backend specific functionality is necessary. */ virtual LayersBackend GetBackendType() = 0; }; +class ThebesLayer; + /** * A Layer represents anything that can be rendered onto a destination * surface. */ class THEBES_API Layer { NS_INLINE_DECL_REFCOUNTING(Layer) public: @@ -293,16 +311,22 @@ public: virtual Layer* GetFirstChild() { return nsnull; } const gfx3DMatrix& GetTransform() { return mTransform; } // This setter and getter can be used anytime. void SetUserData(void* aData) { mUserData = aData; } void* GetUserData() { return mUserData; } /** + * Dynamic downcast to a Thebes layer. Returns null if this is not + * a ThebesLayer. + */ + virtual ThebesLayer* AsThebesLayer() { return nsnull; } + + /** * Only the implementation should call this. This is per-implementation * private data. Normally, all layers with a given layer manager * use the same type of ImplData. */ void* ImplData() { return mImplData; } /** * Only the implementation should use these methods. @@ -353,46 +377,17 @@ public: /** * CONSTRUCTION PHASE ONLY * Tell this layer that the content in some region has changed and * will need to be repainted. This area is removed from the valid * region. */ virtual void InvalidateRegion(const nsIntRegion& aRegion) = 0; - /** - * DRAWING PHASE ONLY - * Start drawing into the layer. On return, aRegionToDraw contains the - * region that needs to be drawn in by the caller. This would normally - * be a subregion of the visible region. Drawing is not necessarily - * clipped to aRegionToDraw. - * - * No other layer operations are allowed until we call EndDrawing on this - * layer. During the drawing phase, all ThebesLayers in the tree must be - * drawn in tree order, exactly once each, except for those layers - * where it is known that the visible region is empty. (Calling - * BeginDrawing on non-visible layers is allowed, but aRegionToDraw - * will return empty.) - * - * When an empty region is returned in aRegionToDraw, BeginDrawing - * may return a null context. - * - * The layer system will hold a reference to the returned gfxContext* - * until EndDrawing is called. The returned gfxContext must not be used - * after EndDrawing is called. - */ - virtual gfxContext* BeginDrawing(nsIntRegion* aRegionToDraw) = 0; - /** - * DRAWING PHASE ONLY - * We've finished drawing into this layer. At this point the caller - * must have drawn all of aRegionToDraw that was returned by - * BeginDrawing, and we guarantee that buffered contents in the visible - * region are now valid. - */ - virtual void EndDrawing() = 0; + virtual ThebesLayer* AsThebesLayer() { return this; } protected: ThebesLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData) {} }; /** * A Layer which other layers render into. It holds references to its
--- a/gfx/layers/Makefile.in +++ b/gfx/layers/Makefile.in @@ -37,26 +37,30 @@ DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = \ $(srcdir) \ $(srcdir)/basic \ $(srcdir)/opengl \ + $(srcdir)/d3d9 \ $(NULL) include $(DEPTH)/config/autoconf.mk MODULE = thebes LIBRARY_NAME = layers LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 DEFINES += -DIMPL_THEBES +ifdef MOZ_DEBUG +DEFINES += -DD3D_DEBUG_INFO +endif EXPORTS = \ BasicLayers.h \ ImageLayers.h \ Layers.h \ LayerManagerOGL.h \ $(NULL) @@ -65,12 +69,27 @@ CPPSRCS = \ BasicLayers.cpp \ LayerManagerOGL.cpp \ ColorLayerOGL.cpp \ ThebesLayerOGL.cpp \ ContainerLayerOGL.cpp \ ImageLayerOGL.cpp \ CanvasLayerOGL.cpp \ $(NULL) + +ifeq ($(MOZ_WIDGET_TOOLKIT),windows) +ifndef WINCE +EXPORTS += LayerManagerD3D9.h + +CPPSRCS += \ + LayerManagerD3D9.cpp \ + ThebesLayerD3D9.cpp \ + ContainerLayerD3D9.cpp \ + ImageLayerD3D9.cpp \ + ColorLayerD3D9.cpp \ + CanvasLayerD3D9.cpp \ + $(NULL) +endif +endif include $(topsrcdir)/config/rules.mk CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
--- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -89,17 +89,19 @@ public: const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; } /** * Layers that paint themselves, such as ImageLayers, should paint * in response to this method call. aContext will already have been * set up to account for all the properties of the layer (transform, * opacity, etc). */ - virtual void Paint(gfxContext* aContext) {} + virtual void Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData) {} protected: nsIntRegion mVisibleRegion; }; static BasicImplData* ToData(Layer* aLayer) { @@ -235,50 +237,38 @@ public: mVisibleRegion = aRegion; } virtual void InvalidateRegion(const nsIntRegion& aRegion) { NS_ASSERTION(BasicManager()->InConstruction(), "Can only set properties in construction phase"); } - virtual gfxContext* BeginDrawing(nsIntRegion* aRegionToDraw); - virtual void EndDrawing(); + virtual void Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData); protected: BasicLayerManager* BasicManager() { return static_cast<BasicLayerManager*>(mManager); } }; -gfxContext* -BasicThebesLayer::BeginDrawing(nsIntRegion* aRegionToDraw) +void +BasicThebesLayer::Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData) { - NS_ASSERTION(BasicManager()->IsBeforeInTree(BasicManager()->GetLastPainted(), this), - "Painting layers out of order"); NS_ASSERTION(BasicManager()->InDrawing(), "Can only draw in drawing phase"); gfxContext* target = BasicManager()->GetTarget(); - if (!target) - return nsnull; - - BasicManager()->AdvancePaintingTo(this); + NS_ASSERTION(target, "We shouldn't be called if there's no target"); - *aRegionToDraw = mVisibleRegion; - return target; -} - -void -BasicThebesLayer::EndDrawing() -{ - NS_ASSERTION(BasicManager()->InDrawing(), - "Can only draw in drawing phase"); - NS_ASSERTION(BasicManager()->GetLastPainted() == this, - "Not currently drawing this layer"); + aCallback(this, target, mVisibleRegion, aCallbackData); } class BasicImageLayer : public ImageLayer, BasicImplData { public: BasicImageLayer(BasicLayerManager* aLayerManager) : ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)) { MOZ_COUNT_CTOR(BasicImageLayer); @@ -290,27 +280,31 @@ public: virtual void SetVisibleRegion(const nsIntRegion& aRegion) { NS_ASSERTION(BasicManager()->InConstruction(), "Can only set properties in construction phase"); mVisibleRegion = aRegion; } - virtual void Paint(gfxContext* aContext); + virtual void Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData); protected: BasicLayerManager* BasicManager() { return static_cast<BasicLayerManager*>(mManager); } }; void -BasicImageLayer::Paint(gfxContext* aContext) +BasicImageLayer::Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData) { if (!mContainer) return; gfxIntSize size; nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&size); if (!surface) { return; @@ -360,27 +354,31 @@ public: virtual void SetVisibleRegion(const nsIntRegion& aRegion) { NS_ASSERTION(BasicManager()->InConstruction(), "Can only set properties in construction phase"); mVisibleRegion = aRegion; } - virtual void Paint(gfxContext* aContext); + virtual void Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData); protected: BasicLayerManager* BasicManager() { return static_cast<BasicLayerManager*>(mManager); } }; void -BasicColorLayer::Paint(gfxContext* aContext) +BasicColorLayer::Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData) { aContext->SetColor(mColor); aContext->Paint(); } class BasicCanvasLayer : public CanvasLayer, BasicImplData { @@ -392,17 +390,19 @@ public: } virtual ~BasicCanvasLayer() { MOZ_COUNT_DTOR(BasicCanvasLayer); } virtual void Initialize(const Data& aData); virtual void Updated(const nsIntRect& aRect); - virtual void Paint(gfxContext* aContext); + virtual void Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData); protected: nsRefPtr<gfxASurface> mSurface; nsRefPtr<mozilla::gl::GLContext> mGLContext; nsIntRect mBounds; nsIntRect mUpdatedRect; @@ -479,17 +479,19 @@ BasicCanvasLayer::Updated(const nsIntRec } // sanity NS_ASSERTION(mUpdatedRect.IsEmpty() || mBounds.Contains(mUpdatedRect), "CanvasLayer: Updated rect bigger than bounds!"); } void -BasicCanvasLayer::Paint(gfxContext* aContext) +BasicCanvasLayer::Paint(gfxContext* aContext, + LayerManager::DrawThebesLayerCallback aCallback, + void* aCallbackData) { nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface); pat->SetFilter(mFilter); pat->SetExtend(gfxPattern::EXTEND_PAD); gfxRect r(0, 0, mBounds.width, mBounds.height); gfxMatrix m; @@ -506,17 +508,17 @@ BasicCanvasLayer::Paint(gfxContext* aCon if (mNeedsYFlip) { aContext->SetMatrix(m); } mUpdatedRect.Empty(); } BasicLayerManager::BasicLayerManager(gfxContext* aContext) : - mDefaultTarget(aContext), mLastPainted(nsnull) + mDefaultTarget(aContext) #ifdef DEBUG , mPhase(PHASE_NONE) #endif { MOZ_COUNT_CTOR(BasicLayerManager); } BasicLayerManager::~BasicLayerManager() @@ -549,34 +551,33 @@ BasicLayerManager::BeginTransactionWithT NS_ASSERTION(mPhase == PHASE_NONE, "Nested transactions not allowed"); #ifdef DEBUG mPhase = PHASE_CONSTRUCTION; #endif mTarget = aTarget; } void -BasicLayerManager::EndConstruction() +BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback, + void* aCallbackData) { NS_ASSERTION(mRoot, "Root not set"); NS_ASSERTION(mPhase == PHASE_CONSTRUCTION, "Should be in construction phase"); #ifdef DEBUG mPhase = PHASE_DRAWING; #endif -} -void -BasicLayerManager::EndTransaction() -{ - NS_ASSERTION(mPhase == PHASE_DRAWING, "Should be in drawing phase"); + if (mTarget) { + PaintLayer(mRoot, aCallback, aCallbackData); + mTarget = nsnull; + } + #ifdef DEBUG mPhase = PHASE_NONE; #endif - AdvancePaintingTo(nsnull); - mTarget = nsnull; // No retained layers supported for now mRoot = nsnull; } void BasicLayerManager::SetRoot(Layer* aLayer) { NS_ASSERTION(aLayer, "Root can't be null"); @@ -620,20 +621,24 @@ UseOpaqueSurface(Layer* aLayer) // in the container. BasicContainerLayer* parent = static_cast<BasicContainerLayer*>(aLayer->GetParent()); return parent && parent->GetFirstChild() == aLayer && UseOpaqueSurface(parent); } void -BasicLayerManager::BeginPaintingLayer(Layer* aLayer) +BasicLayerManager::PaintLayer(Layer* aLayer, + DrawThebesLayerCallback aCallback, + void* aCallbackData) { PRBool needsGroup = NeedsGroup(aLayer); - if ((needsGroup || NeedsState(aLayer)) && mTarget) { + PRBool needsSaveRestore = needsGroup || NeedsState(aLayer); + + if (needsSaveRestore) { mTarget->Save(); if (aLayer->GetClipRect()) { const nsIntRect& r = *aLayer->GetClipRect(); mTarget->NewPath(); mTarget->Rectangle(gfxRect(r.x, r.y, r.width, r.height), PR_TRUE); mTarget->Clip(); } @@ -662,76 +667,32 @@ BasicLayerManager::BeginPaintingLayer(La mTarget->SetMatrix(currentMatrix); gfxASurface::gfxContentType type = UseOpaqueSurface(aLayer) ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA; mTarget->PushGroup(type); } } - mLastPainted = aLayer; + ToData(aLayer)->Paint(mTarget, aCallback, aCallbackData); + for (Layer* child = aLayer->GetFirstChild(); child; + child = child->GetNextSibling()) { + PaintLayer(child, aCallback, aCallbackData); + } - // For layers that paint themselves (e.g., BasicImageLayer), paint - // them now. - ToData(aLayer)->Paint(mTarget); -} - -void -BasicLayerManager::EndPaintingLayer() -{ - PRBool needsGroup = NeedsGroup(mLastPainted); - if ((needsGroup || NeedsState(mLastPainted)) && mTarget) { + if (needsSaveRestore) { if (needsGroup) { mTarget->PopGroupToSource(); - mTarget->Paint(mLastPainted->GetOpacity()); + mTarget->Paint(aLayer->GetOpacity()); } mTarget->Restore(); } } -void -BasicLayerManager::AdvancePaintingTo(BasicThebesLayer* aLayer) -{ - NS_ASSERTION(!aLayer || IsBeforeInTree(mLastPainted, aLayer), - "Painting layers out of order"); - - // Traverse the layer tree from mLastPainted to aLayer, calling - // BeginPaintingLayer and EndPaintingLayer as we enter or exit layers. - do { - Layer* firstChild; - Layer* nextSibling; - // Advance mLastPainted one step through the tree in preorder - if (!mLastPainted) { - // This is the first AdvancePaintingTo call. Start at the root. - BeginPaintingLayer(mRoot); - } else if ((firstChild = mLastPainted->GetFirstChild()) != nsnull) { - // Descend into our first child, if there is one. - BeginPaintingLayer(firstChild); - } else if ((nextSibling = mLastPainted->GetNextSibling()) != nsnull) { - // There are no children to descend into. Leave this layer and - // advance to our next sibling, if there is one. - EndPaintingLayer(); - BeginPaintingLayer(nextSibling); - } else { - // There are no children to descend into and we have no next sibling. - // Exit layers until we find a layer which has a next sibling - // (or we exit the root). - do { - EndPaintingLayer(); - mLastPainted = mLastPainted->GetParent(); - } while (mLastPainted && !mLastPainted->GetNextSibling()); - if (mLastPainted) { - EndPaintingLayer(); - BeginPaintingLayer(mLastPainted->GetNextSibling()); - } - } - } while (mLastPainted != aLayer); -} - already_AddRefed<ThebesLayer> BasicLayerManager::CreateThebesLayer() { NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); nsRefPtr<ThebesLayer> layer = new BasicThebesLayer(this); return layer.forget(); } @@ -762,59 +723,10 @@ BasicLayerManager::CreateColorLayer() already_AddRefed<CanvasLayer> BasicLayerManager::CreateCanvasLayer() { NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); nsRefPtr<CanvasLayer> layer = new BasicCanvasLayer(this); return layer.forget(); } -#ifdef DEBUG -static void -AppendAncestors(Layer* aLayer, nsTArray<Layer*>* aAncestors) -{ - while (aLayer) { - aAncestors->AppendElement(aLayer); - aLayer = aLayer->GetParent(); - } -} - -PRBool -BasicLayerManager::IsBeforeInTree(Layer* aBefore, Layer* aLayer) -{ - if (!aBefore) { - return PR_TRUE; - } - nsAutoTArray<Layer*,8> beforeAncestors, afterAncestors; - AppendAncestors(aBefore, &beforeAncestors); - AppendAncestors(aLayer, &afterAncestors); - PRInt32 beforeIndex = beforeAncestors.Length() - 1; - PRInt32 afterIndex = afterAncestors.Length() - 1; - NS_ASSERTION(beforeAncestors[beforeIndex] == mRoot, "aBefore not in tree?"); - NS_ASSERTION(afterAncestors[afterIndex] == mRoot, "aLayer not in tree?"); - --beforeIndex; - --afterIndex; - while (beforeIndex >= 0 && afterIndex >= 0) { - if (beforeAncestors[beforeIndex] != afterAncestors[afterIndex]) { - BasicContainerLayer* parent = - static_cast<BasicContainerLayer*>(beforeAncestors[beforeIndex + 1]); - for (Layer* child = parent->GetFirstChild(); - child != afterAncestors[afterIndex]; - child = child->GetNextSibling()) { - if (child == beforeAncestors[beforeIndex]) { - return PR_TRUE; - } - } - return PR_FALSE; - } - --beforeIndex; - --afterIndex; - } - if (afterIndex > 0) { - // aBefore is an ancestor of aLayer, so it's before aLayer in preorder - return PR_TRUE; - } - return PR_FALSE; -} -#endif - } }
--- a/gfx/layers/basic/BasicLayers.h +++ b/gfx/layers/basic/BasicLayers.h @@ -73,62 +73,46 @@ public: /** * Set the default target context that will be used when BeginTransaction * is called. This can only be called outside a transaction. */ void SetDefaultTarget(gfxContext* aContext); virtual void BeginTransaction(); virtual void BeginTransactionWithTarget(gfxContext* aTarget); - virtual void EndConstruction(); - virtual void EndTransaction(); + virtual void EndTransaction(DrawThebesLayerCallback aCallback, + void* aCallbackData); virtual void SetRoot(Layer* aLayer); virtual already_AddRefed<ThebesLayer> CreateThebesLayer(); virtual already_AddRefed<ContainerLayer> CreateContainerLayer(); virtual already_AddRefed<ImageLayer> CreateImageLayer(); virtual already_AddRefed<CanvasLayer> CreateCanvasLayer(); virtual already_AddRefed<ImageContainer> CreateImageContainer(); virtual already_AddRefed<ColorLayer> CreateColorLayer(); virtual LayersBackend GetBackendType() { return LAYERS_BASIC; } #ifdef DEBUG PRBool InConstruction() { return mPhase == PHASE_CONSTRUCTION; } PRBool InDrawing() { return mPhase == PHASE_DRAWING; } - PRBool IsBeforeInTree(Layer* aBefore, Layer* aLayer); #endif - // Prepares mTarget for painting into aLayer. Layers are painted - // in tree order, so this method essentially traverses the layer tree - // in preorder from mLastPainted to aLayer, doing whatever's needed - // as we exit container layers and enter new container layers, and - // drawing any non-ThebesLayers we encounter. - void AdvancePaintingTo(BasicThebesLayer* aLayer); - Layer* GetLastPainted() { return mLastPainted; } gfxContext* GetTarget() { return mTarget; } private: - // This gets called when we start painting aLayer. It can change - // the state of mTarget by saving state, setting clipping and/or - // pushing a group. - void BeginPaintingLayer(Layer* aLayer); - // This gets called when we finish painting aLayer. It can change - // the state of mTarget by popping a group and/or restoring the state. - void EndPaintingLayer(); + // Paints aLayer to mTarget. + void PaintLayer(Layer* aLayer, + DrawThebesLayerCallback aCallback, + void* aCallbackData); nsRefPtr<Layer> mRoot; // The default context for BeginTransaction. nsRefPtr<gfxContext> mDefaultTarget; - // The context to draw into. This is always the context that - // our ThebesLayers will return. + // The context to draw into. nsRefPtr<gfxContext> mTarget; - // The most recently painted layer during the drawing phase of - // a transaction, or null if no layer has been painted in this - // transaction. - Layer* mLastPainted; #ifdef DEBUG enum TransactionPhase { PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING }; TransactionPhase mPhase; #endif }; }
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic <vladimir@pobox.com> + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "CanvasLayerD3D9.h" + +#include "gfxImageSurface.h" +#include "gfxWindowsSurface.h" + +namespace mozilla { +namespace layers { + +CanvasLayerD3D9::~CanvasLayerD3D9() +{ +} + +void +CanvasLayerD3D9::Initialize(const Data& aData) +{ + NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!"); + + if (aData.mSurface) { + mSurface = aData.mSurface; + NS_ASSERTION(aData.mGLContext == nsnull, + "CanvasLayer can't have both surface and GLContext"); + mNeedsYFlip = PR_FALSE; + } else if (aData.mGLContext) { + mGLContext = aData.mGLContext; + mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied; + mNeedsYFlip = PR_TRUE; + } else { + NS_ERROR("CanvasLayer created without mSurface or mGLContext?"); + } + + mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); + + device()->CreateTexture(mBounds.width, mBounds.height, 1, 0, + D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, + getter_AddRefs(mTexture), NULL); +} + +void +CanvasLayerD3D9::Updated(const nsIntRect& aRect) +{ + if (!mTexture) { + NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!"); + return; + } + + if (mGLContext) { + // WebGL reads entire surface. + D3DLOCKED_RECT r; + mTexture->LockRect(0, &r, NULL, 0); + + PRUint8 *destination; + if (r.Pitch != mBounds.width * 4) { + destination = new PRUint8[mBounds.width * mBounds.height * 4]; + } else { + destination = (PRUint8*)r.pBits; + } + + // We have to flush to ensure that any buffered GL operations are + // in the framebuffer before we read. + mGLContext->fFlush(); + + // For simplicity, we read the entire framebuffer for now -- in + // the future we should use aRect, though with WebGL we don't + // have an easy way to generate one. + mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height, + LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV, + destination); + + if (r.Pitch != mBounds.width * 4) { + for (int y = 0; y < mBounds.height; y++) { + memcpy((PRUint8*)r.pBits + r.Pitch * y, + destination + mBounds.width * 4 * y, + mBounds.width * 4); + } + delete [] destination; + } + mTexture->UnlockRect(0); + } else if (mSurface) { + RECT r; + r.left = aRect.x; + r.top = aRect.y; + r.right = aRect.XMost(); + r.bottom = aRect.YMost(); + + D3DLOCKED_RECT lockedRect; + mTexture->LockRect(0, &lockedRect, &r, 0); + + PRUint8 *startBits; + PRUint32 sourceStride; + + nsRefPtr<gfxImageSurface> sourceSurface; + + if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) { + sourceSurface = static_cast<gfxWindowsSurface*>(mSurface.get())->GetImageSurface(); + startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y + + aRect.x * 4; + sourceStride = sourceSurface->Stride(); + } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) { + sourceSurface = static_cast<gfxImageSurface*>(sourceSurface.get()); + if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 && + sourceSurface->Format() != gfxASurface::ImageFormatRGB24) + { + mTexture->UnlockRect(0); + return; + } + startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y + + aRect.x * 4; + sourceStride = sourceSurface->Stride(); + } else { + sourceSurface = new gfxImageSurface(gfxIntSize(aRect.width, aRect.height), + gfxASurface::ImageFormatARGB32); + nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface); + ctx->Translate(gfxPoint(-aRect.x, -aRect.y)); + ctx->SetOperator(gfxContext::OPERATOR_SOURCE); + ctx->SetSource(sourceSurface); + ctx->Paint(); + startBits = sourceSurface->Data(); + sourceStride = sourceSurface->Stride(); + } + + for (int y = 0; y < aRect.height; y++) { + memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y, + startBits + sourceStride * y, + aRect.width * 4); + } + + mTexture->UnlockRect(0); + } +} + +LayerD3D9::LayerType +CanvasLayerD3D9::GetType() +{ + return TYPE_CANVAS; +} + +Layer* +CanvasLayerD3D9::GetLayer() +{ + return this; +} + +void +CanvasLayerD3D9::RenderLayer() +{ + float quadTransform[4][4]; + /* + * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position + * and size. To get pixel perfect mapping we offset the quad half a pixel + * to the top-left. We also flip the Y axis here, note we can only do this + * because we are in CULL_NONE mode! + * + * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx + */ + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)mBounds.width; + if (mNeedsYFlip) { + quadTransform[1][1] = (float)-mBounds.height; + quadTransform[3][1] = (float)mBounds.height - 0.5f; + } else { + quadTransform[1][1] = (float)mBounds.height; + quadTransform[3][1] = -0.5f; + } + quadTransform[2][2] = 1.0f; + quadTransform[3][0] = -0.5f; + quadTransform[3][3] = 1.0f; + + device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4); + + device()->SetVertexShaderConstantF(4, &mTransform._11, 4); + + float opacity[4]; + /* + * We always upload a 4 component float, but the shader will use only the + * first component since it's declared as a 'float'. + */ + opacity[0] = GetOpacity(); + device()->SetPixelShaderConstantF(0, opacity, 1); + + mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER); + + if (!mGLBufferIsPremultiplied) { + device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + } + device()->SetTexture(0, mTexture); + device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + if (!mGLBufferIsPremultiplied) { + device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + } +} + +} /* namespace layers */ +} /* namespace mozilla */ \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/CanvasLayerD3D9.h @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Vladimir Vukicevic <vladimir@pobox.com> + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_CANVASLAYEROGL_H +#define GFX_CANVASLAYEROGL_H + +#include "LayerManagerD3D9.h" +#include "GLContext.h" +#include "gfxASurface.h" + +namespace mozilla { +namespace layers { + +class THEBES_API CanvasLayerD3D9 : + public CanvasLayer, + public LayerD3D9 +{ +public: + CanvasLayerD3D9(LayerManagerD3D9 *aManager) + : CanvasLayer(aManager, NULL), + LayerD3D9(aManager), + mTexture(0), + mGLBufferIsPremultiplied(PR_FALSE), + mNeedsYFlip(PR_FALSE) + { + mImplData = static_cast<LayerD3D9*>(this); + } + + ~CanvasLayerD3D9(); + + // CanvasLayer implementation + virtual void Initialize(const Data& aData); + virtual void Updated(const nsIntRect& aRect); + + // LayerD3D9 implementation + virtual LayerType GetType(); + virtual Layer* GetLayer(); + virtual void RenderLayer(); + +protected: + typedef mozilla::gl::GLContext GLContext; + + nsRefPtr<gfxASurface> mSurface; + nsRefPtr<GLContext> mGLContext; + nsRefPtr<IDirect3DTexture9> mTexture; + + nsIntRect mBounds; + + PRPackedBool mGLBufferIsPremultiplied; + PRPackedBool mNeedsYFlip; +}; + +} /* layers */ +} /* mozilla */ +#endif /* GFX_CANVASLAYERD3D9_H */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert O'Callahan <robert@ocallahan.org> + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ColorLayerD3D9.h" + +namespace mozilla { +namespace layers { + +LayerD3D9::LayerType +ColorLayerD3D9::GetType() +{ + return TYPE_COLOR; +} + +Layer* +ColorLayerD3D9::GetLayer() +{ + return this; +} + +void +ColorLayerD3D9::RenderLayer() +{ + // XXX we might be able to improve performance by using + // IDirect3DDevice9::Clear + + float quadTransform[4][4]; + nsIntRect visibleRect = mVisibleRegion.GetBounds(); + // Transform the quad to the size of the visible area. + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)visibleRect.width; + quadTransform[1][1] = (float)visibleRect.height; + quadTransform[2][2] = 1.0f; + quadTransform[3][0] = (float)visibleRect.x; + quadTransform[3][1] = (float)visibleRect.y; + quadTransform[3][3] = 1.0f; + + device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4); + device()->SetVertexShaderConstantF(4, &mTransform._11, 4); + + float color[4]; + // color is premultiplied, so we need to adjust all channels + color[0] = (float)(mColor.r * GetOpacity()); + color[1] = (float)(mColor.g * GetOpacity()); + color[2] = (float)(mColor.b * GetOpacity()); + color[3] = (float)(mColor.a * GetOpacity()); + + device()->SetPixelShaderConstantF(0, color, 1); + + mD3DManager->SetShaderMode(LayerManagerD3D9::SOLIDCOLORLAYER); + + device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); +} + +} /* layers */ +} /* mozilla */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ColorLayerD3D9.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert O'Callahan <robert@ocallahan.org> + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_COLORLAYERD3D9_H +#define GFX_COLORLAYERD3D9_H + +#include "LayerManagerD3D9.h" + +namespace mozilla { +namespace layers { + +class THEBES_API ColorLayerD3D9 : public ColorLayer, + public LayerD3D9 +{ +public: + ColorLayerD3D9(LayerManagerD3D9 *aManager) + : ColorLayer(aManager, NULL) + , LayerD3D9(aManager) + { + mImplData = static_cast<LayerD3D9*>(this); + } + + virtual void SetVisibleRegion(const nsIntRegion& aRegion) { mVisibleRegion = aRegion; } + + // LayerD3D9 Implementation + virtual LayerType GetType(); + + virtual Layer* GetLayer(); + + virtual void RenderLayer(); + +protected: + nsIntRegion mVisibleRegion; +}; + +} /* layers */ +} /* mozilla */ + +#endif /* GFX_COLORLAYERD3D9_H */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp @@ -0,0 +1,252 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ContainerLayerD3D9.h" + +namespace mozilla { +namespace layers { + +ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager) + : ContainerLayer(aManager, NULL) + , LayerD3D9(aManager) +{ + mImplData = static_cast<LayerD3D9*>(this); +} + +const nsIntRect& +ContainerLayerD3D9::GetVisibleRect() +{ + return mVisibleRect; +} + +void +ContainerLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion) +{ + mVisibleRect = aRegion.GetBounds(); +} + +void +ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter) +{ + LayerD3D9 *newChild = static_cast<LayerD3D9*>(aChild->ImplData()); + aChild->SetParent(this); + if (!aAfter) { + LayerD3D9 *oldFirstChild = GetFirstChildD3D9(); + mFirstChild = newChild->GetLayer(); + newChild->SetNextSibling(oldFirstChild); + return; + } + for (LayerD3D9 *child = GetFirstChildD3D9(); + child; child = child->GetNextSibling()) { + if (aAfter == child->GetLayer()) { + LayerD3D9 *oldNextSibling = child->GetNextSibling(); + child->SetNextSibling(newChild); + child->GetNextSibling()->SetNextSibling(oldNextSibling); + return; + } + } + NS_WARNING("Failed to find aAfter layer!"); +} + +void +ContainerLayerD3D9::RemoveChild(Layer *aChild) +{ + if (GetFirstChild() == aChild) { + mFirstChild = GetFirstChildD3D9()->GetNextSibling() ? + GetFirstChildD3D9()->GetNextSibling()->GetLayer() : nsnull; + return; + } + LayerD3D9 *lastChild = NULL; + for (LayerD3D9 *child = GetFirstChildD3D9(); child; + child = child->GetNextSibling()) { + if (child->GetLayer() == aChild) { + // We're sure this is not our first child. So lastChild != NULL. + lastChild->SetNextSibling(child->GetNextSibling()); + child->SetNextSibling(NULL); + child->GetLayer()->SetParent(NULL); + return; + } + lastChild = child; + } +} + +LayerD3D9::LayerType +ContainerLayerD3D9::GetType() +{ + return TYPE_CONTAINER; +} + +Layer* +ContainerLayerD3D9::GetLayer() +{ + return this; +} + +LayerD3D9* +ContainerLayerD3D9::GetFirstChildD3D9() +{ + if (!mFirstChild) { + return nsnull; + } + return static_cast<LayerD3D9*>(mFirstChild->ImplData()); +} + +void +ContainerLayerD3D9::RenderLayer() +{ + float opacity = GetOpacity(); + nsRefPtr<IDirect3DSurface9> previousRenderTarget; + nsRefPtr<IDirect3DTexture9> renderTexture; + float previousRenderTargetOffset[4]; + float renderTargetOffset[] = { 0, 0, 0, 0 }; + float oldViewMatrix[4][4]; + + PRBool useIntermediate = (opacity != 1.0 || !mTransform.IsIdentity()); + + if (useIntermediate) { + device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); + device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1, + D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), + NULL); + nsRefPtr<IDirect3DSurface9> renderSurface; + renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); + device()->SetRenderTarget(0, renderSurface); + device()->GetVertexShaderConstantF(12, previousRenderTargetOffset, 1); + renderTargetOffset[0] = (float)GetVisibleRect().x; + renderTargetOffset[1] = (float)GetVisibleRect().y; + device()->SetVertexShaderConstantF(12, renderTargetOffset, 1); + + float viewMatrix[4][4]; + /* + * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, + * <1.0, -1.0> bottomright) + */ + memset(&viewMatrix, 0, sizeof(viewMatrix)); + viewMatrix[0][0] = 2.0f / mVisibleRect.width; + viewMatrix[1][1] = -2.0f / mVisibleRect.height; + viewMatrix[2][2] = 1.0f; + viewMatrix[3][0] = -1.0f; + viewMatrix[3][1] = 1.0f; + viewMatrix[3][3] = 1.0f; + + device()->GetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4); + device()->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4); + } + + /* + * Render this container's contents. + */ + LayerD3D9 *layerToRender = GetFirstChildD3D9(); + while (layerToRender) { + const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect(); + RECT r; + if (clipRect) { + r.left = (LONG)(clipRect->x - renderTargetOffset[0]); + r.top = (LONG)(clipRect->y - renderTargetOffset[1]); + r.right = (LONG)(clipRect->x - renderTargetOffset[0] + clipRect->width); + r.bottom = (LONG)(clipRect->y - renderTargetOffset[1] + clipRect->height); + } else { + if (useIntermediate) { + r.left = 0; + r.top = 0; + } else { + r.left = GetVisibleRect().x; + r.top = GetVisibleRect().y; + } + r.right = r.left + GetVisibleRect().width; + r.bottom = r.top + GetVisibleRect().height; + } + + nsRefPtr<IDirect3DSurface9> renderSurface; + device()->GetRenderTarget(0, getter_AddRefs(renderSurface)); + + D3DSURFACE_DESC desc; + renderSurface->GetDesc(&desc); + + r.left = NS_MAX<LONG>(0, r.left); + r.top = NS_MAX<LONG>(0, r.top); + r.bottom = NS_MIN<LONG>(r.bottom, desc.Height); + r.right = NS_MIN<LONG>(r.right, desc.Width); + + device()->SetScissorRect(&r); + + layerToRender->RenderLayer(); + layerToRender = layerToRender->GetNextSibling(); + } + + if (useIntermediate) { + device()->SetRenderTarget(0, previousRenderTarget); + device()->SetVertexShaderConstantF(12, previousRenderTargetOffset, 1); + device()->SetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4); + + float quadTransform[4][4]; + /* + * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position + * and size. To get pixel perfect mapping we offset the quad half a pixel + * to the top-left. + * + * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx + */ + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)GetVisibleRect().width; + quadTransform[1][1] = (float)GetVisibleRect().height; + quadTransform[2][2] = 1.0f; + quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f; + quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f; + quadTransform[3][3] = 1.0f; + + device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4); + device()->SetVertexShaderConstantF(4, &mTransform._11, 4); + + float opacityVector[4]; + /* + * We always upload a 4 component float, but the shader will use only the + * first component since it's declared as a 'float'. + */ + opacityVector[0] = opacity; + device()->SetPixelShaderConstantF(0, opacityVector, 1); + + mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER); + + device()->SetTexture(0, renderTexture); + device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } +} + +} /* layers */ +} /* mozilla */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ContainerLayerD3D9.h @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_CONTAINERLAYERD3D9_H +#define GFX_CONTAINERLAYERD3D9_H + +#include "Layers.h" +#include "LayerManagerD3D9.h" + +namespace mozilla { +namespace layers { + +class ContainerLayerD3D9 : public ContainerLayer, + public LayerD3D9 +{ +public: + ContainerLayerD3D9(LayerManagerD3D9 *aManager); + + const nsIntRect &GetVisibleRect(); + + /* ContainerLayer implementation */ + void SetVisibleRegion(const nsIntRegion& aRegion); + + void InsertAfter(Layer* aChild, Layer* aAfter); + + void RemoveChild(Layer* aChild); + + /* LayerD3D9 implementation */ + LayerType GetType(); + + Layer* GetLayer(); + + LayerD3D9* GetFirstChildD3D9(); + + PRBool IsEmpty(); + + void RenderLayer(); + +private: + nsIntRect mVisibleRect; +}; + +} /* layers */ +} /* mozilla */ + +#endif /* GFX_CONTAINERLAYERD3D9_H */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp @@ -0,0 +1,463 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ImageLayerD3D9.h" +#include "gfxImageSurface.h" +#include "yuv_convert.h" + +namespace mozilla { +namespace layers { + +using mozilla::MutexAutoLock; + +ImageContainerD3D9::ImageContainerD3D9(LayerManagerD3D9 *aManager) + : ImageContainer(aManager) + , mActiveImageLock("mozilla.layers.ImageContainerD3D9.mActiveImageLock") +{ +} + +already_AddRefed<Image> +ImageContainerD3D9::CreateImage(const Image::Format *aFormats, + PRUint32 aNumFormats) +{ + if (!aNumFormats) { + return nsnull; + } + nsRefPtr<Image> img; + if (aFormats[0] == Image::PLANAR_YCBCR) { + img = new PlanarYCbCrImageD3D9(static_cast<LayerManagerD3D9*>(mManager)); + } else if (aFormats[0] == Image::CAIRO_SURFACE) { + img = new CairoImageD3D9(static_cast<LayerManagerD3D9*>(mManager)); + } + return img.forget(); +} + +void +ImageContainerD3D9::SetCurrentImage(Image *aImage) +{ + MutexAutoLock lock(mActiveImageLock); + + mActiveImage = aImage; +} + +already_AddRefed<Image> +ImageContainerD3D9::GetCurrentImage() +{ + MutexAutoLock lock(mActiveImageLock); + + nsRefPtr<Image> retval = mActiveImage; + return retval.forget(); +} + +already_AddRefed<gfxASurface> +ImageContainerD3D9::GetCurrentAsSurface(gfxIntSize *aSize) +{ + MutexAutoLock lock(mActiveImageLock); + if (!mActiveImage) { + return nsnull; + } + + if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) { + PlanarYCbCrImageD3D9 *yuvImage = + static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get()); + if (yuvImage->HasData()) { + *aSize = yuvImage->mSize; + } + } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) { + CairoImageD3D9 *cairoImage = + static_cast<CairoImageD3D9*>(mActiveImage.get()); + *aSize = cairoImage->mSize; + } + + return static_cast<ImageD3D9*>(mActiveImage->GetImplData())->GetAsSurface(); +} + +gfxIntSize +ImageContainerD3D9::GetCurrentSize() +{ + MutexAutoLock lock(mActiveImageLock); + if (!mActiveImage) { + return gfxIntSize(0,0); + } + if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) { + PlanarYCbCrImageD3D9 *yuvImage = + static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get()); + if (!yuvImage->HasData()) { + return gfxIntSize(0,0); + } + return yuvImage->mSize; + + } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) { + CairoImageD3D9 *cairoImage = + static_cast<CairoImageD3D9*>(mActiveImage.get()); + return cairoImage->mSize; + } + + return gfxIntSize(0,0); +} + +LayerD3D9::LayerType +ImageLayerD3D9::GetType() +{ + return TYPE_IMAGE; +} + +Layer* +ImageLayerD3D9::GetLayer() +{ + return this; +} + +void +ImageLayerD3D9::RenderLayer() +{ + if (!GetContainer()) { + return; + } + + nsRefPtr<Image> image = GetContainer()->GetCurrentImage(); + + if (image->GetFormat() == Image::PLANAR_YCBCR) { + PlanarYCbCrImageD3D9 *yuvImage = + static_cast<PlanarYCbCrImageD3D9*>(image.get()); + + if (!yuvImage->HasData()) { + return; + } + yuvImage->AllocateTextures(); + + float quadTransform[4][4]; + /* + * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position + * and size. To get pixel perfect mapping we extend the quad half a pixel + * beyond all edges. + */ + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)yuvImage->mSize.width + 0.5f; + quadTransform[1][1] = (float)yuvImage->mSize.height + 0.5f; + quadTransform[2][2] = 1.0f; + quadTransform[3][3] = 1.0f; + + + device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4); + device()->SetVertexShaderConstantF(4, &mTransform._11, 4); + + float opacity[4]; + /* + * We always upload a 4 component float, but the shader will + * only use the the first component since it's declared as a 'float'. + */ + opacity[0] = GetOpacity(); + device()->SetPixelShaderConstantF(0, opacity, 1); + + mD3DManager->SetShaderMode(LayerManagerD3D9::YCBCRLAYER); + + device()->SetTexture(0, yuvImage->mYTexture); + device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + device()->SetTexture(1, yuvImage->mCbTexture); + device()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + device()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + device()->SetTexture(2, yuvImage->mCrTexture); + device()->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + device()->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + + device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + + } else if (image->GetFormat() == Image::CAIRO_SURFACE) { + CairoImageD3D9 *cairoImage = + static_cast<CairoImageD3D9*>(image.get()); + + float quadTransform[4][4]; + /* + * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position + * and size. To get pixel perfect mapping we extend the quad half a pixel + * beyond all edges. + */ + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)cairoImage->mSize.width + 0.5f; + quadTransform[1][1] = (float)cairoImage->mSize.height + 0.5f; + quadTransform[2][2] = 1.0f; + quadTransform[3][3] = 1.0f; + + + device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4); + device()->SetVertexShaderConstantF(4, &mTransform._11, 4); + + float opacity[4]; + /* + * We always upload a 4 component float, but the shader will + * only use the the first component since it's declared as a 'float'. + */ + opacity[0] = GetOpacity(); + device()->SetPixelShaderConstantF(0, opacity, 1); + + mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER); + + device()->SetTexture(0, cairoImage->mTexture); + device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } +} + +PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9(mozilla::layers::LayerManagerD3D9* aManager) + : PlanarYCbCrImage(static_cast<ImageD3D9*>(this)) + , mManager(aManager) + , mHasData(PR_FALSE) +{ +} + +void +PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData) +{ + // For now, we copy the data + int width_shift = 0; + int height_shift = 0; + if (aData.mYSize.width == aData.mCbCrSize.width && + aData.mYSize.height == aData.mCbCrSize.height) { + // YV24 format + width_shift = 0; + height_shift = 0; + } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && + aData.mYSize.height == aData.mCbCrSize.height) { + // YV16 format + width_shift = 1; + height_shift = 0; + } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width && + aData.mYSize.height / 2 == aData.mCbCrSize.height ) { + // YV12 format + width_shift = 1; + height_shift = 1; + } else { + NS_ERROR("YCbCr format not supported"); + } + + mData = aData; + mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift; + mData.mCbCrSize.height = aData.mPicSize.height >> height_shift; + mData.mYSize = aData.mPicSize; + mData.mYStride = mData.mYSize.width; + + mBuffer = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height * 2 + + mData.mYStride * mData.mYSize.height]; + mData.mYChannel = mBuffer; + mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height; + mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height; + + mData.mCrChannel = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height]; + int cbcr_x = aData.mPicX >> width_shift; + int cbcr_y = aData.mPicY >> height_shift; + + for (int i = 0; i < mData.mYSize.height; i++) { + memcpy(mData.mYChannel + i * mData.mYStride, + aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX, + mData.mYStride); + } + for (int i = 0; i < mData.mCbCrSize.height; i++) { + memcpy(mData.mCbChannel + i * mData.mCbCrStride, + aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x, + mData.mCbCrStride); + } + for (int i = 0; i < mData.mCbCrSize.height; i++) { + memcpy(mData.mCrChannel + i * mData.mCbCrStride, + aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x, + mData.mCbCrStride); + } + + // Fix picture rect to be correct + mData.mPicX = mData.mPicY = 0; + mSize = aData.mPicSize; + + mHasData = PR_TRUE; +} + +void +PlanarYCbCrImageD3D9::AllocateTextures() +{ + + + D3DLOCKED_RECT lockrect; + PRUint8* src; + PRUint8* dest; + //XXX: ensure correct usage flags + mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height, + 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, + getter_AddRefs(mYTexture), NULL); + + + /* lock the entire texture */ + mYTexture->LockRect(0, &lockrect, NULL, 0); + + src = mData.mYChannel; + //FIX cast + dest = (PRUint8*)lockrect.pBits; + + // copy over data + for (int h=0; h<mData.mYSize.height; h++) { + memcpy(dest, src, mData.mYSize.width); + dest += lockrect.Pitch; + src += mData.mYStride; + } + + mYTexture->UnlockRect(0); + + //XXX: ensure correct usage flags + mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height, + 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, + getter_AddRefs(mCbTexture), NULL); + + + /* lock the entire texture */ + mCbTexture->LockRect(0, &lockrect, NULL, 0); + + src = mData.mCbChannel; + //FIX cast + dest = (PRUint8*)lockrect.pBits; + + // copy over data + for (int h=0; h<mData.mCbCrSize.height; h++) { + memcpy(dest, src, mData.mCbCrSize.width); + dest += lockrect.Pitch; + src += mData.mCbCrStride; + } + + mCbTexture->UnlockRect(0); + + + //XXX: ensure correct usage flags + mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height, + 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, + getter_AddRefs(mCrTexture), NULL); + + + /* lock the entire texture */ + mCrTexture->LockRect(0, &lockrect, NULL, 0); + + src = mData.mCrChannel; + //FIX cast + dest = (PRUint8*)lockrect.pBits; + + // copy over data + for (int h=0; h<mData.mCbCrSize.height; h++) { + memcpy(dest, src, mData.mCbCrSize.width); + dest += lockrect.Pitch; + src += mData.mCbCrStride; + } + + mCrTexture->UnlockRect(0); + +} + +void +PlanarYCbCrImageD3D9::FreeTextures() +{ +} + +already_AddRefed<gfxASurface> +PlanarYCbCrImageD3D9::GetAsSurface() +{ + nsRefPtr<gfxImageSurface> imageSurface = + new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24); + + // Convert from YCbCr to RGB now + gfx::ConvertYCbCrToRGB32(mData.mYChannel, + mData.mCbChannel, + mData.mCrChannel, + imageSurface->Data(), + 0, + 0, + mSize.width, + mSize.height, + mData.mYStride, + mData.mCbCrStride, + imageSurface->Stride(), + gfx::YV12); + + return imageSurface.forget().get(); +} + +CairoImageD3D9::~CairoImageD3D9() +{ +} + +void +CairoImageD3D9::SetData(const CairoImage::Data &aData) +{ + mSize = aData.mSize; + + nsRefPtr<gfxImageSurface> imageSurface = + new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32); + + nsRefPtr<gfxContext> context = new gfxContext(imageSurface); + + context->SetSource(aData.mSurface); + context->Paint(); + + //XXX: make sure we're using the correct usage flags + mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height, + 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, + getter_AddRefs(mTexture), NULL); + + D3DLOCKED_RECT lockrect; + /* lock the entire texture */ + mTexture->LockRect(0, &lockrect, NULL, 0); + + PRUint8* src = imageSurface->Data(); + //FIX cast + PRUint8* dest = (PRUint8*)lockrect.pBits; + + // copy over data. If we don't need to do any swaping we can + // use memcpy + for (int i=0; i<aData.mSize.width*aData.mSize.height; i++) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += 4; + src += 4; + } + + mTexture->UnlockRect(0); +} + +already_AddRefed<gfxASurface> +CairoImageD3D9::GetAsSurface() +{ + return nsnull; +} + +} /* layers */ +} /* mozilla */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ImageLayerD3D9.h @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_IMAGELAYERD3D9_H +#define GFX_IMAGELAYERD3D9_H + +#include "LayerManagerD3D9.h" +#include "ImageLayers.h" +#include "mozilla/Mutex.h" + +namespace mozilla { +namespace layers { + +class THEBES_API ImageContainerD3D9 : public ImageContainer +{ +public: + ImageContainerD3D9(LayerManagerD3D9 *aManager); + virtual ~ImageContainerD3D9() {} + + virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats, + PRUint32 aNumFormats); + + virtual void SetCurrentImage(Image* aImage); + + virtual already_AddRefed<Image> GetCurrentImage(); + + virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize); + + virtual gfxIntSize GetCurrentSize(); + +private: + typedef mozilla::Mutex Mutex; + + nsRefPtr<Image> mActiveImage; + + Mutex mActiveImageLock; +}; + +class THEBES_API ImageLayerD3D9 : public ImageLayer, + public LayerD3D9 +{ +public: + ImageLayerD3D9(LayerManagerD3D9 *aManager) + : ImageLayer(aManager, NULL) + , LayerD3D9(aManager) + { + mImplData = static_cast<LayerD3D9*>(this); + } + + // LayerD3D9 Implementation + virtual LayerType GetType(); + + virtual Layer* GetLayer(); + + virtual void RenderLayer(); +}; + +class THEBES_API ImageD3D9 +{ +public: + virtual already_AddRefed<gfxASurface> GetAsSurface() = 0; +}; + +class THEBES_API PlanarYCbCrImageD3D9 : public PlanarYCbCrImage, + public ImageD3D9 +{ +public: + PlanarYCbCrImageD3D9(LayerManagerD3D9 *aManager); + + virtual void SetData(const Data &aData); + + /* + * Upload the data from out mData into our textures. For now we use this to + * make sure the textures are created and filled on the main thread. + */ + void AllocateTextures(); + /* + * XXX + * Free the textures, we call this from the main thread when we're done + * drawing this frame. We cannot free this from the constructor since it may + * be destroyed off the main-thread and might not be able to properly clean + * up its textures + */ + void FreeTextures(); + PRBool HasData() { return mHasData; } + + virtual already_AddRefed<gfxASurface> GetAsSurface(); + + nsAutoArrayPtr<PRUint8> mBuffer; + LayerManagerD3D9 *mManager; + Data mData; + gfxIntSize mSize; + nsRefPtr<IDirect3DTexture9> mYTexture; + nsRefPtr<IDirect3DTexture9> mCrTexture; + nsRefPtr<IDirect3DTexture9> mCbTexture; + PRPackedBool mHasData; +}; + + +class THEBES_API CairoImageD3D9 : public CairoImage, + public ImageD3D9 +{ +public: + CairoImageD3D9(LayerManagerD3D9 *aManager) + : CairoImage(static_cast<ImageD3D9*>(this)) + , mManager(aManager) + { } + ~CairoImageD3D9(); + + virtual void SetData(const Data &aData); + + virtual already_AddRefed<gfxASurface> GetAsSurface(); + + nsRefPtr<IDirect3DTexture9> mTexture; + gfxIntSize mSize; + LayerManagerD3D9 *mManager; +}; + +} /* layers */ +} /* mozilla */ +#endif /* GFX_IMAGELAYERD3D9_H */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "LayerManagerD3D9.h" + +#include "ThebesLayerD3D9.h" +#include "ContainerLayerD3D9.h" +#include "ImageLayerD3D9.h" +#include "ColorLayerD3D9.h" +#include "CanvasLayerD3D9.h" + +#include "LayerManagerD3D9Shaders.h" + +#include "nsIServiceManager.h" +#include "nsIConsoleService.h" +#include "nsPrintfCString.h" + +namespace mozilla { +namespace layers { + +struct vertex { + float x, y; +}; + +IDirect3D9 *LayerManagerD3D9::mD3D9 = NULL; + +typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)( + UINT SDKVersion +); + + +LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget) +{ + mWidget = aWidget; + mCurrentCallbackInfo.Callback = NULL; + mCurrentCallbackInfo.CallbackData = NULL; +} + +LayerManagerD3D9::~LayerManagerD3D9() +{ +} + +#define HAS_CAP(a, b) (((a) & (b)) == (b)) +#define LACKS_CAP(a, b) !(((a) & (b)) == (b)) + +PRBool +LayerManagerD3D9::Initialize() +{ + if (!mD3D9) { + Direct3DCreate9Func d3d9create = (Direct3DCreate9Func) + GetProcAddress(LoadLibraryW(L"d3d9.dll"), "Direct3DCreate9"); + if (!d3d9create) { + return PR_FALSE; + } + + mD3D9 = d3d9create(D3D_SDK_VERSION); + if (!mD3D9) { + return PR_FALSE; + } + } + + D3DPRESENT_PARAMETERS pp; + memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS)); + + pp.BackBufferFormat = D3DFMT_A8R8G8B8; + pp.SwapEffect = D3DSWAPEFFECT_COPY; + pp.Windowed = TRUE; + pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW); + + HRESULT hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + NULL, + D3DCREATE_FPU_PRESERVE | + D3DCREATE_MULTITHREADED | + D3DCREATE_MIXED_VERTEXPROCESSING, + &pp, + getter_AddRefs(mDevice)); + + if (FAILED(hr)) { + return PR_FALSE; + } + + if (!VerifyCaps()) { + return PR_FALSE; + } + + hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS, + getter_AddRefs(mLayerVS)); + + if (FAILED(hr)) { + return PR_FALSE; + } + + hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS, + getter_AddRefs(mRGBPS)); + + if (FAILED(hr)) { + return PR_FALSE; + } + + hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS, + getter_AddRefs(mYCbCrPS)); + + if (FAILED(hr)) { + return PR_FALSE; + } + + hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS, + getter_AddRefs(mSolidColorPS)); + + if (FAILED(hr)) { + return PR_FALSE; + } + + hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4, + 0, + 0, + D3DPOOL_MANAGED, + getter_AddRefs(mVB), + NULL); + + if (FAILED(hr)) { + return PR_FALSE; + } + + vertex *vertices; + hr = mVB->Lock(0, 0, (void**)&vertices, 0); + if (FAILED(hr)) { + return PR_FALSE; + } + + vertices[0].x = vertices[0].y = 0; + vertices[1].x = 1; vertices[1].y = 0; + vertices[2].x = 0; vertices[2].y = 1; + vertices[3].x = 1; vertices[3].y = 1; + + mVB->Unlock(); + + hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex)); + if (FAILED(hr)) { + return PR_FALSE; + } + + D3DVERTEXELEMENT9 elements[] = { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, + D3DDECLUSAGE_POSITION, 0 }, + D3DDECL_END() + }; + + mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD)); + + SetupRenderState(); + + nsCOMPtr<nsIConsoleService> + console(do_GetService(NS_CONSOLESERVICE_CONTRACTID)); + + D3DADAPTER_IDENTIFIER9 identifier; + mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier); + + if (console) { + nsString msg; + msg += + NS_LITERAL_STRING("Direct3D 9 LayerManager Initialized Succesfully.\nDriver: "); + msg += NS_ConvertUTF8toUTF16( + nsDependentCString((const char*)identifier.Driver)); + msg += NS_LITERAL_STRING("\nDescription: "); + msg += NS_ConvertUTF8toUTF16( + nsDependentCString((const char*)identifier.Description)); + msg += NS_LITERAL_STRING("\nVersion: "); + msg += NS_ConvertUTF8toUTF16( + nsPrintfCString("%d.%d.%d.%d", + HIWORD(identifier.DriverVersion.HighPart), + LOWORD(identifier.DriverVersion.HighPart), + HIWORD(identifier.DriverVersion.LowPart), + LOWORD(identifier.DriverVersion.LowPart))); + console->LogStringMessage(msg.get()); + } + + return PR_TRUE; +} + +void +LayerManagerD3D9::SetClippingRegion(const nsIntRegion &aClippingRegion) +{ + mClippingRegion = aClippingRegion; +} + +void +LayerManagerD3D9::BeginTransaction() +{ +} + +void +LayerManagerD3D9::BeginTransactionWithTarget(gfxContext *aTarget) +{ + mTarget = aTarget; +} + +void +LayerManagerD3D9::EndConstruction() +{ +} + +void +LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback, + void* aCallbackData) +{ + mCurrentCallbackInfo.Callback = aCallback; + mCurrentCallbackInfo.CallbackData = aCallbackData; + Render(); + /* Clean this out for sanity */ + mCurrentCallbackInfo.Callback = NULL; + mCurrentCallbackInfo.CallbackData = NULL; +} + +void +LayerManagerD3D9::SetRoot(Layer *aLayer) +{ + mRootLayer = static_cast<LayerD3D9*>(aLayer->ImplData()); +} + +already_AddRefed<ThebesLayer> +LayerManagerD3D9::CreateThebesLayer() +{ + nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D9(this); + return layer.forget(); +} + +already_AddRefed<ContainerLayer> +LayerManagerD3D9::CreateContainerLayer() +{ + nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D9(this); + return layer.forget(); +} + +already_AddRefed<ImageLayer> +LayerManagerD3D9::CreateImageLayer() +{ + nsRefPtr<ImageLayer> layer = new ImageLayerD3D9(this); + return layer.forget(); +} + +already_AddRefed<ColorLayer> +LayerManagerD3D9::CreateColorLayer() +{ + nsRefPtr<ColorLayer> layer = new ColorLayerD3D9(this); + return layer.forget(); +} + +already_AddRefed<CanvasLayer> +LayerManagerD3D9::CreateCanvasLayer() +{ + nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D9(this); + return layer.forget(); +} + +already_AddRefed<ImageContainer> +LayerManagerD3D9::CreateImageContainer() +{ + nsRefPtr<ImageContainer> container = new ImageContainerD3D9(this); + return container.forget(); +} + +void +LayerManagerD3D9::SetShaderMode(ShaderMode aMode) +{ + switch (aMode) { + case RGBLAYER: + mDevice->SetVertexShader(mLayerVS); + mDevice->SetPixelShader(mRGBPS); + break; + case YCBCRLAYER: + mDevice->SetVertexShader(mLayerVS); + mDevice->SetPixelShader(mYCbCrPS); + break; + case SOLIDCOLORLAYER: + mDevice->SetVertexShader(mLayerVS); + mDevice->SetPixelShader(mSolidColorPS); + break; + } +} + +void +LayerManagerD3D9::Render() +{ + if (!SetupBackBuffer()) { + return; + } + SetupPipeline(); + nsIntRect rect; + mWidget->GetBounds(rect); + + mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0, 0); + + mDevice->BeginScene(); + + if (mRootLayer) { + const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect(); + RECT r; + if (clipRect) { + r.left = (LONG)clipRect->x; + r.top = (LONG)clipRect->y; + r.right = (LONG)(clipRect->x + clipRect->width); + r.bottom = (LONG)(clipRect->y + clipRect->height); + } else { + r.left = r.top = 0; + r.right = rect.width; + r.bottom = rect.height; + } + mDevice->SetScissorRect(&r); + + mRootLayer->RenderLayer(); + } + + mDevice->EndScene(); + + if (!mTarget) { + const nsIntRect *r; + for (nsIntRegionRectIterator iter(mClippingRegion); + (r = iter.Next()) != nsnull;) { + RECT rect; + rect.left = r->x; + rect.top = r->y; + rect.right = r->XMost(); + rect.bottom = r->YMost(); + + mDevice->Present(&rect, &rect, NULL, NULL); + } + } else { + PaintToTarget(); + } +} + +void +LayerManagerD3D9::SetupPipeline() +{ + nsIntRect rect; + mWidget->GetBounds(rect); + + float viewMatrix[4][4]; + /* + * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, + * <1.0, -1.0> bottomright) + */ + memset(&viewMatrix, 0, sizeof(viewMatrix)); + viewMatrix[0][0] = 2.0f / rect.width; + viewMatrix[1][1] = -2.0f / rect.height; + viewMatrix[2][2] = 1.0f; + viewMatrix[3][0] = -1.0f; + viewMatrix[3][1] = 1.0f; + viewMatrix[3][3] = 1.0f; + + HRESULT hr = mDevice->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4); + + if (FAILED(hr)) { + NS_WARNING("Failed to set projection shader constant!"); + } +} + +PRBool +LayerManagerD3D9::SetupBackBuffer() +{ + nsRefPtr<IDirect3DSurface9> backBuffer; + mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, + getter_AddRefs(backBuffer)); + + D3DSURFACE_DESC desc; + nsIntRect rect; + mWidget->GetBounds(rect); + backBuffer->GetDesc(&desc); + + HRESULT hr = mDevice->TestCooperativeLevel(); + + /* The device is lost or something else is wrong, failure */ + if (FAILED(hr) && hr != D3DERR_DEVICENOTRESET) { + return PR_FALSE; + } + + /* + * If the backbuffer is the right size, and the device is not lost, we can + * safely render without doing anything. + */ + if ((desc.Width == rect.width && desc.Height == rect.height) && + SUCCEEDED(hr)) { + return PR_TRUE; + } + + /* + * Our device is lost or our backbuffer needs resizing, start by clearing + * out all D3DPOOL_DEFAULT surfaces. + */ + for(unsigned int i = 0; i < mThebesLayers.Length(); i++) { + mThebesLayers[i]->CleanResources(); + } + + backBuffer = NULL; + + D3DPRESENT_PARAMETERS pp; + memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS)); + + pp.BackBufferFormat = D3DFMT_A8R8G8B8; + pp.SwapEffect = D3DSWAPEFFECT_COPY; + pp.Windowed = TRUE; + pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW); + + hr = mDevice->Reset(&pp); + if (FAILED(hr)) { + return PR_FALSE; + } + + SetupRenderState(); + + return PR_TRUE; +} + +void +LayerManagerD3D9::PaintToTarget() +{ + nsRefPtr<IDirect3DSurface9> backBuff; + nsRefPtr<IDirect3DSurface9> destSurf; + mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, + getter_AddRefs(backBuff)); + + D3DSURFACE_DESC desc; + backBuff->GetDesc(&desc); + + mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, + D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, + getter_AddRefs(destSurf), NULL); + + mDevice->GetRenderTargetData(backBuff, destSurf); + + D3DLOCKED_RECT rect; + destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY); + + nsRefPtr<gfxImageSurface> imageSurface = + new gfxImageSurface((unsigned char*)rect.pBits, + gfxIntSize(desc.Width, desc.Height), + rect.Pitch, + gfxASurface::ImageFormatARGB32); + + mTarget->SetSource(imageSurface); + mTarget->SetOperator(gfxContext::OPERATOR_OVER); + mTarget->Paint(); + destSurf->UnlockRect(); +} + +void +LayerManagerD3D9::SetupRenderState() +{ + mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex)); + mDevice->SetVertexDeclaration(mVD); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); + mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); +} + +PRBool +LayerManagerD3D9::VerifyCaps() +{ + D3DCAPS9 caps; + HRESULT hr = mDevice->GetDeviceCaps(&caps); + + if (FAILED(hr)) { + return PR_FALSE; + } + + if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) { + return PR_FALSE; + } + + if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) { + return PR_FALSE; + } + + if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) || + LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) || + LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) { + return PR_FALSE; + } + + if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) { + return PR_FALSE; + } + + if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) || + HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) || + (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) && + LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) { + return PR_FALSE; + } + + if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) || + LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) { + return PR_FALSE; + } + + if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) { + return PR_FALSE; + } + + if (caps.MaxTextureHeight < 4096 || + caps.MaxTextureWidth < 4096) { + return PR_FALSE; + } + + if ((caps.PixelShaderVersion & 0xffff) < 0x200 || + (caps.VertexShaderVersion & 0xffff) < 0x200) { + return PR_FALSE; + } + return PR_TRUE; +} + +LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager) + : mD3DManager(aManager) + , mNextSibling(NULL) +{ +} + +LayerD3D9* +LayerD3D9::GetNextSibling() +{ + return mNextSibling; +} + +void +LayerD3D9::SetNextSibling(LayerD3D9 *aNextSibling) +{ + mNextSibling = aNextSibling; +} + +} /* namespace layers */ +} /* namespace mozilla */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/LayerManagerD3D9.h @@ -0,0 +1,239 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_LAYERMANAGERD3D9_H +#define GFX_LAYERMANAGERD3D9_H + +#include "Layers.h" + +#include <windows.h> +#include <d3d9.h> + +#include "gfxContext.h" +#include "nsIWidget.h" + +namespace mozilla { +namespace layers { + +class LayerD3D9; +class ThebesLayerD3D9; + +/* + * This is the LayerManager used for Direct3D 9. For now this will render on + * the main thread. + */ +class THEBES_API LayerManagerD3D9 : public LayerManager { +public: + LayerManagerD3D9(nsIWidget *aWidget); + virtual ~LayerManagerD3D9(); + + /* + * Initializes the layer manager, this is when the layer manager will + * actually access the device and attempt to create the swap chain used + * to draw to the window. If this method fails the device cannot be used. + * This function is not threadsafe. + * + * \return True is initialization was succesful, false when it was not. + */ + PRBool Initialize(); + + /* + * Sets the clipping region for this layer manager. This is important on + * windows because using OGL we no longer have GDI's native clipping. Therefor + * widget must tell us what part of the screen is being invalidated, + * and we should clip to this. + * + * \param aClippingRegion Region to clip to. Setting an empty region + * will disable clipping. + */ + void SetClippingRegion(const nsIntRegion& aClippingRegion); + + /* + * LayerManager implementation. + */ + void BeginTransaction(); + + void BeginTransactionWithTarget(gfxContext* aTarget); + + void EndConstruction(); + + struct CallbackInfo { + DrawThebesLayerCallback Callback; + void *CallbackData; + }; + + void EndTransaction(DrawThebesLayerCallback aCallback, + void* aCallbackData); + + const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; } + + void SetRoot(Layer* aLayer); + + virtual already_AddRefed<ThebesLayer> CreateThebesLayer(); + + virtual already_AddRefed<ContainerLayer> CreateContainerLayer(); + + virtual already_AddRefed<ImageLayer> CreateImageLayer(); + + virtual already_AddRefed<ColorLayer> CreateColorLayer(); + + virtual already_AddRefed<CanvasLayer> CreateCanvasLayer(); + + virtual already_AddRefed<ImageContainer> CreateImageContainer(); + + virtual LayersBackend GetBackendType() { return LAYERS_D3D9; } + + /* + * Helper methods. + */ + void SetClippingEnabled(PRBool aEnabled); + + IDirect3DDevice9 *device() const { return mDevice; } + + enum ShaderMode { + RGBLAYER, + YCBCRLAYER, + SOLIDCOLORLAYER + }; + + void SetShaderMode(ShaderMode aMode); + + nsTArray<ThebesLayerD3D9*> mThebesLayers; + +private: + /* Direct3D9 instance */ + static IDirect3D9 *mD3D9; + + /* Widget associated with this layer manager */ + nsIWidget *mWidget; + /* + * Context target, NULL when drawing directly to our swap chain. + */ + nsRefPtr<gfxContext> mTarget; + + nsRefPtr<IDirect3DDevice9> mDevice; + + /* Vertex shader used for layer quads */ + nsRefPtr<IDirect3DVertexShader9> mLayerVS; + + /* Pixel shader used for RGB textures */ + nsRefPtr<IDirect3DPixelShader9> mRGBPS; + + /* Pixel shader used for RGB textures */ + nsRefPtr<IDirect3DPixelShader9> mYCbCrPS; + + /* Pixel shader used for solid colors */ + nsRefPtr<IDirect3DPixelShader9> mSolidColorPS; + + /* Vertex buffer containing our basic vertex structure */ + nsRefPtr<IDirect3DVertexBuffer9> mVB; + + /* Our vertex declaration */ + nsRefPtr<IDirect3DVertexDeclaration9> mVD; + + /* Current root layer. */ + LayerD3D9 *mRootLayer; + + /* Callback info for current transaction */ + CallbackInfo mCurrentCallbackInfo; + + /* + * Region we're clipping our current drawing to. + */ + nsIntRegion mClippingRegion; + /* + * Render the current layer tree to the active target. + */ + void Render(); + /* + * Setup the pipeline. + */ + void SetupPipeline(); + /* + * Setup the backbuffer. + * + * \return PR_TRUE if setup was succesful + */ + PRBool SetupBackBuffer(); + /* + * Setup the render state for the surface. + */ + void SetupRenderState(); + /* + * Copies the content of our backbuffer to the set transaction target. + */ + void PaintToTarget(); + /* + * Verifies all required device capabilities are present. + */ + PRBool VerifyCaps(); + +}; + +/* + * General information and tree management for OGL layers. + */ +class LayerD3D9 +{ +public: + LayerD3D9(LayerManagerD3D9 *aManager); + + enum LayerType { TYPE_THEBES, TYPE_CONTAINER, TYPE_IMAGE, TYPE_COLOR, + TYPE_CANVAS }; + + virtual LayerType GetType() = 0; + + LayerD3D9 *GetNextSibling(); + virtual LayerD3D9 *GetFirstChildD3D9() { return nsnull; } + + void SetNextSibling(LayerD3D9 *aParent); + void SetFirstChild(LayerD3D9 *aParent); + + virtual Layer* GetLayer() = 0; + + virtual void RenderLayer() = 0; + + IDirect3DDevice9 *device() const { return mD3DManager->device(); } +protected: + LayerManagerD3D9 *mD3DManager; + LayerD3D9 *mNextSibling; +}; + +} /* layers */ +} /* mozilla */ + +#endif /* GFX_LAYERMANAGERD3D9_H */
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h @@ -0,0 +1,435 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 +// +// fxc LayerManagerD3D9Shaders.hlsl /ELayerQuadVS /nologo +// /FhLayerManagerD3D9Shaders.h /VnLayerQuadVS +// +// +// Parameters: +// +// float4x4 mLayerQuadTransform; +// float4x4 mLayerTransform; +// float4x4 mProjection; +// float4 vRenderTargetOffset; +// +// +// Registers: +// +// Name Reg Size +// ------------------- ----- ---- +// mLayerQuadTransform c0 4 +// mLayerTransform c4 4 +// mProjection c8 4 +// vRenderTargetOffset c12 1 +// + + vs_2_0 + dcl_position v0 + mul r0, v0.y, c1 + mad r0, c0, v0.x, r0 + mad r0, c2, v0.z, r0 + mad r0, c3, v0.w, r0 + mul r1, r0.y, c5 + mad r1, c4, r0.x, r1 + mad r1, c6, r0.z, r1 + mad r0, c7, r0.w, r1 + add r0, r0, -c12 + mul r1, r0.y, c9 + mad r1, c8, r0.x, r1 + mad r1, c10, r0.z, r1 + mad oPos, c11, r0.w, r1 + mov oT0.xy, v0 + +// approximately 14 instruction slots used +#endif + +const BYTE LayerQuadVS[] = +{ + 0, 2, 254, 255, 254, 255, + 67, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 215, 0, + 0, 0, 0, 2, 254, 255, + 4, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 208, 0, 0, 0, 108, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 0, 0, 128, 0, + 0, 0, 0, 0, 0, 0, + 144, 0, 0, 0, 2, 0, + 4, 0, 4, 0, 0, 0, + 128, 0, 0, 0, 0, 0, + 0, 0, 160, 0, 0, 0, + 2, 0, 8, 0, 4, 0, + 0, 0, 128, 0, 0, 0, + 0, 0, 0, 0, 172, 0, + 0, 0, 2, 0, 12, 0, + 1, 0, 0, 0, 192, 0, + 0, 0, 0, 0, 0, 0, + 109, 76, 97, 121, 101, 114, + 81, 117, 97, 100, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 3, 0, 3, 0, + 4, 0, 4, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 109, 76, 97, 121, 101, 114, + 84, 114, 97, 110, 115, 102, + 111, 114, 109, 0, 109, 80, + 114, 111, 106, 101, 99, 116, + 105, 111, 110, 0, 118, 82, + 101, 110, 100, 101, 114, 84, + 97, 114, 103, 101, 116, 79, + 102, 102, 115, 101, 116, 0, + 1, 0, 3, 0, 1, 0, + 4, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 118, 115, + 95, 50, 95, 48, 0, 77, + 105, 99, 114, 111, 115, 111, + 102, 116, 32, 40, 82, 41, + 32, 72, 76, 83, 76, 32, + 83, 104, 97, 100, 101, 114, + 32, 67, 111, 109, 112, 105, + 108, 101, 114, 32, 57, 46, + 50, 55, 46, 57, 53, 50, + 46, 51, 48, 50, 50, 0, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 15, 144, + 5, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 85, 144, + 1, 0, 228, 160, 4, 0, + 0, 4, 0, 0, 15, 128, + 0, 0, 228, 160, 0, 0, + 0, 144, 0, 0, 228, 128, + 4, 0, 0, 4, 0, 0, + 15, 128, 2, 0, 228, 160, + 0, 0, 170, 144, 0, 0, + 228, 128, 4, 0, 0, 4, + 0, 0, 15, 128, 3, 0, + 228, 160, 0, 0, 255, 144, + 0, 0, 228, 128, 5, 0, + 0, 3, 1, 0, 15, 128, + 0, 0, 85, 128, 5, 0, + 228, 160, 4, 0, 0, 4, + 1, 0, 15, 128, 4, 0, + 228, 160, 0, 0, 0, 128, + 1, 0, 228, 128, 4, 0, + 0, 4, 1, 0, 15, 128, + 6, 0, 228, 160, 0, 0, + 170, 128, 1, 0, 228, 128, + 4, 0, 0, 4, 0, 0, + 15, 128, 7, 0, 228, 160, + 0, 0, 255, 128, 1, 0, + 228, 128, 2, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 128, 12, 0, 228, 161, + 5, 0, 0, 3, 1, 0, + 15, 128, 0, 0, 85, 128, + 9, 0, 228, 160, 4, 0, + 0, 4, 1, 0, 15, 128, + 8, 0, 228, 160, 0, 0, + 0, 128, 1, 0, 228, 128, + 4, 0, 0, 4, 1, 0, + 15, 128, 10, 0, 228, 160, + 0, 0, 170, 128, 1, 0, + 228, 128, 4, 0, 0, 4, + 0, 0, 15, 192, 11, 0, + 228, 160, 0, 0, 255, 128, + 1, 0, 228, 128, 1, 0, + 0, 2, 0, 0, 3, 224, + 0, 0, 228, 144, 255, 255, + 0, 0 +}; + +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 +// +// fxc LayerManagerD3D9Shaders.hlsl /ERGBShader /nologo /Tps_2_0 +// /FhLayerManagerD3D9Shaders.h /VnRGBShaderPS +// +// +// Parameters: +// +// float fLayerOpacity; +// sampler2D s2D; +// +// +// Registers: +// +// Name Reg Size +// ------------- ----- ---- +// fLayerOpacity c0 1 +// s2D s0 1 +// + + ps_2_0 + dcl t0.xy + dcl_2d s0 + texld r0, t0, s0 + mul r0, r0, c0.x + mov oC0, r0 + +// approximately 3 instruction slots used (1 texture, 2 arithmetic) +#endif + +const BYTE RGBShaderPS[] = +{ + 0, 2, 255, 255, 254, 255, + 45, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 127, 0, + 0, 0, 0, 2, 255, 255, + 2, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 120, 0, 0, 0, 68, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 84, 0, + 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 104, 0, 0, 0, 0, 0, + 0, 0, 102, 76, 97, 121, + 101, 114, 79, 112, 97, 99, + 105, 116, 121, 0, 171, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 115, 50, + 68, 0, 4, 0, 12, 0, + 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 112, 115, 95, 50, 95, 48, + 0, 77, 105, 99, 114, 111, + 115, 111, 102, 116, 32, 40, + 82, 41, 32, 72, 76, 83, + 76, 32, 83, 104, 97, 100, + 101, 114, 32, 67, 111, 109, + 112, 105, 108, 101, 114, 32, + 57, 46, 50, 55, 46, 57, + 53, 50, 46, 51, 48, 50, + 50, 0, 31, 0, 0, 2, + 0, 0, 0, 128, 0, 0, + 3, 176, 31, 0, 0, 2, + 0, 0, 0, 144, 0, 8, + 15, 160, 66, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 176, 0, 8, 228, 160, + 5, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 128, + 0, 0, 0, 160, 1, 0, + 0, 2, 0, 8, 15, 128, + 0, 0, 228, 128, 255, 255, + 0, 0 +}; + +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 +// +// fxc LayerManagerD3D9Shaders.hlsl /EYCbCrShader /nologo /Tps_2_0 +// /FhLayerManagerD3D9Shaders.h /VnYCbCrShaderPS +// +// +// Parameters: +// +// float fLayerOpacity; +// sampler2D s2DCb; +// sampler2D s2DCr; +// sampler2D s2DY; +// +// +// Registers: +// +// Name Reg Size +// ------------- ----- ---- +// fLayerOpacity c0 1 +// s2DY s0 1 +// s2DCb s1 1 +// s2DCr s2 1 +// + + ps_2_0 + def c1, -0.5, -0.0625, 1.16400003, 1.59599996 + def c2, 0.813000023, 0.391000003, 2.01799989, 1 + dcl t0.xy + dcl_2d s0 + dcl_2d s1 + dcl_2d s2 + texld r0, t0, s2 + texld r1, t0, s0 + texld r2, t0, s1 + add r0.x, r0.x, c1.x + add r0.y, r1.x, c1.y + mul r0.y, r0.y, c1.z + mad r0.z, r0.x, -c2.x, r0.y + mad r1.x, r0.x, c1.w, r0.y + add r0.x, r2.x, c1.x + mad r1.y, r0.x, -c2.y, r0.z + mad r1.z, r0.x, c2.z, r0.y + mov r1.w, c2.w + mul r0, r1, c0.x + mov oC0, r0 + +// approximately 14 instruction slots used (3 texture, 11 arithmetic) +#endif + +const BYTE YCbCrShaderPS[] = +{ + 0, 2, 255, 255, 254, 255, + 68, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 219, 0, + 0, 0, 0, 2, 255, 255, + 4, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 212, 0, 0, 0, 108, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 124, 0, + 0, 0, 0, 0, 0, 0, + 140, 0, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 148, 0, 0, 0, 0, 0, + 0, 0, 164, 0, 0, 0, + 3, 0, 2, 0, 1, 0, + 0, 0, 172, 0, 0, 0, + 0, 0, 0, 0, 188, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 196, 0, + 0, 0, 0, 0, 0, 0, + 102, 76, 97, 121, 101, 114, + 79, 112, 97, 99, 105, 116, + 121, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 115, 50, 68, 67, + 98, 0, 171, 171, 4, 0, + 12, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 115, 50, 68, 67, + 114, 0, 171, 171, 4, 0, + 12, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 115, 50, 68, 89, + 0, 171, 171, 171, 4, 0, + 12, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 112, 115, 95, 50, + 95, 48, 0, 77, 105, 99, + 114, 111, 115, 111, 102, 116, + 32, 40, 82, 41, 32, 72, + 76, 83, 76, 32, 83, 104, + 97, 100, 101, 114, 32, 67, + 111, 109, 112, 105, 108, 101, + 114, 32, 57, 46, 50, 55, + 46, 57, 53, 50, 46, 51, + 48, 50, 50, 0, 81, 0, + 0, 5, 1, 0, 15, 160, + 0, 0, 0, 191, 0, 0, + 128, 189, 244, 253, 148, 63, + 186, 73, 204, 63, 81, 0, + 0, 5, 2, 0, 15, 160, + 197, 32, 80, 63, 39, 49, + 200, 62, 233, 38, 1, 64, + 0, 0, 128, 63, 31, 0, + 0, 2, 0, 0, 0, 128, + 0, 0, 3, 176, 31, 0, + 0, 2, 0, 0, 0, 144, + 0, 8, 15, 160, 31, 0, + 0, 2, 0, 0, 0, 144, + 1, 8, 15, 160, 31, 0, + 0, 2, 0, 0, 0, 144, + 2, 8, 15, 160, 66, 0, + 0, 3, 0, 0, 15, 128, + 0, 0, 228, 176, 2, 8, + 228, 160, 66, 0, 0, 3, + 1, 0, 15, 128, 0, 0, + 228, 176, 0, 8, 228, 160, + 66, 0, 0, 3, 2, 0, + 15, 128, 0, 0, 228, 176, + 1, 8, 228, 160, 2, 0, + 0, 3, 0, 0, 1, 128, + 0, 0, 0, 128, 1, 0, + 0, 160, 2, 0, 0, 3, + 0, 0, 2, 128, 1, 0, + 0, 128, 1, 0, 85, 160, + 5, 0, 0, 3, 0, 0, + 2, 128, 0, 0, 85, 128, + 1, 0, 170, 160, 4, 0, + 0, 4, 0, 0, 4, 128, + 0, 0, 0, 128, 2, 0, + 0, 161, 0, 0, 85, 128, + 4, 0, 0, 4, 1, 0, + 1, 128, 0, 0, 0, 128, + 1, 0, 255, 160, 0, 0, + 85, 128, 2, 0, 0, 3, + 0, 0, 1, 128, 2, 0, + 0, 128, 1, 0, 0, 160, + 4, 0, 0, 4, 1, 0, + 2, 128, 0, 0, 0, 128, + 2, 0, 85, 161, 0, 0, + 170, 128, 4, 0, 0, 4, + 1, 0, 4, 128, 0, 0, + 0, 128, 2, 0, 170, 160, + 0, 0, 85, 128, 1, 0, + 0, 2, 1, 0, 8, 128, + 2, 0, 255, 160, 5, 0, + 0, 3, 0, 0, 15, 128, + 1, 0, 228, 128, 0, 0, + 0, 160, 1, 0, 0, 2, + 0, 8, 15, 128, 0, 0, + 228, 128, 255, 255, 0, 0 +}; + +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 +// +// fxc LayerManagerD3D9Shaders.hlsl /ESolidColorShader /nologo /Tps_2_0 +// /FhLayerManagerD3D9Shaders.h /VnSolidColorShaderPS +// +// +// Parameters: +// +// float4 fLayerColor; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// fLayerColor c0 1 +// + + ps_2_0 + mov oC0, c0 + +// approximately 1 instruction slot used +#endif + +const BYTE SolidColorShaderPS[] = +{ + 0, 2, 255, 255, 254, 255, + 34, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 83, 0, + 0, 0, 0, 2, 255, 255, + 1, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 76, 0, 0, 0, 48, 0, + 0, 0, 2, 0, 0, 0, + 1, 0, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 102, 76, 97, 121, 101, 114, + 67, 111, 108, 111, 114, 0, + 1, 0, 3, 0, 1, 0, + 4, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 112, 115, + 95, 50, 95, 48, 0, 77, + 105, 99, 114, 111, 115, 111, + 102, 116, 32, 40, 82, 41, + 32, 72, 76, 83, 76, 32, + 83, 104, 97, 100, 101, 114, + 32, 67, 111, 109, 112, 105, + 108, 101, 114, 32, 57, 46, + 50, 55, 46, 57, 53, 50, + 46, 51, 48, 50, 50, 0, + 1, 0, 0, 2, 0, 8, + 15, 128, 0, 0, 228, 160, + 255, 255, 0, 0 +};
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl @@ -0,0 +1,61 @@ +float4x4 mLayerQuadTransform; +float4x4 mLayerTransform; +float4 vRenderTargetOffset; +float4x4 mProjection; + +texture tex0; +sampler s2D; +sampler s2DY; +sampler s2DCb; +sampler s2DCr; + +float fLayerOpacity; +float4 fLayerColor; + +struct VS_INPUT { + float4 vPosition : POSITION; +}; + +struct VS_OUTPUT { + float4 vPosition : POSITION; + float2 vTexCoords : TEXCOORD0; +}; + +VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex) +{ + VS_OUTPUT outp; + outp.vPosition = aVertex.vPosition; + outp.vPosition = mul(mLayerQuadTransform, outp.vPosition); + outp.vPosition = mul(mLayerTransform, outp.vPosition); + outp.vPosition = outp.vPosition - vRenderTargetOffset; + outp.vPosition = mul(mProjection, outp.vPosition); + outp.vTexCoords = aVertex.vPosition.xy; + return outp; +} + +float4 RGBShader(const VS_OUTPUT aVertex) : COLOR +{ + return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity; +} + +float4 YCbCrShader(const VS_OUTPUT aVertex) : COLOR +{ + float4 yuv; + float4 color; + + yuv.r = tex2D(s2DCr, aVertex.vTexCoords).r - 0.5; + yuv.g = tex2D(s2DY, aVertex.vTexCoords).r - 0.0625; + yuv.b = tex2D(s2DCb, aVertex.vTexCoords).r - 0.5; + + color.r = yuv.g * 1.164 + yuv.r * 1.596; + color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b; + color.b = yuv.g * 1.164 + yuv.b * 2.018; + color.a = 1.0f; + + return color * fLayerOpacity; +} + +float4 SolidColorShader(const VS_OUTPUT aVertex) : COLOR +{ + return fLayerColor; +}
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -0,0 +1,216 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ThebesLayerD3D9.h" +#include "gfxPlatform.h" + +namespace mozilla { +namespace layers { + +ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager) + : ThebesLayer(aManager, NULL) + , LayerD3D9(aManager) +{ + mImplData = static_cast<LayerD3D9*>(this); + aManager->mThebesLayers.AppendElement(this); +} + +ThebesLayerD3D9::~ThebesLayerD3D9() +{ + mD3DManager->mThebesLayers.RemoveElement(this); +} + + +void +ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion) +{ + if (aRegion.GetBounds() == mVisibleRect) { + return; + } + mVisibleRect = aRegion.GetBounds(); + + device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1, + D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL); + + mInvalidatedRect = mVisibleRect; +} + + +void +ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion) +{ + nsIntRegion invalidatedRegion; + invalidatedRegion.Or(aRegion, mInvalidatedRect); + invalidatedRegion.And(invalidatedRegion, mVisibleRect); + mInvalidatedRect = invalidatedRegion.GetBounds(); +} + +LayerD3D9::LayerType +ThebesLayerD3D9::GetType() +{ + return TYPE_THEBES; +} + +const nsIntRect& +ThebesLayerD3D9::GetVisibleRect() +{ + return mVisibleRect; +} + +void +ThebesLayerD3D9::RenderLayer() +{ + if (!mTexture) { + device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1, + D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL); + mInvalidatedRect = mVisibleRect; + } + if (!mInvalidatedRect.IsEmpty()) { + nsIntRegion region = mInvalidatedRect; + + gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;; + nsRefPtr<gfxASurface> destinationSurface; + nsRefPtr<gfxContext> context; + + destinationSurface = + gfxPlatform::GetPlatform()-> + CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width, + mInvalidatedRect.height), + imageFormat); + + context = new gfxContext(destinationSurface); + context->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y)); + LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo(); + cbInfo.Callback(this, context, region, cbInfo.CallbackData); + + nsRefPtr<IDirect3DTexture9> tmpTexture; + device()->CreateTexture(mInvalidatedRect.width, mInvalidatedRect.height, 1, + 0, D3DFMT_A8R8G8B8, + D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL); + + D3DLOCKED_RECT r; + tmpTexture->LockRect(0, &r, NULL, 0); + + nsRefPtr<gfxImageSurface> imgSurface = + new gfxImageSurface((unsigned char *)r.pBits, + gfxIntSize(mInvalidatedRect.width, + mInvalidatedRect.height), + r.Pitch, + imageFormat); + + context = new gfxContext(imgSurface); + context->SetSource(destinationSurface); + context->SetOperator(gfxContext::OPERATOR_SOURCE); + context->Paint(); + + imgSurface = NULL; + + tmpTexture->UnlockRect(0); + + nsRefPtr<IDirect3DSurface9> srcSurface; + nsRefPtr<IDirect3DSurface9> dstSurface; + + mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface)); + tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface)); + + POINT point; + point.x = mInvalidatedRect.x - mVisibleRect.x; + point.y = mInvalidatedRect.y - mVisibleRect.y; + device()->UpdateSurface(srcSurface, NULL, dstSurface, &point); + } + + float quadTransform[4][4]; + /* + * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position + * and size. To get pixel perfect mapping we offset the quad half a pixel + * to the top-left. + * + * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx + */ + memset(&quadTransform, 0, sizeof(quadTransform)); + quadTransform[0][0] = (float)GetVisibleRect().width; + quadTransform[1][1] = (float)GetVisibleRect().height; + quadTransform[2][2] = 1.0f; + quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f; + quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f; + quadTransform[3][3] = 1.0f; + + device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4); + device()->SetVertexShaderConstantF(4, &mTransform._11, 4); + + float opacity[4]; + /* + * We always upload a 4 component float, but the shader will use only the + * first component since it's declared as a 'float'. + */ + opacity[0] = GetOpacity(); + device()->SetPixelShaderConstantF(0, opacity, 1); + + mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER); + + device()->SetTexture(0, mTexture); + device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); +} + +void +ThebesLayerD3D9::CleanResources() +{ + mTexture = nsnull; +} + +const nsIntRect& +ThebesLayerD3D9::GetInvalidatedRect() +{ + return mInvalidatedRect; +} + +Layer* +ThebesLayerD3D9::GetLayer() +{ + return this; +} + +PRBool +ThebesLayerD3D9::IsEmpty() +{ + return !mTexture; +} + +} /* namespace layers */ +} /* namespace mozilla */ \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/gfx/layers/d3d9/ThebesLayerD3D9.h @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bas Schouten <bschouten@mozilla.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef GFX_THEBESLAYERD3D9_H +#define GFX_THEBESLAYERD3D9_H + +#include "Layers.h" +#include "LayerManagerD3D9.h" +#include "gfxImageSurface.h" + + +namespace mozilla { +namespace layers { + +class ThebesLayerD3D9 : public ThebesLayer, + public LayerD3D9 +{ +public: + ThebesLayerD3D9(LayerManagerD3D9 *aManager); + virtual ~ThebesLayerD3D9(); + + /* Layer implementation */ + void SetVisibleRegion(const nsIntRegion& aRegion); + + /* ThebesLayer implementation */ + void InvalidateRegion(const nsIntRegion& aRegion); + + /* LayerD3D9 implementation */ + LayerType GetType(); + Layer* GetLayer(); + virtual PRBool IsEmpty(); + virtual void RenderLayer(); + virtual void CleanResources(); + + /* ThebesLayerD3D9 */ + const nsIntRect &GetVisibleRect(); + const nsIntRect &GetInvalidatedRect(); + +private: + /* + * Visible rectangle, this is used to know the size and position of the quad + * when doing the rendering of this layer. + */ + nsIntRect mVisibleRect; + /* + * Currently invalidated rectangular area. + */ + nsIntRect mInvalidatedRect; + + /* + * D3D9 texture + */ + nsRefPtr<IDirect3DTexture9> mTexture; +}; + +} /* layers */ +} /* mozilla */ +#endif /* GFX_THEBESLAYERD3D9_H */
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp +++ b/gfx/layers/opengl/CanvasLayerOGL.cpp @@ -193,17 +193,19 @@ CanvasLayerOGL::Updated(const nsIntRect& } } // sanity NS_ASSERTION(mUpdatedRect.IsEmpty() || mBounds.Contains(mUpdatedRect), "CanvasLayer: Updated rect bigger than bounds!"); } void -CanvasLayerOGL::RenderLayer(int aPreviousDestination) +CanvasLayerOGL::RenderLayer(int aPreviousDestination, + DrawThebesLayerCallback aCallback, + void* aCallbackData) { LayerManagerOGL *glManager = static_cast<LayerManagerOGL*>(mManager); GLContext *gl = glManager->gl(); glManager->MakeCurrent(); float quadTransform[4][4]; // Transform the quad to the size of the canvas. memset(&quadTransform, 0, sizeof(quadTransform));
--- a/gfx/layers/opengl/CanvasLayerOGL.h +++ b/gfx/layers/opengl/CanvasLayerOGL.h @@ -61,17 +61,19 @@ public: // CanvasLayer implementation virtual void Initialize(const Data& aData); virtual void Updated(const nsIntRect& aRect); // LayerOGL implementation virtual LayerType GetType() { return TYPE_CANVAS; } virtual Layer* GetLayer() { return this; } - virtual void RenderLayer(int aPreviousDestination); + virtual void RenderLayer(int aPreviousDestination, + DrawThebesLayerCallback aCallback, + void* aCallbackData); protected: nsRefPtr<gfxASurface> mSurface; nsRefPtr<GLContext> mGLContext; unsigned int mTexture; nsIntRect mBounds;
--- a/gfx/layers/opengl/ColorLayerOGL.cpp +++ b/gfx/layers/opengl/ColorLayerOGL.cpp @@ -48,17 +48,17 @@ ColorLayerOGL::GetType() Layer* ColorLayerOGL::GetLayer() { return this; } void -ColorLayerOGL::RenderLayer(int) +ColorLayerOGL::RenderLayer(int, DrawThebesLayerCallback, void*) { static_cast<LayerManagerOGL*>(mManager)->MakeCurrent(); // XXX we might be able to improve performance by using glClear float quadTransform[4][4]; nsIntRect visibleRect = mVisibleRegion.GetBounds(); // Transform the quad to the size of the visible area.
--- a/gfx/layers/opengl/ColorLayerOGL.h +++ b/gfx/layers/opengl/ColorLayerOGL.h @@ -56,17 +56,19 @@ public: virtual void SetVisibleRegion(const nsIntRegion& aRegion) { mVisibleRegion = aRegion; } // LayerOGL Implementation virtual LayerType GetType(); virtual Layer* GetLayer(); - virtual void RenderLayer(int aPreviousDestination); + virtual void RenderLayer(int aPreviousDestination, + DrawThebesLayerCallback aCallback, + void* aCallbackData); protected: nsIntRegion mVisibleRegion; }; } /* layers */ } /* mozilla */ #endif /* GFX_COLORLAYEROGL_H */
--- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ b/gfx/layers/opengl/ContainerLayerOGL.cpp @@ -42,16 +42,25 @@ namespace layers { ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *aManager) : ContainerLayer(aManager, NULL) , LayerOGL(aManager) { mImplData = static_cast<LayerOGL*>(this); } +ContainerLayerOGL::~ContainerLayerOGL() +{ + LayerOGL *nextChild; + for (LayerOGL *child = GetFirstChildOGL(); child; child = nextChild) { + nextChild = child->GetNextSibling(); + child->GetLayer()->Release(); + } +} + const nsIntRect& ContainerLayerOGL::GetVisibleRect() { return mVisibleRect; } void ContainerLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion) @@ -60,48 +69,52 @@ ContainerLayerOGL::SetVisibleRegion(cons } void ContainerLayerOGL::InsertAfter(Layer* aChild, Layer* aAfter) { LayerOGL *newChild = static_cast<LayerOGL*>(aChild->ImplData()); aChild->SetParent(this); if (!aAfter) { + NS_ADDREF(aChild); LayerOGL *oldFirstChild = GetFirstChildOGL(); mFirstChild = newChild->GetLayer(); newChild->SetNextSibling(oldFirstChild); return; } for (LayerOGL *child = GetFirstChildOGL(); child; child = child->GetNextSibling()) { if (aAfter == child->GetLayer()) { + NS_ADDREF(aChild); LayerOGL *oldNextSibling = child->GetNextSibling(); child->SetNextSibling(newChild); child->GetNextSibling()->SetNextSibling(oldNextSibling); return; } } NS_WARNING("Failed to find aAfter layer!"); } void ContainerLayerOGL::RemoveChild(Layer *aChild) { if (GetFirstChild() == aChild) { mFirstChild = GetFirstChildOGL()->GetNextSibling()->GetLayer(); + NS_RELEASE(aChild); return; } LayerOGL *lastChild = NULL; for (LayerOGL *child = GetFirstChildOGL(); child; child = child->GetNextSibling()) { if (child->GetLayer() == aChild) { // We're sure this is not our first child. So lastChild != NULL. lastChild->SetNextSibling(child->GetNextSibling()); child->SetNextSibling(NULL); child->GetLayer()->SetParent(NULL); + NS_RELEASE(aChild); return; } lastChild = child; } } LayerOGL::LayerType ContainerLayerOGL::GetType() @@ -120,31 +133,34 @@ ContainerLayerOGL::GetFirstChildOGL() { if (!mFirstChild) { return nsnull; } return static_cast<LayerOGL*>(mFirstChild->ImplData()); } void -ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer) +ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer, + DrawThebesLayerCallback aCallback, + void* aCallbackData) { /** * Setup our temporary texture for rendering the contents of this container. */ GLuint containerSurface; GLuint frameBuffer; RGBLayerProgram *rgbProgram = static_cast<LayerManagerOGL*>(mManager)->GetRGBLayerProgram(); ColorLayerProgram *colorProgram = static_cast<LayerManagerOGL*>(mManager)->GetColorLayerProgram(); YCbCrLayerProgram *yCbCrProgram = static_cast<LayerManagerOGL*>(mManager)->GetYCbCrLayerProgram(); - if (GetOpacity() != 1.0) { + float opacity = GetOpacity(); + if (opacity != 1.0) { gl()->fGenTextures(1, &containerSurface); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); gl()->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, mVisibleRect.width, mVisibleRect.height, 0, @@ -197,21 +213,21 @@ ContainerLayerOGL::RenderLayer(int aPrev gl()->fScissor(clipRect->x - GetVisibleRect().x, clipRect->y - GetVisibleRect().y, clipRect->width, clipRect->height); } else { gl()->fScissor(0, 0, GetVisibleRect().width, GetVisibleRect().height); } - layerToRender->RenderLayer(frameBuffer); + layerToRender->RenderLayer(frameBuffer, aCallback, aCallbackData); layerToRender = layerToRender->GetNextSibling(); } - if (GetOpacity() != 1.0) { + if (opacity != 1.0) { // Unbind the current framebuffer and rebind the previous one. gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); gl()->fDeleteFramebuffers(1, &frameBuffer); // Restore old shader program variables. yCbCrProgram->Activate(); yCbCrProgram->PopRenderTargetOffset(); @@ -236,17 +252,17 @@ ContainerLayerOGL::RenderLayer(int aPrev quadTransform[3][0] = (float)GetVisibleRect().x; quadTransform[3][1] = (float)GetVisibleRect().y; quadTransform[3][3] = 1.0f; rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]); gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, containerSurface); - rgbProgram->SetLayerOpacity(GetOpacity()); + rgbProgram->SetLayerOpacity(opacity); rgbProgram->SetLayerTransform(&mTransform._11); rgbProgram->Apply(); gl()->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); // Clean up resources. gl()->fDeleteTextures(1, &containerSurface); }
--- a/gfx/layers/opengl/ContainerLayerOGL.h +++ b/gfx/layers/opengl/ContainerLayerOGL.h @@ -44,16 +44,17 @@ namespace mozilla { namespace layers { class ContainerLayerOGL : public ContainerLayer, public LayerOGL { public: ContainerLayerOGL(LayerManagerOGL *aManager); + ~ContainerLayerOGL(); const nsIntRect &GetVisibleRect(); /** ContainerLayer implementation */ void SetVisibleRegion(const nsIntRegion& aRegion); void InsertAfter(Layer* aChild, Layer* aAfter); @@ -63,17 +64,19 @@ public: LayerType GetType(); Layer* GetLayer(); LayerOGL* GetFirstChildOGL(); PRBool IsEmpty(); - void RenderLayer(int aPreviousFrameBuffer); + void RenderLayer(int aPreviousFrameBuffer, + DrawThebesLayerCallback aCallback, + void* aCallbackData); private: nsIntRect mVisibleRect; GLuint mTexture; }; } /* layers */ } /* mozilla */
--- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -264,17 +264,18 @@ ImageLayerOGL::GetType() Layer* ImageLayerOGL::GetLayer() { return this; } void -ImageLayerOGL::RenderLayer(int) +ImageLayerOGL::RenderLayer(int, DrawThebesLayerCallback aCallback, + void* aCallbackData) { if (!GetContainer()) { return; } LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mManager); manager->MakeCurrent();
--- a/gfx/layers/opengl/ImageLayerOGL.h +++ b/gfx/layers/opengl/ImageLayerOGL.h @@ -170,17 +170,19 @@ public: mImplData = static_cast<LayerOGL*>(this); } // LayerOGL Implementation virtual LayerType GetType(); virtual Layer* GetLayer(); - virtual void RenderLayer(int aPreviousDestination); + virtual void RenderLayer(int aPreviousDestination, + DrawThebesLayerCallback aCallback, + void* aCallbackData); }; class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage { typedef mozilla::gl::GLContext GLContext; public: PlanarYCbCrImageOGL(RecycleBin *aRecycleBin);
--- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -277,24 +277,20 @@ LayerManagerOGL::BeginTransaction() void LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget) { mTarget = aTarget; } void -LayerManagerOGL::EndConstruction() +LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback, + void* aCallbackData) { -} - -void -LayerManagerOGL::EndTransaction() -{ - Render(); + Render(aCallback, aCallbackData); mTarget = NULL; } void LayerManagerOGL::SetRoot(Layer *aLayer) { mRootLayer = static_cast<LayerOGL*>(aLayer->ImplData());; } @@ -353,17 +349,18 @@ LayerManagerOGL::SetClippingEnabled(PRBo void LayerManagerOGL::MakeCurrent() { mGLContext->MakeCurrent(); } void -LayerManagerOGL::Render() +LayerManagerOGL::Render(DrawThebesLayerCallback aCallback, + void* aCallbackData) { nsIntRect rect; mWidget->GetBounds(rect); GLint width = rect.width; GLint height = rect.height; MakeCurrent(); SetupBackBuffer(); @@ -379,17 +376,17 @@ LayerManagerOGL::Render() if (mRootLayer) { const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect(); if (clipRect) { mGLContext->fScissor(clipRect->x, clipRect->y, clipRect->width, clipRect->height); } else { mGLContext->fScissor(0, 0, width, height); } - mRootLayer->RenderLayer(mFrameBuffer); + mRootLayer->RenderLayer(mFrameBuffer, aCallback, aCallbackData); } if (mTarget) { CopyToTarget(); } else { /** * Draw our backbuffer to the screen without using vertex or fragment * shaders. We're fine with just calculating the viewport coordinates
--- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -211,17 +211,18 @@ public: * LayerManager implementation. */ void BeginTransaction(); void BeginTransactionWithTarget(gfxContext* aTarget); void EndConstruction(); - void EndTransaction(); + virtual void EndTransaction(DrawThebesLayerCallback aCallback, + void* aCallbackData); void SetRoot(Layer* aLayer); virtual already_AddRefed<ThebesLayer> CreateThebesLayer(); virtual already_AddRefed<ContainerLayer> CreateContainerLayer(); virtual already_AddRefed<ImageLayer> CreateImageLayer(); @@ -288,17 +289,18 @@ private: /** * Region we're clipping our current drawing to. */ nsIntRegion mClippingRegion; /** * Render the current layer tree to the active target. */ - void Render(); + void Render(DrawThebesLayerCallback aCallback, + void* aCallbackData); /** * Setup the pipeline. */ void SetupPipeline(); /** * Setup the backbuffer. * * \return PR_TRUE if setup was succesful @@ -311,16 +313,18 @@ private: }; /** * General information and tree management for OGL layers. */ class LayerOGL { public: + typedef LayerManager::DrawThebesLayerCallback DrawThebesLayerCallback; + LayerOGL(LayerManagerOGL *aManager); enum LayerType { TYPE_THEBES, TYPE_CONTAINER, TYPE_IMAGE, TYPE_COLOR, TYPE_CANVAS @@ -331,17 +335,18 @@ public: LayerOGL *GetNextSibling(); virtual LayerOGL *GetFirstChildOGL() { return nsnull; } void SetNextSibling(LayerOGL *aParent); void SetFirstChild(LayerOGL *aParent); virtual Layer* GetLayer() = 0; - virtual void RenderLayer(int aPreviousFrameBuffer) = 0; + virtual void RenderLayer(int aPreviousFrameBuffer, DrawThebesLayerCallback aCallback, + void* aCallbackData) = 0; typedef mozilla::gl::GLContext GLContext; GLContext *gl() const { return mOGLManager->gl(); } protected: LayerManagerOGL *mOGLManager; LayerOGL *mNextSibling; };
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -123,125 +123,100 @@ void ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion) { nsIntRegion invalidatedRegion; invalidatedRegion.Or(aRegion, mInvalidatedRect); invalidatedRegion.And(invalidatedRegion, mVisibleRect); mInvalidatedRect = invalidatedRegion.GetBounds(); } -gfxContext * -ThebesLayerOGL::BeginDrawing(nsIntRegion *aRegion) -{ - if (mInvalidatedRect.IsEmpty()) { - aRegion->SetEmpty(); - return NULL; - } - if (!mTexture) { - aRegion->SetEmpty(); - return NULL; - } - *aRegion = mInvalidatedRect; - - gfxASurface::gfxImageFormat imageFormat; - - if (UseOpaqueSurface(this)) { - imageFormat = gfxASurface::ImageFormatRGB24; - } else { - imageFormat = gfxASurface::ImageFormatARGB32; - } - - mDestinationSurface = - gfxPlatform::GetPlatform()-> - CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width, - mInvalidatedRect.height), - imageFormat); - - mContext = new gfxContext(mDestinationSurface); - mContext->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y)); - return mContext.get(); -} - -void -ThebesLayerOGL::EndDrawing() -{ - static_cast<LayerManagerOGL*>(mManager)->MakeCurrent(); - - nsRefPtr<gfxImageSurface> imageSurface; - - gfxASurface::gfxImageFormat imageFormat; - - if (UseOpaqueSurface(this)) { - imageFormat = gfxASurface::ImageFormatRGB24; - } else { - imageFormat = gfxASurface::ImageFormatARGB32; - } - - switch (mDestinationSurface->GetType()) { - case gfxASurface::SurfaceTypeImage: - imageSurface = static_cast<gfxImageSurface*>(mDestinationSurface.get()); - break; -#ifdef XP_WIN - case gfxASurface::SurfaceTypeWin32: - imageSurface = - static_cast<gfxWindowsSurface*>(mDestinationSurface.get())-> - GetImageSurface(); - break; -#endif - default: - /** - * XXX - This is very undesirable. Implement this for other platforms in - * a more efficient way as well! - */ - { - imageSurface = new gfxImageSurface(gfxIntSize(mInvalidatedRect.width, - mInvalidatedRect.height), - imageFormat); - nsRefPtr<gfxContext> tmpContext = new gfxContext(imageSurface); - tmpContext->SetSource(mDestinationSurface); - tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE); - tmpContext->Paint(); - } - break; - } - - gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); - gl()->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, - 0, - mInvalidatedRect.x - mVisibleRect.x, - mInvalidatedRect.y - mVisibleRect.y, - mInvalidatedRect.width, - mInvalidatedRect.height, - LOCAL_GL_BGRA, - LOCAL_GL_UNSIGNED_BYTE, - imageSurface->Data()); - - mDestinationSurface = NULL; - mContext = NULL; -} - LayerOGL::LayerType ThebesLayerOGL::GetType() { return TYPE_THEBES; } const nsIntRect& ThebesLayerOGL::GetVisibleRect() { return mVisibleRect; } void -ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer) +ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, + DrawThebesLayerCallback aCallback, + void* aCallbackData) { if (!mTexture) { return; } + if (!mInvalidatedRect.IsEmpty()) { + gfxASurface::gfxImageFormat imageFormat; + + if (UseOpaqueSurface(this)) { + imageFormat = gfxASurface::ImageFormatRGB24; + } else { + imageFormat = gfxASurface::ImageFormatARGB32; + } + + nsRefPtr<gfxASurface> surface = + gfxPlatform::GetPlatform()-> + CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width, + mInvalidatedRect.height), + imageFormat); + + nsRefPtr<gfxContext> ctx = new gfxContext(surface); + ctx->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y)); + aCallback(this, ctx, mInvalidatedRect, aCallbackData); + + static_cast<LayerManagerOGL*>(mManager)->MakeCurrent(); + + nsRefPtr<gfxImageSurface> imageSurface; + + switch (surface->GetType()) { + case gfxASurface::SurfaceTypeImage: + imageSurface = static_cast<gfxImageSurface*>(surface.get()); + break; +#ifdef XP_WIN + case gfxASurface::SurfaceTypeWin32: + imageSurface = + static_cast<gfxWindowsSurface*>(surface.get())-> + GetImageSurface(); + break; +#endif + default: + /** + * XXX - This is very undesirable. Implement this for other platforms in + * a more efficient way as well! + */ + { + imageSurface = new gfxImageSurface(gfxIntSize(mInvalidatedRect.width, + mInvalidatedRect.height), + imageFormat); + nsRefPtr<gfxContext> tmpContext = new gfxContext(imageSurface); + tmpContext->SetSource(surface); + tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE); + tmpContext->Paint(); + } + break; + } + + gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); + gl()->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, + 0, + mInvalidatedRect.x - mVisibleRect.x, + mInvalidatedRect.y - mVisibleRect.y, + mInvalidatedRect.width, + mInvalidatedRect.height, + LOCAL_GL_BGRA, + LOCAL_GL_UNSIGNED_BYTE, + imageSurface->Data()); + } + float quadTransform[4][4]; /* * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position * and size. */ memset(&quadTransform, 0, sizeof(quadTransform)); quadTransform[0][0] = (float)GetVisibleRect().width; quadTransform[1][1] = (float)GetVisibleRect().height;
--- a/gfx/layers/opengl/ThebesLayerOGL.h +++ b/gfx/layers/opengl/ThebesLayerOGL.h @@ -54,50 +54,38 @@ public: virtual ~ThebesLayerOGL(); /** Layer implementation */ void SetVisibleRegion(const nsIntRegion& aRegion); /** ThebesLayer implementation */ void InvalidateRegion(const nsIntRegion& aRegion); - gfxContext *BeginDrawing(nsIntRegion* aRegionToDraw); - - void EndDrawing(); - /** LayerOGL implementation */ LayerType GetType(); Layer* GetLayer(); virtual PRBool IsEmpty(); - virtual void RenderLayer(int aPreviousFrameBuffer); + virtual void RenderLayer(int aPreviousFrameBuffer, + DrawThebesLayerCallback aCallback, + void* aCallbackData); /** ThebesLayerOGL */ const nsIntRect &GetVisibleRect(); const nsIntRect &GetInvalidatedRect(); private: /** * Visible rectangle, this is used to know the size and position of the quad * when doing the rendering of this layer. */ nsIntRect mVisibleRect; /** * Currently invalidated rectangular area. */ nsIntRect mInvalidatedRect; - /** - * Destination surface used for this layer's drawing operation. This is - * created on BeginDrawing() and should be removed on EndDrawing(). - */ - nsRefPtr<gfxASurface> mDestinationSurface; - - /** - * We hold the reference to the context. - */ - nsRefPtr<gfxContext> mContext; /** * OpenGL Texture */ GLuint mTexture; };
--- a/gfx/public/nsRegion.h +++ b/gfx/public/nsRegion.h @@ -174,16 +174,17 @@ public: } PRBool IsEmpty () const { return mRectCount == 0; } PRBool IsComplex () const { return mRectCount > 1; } PRBool IsEqual (const nsRegion& aRegion) const; PRUint32 GetNumRects () const { return mRectCount; } const nsRect& GetBounds () const { return mBoundRect; } nsIntRegion ToOutsidePixels (nscoord aAppUnitsPerPixel) const; + nsRect GetLargestRectangle () const; /** * Make sure the region has at most aMaxRects by adding area to it * if necessary. The simplified region will be a superset of the * original region. The simplified region's bounding box will be * the same as for the current region. */ void SimplifyOutward (PRUint32 aMaxRects); @@ -404,16 +405,17 @@ public: PRBool IsEmpty () const { return mImpl.IsEmpty (); } PRBool IsComplex () const { return mImpl.IsComplex (); } PRBool IsEqual (const nsIntRegion& aRegion) const { return mImpl.IsEqual (aRegion.mImpl); } PRUint32 GetNumRects () const { return mImpl.GetNumRects (); } nsIntRect GetBounds () const { return FromRect (mImpl.GetBounds ()); } + nsIntRect GetLargestRectangle () const { return FromRect (mImpl.GetLargestRectangle()); } /** * Make sure the region has at most aMaxRects by adding area to it * if necessary. The simplified region will be a superset of the * original region. The simplified region's bounding box will be * the same as for the current region. */ void SimplifyOutward (PRUint32 aMaxRects)
--- a/gfx/src/nsRegion.cpp +++ b/gfx/src/nsRegion.cpp @@ -32,16 +32,17 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "prlock.h" #include "nsRegion.h" #include "nsISupportsImpl.h" +#include "nsTArray.h" /* * The SENTINEL values below guaranties that a < or > * comparison with it will be false for all values of the * underlying nscoord type. E.g. this is always false: * aCoord > NS_COORD_GREATER_SENTINEL * Setting the mRectListHead dummy rectangle to these values * allows us to loop without checking for the list end. @@ -1294,16 +1295,262 @@ nsIntRegion nsRegion::ToOutsidePixels(ns const nsRect *currentRect; while ((currentRect = rgnIter.Next())) { nsIntRect deviceRect = currentRect->ToOutsidePixels(aAppUnitsPerPixel); result.Or(result, deviceRect); } return result; } +// This algorithm works in three phases: +// 1) Convert the region into a grid by adding vertical/horizontal lines for +// each edge of each rectangle in the region. +// 2) For each rectangle in the region, for each cell it contains, set that +// cells's value to the area of the subrectangle it corresponds to. Cells +// that are not contained by any rectangle have the value 0. +// 3) Calculate the submatrix with the largest sum such that none of its cells +// contain any 0s (empty regions). The rectangle represented by the +// submatrix is the largest rectangle in the region. +// +// Let k be the number of rectangles in the region. +// Let m be the height of the grid generated in step 1. +// Let n be the width of the grid generated in step 1. +// +// Step 1 is O(k) in time and O(m+n) in space for the sparse grid. +// Step 2 is O(mn) in time and O(mn) in additional space for the full grid. +// Step 3 is O(m^2 n) in time and O(mn) in additional space +// +// The implementation of steps 1 and 2 are rather straightforward. However our +// implementation of step 3 uses dynamic programming to achieve its efficiency. +// +// Psuedo code for step 3 is as follows where G is the grid from step 1 and A +// is the array from step 2: +// Phase3 = function (G, A, m, n) { +// let (t,b,l,r,_) = MaxSum2D(A,m,n) +// return rect(G[t],G[l],G[r],G[b]); +// } +// MaxSum2D = function (A, m, n) { +// S = array(m+1,n+1) +// S[0][i] = 0 for i in [0,n] +// S[j][0] = 0 for j in [0,m] +// S[j][i] = (if A[j-1][i-1] = 0 then some large negative number else A[j-1][i-1]) +// + S[j-1][n] + S[j][i-1] - S[j-1][i-1] +// +// // top, bottom, left, right, area +// var maxRect = (-1, -1, -1, -1, 0); +// +// for all (m',m'') in [0, m]^2 { +// let B = { S[m'][i] - S[m''][i] | 0 <= i <= n } +// let ((l,r),area) = MaxSum1D(B,n+1) +// if (area > maxRect.area) { +// maxRect := (m', m'', l, r, area) +// } +// } +// +// return maxRect; +// } +// +// Originally taken from Improved algorithms for the k-maximum subarray problem +// for small k - SE Bae, T Takaoka but modified to show the explicit tracking +// of indices and we already have the prefix sums from our one call site so +// there's no need to construct them. +// MaxSum1D = function (A,n) { +// var minIdx = 0; +// var min = 0; +// var maxIndices = (0,0); +// var max = 0; +// for i in range(n) { +// let cand = A[i] - min; +// if (cand > max) { +// max := cand; +// maxIndices := (minIdx, i) +// } +// if (min > A[i]) { +// min := A[i]; +// minIdx := i; +// } +// } +// return (minIdx, maxIdx, max); +// } + +namespace { + // This class represents a partitioning of an axis delineated by coordinates. + // It internally maintains a sorted array of coordinates. + class AxisPartition { + public: + // Adds a new partition at the given coordinate to this partitioning. If + // the coordinate is already present in the partitioning, this does nothing. + void InsertCoord(nscoord c) { + PRUint32 i; + if (!mStops.GreatestIndexLtEq(c, i)) { + mStops.InsertElementAt(i, c); + } + } + + // Returns the array index of the given partition point. The partition + // point must already be present in the partitioning. + PRInt32 IndexOf(nscoord p) const { + return mStops.BinaryIndexOf(p); + } + + // Returns the partition at the given index which must be non-zero and + // less than the number of partitions in this partitioning. + nscoord StopAt(PRInt32 index) const { + return mStops[index]; + } + + // Returns the size of the gap between the partition at the given index and + // the next partition in this partitioning. If the index is the last index + // in the partitioning, the result is undefined. + nscoord StopSize(PRInt32 index) const { + return mStops[index+1] - mStops[index]; + } + + // Returns the number of partitions in this partitioning. + PRInt32 GetNumStops() const { return mStops.Length(); } + + private: + nsTArray<nscoord> mStops; + }; + + const PRInt64 kVeryLargeNegativeNumber = 0xffff000000000000ll; + + // Returns the sum and indices of the subarray with the maximum sum of the + // given array (A,n), assuming the array is already in prefix sum form. + PRInt64 MaxSum1D(const nsTArray<PRInt64> &A, PRInt32 n, + PRInt32 *minIdx, PRInt32 *maxIdx) { + // The min/max indicies of the largest subarray found so far + PRInt64 min = 0, + max = 0; + PRInt32 currentMinIdx = 0; + + *minIdx = 0; + *maxIdx = 0; + + // Because we're given the array in prefix sum form, we know the first + // element is 0 + for(PRInt32 i = 1; i < n; i++) { + PRInt64 cand = A[i] - min; + if (cand > max) { + max = cand; + *minIdx = currentMinIdx; + *maxIdx = i; + } + if (min > A[i]) { + min = A[i]; + currentMinIdx = i; + } + } + + return max; + } +} + +nsRect nsRegion::GetLargestRectangle () const { + nsRect bestRect; + + if (!mRectCount) + return bestRect; + + AxisPartition xaxis, yaxis; + + // Step 1: Calculate the grid lines + nsRegionRectIterator iter(*this); + const nsRect *currentRect; + while ((currentRect = iter.Next())) { + xaxis.InsertCoord(currentRect->x); + xaxis.InsertCoord(currentRect->XMost()); + yaxis.InsertCoord(currentRect->y); + yaxis.InsertCoord(currentRect->YMost()); + } + + // Step 2: Fill out the grid with the areas + // Note: due to the ordering of rectangles in the region, it is not always + // possible to combine steps 2 and 3 so we don't try to be clever. + PRInt32 matrixHeight = yaxis.GetNumStops() - 1; + PRInt32 matrixWidth = xaxis.GetNumStops() - 1; + PRInt32 matrixSize = matrixHeight * matrixWidth; + nsTArray<PRInt64> areas(matrixSize); + areas.SetLength(matrixSize); + memset(areas.Elements(), 0, matrixSize * sizeof(PRInt64)); + + iter.Reset(); + while ((currentRect = iter.Next())) { + PRInt32 xstart = xaxis.IndexOf(currentRect->x); + PRInt32 xend = xaxis.IndexOf(currentRect->XMost()); + PRInt32 y = yaxis.IndexOf(currentRect->y); + PRInt32 yend = yaxis.IndexOf(currentRect->YMost()); + + for (; y < yend; y++) { + nscoord height = yaxis.StopSize(y); + for (PRInt32 x = xstart; x < xend; x++) { + nscoord width = xaxis.StopSize(x); + areas[y*matrixWidth+x] = width*PRInt64(height); + } + } + } + + // Step 3: Find the maximum submatrix sum that does not contain a rectangle + { + // First get the prefix sum array + PRInt32 m = matrixHeight + 1; + PRInt32 n = matrixWidth + 1; + nsTArray<PRInt64> pareas(m*n); + pareas.SetLength(m*n); + // Zero out the first row + for (PRInt32 x = 0; x < n; x++) + pareas[x] = 0; + for (PRInt32 y = 1; y < m; y++) { + // Zero out the left column + pareas[y*n] = 0; + for (PRInt32 x = 1; x < n; x++) { + PRInt64 area = areas[(y-1)*matrixWidth+x-1]; + if (!area) + area = kVeryLargeNegativeNumber; + area += pareas[ y*n+x-1] + + pareas[(y-1)*n+x ] + - pareas[(y-1)*n+x-1]; + pareas[y*n+x] = area; + } + } + + // No longer need the grid + areas.SetLength(0); + + PRInt64 bestArea = 0; + struct { + PRInt32 left, top, right, bottom; + } bestRectIndices = { 0, 0, 0, 0 }; + for (PRInt32 m1 = 0; m1 < m; m1++) { + for (PRInt32 m2 = m1+1; m2 < m; m2++) { + nsTArray<PRInt64> B; + B.SetLength(n); + for (PRInt32 i = 0; i < n; i++) + B[i] = pareas[m2*n+i] - pareas[m1*n+i]; + PRInt32 minIdx, maxIdx; + PRInt64 area = MaxSum1D(B, n, &minIdx, &maxIdx); + if (area > bestArea) { + bestRectIndices.left = minIdx; + bestRectIndices.top = m1; + bestRectIndices.right = maxIdx; + bestRectIndices.bottom = m2; + bestArea = area; + } + } + } + + bestRect.MoveTo(xaxis.StopAt(bestRectIndices.left), + yaxis.StopAt(bestRectIndices.top)); + bestRect.SizeTo(xaxis.StopAt(bestRectIndices.right) - bestRect.x, + yaxis.StopAt(bestRectIndices.bottom) - bestRect.y); + } + + return bestRect; +} + void nsRegion::SimplifyOutward (PRUint32 aMaxRects) { NS_ASSERTION(aMaxRects >= 1, "Invalid max rect count"); if (mRectCount <= aMaxRects) return; *this = GetBounds();
--- a/gfx/tests/Makefile.in +++ b/gfx/tests/Makefile.in @@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk MODULE = gfx MOZILLA_INTERNAL_API = 1 CPP_UNIT_TESTS = \ TestColorNames.cpp \ TestRect.cpp \ + TestRegion.cpp \ $(NULL) LIBS = \ $(call EXPAND_LIBNAME_PATH,gkgfx,../src) \ $(XPCOM_LIBS) \ $(MOZ_JS_LIBS) \ $(TK_LIBS) \ $(NULL)
new file mode 100644 --- /dev/null +++ b/gfx/tests/TestRegion.cpp @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Rob Arnold <robarnold@cs.cmu.edu> + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "TestHarness.h" +#include "nsRegion.h" + +class TestLargestRegion { + static PRBool TestSingleRect(nsRect r) { + nsRegion region(r); + if (region.GetLargestRectangle() != r) { + fail("largest rect of singleton %d %d %d %d", r.x, r.y, r.width, r.height); + return PR_FALSE; + } + return PR_TRUE; + } + // Construct a rectangle, remove part of it, then check the remainder + static PRBool TestNonRectangular() { + nsRegion r(nsRect(0, 0, 30, 30)); + + const int nTests = 19; + struct { + nsRect rect; + PRInt64 expectedArea; + } tests[nTests] = { + // Remove a 20x10 chunk from the square + { nsRect(0, 0, 20, 10), 600 }, + { nsRect(10, 0, 20, 10), 600 }, + { nsRect(10, 20, 20, 10), 600 }, + { nsRect(0, 20, 20, 10), 600 }, + // Remove a 10x20 chunk from the square + { nsRect(0, 0, 10, 20), 600 }, + { nsRect(20, 0, 10, 20), 600 }, + { nsRect(20, 10, 10, 20), 600 }, + { nsRect(0, 10, 10, 20), 600 }, + // Remove the center 10x10 + { nsRect(10, 10, 10, 10), 300 }, + // Remove the middle column + { nsRect(10, 0, 10, 30), 300 }, + // Remove the middle row + { nsRect(0, 10, 30, 10), 300 }, + // Remove the corners 10x10 + { nsRect(0, 0, 10, 10), 600 }, + { nsRect(20, 20, 10, 10), 600 }, + { nsRect(20, 0, 10, 10), 600 }, + { nsRect(0, 20, 10, 10), 600 }, + // Remove the corners 20x20 + { nsRect(0, 0, 20, 20), 300 }, + { nsRect(10, 10, 20, 20), 300 }, + { nsRect(10, 0, 20, 20), 300 }, + { nsRect(0, 10, 20, 20), 300 } + }; + + PRBool success = PR_TRUE; + for (PRInt32 i = 0; i < nTests; i++) { + nsRegion r2; + r2.Sub(r, tests[i].rect); + + if (!r2.IsComplex()) + fail("nsRegion code got unexpectedly smarter!"); + + nsRect largest = r2.GetLargestRectangle(); + if (largest.width * largest.height != tests[i].expectedArea) { + fail("Did not succesfully find largest rectangle in non-rectangular region on iteration %d", i); + success = PR_FALSE; + } + } + + return success; + } + static PRBool TwoRectTest() { + nsRegion r(nsRect(0, 0, 100, 100)); + const int nTests = 4; + struct { + nsRect rect1, rect2; + PRInt64 expectedArea; + } tests[nTests] = { + { nsRect(0, 0, 75, 40), nsRect(0, 60, 75, 40), 2500 }, + { nsRect(25, 0, 75, 40), nsRect(25, 60, 75, 40), 2500 }, + { nsRect(25, 0, 75, 40), nsRect(0, 60, 75, 40), 2000 }, + { nsRect(0, 0, 75, 40), nsRect(25, 60, 75, 40), 2000 }, + }; + PRBool success = PR_TRUE; + for (PRInt32 i = 0; i < nTests; i++) { + nsRegion r2; + + r2.Sub(r, tests[i].rect1); + r2.Sub(r2, tests[i].rect2); + + if (!r2.IsComplex()) + fail("nsRegion code got unexpectedly smarter!"); + + nsRect largest = r2.GetLargestRectangle(); + if (largest.width * largest.height != tests[i].expectedArea) { + fail("Did not succesfully find largest rectangle in two-rect-subtract region on iteration %d", i); + success = PR_FALSE; + } + } + return success; + } +public: + static PRBool Test() { + if (!TestSingleRect(nsRect(0, 52, 720, 480)) || + !TestSingleRect(nsRect(-20, 40, 50, 20)) || + !TestSingleRect(nsRect(-20, 40, 10, 8)) || + !TestSingleRect(nsRect(-20, -40, 10, 8)) || + !TestSingleRect(nsRect(-10, -10, 20, 20))) + return PR_FALSE; + if (!TestNonRectangular()) + return PR_FALSE; + if (!TwoRectTest()) + return PR_FALSE; + passed("TestLargestRegion"); + return PR_TRUE; + } +}; + +int main(int argc, char** argv) { + ScopedXPCOM xpcom("TestRegion"); + if (xpcom.failed()) + return -1; + if (NS_FAILED(nsRegion::InitStatic())) { + fail("Could not initialize region statics"); + return -1; + } + if (!TestLargestRegion::Test()) + return -1; + nsRegion::ShutdownStatic(); + return 0; +}
--- a/gfx/thebes/public/GLContextProvider.h +++ b/gfx/thebes/public/GLContextProvider.h @@ -57,17 +57,17 @@ public: Empty, BasicRGBA32, StrictBasicRGBA32, BasicRGBX32, StrictBasicRGBX32 }; ContextFormat(const StandardContextFormat cf) { - memset(this, sizeof(ContextFormat), 0); + memset(this, 0, sizeof(ContextFormat)); switch (cf) { case BasicRGBA32: red = green = blue = alpha = 8; minRed = minGreen = minBlue = minAlpha = 1; break; case StrictBasicRGBA32:
--- a/gfx/thebes/src/GLContextProviderOSMesa.cpp +++ b/gfx/thebes/src/GLContextProviderOSMesa.cpp @@ -190,16 +190,20 @@ public: mContext = sOSMesaLibrary.fCreateContextExt(osmesa_format, aFormat.depth, aFormat.stencil, 0, NULL); if (!mContext) { NS_WARNING("OSMesaCreateContextExt failed!"); return PR_FALSE; } if (!MakeCurrent()) return PR_FALSE; if (!SetupLookupFunction()) return PR_FALSE; + + // OSMesa's different from the other GL providers, it renders to an image surface, not to a pbuffer + sOSMesaLibrary.fPixelStore(OSMESA_Y_UP, 0); + return InitWithPrefix("gl", PR_TRUE); } PRBool MakeCurrent() { PRBool succeeded = sOSMesaLibrary.fMakeCurrent (mContext, mThebesSurface->Data(), LOCAL_GL_UNSIGNED_BYTE,
--- a/intl/unicharutil/tools/ccmapbin.pl +++ b/intl/unicharutil/tools/ccmapbin.pl @@ -223,17 +223,17 @@ sub read_input ($comments_p->{'FILE'} = $_) =~ s/^\s*FILE::\s*//, next; next unless /^\s*0[Xx][0-9A-Fa-f]{4}/; /^\s*(.*)\s*$/; my ($u, $comment) = split /\s+/, $1, 2; $u =~ s/,//g; $u =~ tr/A-Z/a-z/; - next if /^0x.*[^0-9a-f]+.*/; + next if $u =~ /^0x.*[^0-9a-f]+.*/; my $usv = oct $u; if ( 0xd800 <= $usv && $usv <= 0xdfff || # surrogate code points $usv > 0x10ffff ) { printf STDERR "Invalid input $u at %4d\n", $lc; next; } $fillinfo_p->[($usv >> 4)] |= (1 << ($usv & 0x0f));
new file mode 100644 --- /dev/null +++ b/intl/unicharutil/tools/genignorable.pl @@ -0,0 +1,66 @@ +#!/usr/bin/perl + +open $f, 'UnicodeData-Latest.txt' or die $!; +while (<$f>) { + @columns = split(/;/); +# print "$columns[0] : $columns[1]\n"; + $names{hex($columns[0])} = $columns[1]; +} +close $f; + +open $f, 'DerivedCoreProperties.txt' or die $!; +$re = '['; +while (<$f>) { + next unless /Default_Ignorable_Code_Point/; + next unless /^([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))?/; + + ($start, $end) = (hex($1), hex($2)); + $end = $start unless $end; + + for ($c = $start; $c <= $end; $c++) { + printf "0x%04X", $c; + printf " // $names{$c}" if $names{$c}; + print "\n"; + } + + if (!$prevend || $start > $prevend + 1) { + $re .= make_unicode_range($prevstart, $prevend) if $prevstart; + $prevstart = $start; + } + $prevend = $end; +} +$re .= make_unicode_range($prevstart, $prevend).']'; +print STDERR $re; +close $f; + +sub make_unicode_range +{ + my ($start, $end) = @_; + + if ($start > 0xffff) { + my $starths = ($start - 0x10000) >> 10 | 0xd800; + my $startls = ($start - 0x10000) & 0x3ff | 0xdc00; + my $endhs = ($end - 0x10000) >> 10 | 0xd800; + my $endls = ($end - 0x10000) & 0x3ff | 0xdc00; + if ($starths == $endhs) { + return sprintf("]|\\u%04x[\\u%04x-\\u%04x", $starths, $startls, $endls) + } + my $re = ''; + if ($startls > 0xdc00) { + $re .= sprintf("]|\\u%04x[\\u%04x-\\udfff", $starths, $startls); + $starths++; + } + if ($endhs > $starths) { + $endhs-- if ($endls < 0xdfff); + $re .= sprintf("]|[\\u%04x-\\u%04x][\\udc00-\\udfff", $starths, $endhs); + } + if ($endls < 0xdfff) { + $re .= sprintf("]|\\u%04x[\\udc00-\\u%04x", $endhs, $endls); + } + return $re; + } elsif ($start == $end) { + return sprintf("\\u%04x", $start); + } else { + return sprintf("\\u%04x-\\u%04x", $start, $end); + } +}
--- a/ipc/chromium/Makefile.in +++ b/ipc/chromium/Makefile.in @@ -69,22 +69,16 @@ vpath %.cc \ $(srcdir)/src/chrome/common \ $(NULL) vpath %.mm \ $(srcdir)/src/base \ $(srcdir)/src/chrome/common \ $(NULL) -# TODO: remove this hack when we switch to GCC 4.3! GCC 4.1 -# instantiates template declarations in wrapped system headers with -# the wrong visibility, which is causing the Linux tinderboxen to die in -# std::string internals. -VISIBILITY_FLAGS= - include $(topsrcdir)/config/config.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk CPPSRCS += \ dtoa.cc \ g_fmt.cc \ prtime.cc \ at_exit.cc \
--- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -1513,17 +1513,17 @@ SPACE := $(EMPTY) $(EMPTY) # and class paths to be in the DOS form (i.e. e:/builds/...). This function # does the appropriate conversion on Windows, but is a noop on other systems. ifeq (,$(filter-out WINNT WINCE, $(HOST_OS_ARCH))) ifdef CYGWIN_WRAPPER normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p))) else # assume MSYS # We use 'pwd -W' to get DOS form of the path. However, since the given path -# could be a file or a non-existent path, we cannot call 'pwd -W' directly +# could be a file or a nonexistent path, we cannot call 'pwd -W' directly # on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W' # on it, then merge with the rest of the path. root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|") non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|") normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1))) endif else normalizepath = $(1)
--- a/js/src/config/system-headers +++ b/js/src/config/system-headers @@ -207,16 +207,17 @@ curl/types.h curses.h cxxabi.h DateTimeUtils.h dbus/dbus.h dbus/dbus-glib.h dbus/dbus-glib-lowlevel.h ddeml.h Debug.h +deque dem.h descrip.h Devices.h Dialogs.h direct.h dirent.h DiskInit.h dlfcn.h @@ -269,16 +270,17 @@ freetype/ftcache.h freetype/ftglyph.h freetype/ftsynth.h freetype/ftoutln.h freetype/ttnameid.h freetype/tttables.h freetype/t1tables.h fribidi/fribidi.h FSp_fopen.h +fstream fstream.h ft2build.h fts.h gconf/gconf-client.h Gdiplus.h gdk/gdk.h gdk/gdkkeysyms.h gdk/gdkprivate.h @@ -324,16 +326,17 @@ inttypes.h iodef.h io.h IOKit/IOKitLib.h IOKit/IOMessage.h IOKit/pwr_mgt/IOPMLib.h iomanip iostream iostream.h +iterator jar.h JavaControl.h JavaEmbedding/JavaControl.h JavaVM/jni.h JManager.h JNIEnvTests.h jni.h #if MOZ_NATIVE_JPEG==1 @@ -602,16 +605,17 @@ Process.h proto/dos.h proto/exec.h psap.h Pt.h pthread.h pwd.h Python.h QDOffscreen.h +queue Quickdraw.h QuickDraw.h QuickTimeComponents.h quipu/attr.h rasdlg.h raserror.h ras.h regex.h @@ -636,16 +640,17 @@ seccomon.h sec.h secmod.h secmodt.h secrng.h security.h secutil.h semaphore.h servprov.h +set setjmp.h SFNTLayoutTypes.h SFNTTypes.h share.h shellapi.h shlguid.h shlobj.h sigcontext.h @@ -829,16 +834,17 @@ unixio.h unixlib.h unknwn.h UPrinting.h UQuickTime.h UReanimator.h URegions.h URegistrar.h UResourceMgr.h +utility urlhist.h urlmon.h UScrap.h UScreenPort.h UTCUtils.h UTETextAction.h UTEViewTextAction.h UTextEdit.h
--- a/js/src/configure.in +++ b/js/src/configure.in @@ -4994,17 +4994,16 @@ AC_SUBST(MOZ_DEBUG_DISABLE_DEFS) AC_SUBST(MOZ_DEBUG_FLAGS) AC_SUBST(MOZ_DEBUG_LDFLAGS) AC_SUBST(WARNINGS_AS_ERRORS) AC_SUBST(MOZ_LEAKY) AC_SUBST(MOZ_JPROF) AC_SUBST(MOZ_SHARK) AC_SUBST(MOZ_CALLGRIND) AC_SUBST(MOZ_VTUNE) -AC_SUBST(MOZ_XPCTOOLS) AC_SUBST(MOZ_JSLOADER) AC_SUBST(MOZ_QUANTIFY) AC_SUBST(LIBICONV) AC_SUBST(BUILD_STATIC_LIBS) AC_SUBST(ENABLE_TESTS) AC_SUBST(ENABLE_STRIP)
--- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -2778,17 +2778,17 @@ array_concat(JSContext *cx, uintN argc, return false; for (slot = 0; slot < alength; slot++) { if (!JS_CHECK_OPERATION_LIMIT(cx) || !GetArrayElement(cx, aobj, slot, &hole, tvr.addr())) { return false; } /* - * Per ECMA 262, 15.4.4.4, step 9, ignore non-existent + * Per ECMA 262, 15.4.4.4, step 9, ignore nonexistent * properties. */ if (!hole && !SetArrayElement(cx, nobj, length+slot, tvr.value())) { return false; } } length += alength;
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -408,17 +408,17 @@ inline void JSGCChunkInfo::init(JSRuntime *rt) { runtime = rt; numFreeArenas = GC_ARENAS_PER_CHUNK; gcChunkAge = 0; /* * For simplicity we set all bits to 1 including the high bits in the - * last word that corresponds to non-existing arenas. This is fine since + * last word that corresponds to nonexistent arenas. This is fine since * the arena scans the bitmap words from lowest to highest bits and the * allocation checks numFreeArenas before doing the search. */ memset(getFreeArenaBitmap(), 0xFF, GC_FREE_ARENA_BITMAP_SIZE); } inline void CheckValidGCThingPtr(void *thing)
--- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1092,17 +1092,17 @@ js_CheckRedeclaration(JSContext *cx, JSO uintN oldAttrs, report; bool isFunction; jsval value; const char *type, *name; /* * Both objp and propp must be either null or given. When given, *propp * must be null. This way we avoid an extra "if (propp) *propp = NULL" for - * the common case of a non-existing property. + * the common case of a nonexistent property. */ JS_ASSERT(!objp == !propp); JS_ASSERT_IF(propp, !*propp); /* The JSPROP_INITIALIZER case below may generate a warning. Since we must * drop the property before reporting it, we insists on !propp to avoid * looking up the property again after the reporting is done. */
--- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -3708,18 +3708,16 @@ js_InflateUTF8StringToBuffer(JSContext * JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL, JSMSG_UTF8_CHAR_TOO_LARGE, buffer); } return JS_FALSE; } - if (dstlen < 2) - goto bufferTooSmall; if (dst) { *dst++ = (jschar)((v >> 10) + 0xD800); v = (jschar)((v & 0x3FF) + 0xDC00); } dstlen--; } } if (!dstlen)
--- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -12981,17 +12981,17 @@ TraceRecorder::prop(JSObject* obj, LIns* /* * Property cache ensures that we are dealing with an existing property, * and guards the shape for us. */ JSObject* obj2; PCVal pcval; CHECK_STATUS_A(test_property_cache(obj, obj_ins, obj2, pcval)); - /* Check for non-existent property reference, which results in undefined. */ + /* Check for nonexistent property reference, which results in undefined. */ if (pcval.isNull()) { if (slotp) RETURN_STOP_A("property not found"); /* * We could specialize to guard on just JSClass.getProperty, but a mere * class guard is simpler and slightly faster. */
--- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3586,19 +3586,20 @@ static void CancelExecution(JSRuntime *rt) { gCanceled = true; if (gExitCode == 0) gExitCode = EXITCODE_TIMEOUT; #ifdef JS_THREADSAFE if (gWorkers) { JSContext *cx = JS_NewContext(rt, 8192); - if (cx) + if (cx) { js::workers::terminateAll(cx, gWorkers); - JS_DestroyContextNoGC(cx); + JS_DestroyContextNoGC(cx); + } } #endif JS_TriggerAllOperationCallbacks(rt); static const char msg[] = "Script runs for too long, terminating.\n"; #if defined(XP_UNIX) && !defined(JS_THREADSAFE) /* It is not safe to call fputs from signals. */ /* Dummy assignment avoids GCC warning on "attribute warn_unused_result" */
--- a/js/src/tests/js1_5/Regress/regress-156354.js +++ b/js/src/tests/js1_5/Regress/regress-156354.js @@ -34,25 +34,25 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* * * Date: 16 September 2002 - * SUMMARY: Testing propertyIsEnumerable() on non-existent property + * SUMMARY: Testing propertyIsEnumerable() on nonexistent property * See http://bugzilla.mozilla.org/show_bug.cgi?id=156354 * */ //----------------------------------------------------------------------------- var gTestfile = 'regress-156354.js'; var UBound = 0; var BUGNUMBER = 156354; -var summary = 'Testing propertyIsEnumerable() on non-existent property'; +var summary = 'Testing propertyIsEnumerable() on nonexistent property'; var status = ''; var statusitems = []; var actual = ''; var actualvalues = []; var expect= ''; var expectedvalues = [];
--- a/js/src/tests/js1_5/extensions/getset-006.js +++ b/js/src/tests/js1_5/extensions/getset-006.js @@ -142,17 +142,17 @@ obj = new TestObject(); obj.name = cnFRED; obj.color = cnRED; status = 'In SECTION3 of test looking up extant getter/setter'; actual = [obj.__lookupSetter__(cnName), obj.__lookupGetter__(cnName)]; expect = [cnNameSetter, cnNameGetter]; addThis(); -status = 'In SECTION3 of test; looking up non-existent getter/setter'; +status = 'In SECTION3 of test; looking up nonexistent getter/setter'; actual = [obj.__lookupSetter__(cnColor), obj.__lookupGetter__(cnColor)]; expect = [undefined, undefined]; addThis(); status = 'In SECTION3 of test; looking up getter/setter on nonexistent property'; actual = [obj.__lookupSetter__(cnNonExistingProp), obj.__lookupGetter__(cnNonExistingProp)]; expect = [undefined, undefined]; addThis();
--- a/js/src/tests/js1_7/iterable/regress-341510.js +++ b/js/src/tests/js1_7/iterable/regress-341510.js @@ -34,17 +34,17 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var gTestfile = 'regress-341510.js'; //----------------------------------------------------------------------------- var BUGNUMBER = 341510; var summary = 'Iterators: crash in close handler with assignment to ' + - 'non-existing name'; + 'nonexistent name'; var actual = 'No Crash'; var expect = 'No Crash'; printBugNumber(BUGNUMBER); printStatus (summary); function gen(i) { try {
--- a/js/src/xpconnect/src/Makefile.in +++ b/js/src/xpconnect/src/Makefile.in @@ -155,20 +155,16 @@ DEFINES += \ -DFEATURE_NANOJIT=1 \ $(addprefix -D,$(filter AVMPLUS%,$(CONFIG))) \ $(NULL) ENABLE_TRACEABLE_FLAGS = --enable-traceables endif # ENABLE_JIT -ifdef MOZ_XPCTOOLS -DEFINES += -DXPC_TOOLS_SUPPORT -endif - ifdef XPC_IDISPATCH_SUPPORT DEFINES += -DXPC_IDISPATCH_SUPPORT ifdef XPC_COMOBJECT DEFINES += -DXPC_COMOBJECT endif endif
--- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -92,40 +92,16 @@ nsXPConnect::nsXPConnect() { mRuntime = XPCJSRuntime::newXPCJSRuntime(this); nsCycleCollector_registerRuntime(nsIProgrammingLanguage::JAVASCRIPT, this); #ifdef DEBUG_CC mJSRoots.ops = nsnull; #endif -#ifdef XPC_TOOLS_SUPPORT - { - char* filename = PR_GetEnv("MOZILLA_JS_PROFILER_OUTPUT"); - if(filename && *filename) - { - mProfilerOutputFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); - if(mProfilerOutputFile && - NS_SUCCEEDED(mProfilerOutputFile->InitWithNativePath(nsDependentCString(filename)))) - { - mProfiler = do_GetService(XPCTOOLS_PROFILER_CONTRACTID); - if(mProfiler) - { - if(NS_SUCCEEDED(mProfiler->Start())) - { -#ifdef DEBUG - printf("***** profiling JavaScript. Output to: %s\n", - filename); -#endif - } - } - } - } - } -#endif char* reportableEnv = PR_GetEnv("MOZ_REPORT_ALL_JS_EXCEPTIONS"); if(reportableEnv && *reportableEnv) gReportAllJSExceptions = 1; } nsXPConnect::~nsXPConnect() { NS_ASSERTION(!mCycleCollectionContext, @@ -215,24 +191,16 @@ nsXPConnect::GetSingleton() void nsXPConnect::ReleaseXPConnectSingleton() { nsXPConnect* xpc = gSelf; if(xpc) { NS_SetGlobalThreadObserver(nsnull); -#ifdef XPC_TOOLS_SUPPORT - if(xpc->mProfiler) - { - xpc->mProfiler->Stop(); - xpc->mProfiler->WriteResults(xpc->mProfilerOutputFile); - } -#endif - #ifdef DEBUG // force a dump of the JavaScript gc heap if JS is still alive // if requested through XPC_SHUTDOWN_HEAP_DUMP environment variable { // autoscope XPCCallContext ccx(NATIVE_CALLER); if(ccx.IsValid()) {
--- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -122,20 +122,16 @@ #include "nsIScriptObjectPrincipal.h" #include "nsIPrincipal.h" #endif #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT #include "nsISecurityCheckedComponent.h" #endif -#ifdef XPC_TOOLS_SUPPORT -#include "nsIXPCToolsProfiler.h" -#endif - #include "nsIThreadInternal.h" #ifdef XPC_IDISPATCH_SUPPORT // This goop was added because of EXCEPINFO in ThrowCOMError // This include is here, because it needs to occur before the undefines below #ifdef WINCE /* atlbase.h on WINCE has a bug, in that it tries to use * GetProcAddress with a wide string, when that is explicitly not @@ -549,21 +545,16 @@ private: JSBool mShuttingDown; XPCCallContext* mCycleCollectionContext; #ifdef DEBUG_CC nsAutoPtr<XPCCallContext> mExplainCycleCollectionContext; PLDHashTable mJSRoots; #endif PRBool mCycleCollecting; -#ifdef XPC_TOOLS_SUPPORT - nsCOMPtr<nsIXPCToolsProfiler> mProfiler; - nsCOMPtr<nsILocalFile> mProfilerOutputFile; -#endif - #ifndef XPCONNECT_STANDALONE typedef nsBaseHashtable<nsVoidPtrHashKey, nsISupports*, nsISupports*> ScopeSet; ScopeSet mScopes; #endif nsCOMPtr<nsIXPCScriptable> mBackstagePass; static PRUint32 gReportAllJSExceptions; };
--- a/js/src/xpconnect/src/xpcthreadcontext.cpp +++ b/js/src/xpconnect/src/xpcthreadcontext.cpp @@ -278,17 +278,17 @@ XPCJSContextStack::GetSafeJSContext(JSCo // hook. #endif if(glob && NS_FAILED(xpc->InitClasses(mSafeJSContext, glob))) { glob = nsnull; } } - if(!glob && mSafeJSContext) + if(mSafeJSContext && !glob) { // Destroy the context outside the scope of JSAutoRequest that // uses the context in its destructor. JS_DestroyContext(mSafeJSContext); mSafeJSContext = nsnull; } // Save it off so we can destroy it later, even if // mSafeJSContext has been set to another context
--- a/js/src/xpconnect/tests/mochitest/test_cows.html +++ b/js/src/xpconnect/tests/mochitest/test_cows.html @@ -74,19 +74,19 @@ function COWTests() { } catch (e) { ok(/SECURITY_MANAGER/.test(e), "not able to access arbitrary property " + uneval(name)); } }); try { if (strictCOW.foo) - ok(false, "non-existent property shouldn't be truthy."); + ok(false, "nonexistent property shouldn't be truthy."); else - ok(true, "'duck-typing' detection on non-existent prop " + + ok(true, "'duck-typing' detection on nonexistent prop " + "should work."); } catch (e) { todo(false, "'duck-typing' detection on a non-exposed prop of a COWed " + "obj should not throw"); } var writable = { __exposedProps__: {foo: 'w'}};
deleted file mode 100644 --- a/js/src/xpconnect/tools/Makefile.in +++ /dev/null @@ -1,49 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -DIRS = idl src - -include $(topsrcdir)/config/rules.mk -
deleted file mode 100644 --- a/js/src/xpconnect/tools/idl/Makefile.in +++ /dev/null @@ -1,53 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1999 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = xpctools - -XPIDLSRCS = \ - nsIXPCToolsCompiler.idl \ - nsIXPCToolsProfiler.idl \ - $(NULL) - -include $(topsrcdir)/config/rules.mk
deleted file mode 100644 --- a/js/src/xpconnect/tools/idl/nsIXPCToolsCompiler.idl +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * John Bandhauer <jband@netscape.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* Interface for JS code testing tool which does compile-time checking. */ - -#include "nsISupports.idl" -#include "nsILocalFile.idl" - -[scriptable, uuid(71151570-e56f-11d3-8f65-0010a4e73d9a)] -interface nsIXPCToolsCompiler : nsISupports -{ - /** - * XXX temporary hack because there does not seem to be another scriptable - * way to get this info. - */ - readonly attribute nsILocalFile binDir; - - void CompileFile(in nsILocalFile aFile, in PRBool strict); -}; - -%{ C++ -#define XPCTOOLS_COMPILER_CONTRACTID "xpctools.compiler.1" -%}
deleted file mode 100644 --- a/js/src/xpconnect/tools/idl/nsIXPCToolsProfiler.idl +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * John Bandhauer <jband@netscape.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* Interface for JS code testing tool which does code coverage and profiling. */ - -#include "nsISupports.idl" -#include "nsILocalFile.idl" - -[scriptable, uuid(09ef19b0-e97a-11d3-8f69-0010a4e73d9a)] -interface nsIXPCToolsProfiler : nsISupports -{ - void start(); - void stop(); - void clear(); - void writeResults(in nsILocalFile aFile); -}; - -%{ C++ -#define XPCTOOLS_PROFILER_CONTRACTID "xpctools.profiler.1" -%}
deleted file mode 100644 --- a/js/src/xpconnect/tools/js/CompileJSFiles.js +++ /dev/null @@ -1,28 +0,0 @@ -const nsIFile = Components.interfaces.nsIFile; -var Compiler = new Components.Constructor("xpctools.compiler.1", - "nsIXPCToolsCompiler"); -var c = new Compiler; - -dump("\n"); -dump("Compiling all .js files under "+c.binDir.path+"\n"); -dump("Will report any compile-time errors...\n\n"); -dump( "compiled "+CompileJSFilesInDir(c.binDir)+" files\n\n"); - -function CompileJSFilesInDir(dir) { - var count = 0; - if(!dir.isDirectory()) - return; - var list = dir.directoryEntries; - while(list.hasMoreElements()) { - file = list.getNext().QueryInterface(nsIFile); - if(file.isDirectory()) - count += CompileJSFilesInDir(file); - else if(file.leafName.match(/\.js$/i)) { - // dump("compiling... "+file.path+"\n"); - c.CompileFile(file, false); - ++count; - } - } - return count; -} -
deleted file mode 100644 --- a/js/src/xpconnect/tools/js/ListJSFiles.js +++ /dev/null @@ -1,18 +0,0 @@ -const nsIFile = Components.interfaces.nsIFile; -var Compiler = new Components.Constructor("xpctools.compiler.1","nsIXPCToolsCompiler"); -var c = new Compiler; -ListJSFilesInDir(c.binDir); - -function ListJSFilesInDir(dir) { - if(!dir.isDirectory()) - return; - var list = dir.directoryEntries; - while(list.hasMoreElements()) { - file = list.getNext().QueryInterface(nsIFile); - if(file.isDirectory()) - ListJSFilesInDir(file); - else if(file.leafName.match(/\.js$/i)) - dump(file.path+"\n"); - } -} -
deleted file mode 100644 --- a/js/src/xpconnect/tools/src/Makefile.in +++ /dev/null @@ -1,71 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is Mozilla Communicator client code, released -# March 31, 1998. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# John Bandhauer <jband@netscape.com> -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -DEPTH = ../../../../.. -topsrcdir = @top_srcdir@ -srcdir = @srcdir@ -VPATH = @srcdir@ - -include $(DEPTH)/config/autoconf.mk - -MODULE = xpctools -LIBRARY_NAME = xpctools - -MODULE_NAME = xpctools -IS_COMPONENT = 1 -FORCE_SHARED_LIB = 1 - -CPPSRCS = \ - nsXPCToolsCompiler.cpp \ - nsXPCToolsProfiler.cpp \ - nsXPCToolsModule.cpp \ - $(NULL) - -include $(topsrcdir)/config/config.mk - -EXTRA_DSO_LDOPTS += \ - $(XPCOM_GLUE_LDOPTS) \ - $(MOZ_JS_LIBS) \ - $(NSPR_LIBS) \ - $(NULL) - -include $(topsrcdir)/config/rules.mk - -DEFINES += -DJSFILE -DJS_THREADSAFE -
deleted file mode 100644 --- a/js/src/xpconnect/tools/src/nsXPCToolsCompiler.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * John Bandhauer <jband@netscape.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* Implements nsXPCToolsCompiler. */ - -#include "xpctools_private.h" -#include "nsDirectoryServiceDefs.h" -#include "nsDirectoryServiceUtils.h" - -NS_IMPL_ISUPPORTS1(nsXPCToolsCompiler, nsIXPCToolsCompiler) - -nsXPCToolsCompiler::nsXPCToolsCompiler() -{ -} - -nsXPCToolsCompiler::~nsXPCToolsCompiler() -{ -} - -/* readonly attribute nsILocalFile binDir; */ -NS_IMETHODIMP nsXPCToolsCompiler::GetBinDir(nsILocalFile * *aBinDir) -{ - *aBinDir = nsnull; - - nsCOMPtr<nsIFile> file; - nsresult rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(file)); - if(NS_FAILED(rv)) - return rv; - - nsCOMPtr<nsILocalFile> lfile = do_QueryInterface(file); - NS_ADDREF(*aBinDir = lfile); - return NS_OK; -} - -static void ErrorReporter(JSContext *cx, const char *message, - JSErrorReport *report) -{ - printf("compile error!\n"); -} - -static JSClass global_class = { - "nsXPCToolsCompiler::global", 0, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nsnull -}; - -/* void CompileFile (in nsILocalFile aFile, in PRBool strict); */ -NS_IMETHODIMP nsXPCToolsCompiler::CompileFile(nsILocalFile *aFile, PRBool strict) -{ - // use the xpccallcontext stuff to get the current JSContext - - // get the xpconnect service - nsresult rv; - nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv)); - if(NS_FAILED(rv)) - return NS_ERROR_FAILURE; - - // get the xpconnect native call context - nsAXPCNativeCallContext *callContext = nsnull; - xpc->GetCurrentNativeCallContext(&callContext); - if(!callContext) - return NS_ERROR_FAILURE; - - // verify that we are being called from JS (i.e. the current call is - // to this object - though we don't verify that it is to this exact method) - nsCOMPtr<nsISupports> callee; - callContext->GetCallee(getter_AddRefs(callee)); - if(!callee || callee.get() != (nsISupports*)this) - return NS_ERROR_FAILURE; - - // Get JSContext of current call - JSContext* cx; - rv = callContext->GetJSContext(&cx); - if(NS_FAILED(rv) || !cx) - return NS_ERROR_FAILURE; - - FILE* handle; - if(NS_FAILED(aFile->OpenANSIFileDesc("r", &handle))) - return NS_ERROR_FAILURE; - - JSObject* glob = JS_NewObject(cx, &global_class, NULL, NULL); - if (!glob) - return NS_ERROR_FAILURE; - if (!JS_InitStandardClasses(cx, glob)) - return NS_ERROR_FAILURE; - - nsCAutoString path; - if(NS_FAILED(aFile->GetNativePath(path))) - return NS_ERROR_FAILURE; - - uint32 oldoptions = JS_GetOptions(cx); - JS_SetOptions(cx, JSOPTION_WERROR | (strict ? JSOPTION_STRICT : 0)); - JSErrorReporter older = JS_SetErrorReporter(cx, ErrorReporter); - JSExceptionState *es =JS_SaveExceptionState(cx); - - if(!JS_CompileFileHandle(cx, glob, path.get(), handle)) - { - jsval v; - JSErrorReport* report; - if(JS_GetPendingException(cx, &v) && - nsnull != (report = JS_ErrorFromException(cx, v))) - { - JSString* str; - const char* msg = "Error"; - str = JS_ValueToString(cx, v); - if(str) - msg = JS_GetStringBytes(str); - printf("%s [%s,%d]\n\n", - msg, - report->filename, - (int)report->lineno); - } - else - { - printf("no script and no error report!\n"); - } - - } - JS_RestoreExceptionState(cx, es); - JS_SetErrorReporter(cx, older); - JS_SetOptions(cx, oldoptions); - - return NS_OK; -}
deleted file mode 100644 --- a/js/src/xpconnect/tools/src/nsXPCToolsModule.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * John Bandhauer <jband@netscape.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* Module code for XPCTools. */ - -#include "xpctools_private.h" - -// Module implementation for the xpctools library - -NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCToolsCompiler) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCToolsProfiler) - -// {331148C0-E599-11d3-8F65-0010A4E73D9A} -#define COMPILER_CID \ - { 0x331148c0, 0xe599, 0x11d3, \ - { 0x8f, 0x65, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } } - -// {7F5D12E0-E97B-11d3-8F69-0010A4E73D9A} -#define PROFILER_CID \ - { 0x7f5d12e0, 0xe97b, 0x11d3, \ - { 0x8f, 0x69, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } } - -static const nsModuleComponentInfo components[] = { - {nsnull, COMPILER_CID, XPCTOOLS_COMPILER_CONTRACTID, nsXPCToolsCompilerConstructor}, - {nsnull, PROFILER_CID, XPCTOOLS_PROFILER_CONTRACTID, nsXPCToolsProfilerConstructor} -}; - -NS_IMPL_NSGETMODULE(xpctools, components)
deleted file mode 100644 --- a/js/src/xpconnect/tools/src/nsXPCToolsProfiler.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * John Bandhauer <jband@netscape.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* Implements nsXPCToolsProfiler. */ - -#include "xpctools_private.h" - -/***************************************************************************/ - -ProfilerFile::ProfilerFile(const char* filename) - : mName(filename ? strdup(filename) : nsnull) -{ - mFunctionTable.Init(); -} - -ProfilerFile::~ProfilerFile() -{ - if(mName) - free(mName); -} - -ProfilerFunction* -ProfilerFile::FindOrAddFunction(const char* aName, - uintN aBaseLineNumber, - uintN aLineExtent, - size_t aTotalSize) -{ - FunctionID key(aBaseLineNumber, aLineExtent); - ProfilerFunction* fun; - - if (!mFunctionTable.Get(key, &fun)) - { - fun = new ProfilerFunction(aName, aBaseLineNumber, aLineExtent, - aTotalSize, this); - if(fun) - mFunctionTable.Put(key, fun); - } - return fun; -} - -void -ProfilerFile::EnumerateFunctions(EnumeratorType aFunc, void *aClosure) const -{ - mFunctionTable.EnumerateRead(aFunc, aClosure); -} - -ProfilerFunction::ProfilerFunction(const char* name, - uintN lineno, uintn extent, size_t totalsize, - ProfilerFile* file) - : mName(name ? strdup(name) : nsnull), - mBaseLineNumber(lineno), - mLineExtent(extent), - mTotalSize(totalsize), - mFile(file), - mCallCount(0), - mCompileCount(0), - mQuickTime((PRUint32) -1), - mLongTime(0), - mStartTime(0), - mSum(0) -{ - // empty -} - -ProfilerFunction::~ProfilerFunction() -{ - if(mName) - free(mName); -} - -/***************************************************************************/ - - -NS_IMPL_ISUPPORTS1(nsXPCToolsProfiler, nsIXPCToolsProfiler) - -nsXPCToolsProfiler::nsXPCToolsProfiler() - : mLock(PR_NewLock()), - mRuntime(nsnull) -{ - InitializeRuntime(); - mFileTable.Init(); - mScriptTable.Init(); -} - -nsXPCToolsProfiler::~nsXPCToolsProfiler() -{ - Stop(); - if(mLock) - PR_DestroyLock(mLock); -} - -/***************************************************************************/ -// the hooks... - -/* called just after script creation */ -static void -xpctools_JSNewScriptHook(JSContext *cx, - const char *filename, /* URL of script */ - uintN lineno, /* line script starts */ - JSScript *script, - JSFunction *fun, - void *callerdata) -{ - if(!script) - return; - if(!filename) - filename = "<<<!!! has no name so may represent many different pages !!!>>>"; - nsXPCToolsProfiler* self = (nsXPCToolsProfiler*) callerdata; - - PR_Lock(self->mLock); - - ProfilerFile* file; - if (!self->mFileTable.Get(filename, &file)) - { - file = new ProfilerFile(filename); - if (file) - self->mFileTable.Put(filename, file); - } - if(file) - { - ProfilerFunction* function = - file->FindOrAddFunction(fun ? JS_GetFunctionName(fun) : nsnull, - JS_GetScriptBaseLineNumber(cx, script), - JS_GetScriptLineExtent(cx, script), - fun - ? JS_GetFunctionTotalSize(cx, fun) - : JS_GetScriptTotalSize(cx, script)); - if(function) - { - function->IncrementCompileCount(); - self->mScriptTable.Put(script, function); - } - } - PR_Unlock(self->mLock); -} - -/* called just before script destruction */ -static void -xpctools_JSDestroyScriptHook(JSContext *cx, - JSScript *script, - void *callerdata) -{ - if(!script) - return; - nsXPCToolsProfiler* self = (nsXPCToolsProfiler*) callerdata; - - PR_Lock(self->mLock); - self->mScriptTable.Remove(script); - PR_Unlock(self->mLock); -} - - -/* called on entry and return of functions and top level scripts */ -static void* -xpctools_InterpreterHook(JSContext *cx, JSStackFrame *fp, JSBool before, - JSBool *ok, void *closure) -{ - // ignore returns - NS_ASSERTION(fp, "bad frame pointer!"); - - JSScript* script = fp->script; - if(script) - { - nsXPCToolsProfiler* self = (nsXPCToolsProfiler*) closure; - - PR_Lock(self->mLock); - - ProfilerFunction* fun; - if (self->mScriptTable.Get(script, &fun)) - { - if(before) - { - fun->IncrementCallCount(); - fun->SetStartTime(); - } - else - { - PRUint32 delta = fun->SetEndTime(); - - JSStackFrame* down = fp->down; - if (down) { - JSScript* caller = down->script; - if (caller) { - ProfilerFunction* callfun; - if (self->mScriptTable.Get(caller, &callfun)) - { - callfun->AddNotSelfTime(delta); - } - } - } - } - } - - PR_Unlock(self->mLock); - } - return closure; -} - -/***************************************************************************/ -// interface methods - -/* void start (); */ -NS_IMETHODIMP nsXPCToolsProfiler::Start() -{ - PR_Lock(mLock); - - if(!VerifyRuntime()) - { - PR_Unlock(mLock); - return NS_ERROR_UNEXPECTED; - } - - JS_SetNewScriptHook(mRuntime, xpctools_JSNewScriptHook, this); - JS_SetDestroyScriptHook(mRuntime, xpctools_JSDestroyScriptHook, this); - JS_SetExecuteHook(mRuntime, xpctools_InterpreterHook, this); - JS_SetCallHook(mRuntime, xpctools_InterpreterHook, this); - - PR_Unlock(mLock); - return NS_OK; -} - -/* void stop (); */ -NS_IMETHODIMP nsXPCToolsProfiler::Stop() -{ - PR_Lock(mLock); - - if(!VerifyRuntime()) - { - PR_Unlock(mLock); - return NS_ERROR_UNEXPECTED; - } - - JS_SetNewScriptHook(mRuntime, nsnull, nsnull); - JS_SetDestroyScriptHook(mRuntime, nsnull, nsnull); - JS_SetExecuteHook(mRuntime, nsnull, this); - JS_SetCallHook(mRuntime, nsnull, this); - - PR_Unlock(mLock); - return NS_OK; -} - -/* void clear (); */ -NS_IMETHODIMP nsXPCToolsProfiler::Clear() -{ - // XXX implement me! - return NS_ERROR_NOT_IMPLEMENTED; -} - - -static PLDHashOperator -xpctools_FunctionNamePrinter(const FunctionID &aKey, - ProfilerFunction* fun, void* closure) -{ - FILE* out = (FILE*) closure; - const char* name = fun->GetName(); - PRUint32 average; - PRUint32 count; - - count = fun->GetCallCount(); - if (count != 0) - average = fun->GetSum() / count; - if(!name) - name = "<top level>"; - fprintf(out, - " [%lu,%lu] %s() {%d-%d} %lu ", - (unsigned long) fun->GetCompileCount(), - (unsigned long) fun->GetCallCount(), - name, - (int) fun->GetBaseLineNumber(), - (int)(fun->GetBaseLineNumber()+fun->GetLineExtent()-1), - (unsigned long) fun->GetTotalSize()); - if(count != 0) - fprintf(out, - "{min %lu, max %lu, avg %lu, sum %lu, self %lu}\n", - (unsigned long) fun->GetQuickTime(), - (unsigned long) fun->GetLongTime(), - (unsigned long) average, - (unsigned long) fun->GetSum(), - (unsigned long) fun->GetSelf()); - else - fprintf(out, "\n" ); - return PL_DHASH_NEXT; -} - -static PLDHashOperator -xpctools_FilenamePrinter(const char *keyname, ProfilerFile* file, - void *closure) -{ - FILE* out = (FILE*) closure; - fprintf(out, "%s\n", file->GetName()); - file->EnumerateFunctions(xpctools_FunctionNamePrinter, closure); - return PL_DHASH_NEXT; -} - -/* void writeResults (in nsILocalFile aFile); */ -NS_IMETHODIMP nsXPCToolsProfiler::WriteResults(nsILocalFile *aFile) -{ - NS_ENSURE_ARG(aFile); - - FILE* out; - if(NS_FAILED(aFile->OpenANSIFileDesc("w", &out)) || ! out) - return NS_ERROR_FAILURE; - - fprintf(out, "[CompileCount, CallCount] Name {StartLine, EndLine} TotalSize {MinTime, MaxTime, Average, Total, Self}\n\n"); - - PR_Lock(mLock); - mFileTable.EnumerateRead(xpctools_FilenamePrinter, out); - PR_Unlock(mLock); - - return NS_OK; -} - -/***************************************************************************/ -// additional utility methods - -JSBool -nsXPCToolsProfiler::VerifyRuntime() -{ - JSRuntime* rt; - nsCOMPtr<nsIJSRuntimeService> rts = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); - return rts && NS_SUCCEEDED(rts->GetRuntime(&rt)) && rt && rt == mRuntime; -} - -JSBool -nsXPCToolsProfiler::InitializeRuntime() -{ - NS_ASSERTION(!mRuntime, "can't init runtime twice"); - JSRuntime* rt; - nsCOMPtr<nsIJSRuntimeService> rts = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); - if(rts && NS_SUCCEEDED(rts->GetRuntime(&rt)) && rt) - mRuntime = rt; - return mRuntime != nsnull; -}
deleted file mode 100644 --- a/js/src/xpconnect/tools/src/xpctools_private.h +++ /dev/null @@ -1,236 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * John Bandhauer <jband@netscape.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* All the XPCTools private declarations - only include locally. */ - -#ifndef xpctoolsprivate_h___ -#define xpctoolsprivate_h___ - -#include <string.h> -#include <stdlib.h> -#include "nscore.h" -#include "nsISupports.h" -#include "nsIServiceManager.h" -#include "nsIComponentManager.h" -#include "nsIGenericFactory.h" -#include "nsIMemory.h" -#include "nsIXPConnect.h" -#include "nsCOMPtr.h" -#include "nsIModule.h" -#include "jsapi.h" -#include "jshash.h" -#include "jsprf.h" -#include "jsinterp.h" -#include "jscntxt.h" -#include "jsdbgapi.h" - -#include "nsILocalFile.h" - -#include "nsIJSRuntimeService.h" -#include "nsClassHashtable.h" -#include "nsDataHashtable.h" -#include "nsServiceManagerUtils.h" - -#include "nsIXPCToolsCompiler.h" -#include "nsIXPCToolsProfiler.h" - -class nsXPCToolsCompiler : public nsIXPCToolsCompiler -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIXPCTOOLSCOMPILER - - nsXPCToolsCompiler(); - virtual ~nsXPCToolsCompiler(); - // XXX add additional members -}; - -/***************************************************************************/ - -class ProfilerFile; - -class ProfilerFunction -{ -public: - ProfilerFunction(const char* name, - uintN lineno, uintn extent, size_t totalsize, - ProfilerFile* file); - ~ProfilerFunction(); - - const char* GetName() const {return mName;} - ProfilerFile* GetFile() const {return mFile;} - uintN GetBaseLineNumber() const {return mBaseLineNumber;} - uintN GetLineExtent() const {return mLineExtent;} - size_t GetTotalSize() const { return mTotalSize; } - void IncrementCallCount() {++mCallCount;} - PRUint32 GetCallCount() {return mCallCount;} - PRUint32 GetSum() {return mSum;} - void IncrementCompileCount() {++mCompileCount;} - PRUint32 GetCompileCount() {return mCompileCount;} - PRUint32 NowInMilliSecs() - {PRUint64 now64 = LL_INIT(0,1000); - PRUint32 now32; - LL_DIV(now64,PR_Now(),now64); - LL_L2UI(now32, now64); - return now32; - } - void SetStartTime() {mStartTime = NowInMilliSecs();} - PRUint32 SetEndTime() - {PRUint32 delta = NowInMilliSecs() - mStartTime; - if(delta < mQuickTime) - mQuickTime = delta; - if (delta > mLongTime) - mLongTime = delta; - mSum += delta; - return delta;} - PRUint32 GetQuickTime() {return mQuickTime;} - PRUint32 GetLongTime() {return mLongTime;} - - void AddNotSelfTime(PRUint32 delta) {mNotSelfSum += delta;} - PRUint32 GetSelf() { return mSum - mNotSelfSum;} - - ProfilerFunction(); // not implemented - -private: - char* mName; - uintN mBaseLineNumber; - uintN mLineExtent; - size_t mTotalSize; // JSFunction, JSScript, bytecode, &c, size - ProfilerFile* mFile; - PRUint32 mCallCount; - PRUint32 mCompileCount; - PRUint32 mQuickTime; // quickest delta in msec - PRUint32 mLongTime; // longest delta in msec - PRUint32 mStartTime; // time on enter - PRUint32 mSum; - PRUint32 mNotSelfSum; -}; - -struct FunctionID -{ - uintN lineno; - uintN extent; - - FunctionID(uintN aLineno, uintN aExtent) : - lineno(aLineno), extent(aExtent) { } - - PRBool operator==(const FunctionID &aOther) const { - return aOther.lineno == this->lineno && - aOther.extent == this->extent; - } -}; - -class FunctionKey : public PLDHashEntryHdr -{ -public: - typedef const FunctionID &KeyType; - typedef const FunctionID *KeyTypePointer; - - FunctionKey(KeyTypePointer aF) : mF(*aF) { } - FunctionKey(const FunctionKey &toCopy) : mF(toCopy.mF) { } - ~FunctionKey() { } - - KeyType GetKey() const { return mF; } - PRBool KeyEquals(const KeyTypePointer aKey) const - { - return mF == *aKey; - } - - static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } - static PLDHashNumber HashKey(const KeyTypePointer aKey) { - return (aKey->lineno * 17) | (aKey->extent * 7); - } - - enum { ALLOW_MEMMOVE = PR_TRUE }; - -private: - const FunctionID mF; -}; - -class ProfilerFile -{ -public: - ProfilerFile(const char* filename); - ~ProfilerFile(); - - - ProfilerFunction* FindOrAddFunction(const char* aName, - uintN aBaseLineNumber, - uintN aLineExtent, - size_t aTotalSize); - - typedef nsClassHashtable<FunctionKey, ProfilerFunction> FunctionTableType; - typedef FunctionTableType::EnumReadFunction EnumeratorType; - - void EnumerateFunctions(EnumeratorType aFunc, - void *aClosure) const; - - const char* GetName() const {return mName;} - -private: - char* mName; - FunctionTableType mFunctionTable; -}; - -class nsXPCToolsProfiler : public nsIXPCToolsProfiler -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIXPCTOOLSPROFILER - - nsXPCToolsProfiler(); - virtual ~nsXPCToolsProfiler(); - -private: - JSBool InitializeRuntime(); - JSBool VerifyRuntime(); - - /* Taking the unusual step of making all data public to simplify - * the implementation of the "C" static debugger hooks. - */ - -public: - PRLock* mLock; - JSRuntime* mRuntime; - nsClassHashtable<nsCharPtrHashKey, ProfilerFile> mFileTable; - nsDataHashtable<nsVoidPtrHashKey, ProfilerFunction*> mScriptTable; -}; - -#endif /* xpctoolsprivate_h___ */
new file mode 100644 --- /dev/null +++ b/layout/base/FrameLayerBuilder.cpp @@ -0,0 +1,540 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert O'Callahan <robert@ocallahan.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "FrameLayerBuilder.h" + +#include "nsDisplayList.h" +#include "nsPresContext.h" +#include "nsLayoutUtils.h" + +using namespace mozilla::layers; + +namespace mozilla { + +namespace { + +/** + * This class iterates through a display list tree, descending only into + * nsDisplayClip items, and returns each display item encountered during + * such iteration. Along with each item we also return the clip rect + * accumulated for the item. + */ +class ClippedItemIterator { +public: + ClippedItemIterator(const nsDisplayList* aList) + { + DescendIntoList(aList, nsnull, nsnull); + AdvanceToItem(); + } + PRBool IsDone() + { + return mStack.IsEmpty(); + } + void Next() + { + State* top = StackTop(); + top->mItem = top->mItem->GetAbove(); + AdvanceToItem(); + } + // Returns null if there is no clipping affecting the item. The + // clip rect is in device pixels + const gfxRect* GetEffectiveClipRect() + { + State* top = StackTop(); + return top->mHasClipRect ? &top->mEffectiveClipRect : nsnull; + } + nsDisplayItem* Item() + { + return StackTop()->mItem; + } + +private: + // We maintain a stack of state objects. Each State object represents + // where we're up to in the iteration of a list. + struct State { + // The current item we're at in the list + nsDisplayItem* mItem; + // The effective clip rect applying to all the items in this list + gfxRect mEffectiveClipRect; + PRPackedBool mHasClipRect; + }; + + State* StackTop() + { + return &mStack[mStack.Length() - 1]; + } + void DescendIntoList(const nsDisplayList* aList, + nsPresContext* aPresContext, + const nsRect* aClipRect) + { + State* state = mStack.AppendElement(); + if (!state) + return; + if (mStack.Length() >= 2) { + *state = mStack[mStack.Length() - 2]; + } else { + state->mHasClipRect = PR_FALSE; + } + state->mItem = aList->GetBottom(); + if (aClipRect) { + gfxRect r(aClipRect->x, aClipRect->y, aClipRect->width, aClipRect->height); + r.ScaleInverse(aPresContext->AppUnitsPerDevPixel()); + if (state->mHasClipRect) { + state->mEffectiveClipRect = state->mEffectiveClipRect.Intersect(r); + } else { + state->mEffectiveClipRect = r; + state->mHasClipRect = PR_TRUE; + } + } + } + // Advances to an item that the iterator should return. + void AdvanceToItem() + { + while (!mStack.IsEmpty()) { + State* top = StackTop(); + if (!top->mItem) { + mStack.SetLength(mStack.Length() - 1); + if (!mStack.IsEmpty()) { + top = StackTop(); + top->mItem = top->mItem->GetAbove(); + } + continue; + } + if (top->mItem->GetType() != nsDisplayItem::TYPE_CLIP) + return; + nsDisplayClip* clipItem = static_cast<nsDisplayClip*>(top->mItem); + nsRect clip = clipItem->GetClipRect(); + DescendIntoList(clipItem->GetList(), + clipItem->GetClippingFrame()->PresContext(), + &clip); + } + } + + nsAutoTArray<State,10> mStack; +}; + +/** + * This class represents a sublist of consecutive items in an nsDisplayList. + * The first item in the sublist is mStartItem and the last item + * is the item before mEndItem. + * + * These sublists are themselves organized into a linked list of all + * the ItemGroups associated with a given layer, via mNextItemsForLayer. + * This list will have more than one element if the display items in a layer + * come from different nsDisplayLists, or if they come from the same + * nsDisplayList but they aren't consecutive in that list. + * + * These objects are allocated from the nsDisplayListBuilder arena. + */ +struct ItemGroup { + // If null, then the item group is empty. + nsDisplayItem* mStartItem; + nsDisplayItem* mEndItem; + ItemGroup* mNextItemsForLayer; + // The clipping (if any) that needs to be applied to all these items. + gfxRect mClipRect; + PRPackedBool mHasClipRect; + + ItemGroup() : mStartItem(nsnull), mEndItem(nsnull), + mNextItemsForLayer(nsnull), mHasClipRect(PR_FALSE) {} + + void* operator new(size_t aSize, + nsDisplayListBuilder* aBuilder) CPP_THROW_NEW { + return aBuilder->Allocate(aSize); + } +}; + +/** + * This class represents a layer and the display item(s) it + * will render. The items are stored in a linked list of ItemGroups. + */ +struct LayerItems { + nsRefPtr<Layer> mLayer; + // equal to mLayer, or null if mLayer is not a ThebesLayer + ThebesLayer* mThebesLayer; + ItemGroup* mItems; + // The bounds of the visible region for this layer, in device pixels + nsIntRect mVisibleRect; + + LayerItems(ItemGroup* aItems) : + mThebesLayer(nsnull), mItems(aItems) + { + } + + void* operator new(size_t aSize, + nsDisplayListBuilder* aBuilder) CPP_THROW_NEW { + return aBuilder->Allocate(aSize); + } +}; + +/** + * Given a (possibly clipped) display item in aItem, try to append it to + * the items in aGroup. If aItem is the next item in the sublist in + * aGroup, and the clipping matches, we can just update aGroup in-place, + * otherwise we'll allocate a new ItemGroup, add it to the linked list, + * and put aItem in the new ItemGroup. We return the ItemGroup into which + * aItem was inserted. + */ +static ItemGroup* +AddToItemGroup(nsDisplayListBuilder* aBuilder, + ItemGroup* aGroup, nsDisplayItem* aItem, + const gfxRect* aClipRect) +{ + NS_ASSERTION(!aGroup->mNextItemsForLayer, + "aGroup must be the last group in the chain"); + + if (!aGroup->mStartItem) { + aGroup->mStartItem = aItem; + aGroup->mEndItem = aItem->GetAbove(); + aGroup->mHasClipRect = aClipRect != nsnull; + if (aClipRect) { + aGroup->mClipRect = *aClipRect; + } + return aGroup; + } + + if (aGroup->mEndItem == aItem && + (aGroup->mHasClipRect + ? (aClipRect && aGroup->mClipRect == *aClipRect) + : !aClipRect)) { + aGroup->mEndItem = aItem->GetAbove(); + return aGroup; + } + + ItemGroup* itemGroup = new (aBuilder) ItemGroup(); + if (!itemGroup) + return aGroup; + aGroup->mNextItemsForLayer = itemGroup; + return AddToItemGroup(aBuilder, itemGroup, aItem, aClipRect); +} + +/** + * Create an empty Thebes layer, with an empty ItemGroup associated with + * it, and append it to aLayers. + */ +static ItemGroup* +CreateEmptyThebesLayer(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + nsTArray<LayerItems*>* aLayers) +{ + ItemGroup* itemGroup = new (aBuilder) ItemGroup(); + if (!itemGroup) + return nsnull; + nsRefPtr<ThebesLayer> thebesLayer = aManager->CreateThebesLayer(); + if (!thebesLayer) + return nsnull; + LayerItems* layerItems = new (aBuilder) LayerItems(itemGroup); + aLayers->AppendElement(layerItems); + thebesLayer->SetUserData(layerItems); + layerItems->mThebesLayer = thebesLayer; + layerItems->mLayer = thebesLayer.forget(); + return itemGroup; +} + +static PRBool +IsAllUniform(nsDisplayListBuilder* aBuilder, ItemGroup* aGroup, + nscolor* aColor) +{ + nsRect visibleRect = aGroup->mStartItem->GetVisibleRect(); + nscolor finalColor = NS_RGBA(0,0,0,0); + for (ItemGroup* group = aGroup; group; + group = group->mNextItemsForLayer) { + for (nsDisplayItem* item = group->mStartItem; item != group->mEndItem; + item = item->GetAbove()) { + nscolor color; + if (visibleRect != item->GetVisibleRect()) + return PR_FALSE; + if (!item->IsUniform(aBuilder, &color)) + return PR_FALSE; + finalColor = NS_ComposeColors(finalColor, color); + } + } + *aColor = finalColor; + return PR_TRUE; +} + +/** + * This is the heart of layout's integration with layers. We + * use a ClippedItemIterator to iterate through descendant display + * items. Each item either has its own layer or is assigned to a + * ThebesLayer. We create ThebesLayers as necessary, although we try + * to put items in the bottom-most ThebesLayer because that is most + * likely to be able to render with an opaque background, which will often + * be required for subpixel text antialiasing to work. + */ +static void BuildLayers(nsDisplayListBuilder* aBuilder, + const nsDisplayList& aList, + LayerManager* aManager, + nsTArray<LayerItems*>* aLayers) +{ + NS_ASSERTION(aLayers->IsEmpty(), "aLayers must be initially empty"); + + // Create "bottom" Thebes layer. We'll try to put as much content + // as possible in this layer because if the container is filled with + // opaque content, this bottommost layer can also be treated as opaque, + // which means content in this layer can have subpixel AA. + // firstThebesLayerItems always points to the last ItemGroup for the + // first Thebes layer. + ItemGroup* firstThebesLayerItems = + CreateEmptyThebesLayer(aBuilder, aManager, aLayers); + if (!firstThebesLayerItems) + return; + // lastThebesLayerItems always points to the last ItemGroup for the + // topmost layer, if it's a ThebesLayer. If the top layer is not a + // Thebes layer, this is null. + ItemGroup* lastThebesLayerItems = firstThebesLayerItems; + // This region contains the bounds of all the content that is above + // the first Thebes layer. + nsRegion areaAboveFirstThebesLayer; + + for (ClippedItemIterator iter(&aList); !iter.IsDone(); iter.Next()) { + nsDisplayItem* item = iter.Item(); + const gfxRect* clipRect = iter.GetEffectiveClipRect(); + // Ask the item if it manages its own layer + nsRefPtr<Layer> layer = item->BuildLayer(aBuilder, aManager); + nsRect bounds = item->GetBounds(aBuilder); + // We set layerItems to point to the LayerItems object where the + // item ends up. + LayerItems* layerItems = nsnull; + if (layer) { + // item has a dedicated layer. Add it to the list, with an ItemGroup + // covering this item only. + ItemGroup* itemGroup = new (aBuilder) ItemGroup(); + if (itemGroup) { + AddToItemGroup(aBuilder, itemGroup, item, clipRect); + layerItems = new (aBuilder) LayerItems(itemGroup); + aLayers->AppendElement(layerItems); + if (layerItems) { + if (itemGroup->mHasClipRect) { + gfxRect r = itemGroup->mClipRect; + r.Round(); + nsIntRect intRect(r.X(), r.Y(), r.Width(), r.Height()); + layer->IntersectClipRect(intRect); + } + layerItems->mLayer = layer.forget(); + } + } + // This item is above the first Thebes layer. + areaAboveFirstThebesLayer.Or(areaAboveFirstThebesLayer, bounds); + lastThebesLayerItems = nsnull; + } else { + // No dedicated layer. Add it to a Thebes layer. First try to add + // it to the first Thebes layer, which we can do if there's no + // content between the first Thebes layer and our display item that + // overlaps our display item. + if (!areaAboveFirstThebesLayer.Intersects(bounds)) { + firstThebesLayerItems = + AddToItemGroup(aBuilder, firstThebesLayerItems, item, clipRect); + layerItems = aLayers->ElementAt(0); + } else if (lastThebesLayerItems) { + // Try to add to the last Thebes layer + lastThebesLayerItems = + AddToItemGroup(aBuilder, lastThebesLayerItems, item, clipRect); + // This item is above the first Thebes layer. + areaAboveFirstThebesLayer.Or(areaAboveFirstThebesLayer, bounds); + layerItems = aLayers->ElementAt(aLayers->Length() - 1); + } else { + // Create a new Thebes layer + ItemGroup* itemGroup = + CreateEmptyThebesLayer(aBuilder, aManager, aLayers); + if (itemGroup) { + lastThebesLayerItems = + AddToItemGroup(aBuilder, itemGroup, item, clipRect); + NS_ASSERTION(lastThebesLayerItems == itemGroup, + "AddToItemGroup shouldn't create a new group if the " + "initial group is empty"); + // This item is above the first Thebes layer. + areaAboveFirstThebesLayer.Or(areaAboveFirstThebesLayer, bounds); + layerItems = aLayers->ElementAt(aLayers->Length() - 1); + } + } + } + + if (layerItems) { + // Update the visible region of the layer to account for the new + // item + nscoord appUnitsPerDevPixel = + item->GetUnderlyingFrame()->PresContext()->AppUnitsPerDevPixel(); + layerItems->mVisibleRect.UnionRect(layerItems->mVisibleRect, + item->GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel)); + } + } + + if (!firstThebesLayerItems->mStartItem) { + // The first Thebes layer has nothing in it. Delete the layer. + // Ensure layer is released. + aLayers->ElementAt(0)->mLayer = nsnull; + aLayers->RemoveElementAt(0); + } + + for (PRUint32 i = 0; i < aLayers->Length(); ++i) { + LayerItems* layerItems = aLayers->ElementAt(i); + + nscolor color; + // Only convert layers with identity transform to ColorLayers, for now. + // This simplifies the code to set the clip region. + if (layerItems->mThebesLayer && + IsAllUniform(aBuilder, layerItems->mItems, &color) && + layerItems->mLayer->GetTransform().IsIdentity()) { + nsRefPtr<ColorLayer> layer = aManager->CreateColorLayer(); + layer->SetClipRect(layerItems->mThebesLayer->GetClipRect()); + // Clip to mVisibleRect to ensure only the pixels we want are filled. + layer->IntersectClipRect(layerItems->mVisibleRect); + layer->SetColor(gfxRGBA(color)); + layerItems->mLayer = layer.forget(); + layerItems->mThebesLayer = nsnull; + } + + gfxMatrix transform; + nsIntRect visibleRect = layerItems->mVisibleRect; + if (layerItems->mLayer->GetTransform().Is2D(&transform)) { + // if 'transform' is not invertible, then nothing will be displayed + // for the layer, so it doesn't really matter what we do here + transform.Invert(); + gfxRect layerVisible = transform.TransformBounds( + gfxRect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height)); + layerVisible.RoundOut(); + if (NS_FAILED(nsLayoutUtils::GfxRectToIntRect(layerVisible, &visibleRect))) { + NS_ERROR("Visible rect transformed out of bounds"); + } + } else { + NS_ERROR("Only 2D transformations currently supported"); + } + layerItems->mLayer->SetVisibleRegion(nsIntRegion(visibleRect)); + } +} + +} // anonymous namespace + +already_AddRefed<Layer> +FrameLayerBuilder::MakeContainerLayerFor(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + nsDisplayItem* aContainer, + const nsDisplayList& aChildren) +{ + // If there's only one layer, then in principle we can try to flatten + // things by returning that layer here. But that adds complexity to + // retained layer management so we don't do it. Layer backends can + // flatten internally. + nsRefPtr<ContainerLayer> container = aManager->CreateContainerLayer(); + if (!container) + return nsnull; + + nsAutoTArray<LayerItems*,10> layerItems; + BuildLayers(aBuilder, aChildren, aManager, &layerItems); + + Layer* lastChild = nsnull; + for (PRUint32 i = 0; i < layerItems.Length(); ++i) { + Layer* child = layerItems[i]->mLayer; + container->InsertAfter(child, lastChild); + lastChild = child; + // release the layer now because the ItemGroup destructor doesn't run; + // the container is still holding a reference to it + layerItems[i]->mLayer = nsnull; + } + container->SetIsOpaqueContent(aChildren.IsOpaque()); + nsRefPtr<Layer> layer = container.forget(); + return layer.forget(); +} + +/* static */ void +FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer, + gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + void* aCallbackData) +{ + LayerItems* layerItems = static_cast<LayerItems*>(aLayer->GetUserData()); + nsDisplayListBuilder* builder = + static_cast<nsDisplayListBuilder*>(aCallbackData); + + // For now, we'll ignore toDraw and just draw the entire visible + // area, because the "visible area" is already confined to just the + // area that needs to be repainted. Later, when we start reusing layers + // from paint to paint, we'll need to pay attention to toDraw and + // actually try to avoid drawing stuff that's not in it. + + // Our list may contain content with different prescontexts at + // different zoom levels. 'rc' contains the nsIRenderingContext + // used for the previous display item, and lastPresContext is the + // prescontext for that item. We also cache the clip state for that + // item. + nsRefPtr<nsIRenderingContext> rc; + nsPresContext* lastPresContext = nsnull; + gfxRect currentClip; + PRBool setClipRect = PR_FALSE; + NS_ASSERTION(layerItems->mItems, "No empty layers allowed"); + for (ItemGroup* group = layerItems->mItems; group; + group = group->mNextItemsForLayer) { + // If the new desired clip state is different from the current state, + // update the clip. + if (setClipRect != group->mHasClipRect || + (group->mHasClipRect && group->mClipRect != currentClip)) { + if (setClipRect) { + aContext->Restore(); + } + setClipRect = group->mHasClipRect; + if (setClipRect) { + aContext->Save(); + aContext->NewPath(); + aContext->Rectangle(group->mClipRect, PR_TRUE); + aContext->Clip(); + currentClip = group->mClipRect; + } + } + NS_ASSERTION(group->mStartItem, "No empty groups allowed"); + for (nsDisplayItem* item = group->mStartItem; item != group->mEndItem; + item = item->GetAbove()) { + nsPresContext* presContext = item->GetUnderlyingFrame()->PresContext(); + if (presContext != lastPresContext) { + // Create a new rendering context with the right + // appunits-per-dev-pixel. + nsresult rv = + presContext->DeviceContext()->CreateRenderingContextInstance(*getter_AddRefs(rc)); + if (NS_FAILED(rv)) + break; + rc->Init(presContext->DeviceContext(), aContext); + lastPresContext = presContext; + } + item->Paint(builder, rc); + } + } + if (setClipRect) { + aContext->Restore(); + } +} + +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/layout/base/FrameLayerBuilder.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Corporation code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert O'Callahan <robert@ocallahan.org> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef FRAMELAYERBUILDER_H_ +#define FRAMELAYERBUILDER_H_ + +#include "Layers.h" + +class nsDisplayListBuilder; +class nsDisplayList; +class nsDisplayItem; + +namespace mozilla { + +class FrameLayerBuilder { +public: + typedef mozilla::layers::Layer Layer; + typedef mozilla::layers::ThebesLayer ThebesLayer; + typedef mozilla::layers::LayerManager LayerManager; + + /** + * Create a container layer for a display item that contains a child + * list, either reusing an existing one or creating a new one. + * aContainer may be null, in which case we construct a root layer. + */ + already_AddRefed<Layer> MakeContainerLayerFor(nsDisplayListBuilder* aBuilder, + LayerManager* aManager, + nsDisplayItem* aContainer, + const nsDisplayList& aChildren); + + /** + * This callback must be provided to EndTransaction. The callback data + * must be the nsDisplayListBuilder containing this FrameLayerBuilder. + */ + static void DrawThebesLayer(ThebesLayer* aLayer, + gfxContext* aContext, + const nsIntRegion& aRegionToDraw, + void* aCallbackData); +}; + +} + +#endif /* FRAMELAYERBUILDER_H_ */
--- a/layout/base/Makefile.in +++ b/layout/base/Makefile.in @@ -54,16 +54,17 @@ LIBXUL_LIBRARY = 1 XPIDLSRCS = \ nsIStyleSheetService.idl \ $(NULL) EXPORTS = \ + FrameLayerBuilder.h \ FramePropertyTable.h \ nsBidi.h \ nsBidiPresUtils.h \ nsCaret.h \ nsCSSFrameConstructor.h \ nsChangeHint.h \ nsCompatibility.h \ nsDisplayList.h \ @@ -83,16 +84,17 @@ EXPORTS = \ nsPresContext.h \ nsPresState.h \ nsRefreshDriver.h \ nsStyleChangeList.h \ nsStyleConsts.h \ $(NULL) CPPSRCS = \ + FrameLayerBuilder.cpp \ FramePropertyTable.cpp \ nsCSSColorUtils.cpp \ nsCSSFrameConstructor.cpp \ nsCSSRendering.cpp \ nsCSSRenderingBorders.cpp \ nsCaret.cpp \ nsChildIterator.cpp \ nsCounterManager.cpp \
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -57,16 +57,17 @@ #include "nsSVGIntegrationUtils.h" #endif #include "nsLayoutUtils.h" #include "imgIContainer.h" #include "nsIInterfaceRequestorUtils.h" #include "BasicLayers.h" +using namespace mozilla; using namespace mozilla::layers; nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, PRBool aIsForEvents, PRBool aBuildCaret) : mReferenceFrame(aReferenceFrame), mMovingFrame(nsnull), mSaveVisibleRegionOfMovingContent(nsnull), mIgnoreScrollFrame(nsnull), @@ -400,380 +401,16 @@ nsDisplayList::ComputeVisibility(nsDispl movingContentVisibleRegionAfterMove); mIsOpaque = aVisibleRegion->IsEmpty(); #ifdef DEBUG mDidComputeVisibility = PR_TRUE; #endif } -namespace { -/** - * This class iterates through a display list tree, descending only into - * nsDisplayClip items, and returns each display item encountered during - * such iteration. Along with each item we also return the clip rect - * accumulated for the item. - */ -class ClippedItemIterator { -public: - ClippedItemIterator(const nsDisplayList* aList) - { - DescendIntoList(aList, nsnull, nsnull); - AdvanceToItem(); - } - PRBool IsDone() - { - return mStack.IsEmpty(); - } - void Next() - { - State* top = StackTop(); - top->mItem = top->mItem->GetAbove(); - AdvanceToItem(); - } - // Returns null if there is no clipping affecting the item. The - // clip rect is in device pixels - const gfxRect* GetEffectiveClipRect() - { - State* top = StackTop(); - return top->mHasClipRect ? &top->mEffectiveClipRect : nsnull; - } - nsDisplayItem* Item() - { - return StackTop()->mItem; - } - -private: - // We maintain a stack of state objects. Each State object represents - // where we're up to in the iteration of a list. - struct State { - // The current item we're at in the list - nsDisplayItem* mItem; - // The effective clip rect applying to all the items in this list - gfxRect mEffectiveClipRect; - PRPackedBool mHasClipRect; - }; - - State* StackTop() - { - return &mStack[mStack.Length() - 1]; - } - void DescendIntoList(const nsDisplayList* aList, - nsPresContext* aPresContext, - const nsRect* aClipRect) - { - State* state = mStack.AppendElement(); - if (!state) - return; - if (mStack.Length() >= 2) { - *state = mStack[mStack.Length() - 2]; - } else { - state->mHasClipRect = PR_FALSE; - } - state->mItem = aList->GetBottom(); - if (aClipRect) { - gfxRect r(aClipRect->x, aClipRect->y, aClipRect->width, aClipRect->height); - r.ScaleInverse(aPresContext->AppUnitsPerDevPixel()); - if (state->mHasClipRect) { - state->mEffectiveClipRect = state->mEffectiveClipRect.Intersect(r); - } else { - state->mEffectiveClipRect = r; - state->mHasClipRect = PR_TRUE; - } - } - } - // Advances to an item that the iterator should return. - void AdvanceToItem() - { - while (!mStack.IsEmpty()) { - State* top = StackTop(); - if (!top->mItem) { - mStack.SetLength(mStack.Length() - 1); - if (!mStack.IsEmpty()) { - top = StackTop(); - top->mItem = top->mItem->GetAbove(); - } - continue; - } - if (top->mItem->GetType() != nsDisplayItem::TYPE_CLIP) - return; - nsDisplayClip* clipItem = static_cast<nsDisplayClip*>(top->mItem); - nsRect clip = clipItem->GetClipRect(); - DescendIntoList(clipItem->GetList(), - clipItem->GetClippingFrame()->PresContext(), - &clip); - } - } - - nsAutoTArray<State,10> mStack; -}; -} - -/** - * Given a (possibly clipped) display item in aItem, try to append it to - * the items in aGroup. If aItem is the next item in the sublist in - * aGroup, and the clipping matches, we can just update aGroup in-place, - * otherwise we'll allocate a new ItemGroup, add it to the linked list, - * and put aItem in the new ItemGroup. We return the ItemGroup into which - * aItem was inserted. - */ -static nsDisplayList::ItemGroup* -AddToItemGroup(nsDisplayListBuilder* aBuilder, - nsDisplayList::ItemGroup* aGroup, nsDisplayItem* aItem, - const gfxRect* aClipRect) { - NS_ASSERTION(!aGroup->mNextItemsForLayer, - "aGroup must be the last group in the chain"); - - if (!aGroup->mStartItem) { - aGroup->mStartItem = aItem; - aGroup->mEndItem = aItem->GetAbove(); - aGroup->mHasClipRect = aClipRect != nsnull; - if (aClipRect) { - aGroup->mClipRect = *aClipRect; - } - return aGroup; - } - - if (aGroup->mEndItem == aItem && - (aGroup->mHasClipRect - ? (aClipRect && aGroup->mClipRect == *aClipRect) - : !aClipRect)) { - aGroup->mEndItem = aItem->GetAbove(); - return aGroup; - } - - nsDisplayList::ItemGroup* itemGroup = - new (aBuilder) nsDisplayList::ItemGroup(); - if (!itemGroup) - return aGroup; - aGroup->mNextItemsForLayer = itemGroup; - return AddToItemGroup(aBuilder, itemGroup, aItem, aClipRect); -} - -/** - * Create an empty Thebes layer, with an empty ItemGroup associated with - * it, and append it to aLayers. - */ -static nsDisplayList::ItemGroup* -CreateEmptyThebesLayer(nsDisplayListBuilder* aBuilder, - LayerManager* aManager, - nsTArray<nsDisplayList::LayerItems>* aLayers) { - nsDisplayList::ItemGroup* itemGroup = - new (aBuilder) nsDisplayList::ItemGroup(); - if (!itemGroup) - return nsnull; - nsRefPtr<ThebesLayer> thebesLayer = - aManager->CreateThebesLayer(); - if (!thebesLayer) - return nsnull; - nsDisplayList::LayerItems* layerItems = - aLayers->AppendElement(nsDisplayList::LayerItems(itemGroup)); - layerItems->mThebesLayer = thebesLayer; - layerItems->mLayer = thebesLayer.forget(); - return itemGroup; -} - -static PRBool -IsAllUniform(nsDisplayListBuilder* aBuilder, nsDisplayList::ItemGroup* aGroup, - nscolor* aColor) -{ - nsRect visibleRect = aGroup->mStartItem->GetVisibleRect(); - nscolor finalColor = NS_RGBA(0,0,0,0); - for (nsDisplayList::ItemGroup* group = aGroup; group; - group = group->mNextItemsForLayer) { - for (nsDisplayItem* item = group->mStartItem; item != group->mEndItem; - item = item->GetAbove()) { - nscolor color; - if (visibleRect != item->GetVisibleRect()) - return PR_FALSE; - if (!item->IsUniform(aBuilder, &color)) - return PR_FALSE; - finalColor = NS_ComposeColors(finalColor, color); - } - } - *aColor = finalColor; - return PR_TRUE; -} - -/** - * This is the heart of layout's integration with layers. We - * use a ClippedItemIterator to iterate through descendant display - * items. Each item either has its own layer or is assigned to a - * ThebesLayer. We create ThebesLayers as necessary, although we try - * to put items in the bottom-most ThebesLayer because that is most - * likely to be able to render with an opaque background, which will often - * be required for subpixel text antialiasing to work. - */ -void nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder, - LayerManager* aManager, - nsTArray<LayerItems>* aLayers) const { - NS_ASSERTION(aLayers->IsEmpty(), "aLayers must be initially empty"); - - // Create "bottom" Thebes layer. We'll try to put as much content - // as possible in this layer because if the container is filled with - // opaque content, this bottommost layer can also be treated as opaque, - // which means content in this layer can have subpixel AA. - // firstThebesLayerItems always points to the last ItemGroup for the - // first Thebes layer. - ItemGroup* firstThebesLayerItems = - CreateEmptyThebesLayer(aBuilder, aManager, aLayers); - if (!firstThebesLayerItems) - return; - // lastThebesLayerItems always points to the last ItemGroup for the - // topmost layer, if it's a ThebesLayer. If the top layer is not a - // Thebes layer, this is null. - ItemGroup* lastThebesLayerItems = firstThebesLayerItems; - // This region contains the bounds of all the content that is above - // the first Thebes layer. - nsRegion areaAboveFirstThebesLayer; - - for (ClippedItemIterator iter(this); !iter.IsDone(); iter.Next()) { - nsDisplayItem* item = iter.Item(); - const gfxRect* clipRect = iter.GetEffectiveClipRect(); - // Ask the item if it manages its own layer - nsRefPtr<Layer> layer = item->BuildLayer(aBuilder, aManager); - nsRect bounds = item->GetBounds(aBuilder); - // We set layerItems to point to the LayerItems object where the - // item ends up. - LayerItems* layerItems = nsnull; - if (layer) { - // item has a dedicated layer. Add it to the list, with an ItemGroup - // covering this item only. - ItemGroup* itemGroup = new (aBuilder) ItemGroup(); - if (itemGroup) { - AddToItemGroup(aBuilder, itemGroup, item, clipRect); - layerItems = aLayers->AppendElement(LayerItems(itemGroup)); - if (layerItems) { - if (itemGroup->mHasClipRect) { - gfxRect r = itemGroup->mClipRect; - r.Round(); - nsIntRect intRect(r.X(), r.Y(), r.Width(), r.Height()); - layer->IntersectClipRect(intRect); - } - layerItems->mLayer = layer.forget(); - } - }