From 5f2897868af271a785d04facf9c6b19f6286e491 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Tue, 29 Jan 2013 11:57:01 -0500 Subject: [PATCH 01/70] Bug 796388 - part 1 - delete TelemetryVFS; r=mak --- storage/src/Makefile.in | 1 - storage/src/TelemetryVFS.cpp | 531 ------------------------ storage/src/mozStorageConnection.cpp | 5 +- storage/src/mozStorageService.cpp | 63 ++- storage/src/mozStorageService.h | 10 +- storage/test/unit/test_telemetry_vfs.js | 30 -- storage/test/unit/xpcshell.ini | 1 - 7 files changed, 52 insertions(+), 589 deletions(-) delete mode 100644 storage/src/TelemetryVFS.cpp delete mode 100644 storage/test/unit/test_telemetry_vfs.js diff --git a/storage/src/Makefile.in b/storage/src/Makefile.in index 50dd3c78285..0c3b67172c6 100644 --- a/storage/src/Makefile.in +++ b/storage/src/Makefile.in @@ -63,7 +63,6 @@ CPPSRCS = \ StorageBaseStatementInternal.cpp \ SQLCollations.cpp \ VacuumManager.cpp \ - TelemetryVFS.cpp \ FileSystemModule.cpp \ $(NULL) diff --git a/storage/src/TelemetryVFS.cpp b/storage/src/TelemetryVFS.cpp deleted file mode 100644 index e4fce091f72..00000000000 --- a/storage/src/TelemetryVFS.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include -#include "mozilla/Telemetry.h" -#include "mozilla/Preferences.h" -#include "sqlite3.h" -#include "nsThreadUtils.h" -#include "mozilla/Util.h" -#include "mozilla/dom/quota/QuotaManager.h" - -/** - * This preference is a workaround to allow users/sysadmins to identify - * that the profile exists on an NFS share whose implementation - * is incompatible with SQLite's default locking implementation. - * Bug 433129 attempted to automatically identify such file-systems, - * but a reliable way was not found and it was determined that the fallback - * locking is slower than POSIX locking, so we do not want to do it by default. -*/ -#define PREF_NFS_FILESYSTEM "storage.nfs_filesystem" - -namespace { - -using namespace mozilla; -using namespace mozilla::dom::quota; - -struct Histograms { - const char *name; - const Telemetry::ID readB; - const Telemetry::ID writeB; - const Telemetry::ID readMS; - const Telemetry::ID writeMS; - const Telemetry::ID syncMS; -}; - -#define SQLITE_TELEMETRY(FILENAME, HGRAM) \ - { FILENAME, \ - Telemetry::MOZ_SQLITE_ ## HGRAM ## _READ_B, \ - Telemetry::MOZ_SQLITE_ ## HGRAM ## _WRITE_B, \ - Telemetry::MOZ_SQLITE_ ## HGRAM ## _READ_MS, \ - Telemetry::MOZ_SQLITE_ ## HGRAM ## _WRITE_MS, \ - Telemetry::MOZ_SQLITE_ ## HGRAM ## _SYNC_MS \ - } - -Histograms gHistograms[] = { - SQLITE_TELEMETRY("places.sqlite", PLACES), - SQLITE_TELEMETRY("cookies.sqlite", COOKIES), - SQLITE_TELEMETRY("webappsstore.sqlite", WEBAPPS), - SQLITE_TELEMETRY(NULL, OTHER) -}; -#undef SQLITE_TELEMETRY - -/** RAII class for measuring how long io takes on/off main thread - */ -class IOThreadAutoTimer { -public: - /** - * IOThreadAutoTimer measures time spent in IO. Additionally it - * automatically determines whether IO is happening on the main - * thread and picks an appropriate histogram. - * - * @param id takes a telemetry histogram id. The id+1 must be an - * equivalent histogram for the main thread. Eg, MOZ_SQLITE_OPEN_MS - * is followed by MOZ_SQLITE_OPEN_MAIN_THREAD_MS. - */ - IOThreadAutoTimer(Telemetry::ID id) - : start(TimeStamp::Now()), - id(id) - { - } - - ~IOThreadAutoTimer() { - uint32_t mainThread = NS_IsMainThread() ? 1 : 0; - Telemetry::AccumulateTimeDelta(static_cast(id + mainThread), - start); - } - -private: - const TimeStamp start; - const Telemetry::ID id; -}; - -struct telemetry_file { - // Base class. Must be first - sqlite3_file base; - - // histograms pertaining to this file - Histograms *histograms; - - // quota object for this file - nsRefPtr quotaObject; - - // This contains the vfs that actually does work - sqlite3_file pReal[1]; -}; - -/* -** Close a telemetry_file. -*/ -int -xClose(sqlite3_file *pFile) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xClose(p->pReal); - if( rc==SQLITE_OK ){ - delete p->base.pMethods; - p->base.pMethods = NULL; - p->quotaObject = nullptr; - } - return rc; -} - -/* -** Read data from a telemetry_file. -*/ -int -xRead(sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst) -{ - telemetry_file *p = (telemetry_file *)pFile; - IOThreadAutoTimer ioTimer(p->histograms->readMS); - int rc; - rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); - // sqlite likes to read from empty files, this is normal, ignore it. - if (rc != SQLITE_IOERR_SHORT_READ) - Telemetry::Accumulate(p->histograms->readB, rc == SQLITE_OK ? iAmt : 0); - return rc; -} - -/* -** Write data to a telemetry_file. -*/ -int -xWrite(sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst) -{ - telemetry_file *p = (telemetry_file *)pFile; - if (p->quotaObject && !p->quotaObject->MaybeAllocateMoreSpace(iOfst, iAmt)) { - return SQLITE_FULL; - } - IOThreadAutoTimer ioTimer(p->histograms->writeMS); - int rc; - rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); - Telemetry::Accumulate(p->histograms->writeB, rc == SQLITE_OK ? iAmt : 0); - return rc; -} - -/* -** Truncate a telemetry_file. -*/ -int -xTruncate(sqlite3_file *pFile, sqlite_int64 size) -{ - IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_TRUNCATE_MS); - telemetry_file *p = (telemetry_file *)pFile; - int rc; - Telemetry::AutoTimer timer; - rc = p->pReal->pMethods->xTruncate(p->pReal, size); - if (rc == SQLITE_OK && p->quotaObject) { - p->quotaObject->UpdateSize(size); - } - return rc; -} - -/* -** Sync a telemetry_file. -*/ -int -xSync(sqlite3_file *pFile, int flags) -{ - telemetry_file *p = (telemetry_file *)pFile; - IOThreadAutoTimer ioTimer(p->histograms->syncMS); - return p->pReal->pMethods->xSync(p->pReal, flags); -} - -/* -** Return the current file-size of a telemetry_file. -*/ -int -xFileSize(sqlite3_file *pFile, sqlite_int64 *pSize) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); - return rc; -} - -/* -** Lock a telemetry_file. -*/ -int -xLock(sqlite3_file *pFile, int eLock) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xLock(p->pReal, eLock); - return rc; -} - -/* -** Unlock a telemetry_file. -*/ -int -xUnlock(sqlite3_file *pFile, int eLock) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xUnlock(p->pReal, eLock); - return rc; -} - -/* -** Check if another file-handle holds a RESERVED lock on a telemetry_file. -*/ -int -xCheckReservedLock(sqlite3_file *pFile, int *pResOut) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); - return rc; -} - -/* -** File control method. For custom operations on a telemetry_file. -*/ -int -xFileControl(sqlite3_file *pFile, int op, void *pArg) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); - return rc; -} - -/* -** Return the sector-size in bytes for a telemetry_file. -*/ -int -xSectorSize(sqlite3_file *pFile) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xSectorSize(p->pReal); - return rc; -} - -/* -** Return the device characteristic flags supported by a telemetry_file. -*/ -int -xDeviceCharacteristics(sqlite3_file *pFile) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal); - return rc; -} - -/* -** Shared-memory operations. -*/ -int -xShmLock(sqlite3_file *pFile, int ofst, int n, int flags) -{ - telemetry_file *p = (telemetry_file *)pFile; - return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); -} - -int -xShmMap(sqlite3_file *pFile, int iRegion, int szRegion, int isWrite, void volatile **pp) -{ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); - return rc; -} - -void -xShmBarrier(sqlite3_file *pFile){ - telemetry_file *p = (telemetry_file *)pFile; - p->pReal->pMethods->xShmBarrier(p->pReal); -} - -int -xShmUnmap(sqlite3_file *pFile, int delFlag){ - telemetry_file *p = (telemetry_file *)pFile; - int rc; - rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); - return rc; -} - -int -xOpen(sqlite3_vfs* vfs, const char *zName, sqlite3_file* pFile, - int flags, int *pOutFlags) -{ - IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_OPEN_MS); - Telemetry::AutoTimer timer; - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - int rc; - telemetry_file *p = (telemetry_file *)pFile; - Histograms *h = NULL; - // check if the filename is one we are probing for - for(size_t i = 0;i < sizeof(gHistograms)/sizeof(gHistograms[0]);i++) { - h = &gHistograms[i]; - // last probe is the fallback probe - if (!h->name) - break; - if (!zName) - continue; - const char *match = strstr(zName, h->name); - if (!match) - continue; - char c = match[strlen(h->name)]; - // include -wal/-journal too - if (!c || c == '-') - break; - } - p->histograms = h; - - const char* origin; - if ((flags & SQLITE_OPEN_URI) && - (origin = sqlite3_uri_parameter(zName, "origin"))) { - QuotaManager* quotaManager = QuotaManager::Get(); - MOZ_ASSERT(quotaManager); - - p->quotaObject = quotaManager->GetQuotaObject(nsDependentCString(origin), - NS_ConvertUTF8toUTF16(zName)); - - } - - rc = orig_vfs->xOpen(orig_vfs, zName, p->pReal, flags, pOutFlags); - if( rc != SQLITE_OK ) - return rc; - if( p->pReal->pMethods ){ - sqlite3_io_methods *pNew = new sqlite3_io_methods; - const sqlite3_io_methods *pSub = p->pReal->pMethods; - memset(pNew, 0, sizeof(*pNew)); - pNew->iVersion = pSub->iVersion; - pNew->xClose = xClose; - pNew->xRead = xRead; - pNew->xWrite = xWrite; - pNew->xTruncate = xTruncate; - pNew->xSync = xSync; - pNew->xFileSize = xFileSize; - pNew->xLock = xLock; - pNew->xUnlock = xUnlock; - pNew->xCheckReservedLock = xCheckReservedLock; - pNew->xFileControl = xFileControl; - pNew->xSectorSize = xSectorSize; - pNew->xDeviceCharacteristics = xDeviceCharacteristics; - if( pNew->iVersion>=2 ){ - pNew->xShmMap = pSub->xShmMap ? xShmMap : 0; - pNew->xShmLock = pSub->xShmLock ? xShmLock : 0; - pNew->xShmBarrier = pSub->xShmBarrier ? xShmBarrier : 0; - pNew->xShmUnmap = pSub->xShmUnmap ? xShmUnmap : 0; - } - pFile->pMethods = pNew; - } - return rc; -} - -int -xDelete(sqlite3_vfs* vfs, const char *zName, int syncDir) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xDelete(orig_vfs, zName, syncDir); -} - -int -xAccess(sqlite3_vfs *vfs, const char *zName, int flags, int *pResOut) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xAccess(orig_vfs, zName, flags, pResOut); -} - -int -xFullPathname(sqlite3_vfs *vfs, const char *zName, int nOut, char *zOut) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xFullPathname(orig_vfs, zName, nOut, zOut); -} - -void* -xDlOpen(sqlite3_vfs *vfs, const char *zFilename) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xDlOpen(orig_vfs, zFilename); -} - -void -xDlError(sqlite3_vfs *vfs, int nByte, char *zErrMsg) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - orig_vfs->xDlError(orig_vfs, nByte, zErrMsg); -} - -void -(*xDlSym(sqlite3_vfs *vfs, void *pHdle, const char *zSym))(void){ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xDlSym(orig_vfs, pHdle, zSym); -} - -void -xDlClose(sqlite3_vfs *vfs, void *pHandle) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - orig_vfs->xDlClose(orig_vfs, pHandle); -} - -int -xRandomness(sqlite3_vfs *vfs, int nByte, char *zOut) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xRandomness(orig_vfs, nByte, zOut); -} - -int -xSleep(sqlite3_vfs *vfs, int microseconds) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xSleep(orig_vfs, microseconds); -} - -int -xCurrentTime(sqlite3_vfs *vfs, double *prNow) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xCurrentTime(orig_vfs, prNow); -} - -int -xGetLastError(sqlite3_vfs *vfs, int nBuf, char *zBuf) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xGetLastError(orig_vfs, nBuf, zBuf); -} - -int -xCurrentTimeInt64(sqlite3_vfs *vfs, sqlite3_int64 *piNow) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xCurrentTimeInt64(orig_vfs, piNow); -} - -static -int -xSetSystemCall(sqlite3_vfs *vfs, const char *zName, sqlite3_syscall_ptr pFunc) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xSetSystemCall(orig_vfs, zName, pFunc); -} - -static -sqlite3_syscall_ptr -xGetSystemCall(sqlite3_vfs *vfs, const char *zName) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xGetSystemCall(orig_vfs, zName); -} - -static -const char * -xNextSystemCall(sqlite3_vfs *vfs, const char *zName) -{ - sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); - return orig_vfs->xNextSystemCall(orig_vfs, zName); -} - -} - -namespace mozilla { -namespace storage { - -sqlite3_vfs* ConstructTelemetryVFS() -{ -#if defined(XP_WIN) -#define EXPECTED_VFS "win32" -#define EXPECTED_VFS_NFS "win32" -#else -#define EXPECTED_VFS "unix" -#define EXPECTED_VFS_NFS "unix-excl" -#endif - - bool expected_vfs; - sqlite3_vfs *vfs; - if (Preferences::GetBool(PREF_NFS_FILESYSTEM)) { - vfs = sqlite3_vfs_find(EXPECTED_VFS_NFS); - expected_vfs = (vfs != nullptr); - } - else { - vfs = sqlite3_vfs_find(NULL); - expected_vfs = vfs->zName && !strcmp(vfs->zName, EXPECTED_VFS); - } - if (!expected_vfs) { - return NULL; - } - - sqlite3_vfs *tvfs = new ::sqlite3_vfs; - memset(tvfs, 0, sizeof(::sqlite3_vfs)); - tvfs->iVersion = 3; - // If the SQLite VFS version is updated, this shim must be updated as well. - MOZ_ASSERT(vfs->iVersion == tvfs->iVersion); - tvfs->szOsFile = sizeof(telemetry_file) - sizeof(sqlite3_file) + vfs->szOsFile; - tvfs->mxPathname = vfs->mxPathname; - tvfs->zName = "telemetry-vfs"; - tvfs->pAppData = vfs; - tvfs->xOpen = xOpen; - tvfs->xDelete = xDelete; - tvfs->xAccess = xAccess; - tvfs->xFullPathname = xFullPathname; - tvfs->xDlOpen = xDlOpen; - tvfs->xDlError = xDlError; - tvfs->xDlSym = xDlSym; - tvfs->xDlClose = xDlClose; - tvfs->xRandomness = xRandomness; - tvfs->xSleep = xSleep; - tvfs->xCurrentTime = xCurrentTime; - tvfs->xGetLastError = xGetLastError; - // Added in version 2. - tvfs->xCurrentTimeInt64 = xCurrentTimeInt64; - // Added in version 3. - tvfs->xSetSystemCall = xSetSystemCall; - tvfs->xGetSystemCall = xGetSystemCall; - tvfs->xNextSystemCall = xNextSystemCall; - - return tvfs; -} - -} -} diff --git a/storage/src/mozStorageConnection.cpp b/storage/src/mozStorageConnection.cpp index da19f6e0154..14ca2d33e08 100644 --- a/storage/src/mozStorageConnection.cpp +++ b/storage/src/mozStorageConnection.cpp @@ -502,7 +502,7 @@ Connection::initialize(nsIFile *aDatabaseFile) NS_ENSURE_SUCCESS(rv, rv); int srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, - mFlags, NULL); + mFlags, mStorageService->getVFSName()); if (srv != SQLITE_OK) { mDBConn = nullptr; return convertResultCode(srv); @@ -531,7 +531,8 @@ Connection::initialize(nsIFileURL *aFileURL) rv = aFileURL->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); - int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, NULL); + int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, + mStorageService->getVFSName()); if (srv != SQLITE_OK) { mDBConn = nullptr; return convertResultCode(srv); diff --git a/storage/src/mozStorageService.cpp b/storage/src/mozStorageService.cpp index 51c06743563..23aaf9d2866 100644 --- a/storage/src/mozStorageService.cpp +++ b/storage/src/mozStorageService.cpp @@ -39,6 +39,25 @@ #define PREF_TS_SYNCHRONOUS "toolkit.storage.synchronous" #define PREF_TS_SYNCHRONOUS_DEFAULT 1 +/** + * This preference is a workaround to allow users/sysadmins to identify + * that the profile exists on an NFS share whose implementation is + * incompatible with SQLite's default locking implementation. Bug + * 433129 attempted to automatically identify such file-systems, but a + * reliable way was not found and it was determined that the fallback + * locking is slower than POSIX locking, so we do not want to do it by + * default. + */ +#define PREF_NFS_FILESYSTEM "storage.nfs_filesystem" + +#if defined(XP_WIN) +#define STANDARD_VFS "win32" +#define NFS_VFS "win32" +#else +#define STANDARD_VFS "unix" +#define NFS_VFS "unix-excl" +#endif + namespace mozilla { namespace storage { @@ -229,11 +248,13 @@ public: ServiceMainThreadInitializer(Service *aService, nsIObserver *aObserver, nsIXPConnect **aXPConnectPtr, - int32_t *aSynchronousPrefValPtr) + int32_t *aSynchronousPrefValPtr, + const char **aVFSNamePtr) : mService(aService) , mObserver(aObserver) , mXPConnectPtr(aXPConnectPtr) , mSynchronousPrefValPtr(aSynchronousPrefValPtr) + , mVFSNamePtr(aVFSNamePtr) { } @@ -268,6 +289,13 @@ public: Preferences::GetInt(PREF_TS_SYNCHRONOUS, PREF_TS_SYNCHRONOUS_DEFAULT); ::PR_ATOMIC_SET(mSynchronousPrefValPtr, synchronous); + // Likewise for whether we're on an NFS filesystem. + if (Preferences::GetBool(PREF_NFS_FILESYSTEM)) { + *mVFSNamePtr = NFS_VFS; + } else { + *mVFSNamePtr = STANDARD_VFS; + } + // Create and register our SQLite memory reporters. Registration can only // happen on the main thread (otherwise you'll get cryptic crashes). mService->mStorageSQLiteReporter = new NS_MEMORY_REPORTER_NAME(StorageSQLite); @@ -283,6 +311,7 @@ private: nsIObserver *mObserver; nsIXPConnect **mXPConnectPtr; int32_t *mSynchronousPrefValPtr; + const char **mVFSNamePtr; }; //////////////////////////////////////////////////////////////////////////////// @@ -359,9 +388,17 @@ Service::getSynchronousPref() return sSynchronousPref; } +const char *Service::sVFSName; + +// static +const char * +Service::getVFSName() +{ + return sVFSName; +} + Service::Service() : mMutex("Service::mMutex") -, mSqliteVFS(nullptr) , mRegistrationMutex("Service::mRegistrationMutex") , mConnections() , mStorageSQLiteReporter(nullptr) @@ -374,13 +411,9 @@ Service::~Service() (void)::NS_UnregisterMemoryReporter(mStorageSQLiteReporter); (void)::NS_UnregisterMemoryMultiReporter(mStorageSQLiteMultiReporter); - int rc = sqlite3_vfs_unregister(mSqliteVFS); - if (rc != SQLITE_OK) - NS_WARNING("Failed to unregister sqlite vfs wrapper."); - // Shutdown the sqlite3 API. Warn if shutdown did not turn out okay, but // there is nothing actionable we can do in that case. - rc = ::sqlite3_shutdown(); + int rc = ::sqlite3_shutdown(); if (rc != SQLITE_OK) NS_WARNING("sqlite3 did not shutdown cleanly."); @@ -388,8 +421,6 @@ Service::~Service() NS_ASSERTION(shutdownObserved, "Shutdown was not observed!"); gService = nullptr; - delete mSqliteVFS; - mSqliteVFS = nullptr; } void @@ -431,8 +462,6 @@ Service::shutdown() NS_IF_RELEASE(sXPConnect); } -sqlite3_vfs *ConstructTelemetryVFS(); - #ifdef MOZ_STORAGE_MEMORY # include "mozmemory.h" @@ -566,22 +595,14 @@ Service::initialize() if (rc != SQLITE_OK) return convertResultCode(rc); - mSqliteVFS = ConstructTelemetryVFS(); - if (mSqliteVFS) { - rc = sqlite3_vfs_register(mSqliteVFS, 1); - if (rc != SQLITE_OK) - return convertResultCode(rc); - } else { - NS_WARNING("Failed to register telemetry VFS"); - } - // Set the default value for the toolkit.storage.synchronous pref. It will be // updated with the user preference on the main thread. sSynchronousPref = PREF_TS_SYNCHRONOUS_DEFAULT; // Run the things that need to run on the main thread there. nsCOMPtr event = - new ServiceMainThreadInitializer(this, this, &sXPConnect, &sSynchronousPref); + new ServiceMainThreadInitializer(this, this, &sXPConnect, &sSynchronousPref, + &sVFSName); if (event && ::NS_IsMainThread()) { (void)event->Run(); } diff --git a/storage/src/mozStorageService.h b/storage/src/mozStorageService.h index 3f5a546695e..448abd5b705 100644 --- a/storage/src/mozStorageService.h +++ b/storage/src/mozStorageService.h @@ -19,7 +19,6 @@ class nsIMemoryReporter; class nsIMemoryMultiReporter; class nsIXPConnect; -struct sqlite3_vfs; namespace mozilla { namespace storage { @@ -68,6 +67,11 @@ public: */ static int32_t getSynchronousPref(); + /** + * Returns the name of the sqlite3 VFS to use for file-backed databases. + */ + static const char *getVFSName(); + /** * Registers the connection with the storage service. Connections are * registered so they can be iterated over. @@ -114,8 +118,6 @@ private: */ Mutex mMutex; - sqlite3_vfs *mSqliteVFS; - /** * Protects mConnections. */ @@ -161,6 +163,8 @@ private: static int32_t sSynchronousPref; + static const char *sVFSName; + friend class ServiceMainThreadInitializer; }; diff --git a/storage/test/unit/test_telemetry_vfs.js b/storage/test/unit/test_telemetry_vfs.js deleted file mode 100644 index b8c7ff87901..00000000000 --- a/storage/test/unit/test_telemetry_vfs.js +++ /dev/null @@ -1,30 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -// Make sure that there are telemetry entries created by sqlite io - -function run_sql(d, sql) { - var stmt = d.createStatement(sql) - stmt.execute() - stmt.finalize(); -} - -function new_file(name) -{ - var file = dirSvc.get("ProfD", Ci.nsIFile); - file.append(name); - return file; -} -function run_test() -{ - const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); - let read_hgram = Telemetry.getHistogramById("MOZ_SQLITE_OTHER_READ_B"); - let old_sum = read_hgram.snapshot().sum; - const file = new_file("telemetry.sqlite"); - var d = getDatabase(file); - run_sql(d, "CREATE TABLE bloat(data varchar)"); - run_sql(d, "DROP TABLE bloat") - do_check_true(read_hgram.snapshot().sum > old_sum) -} - diff --git a/storage/test/unit/xpcshell.ini b/storage/test/unit/xpcshell.ini index fa996642b22..4f9b05498b9 100644 --- a/storage/test/unit/xpcshell.ini +++ b/storage/test/unit/xpcshell.ini @@ -31,6 +31,5 @@ fail-if = os == "android" [test_storage_value_array.js] [test_unicode.js] [test_vacuum.js] -[test_telemetry_vfs.js] # Bug 676981: test fails consistently on Android # fail-if = os == "android" From bf2034ca46ab911762220e209b4a3d457dfea109 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Tue, 29 Jan 2013 15:04:20 -0500 Subject: [PATCH 02/70] Bug 796388 - part 2 - delete MOZ_SQLITE histogram definitions; r=taras --- toolkit/components/telemetry/Histograms.json | 216 ------------------- 1 file changed, 216 deletions(-) diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 5e817acb8bc..7323c406e7f 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -1478,222 +1478,6 @@ "n_buckets": 20, "description": "Time spent shutting down plugins (ms)" }, - "MOZ_SQLITE_OPEN_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite open() (ms)" - }, - "MOZ_SQLITE_OPEN_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite open() (ms)" - }, - "MOZ_SQLITE_TRUNCATE_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite truncate() (ms)" - }, - "MOZ_SQLITE_TRUNCATE_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite truncate() (ms)" - }, - "MOZ_SQLITE_OTHER_READ_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_OTHER_READ_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_PLACES_READ_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_PLACES_READ_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_COOKIES_READ_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_COOKIES_READ_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_WEBAPPS_READ_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_WEBAPPS_READ_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite read() (ms)" - }, - "MOZ_SQLITE_OTHER_WRITE_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_OTHER_WRITE_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_PLACES_WRITE_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_PLACES_WRITE_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_COOKIES_WRITE_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_COOKIES_WRITE_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_WEBAPPS_WRITE_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_WEBAPPS_WRITE_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite write() (ms)" - }, - "MOZ_SQLITE_OTHER_SYNC_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_OTHER_SYNC_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_PLACES_SYNC_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_PLACES_SYNC_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_COOKIES_SYNC_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_COOKIES_SYNC_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_WEBAPPS_SYNC_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_WEBAPPS_SYNC_MAIN_THREAD_MS": { - "kind": "exponential", - "high": "3000", - "n_buckets": 10, - "description": "Time spent on SQLite fsync() (ms)" - }, - "MOZ_SQLITE_OTHER_READ_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite read() (bytes)" - }, - "MOZ_SQLITE_PLACES_READ_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite read() (bytes)" - }, - "MOZ_SQLITE_COOKIES_READ_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite read() (bytes)" - }, - "MOZ_SQLITE_WEBAPPS_READ_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite read() (bytes)" - }, - "MOZ_SQLITE_PLACES_WRITE_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite write (bytes)" - }, - "MOZ_SQLITE_COOKIES_WRITE_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite write (bytes)" - }, - "MOZ_SQLITE_WEBAPPS_WRITE_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite write (bytes)" - }, - "MOZ_SQLITE_OTHER_WRITE_B": { - "kind": "linear", - "high": "32768", - "n_buckets": 3, - "description": "SQLite write (bytes)" - }, "MOZ_STORAGE_ASYNC_REQUESTS_MS": { "kind": "exponential", "high": "32768", From 0e1d434873398db0116d6a8c213eaa3a7c0fa5db Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Tue, 29 Jan 2013 11:55:09 -0500 Subject: [PATCH 03/70] Bug 818670: Enable AEC in PeerConnection, AGC/NoiseSuppression in gUM (w/bustage fix) r=derf --- content/media/webrtc/MediaEngine.h | 5 ++ content/media/webrtc/MediaEngineDefault.h | 6 ++ content/media/webrtc/MediaEngineWebRTC.h | 18 ++++++ .../media/webrtc/MediaEngineWebRTCAudio.cpp | 64 +++++++++++++++++++ dom/media/MediaManager.cpp | 29 +++++++++ dom/media/MediaManager.h | 21 ++++++ media/mtransport/build/Makefile.in | 1 + .../src/media-conduit/AudioConduit.cpp | 47 +++++++++++++- .../src/media-conduit/AudioConduit.h | 14 +++- media/webrtc/webrtc_config.gypi | 5 ++ modules/libpref/src/init/all.js | 9 +++ 11 files changed, 216 insertions(+), 3 deletions(-) diff --git a/content/media/webrtc/MediaEngine.h b/content/media/webrtc/MediaEngine.h index ce66ba11aa0..f4c7eed3783 100644 --- a/content/media/webrtc/MediaEngine.h +++ b/content/media/webrtc/MediaEngine.h @@ -89,6 +89,11 @@ public: /* Stop the device and release the corresponding MediaStream */ virtual nsresult Stop(SourceMediaStream *aSource, TrackID aID) = 0; + /* Change device configuration. */ + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) = 0; + /* Return false if device is currently allocated or started */ bool IsAvailable() { if (mState == kAllocated || mState == kStarted) { diff --git a/content/media/webrtc/MediaEngineDefault.h b/content/media/webrtc/MediaEngineDefault.h index e34b7b1b95d..bd1149adf4e 100644 --- a/content/media/webrtc/MediaEngineDefault.h +++ b/content/media/webrtc/MediaEngineDefault.h @@ -44,6 +44,9 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) { return NS_OK; }; virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime); virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, @@ -86,6 +89,9 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) { return NS_OK; }; virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime); virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, diff --git a/content/media/webrtc/MediaEngineWebRTC.h b/content/media/webrtc/MediaEngineWebRTC.h index 34ac056a078..8f553befec1 100644 --- a/content/media/webrtc/MediaEngineWebRTC.h +++ b/content/media/webrtc/MediaEngineWebRTC.h @@ -35,6 +35,7 @@ #include "voice_engine/include/voe_audio_processing.h" #include "voice_engine/include/voe_volume_control.h" #include "voice_engine/include/voe_external_media.h" +#include "voice_engine/include/voe_audio_processing.h" // Video Engine #include "video_engine/include/vie_base.h" @@ -90,6 +91,9 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) { return NS_OK; }; virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aId, @@ -177,6 +181,10 @@ public: , mCapIndex(aIndex) , mChannel(-1) , mInitDone(false) + , mEchoOn(false), mAgcOn(false), mNoiseOn(false) + , mEchoCancel(webrtc::kEcDefault) + , mAGC(webrtc::kAgcDefault) + , mNoiseSuppress(webrtc::kNsDefault) , mNullTransport(nullptr) { MOZ_ASSERT(aVoiceEnginePtr); mState = kReleased; @@ -194,6 +202,10 @@ public: virtual nsresult Start(SourceMediaStream*, TrackID); virtual nsresult Stop(SourceMediaStream*, TrackID); virtual nsresult Snapshot(uint32_t aDuration, nsIDOMFile** aFile); + virtual nsresult Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise); + virtual void NotifyPull(MediaStreamGraph* aGraph, SourceMediaStream *aSource, TrackID aId, @@ -218,6 +230,7 @@ private: webrtc::VoEBase* mVoEBase; webrtc::VoEExternalMedia* mVoERender; webrtc::VoENetwork* mVoENetwork; + webrtc::VoEAudioProcessing *mVoEProcessing; // mMonitor protects mSources[] access/changes, and transitions of mState // from kStarted to kStopped (which are combined with EndTrack()). @@ -233,6 +246,11 @@ private: nsString mDeviceName; nsString mDeviceUUID; + bool mEchoOn, mAgcOn, mNoiseOn; + webrtc::EcModes mEchoCancel; + webrtc::AgcModes mAGC; + webrtc::NsModes mNoiseSuppress; + NullTransport *mNullTransport; }; diff --git a/content/media/webrtc/MediaEngineWebRTCAudio.cpp b/content/media/webrtc/MediaEngineWebRTCAudio.cpp index 85981ca6da2..4da1e2af56a 100644 --- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp +++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -46,6 +46,60 @@ MediaEngineWebRTCAudioSource::GetUUID(nsAString& aUUID) return; } +nsresult +MediaEngineWebRTCAudioSource::Config(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) +{ + LOG(("Audio config: aec: %d, agc: %d, noise: %d", + aEchoOn ? aEcho : -1, + aAgcOn ? aAGC : -1, + aNoiseOn ? aNoise : -1)); + + bool update_agc = (mAgcOn == aAgcOn); + bool update_noise = (mNoiseOn == aNoiseOn); + mAgcOn = aAgcOn; + mNoiseOn = aNoiseOn; + + if ((webrtc::AgcModes) aAGC != webrtc::kAgcUnchanged) { + if (mAGC != (webrtc::AgcModes) aAGC) { + update_agc = true; + mAGC = (webrtc::AgcModes) aAGC; + } + } + if ((webrtc::NsModes) aNoise != webrtc::kNsUnchanged) { + if (mNoiseSuppress != (webrtc::NsModes) aNoise) { + update_noise = true; + mNoiseSuppress = (webrtc::NsModes) aNoise; + } + } + + if (mInitDone) { + int error; +#if 0 + // Until we can support feeding our full output audio from the browser + // through the MediaStream, this won't work. Or we need to move AEC to + // below audio input and output, perhaps invoked from here. + mEchoOn = aEchoOn; + if ((webrtc::EcModes) aEcho != webrtc::kEcUnchanged) + mEchoCancel = (webrtc::EcModes) aEcho; + mVoEProcessing->SetEcStatus(mEchoOn, aEcho); +#else + (void) aEcho; (void) aEchoOn; // suppress warnings +#endif + + if (update_agc && + 0 != (error = mVoEProcessing->SetAgcStatus(mAgcOn, (webrtc::AgcModes) aAGC))) { + LOG(("%s Error setting AGC Status: %d ",__FUNCTION__, error)); + } + if (update_noise && + 0 != (error = mVoEProcessing->SetNsStatus(mNoiseOn, (webrtc::NsModes) aNoise))) { + LOG(("%s Error setting NoiseSuppression Status: %d ",__FUNCTION__, error)); + } + } + return NS_OK; +} + nsresult MediaEngineWebRTCAudioSource::Allocate() { @@ -106,6 +160,11 @@ MediaEngineWebRTCAudioSource::Start(SourceMediaStream* aStream, TrackID aID) } mState = kStarted; + // Configure audio processing in webrtc code + Config(mEchoOn, webrtc::kEcUnchanged, + mAgcOn, webrtc::kAgcUnchanged, + mNoiseOn, webrtc::kNsUnchanged); + if (mVoEBase->StartReceive(mChannel)) { return NS_ERROR_FAILURE; } @@ -192,6 +251,11 @@ MediaEngineWebRTCAudioSource::Init() return; } + mVoEProcessing = webrtc::VoEAudioProcessing::GetInterface(mVoiceEngine); + if (!mVoEProcessing) { + return; + } + mChannel = mVoEBase->CreateChannel(); if (mChannel < 0) { return; diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 97a6c1eeed0..e85d1dfe970 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -11,6 +11,8 @@ #include "nsIScriptGlobalObject.h" #include "nsIPopupWindowManager.h" #include "nsISupportsArray.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" // For PR_snprintf #include "prprf.h" @@ -382,6 +384,33 @@ public: mAudioSource, mVideoSource, false)); mediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); +#ifdef MOZ_WEBRTC + // Right now these configs are only of use if webrtc is available + nsresult rv; + nsCOMPtr prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr branch = do_QueryInterface(prefs); + + if (branch) { + int32_t aec = (int32_t) webrtc::kEcUnchanged; + int32_t agc = (int32_t) webrtc::kAgcUnchanged; + int32_t noise = (int32_t) webrtc::kNsUnchanged; + bool aec_on = false, agc_on = false, noise_on = false; + + branch->GetBoolPref("media.peerconnection.aec_enabled", &aec_on); + branch->GetIntPref("media.peerconnection.aec", &aec); + branch->GetBoolPref("media.peerconnection.agc_enabled", &agc_on); + branch->GetIntPref("media.peerconnection.agc", &agc); + branch->GetBoolPref("media.peerconnection.noise_enabled", &noise_on); + branch->GetIntPref("media.peerconnection.noise", &noise); + + mListener->AudioConfig(aec_on, (uint32_t) aec, + agc_on, (uint32_t) agc, + noise_on, (uint32_t) noise); + } + } +#endif + // We're in the main thread, so no worries here either. nsCOMPtr success(mSuccess); nsCOMPtr error(mError); diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index fc1263d8a25..74795b02f3b 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -21,6 +21,10 @@ #include "mozilla/StaticPtr.h" #include "prlog.h" +#ifdef MOZ_WEBRTC +#include "mtransport/runnable_utils.h" +#endif + namespace mozilla { #ifdef PR_LOGGING @@ -128,6 +132,23 @@ public: // Can be invoked from EITHER MainThread or MSG thread void Invalidate(); + void + AudioConfig(bool aEchoOn, uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise) + { + if (mAudioSource) { +#ifdef MOZ_WEBRTC + // Right now these configs are only of use if webrtc is available + RUN_ON_THREAD(mMediaThread, + WrapRunnable(nsRefPtr(mAudioSource), // threadsafe + &MediaEngineSource::Config, + aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn, aNoise), + NS_DISPATCH_NORMAL); +#endif + } + } + void Remove() { diff --git a/media/mtransport/build/Makefile.in b/media/mtransport/build/Makefile.in index 7eb850b5894..ca9d1ad28e7 100644 --- a/media/mtransport/build/Makefile.in +++ b/media/mtransport/build/Makefile.in @@ -37,6 +37,7 @@ EXPORTS_mtransport = \ ../transportlayerprsock.h \ ../m_cpp_utils.h \ ../runnable_utils.h \ + ../runnable_utils_generated.h \ ../sigslot.h \ $(NULL) diff --git a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp index 8434363e12f..af29c6e11cb 100644 --- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp +++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp @@ -3,6 +3,12 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AudioConduit.h" +#include "nsCOMPtr.h" +#include "mozilla/Services.h" +#include "nsServiceManagerUtils.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" + #include "CSFLog.h" #include "voice_engine/include/voe_errors.h" @@ -51,6 +57,11 @@ WebrtcAudioConduit::~WebrtcAudioConduit() mPtrVoEXmedia->Release(); } + if(mPtrVoEProcessing) + { + mPtrVoEProcessing->Release(); + } + //Deal with the transport if(mPtrVoENetwork) { @@ -126,6 +137,12 @@ MediaConduitErrorCode WebrtcAudioConduit::Init() return kMediaConduitSessionNotInited; } + if(!(mPtrVoEProcessing = VoEAudioProcessing::GetInterface(mVoiceEngine))) + { + CSFLogError(logTag, "%s Unable to initialize VoEProcessing", __FUNCTION__); + return kMediaConduitSessionNotInited; + } + if(!(mPtrVoEXmedia = VoEExternalMedia::GetInterface(mVoiceEngine))) { CSFLogError(logTag, "%s Unable to initialize VoEExternalMedia", __FUNCTION__); @@ -235,6 +252,33 @@ WebrtcAudioConduit::ConfigureSendMediaCodec(const AudioCodecConfig* codecConfig) return kMediaConduitUnknownError; } + // TEMPORARY - see bug 694814 comment 2 + nsresult rv; + nsCOMPtr prefs = do_GetService("@mozilla.org/preferences-service;1", &rv); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr branch = do_QueryInterface(prefs); + + if (branch) { + int32_t aec = 0; // 0 == unchanged + bool aec_on = false; + + branch->GetBoolPref("media.peerconnection.aec_enabled", &aec_on); + branch->GetIntPref("media.peerconnection.aec", &aec); + + CSFLogDebug(logTag,"Audio config: aec: %d", aec_on ? aec : -1); + mEchoOn = aec_on; + if (static_cast(aec) != webrtc::kEcUnchanged) + mEchoCancel = static_cast(aec); + + branch->GetIntPref("media.peerconnection.capture_delay", &mCaptureDelay); + } + } + + if (0 != (error = mPtrVoEProcessing->SetEcStatus(mEchoOn, mEchoCancel))) { + CSFLogError(logTag,"%s Error setting EVStatus: %d ",__FUNCTION__, error); + return kMediaConduitUnknownError; + } + //Let's Send Transport State-machine on the Engine if(mPtrVoEBase->StartSend(mChannel) == -1) { @@ -404,7 +448,7 @@ WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[], return kMediaConduitSessionNotInited; } - + capture_delay = mCaptureDelay; //Insert the samples if(mPtrVoEXmedia->ExternalRecordingInsertData(audio_data, lengthSamples, @@ -748,4 +792,3 @@ WebrtcAudioConduit::DumpCodecDB() const } } }// end namespace - diff --git a/media/webrtc/signaling/src/media-conduit/AudioConduit.h b/media/webrtc/signaling/src/media-conduit/AudioConduit.h index 9b484f4b9a2..5e51d322998 100755 --- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h +++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h @@ -18,12 +18,14 @@ #include "voice_engine/include/voe_file.h" #include "voice_engine/include/voe_network.h" #include "voice_engine/include/voe_external_media.h" +#include "voice_engine/include/voe_audio_processing.h" //Some WebRTC types for short notations using webrtc::VoEBase; using webrtc::VoENetwork; using webrtc::VoECodec; using webrtc::VoEExternalMedia; + using webrtc::VoEAudioProcessing; /** This file hosts several structures identifying different aspects * of a RTP Session. @@ -146,7 +148,10 @@ public: mEngineTransmitting(false), mEngineReceiving(false), mChannel(-1), - mCurSendCodecConfig(NULL) + mCurSendCodecConfig(NULL), + mCaptureDelay(150), + mEchoOn(true), + mEchoCancel(webrtc::kEcAec) { } @@ -191,6 +196,7 @@ private: webrtc::VoEBase* mPtrVoEBase; webrtc::VoECodec* mPtrVoECodec; webrtc::VoEExternalMedia* mPtrVoEXmedia; + webrtc::VoEAudioProcessing* mPtrVoEProcessing; //engine states of our interets bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up @@ -200,6 +206,12 @@ private: int mChannel; RecvCodecList mRecvCodecList; AudioCodecConfig* mCurSendCodecConfig; + + // Current "capture" delay (really output plus input delay) + int32_t mCaptureDelay; + + bool mEchoOn; + webrtc::EcModes mEchoCancel; }; } // end namespace diff --git a/media/webrtc/webrtc_config.gypi b/media/webrtc/webrtc_config.gypi index b504d3d8c56..c7195fcfc02 100644 --- a/media/webrtc/webrtc_config.gypi +++ b/media/webrtc/webrtc_config.gypi @@ -3,6 +3,9 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # definitions to control what gets built in webrtc +# NOTE!!! if you change something here, due to .gyp files not +# being reprocessed on .gypi changes, run this before building: +# "find . -name '*.gyp' | xargs touch" { 'variables': { # basic stuff for everything @@ -13,6 +16,8 @@ 'include_tests': 0, 'use_system_libjpeg': 1, 'use_system_libvpx': 1, +# Creates AEC internal sample dump files in current directory +# 'aec_debug_dump': 1, # codec enable/disables: # Note: if you change one here, you must modify shared_libs.mk! diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 897300bcc08..69705b5634a 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -178,6 +178,15 @@ pref("media.gstreamer.enabled", true); pref("media.navigator.enabled", true); pref("media.peerconnection.enabled", false); pref("media.navigator.permission.disabled", false); +// These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h +// kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each +// setting (for Xxx = Ec, Agc, or Ns). Defaults are all set to kXxxDefault here. +pref("media.peerconnection.aec_enabled", true); +pref("media.peerconnection.aec", 1); +pref("media.peerconnection.agc_enabled", false); +pref("media.peerconnection.agc", 1); +pref("media.peerconnection.noise_enabled", false); +pref("media.peerconnection.noise", 1); #else #ifdef ANDROID pref("media.navigator.enabled", true); From aa033db95bea2924435d8912d3991386572ebcb6 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Tue, 29 Jan 2013 11:57:44 -0500 Subject: [PATCH 04/70] Bug 818670: merge AudioConduits to allow AEC to work r=ekr --- .../src/media-conduit/AudioConduit.cpp | 210 +++++++++++------- .../src/media-conduit/AudioConduit.h | 10 +- .../src/media-conduit/MediaConduitInterface.h | 2 +- .../signaling/src/media/VcmSIPCCBinding.cpp | 15 +- .../src/peerconnection/PeerConnectionMedia.h | 23 ++ .../signaling/test/mediaconduit_unittests.cpp | 4 +- .../signaling/test/mediapipeline_unittest.cpp | 2 +- 7 files changed, 181 insertions(+), 85 deletions(-) diff --git a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp index af29c6e11cb..f1a20e60dcc 100644 --- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp +++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp @@ -8,6 +8,7 @@ #include "nsServiceManagerUtils.h" #include "nsIPrefService.h" #include "nsIPrefBranch.h" +#include "nsThreadUtils.h" #include "CSFLog.h" #include "voice_engine/include/voe_errors.h" @@ -23,11 +24,13 @@ const unsigned int WebrtcAudioConduit::CODEC_PLNAME_SIZE = 32; /** * Factory Method for AudioConduit */ -mozilla::RefPtr AudioSessionConduit::Create() +mozilla::RefPtr AudioSessionConduit::Create(AudioSessionConduit *aOther) { CSFLogDebug(logTag, "%s ", __FUNCTION__); + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); + WebrtcAudioConduit* obj = new WebrtcAudioConduit(); - if(obj->Init() != kMediaConduitNoError) + if(obj->Init(static_cast(aOther)) != kMediaConduitNoError) { CSFLogError(logTag, "%s AudioConduit Init Failed ", __FUNCTION__); delete obj; @@ -42,6 +45,8 @@ mozilla::RefPtr AudioSessionConduit::Create() */ WebrtcAudioConduit::~WebrtcAudioConduit() { + NS_ASSERTION(NS_IsMainThread(), "Only call on main thread"); + CSFLogDebug(logTag, "%s ", __FUNCTION__); for(std::vector::size_type i=0;i < mRecvCodecList.size();i++) { @@ -50,10 +55,13 @@ WebrtcAudioConduit::~WebrtcAudioConduit() delete mCurSendCodecConfig; + // The first one of a pair to be deleted shuts down media for both if(mPtrVoEXmedia) { - mPtrVoEXmedia->SetExternalRecordingStatus(false); - mPtrVoEXmedia->SetExternalPlayoutStatus(false); + if (!mShutDown) { + mPtrVoEXmedia->SetExternalRecordingStatus(false); + mPtrVoEXmedia->SetExternalPlayoutStatus(false); + } mPtrVoEXmedia->Release(); } @@ -65,7 +73,9 @@ WebrtcAudioConduit::~WebrtcAudioConduit() //Deal with the transport if(mPtrVoENetwork) { - mPtrVoENetwork->DeRegisterExternalTransport(mChannel); + if (!mShutDown) { + mPtrVoENetwork->DeRegisterExternalTransport(mChannel); + } mPtrVoENetwork->Release(); } @@ -76,47 +86,69 @@ WebrtcAudioConduit::~WebrtcAudioConduit() if(mPtrVoEBase) { - mPtrVoEBase->StopPlayout(mChannel); - mPtrVoEBase->StopSend(mChannel); - mPtrVoEBase->StopReceive(mChannel); - mPtrVoEBase->DeleteChannel(mChannel); - mPtrVoEBase->Terminate(); + if (!mShutDown) { + mPtrVoEBase->StopPlayout(mChannel); + mPtrVoEBase->StopSend(mChannel); + mPtrVoEBase->StopReceive(mChannel); + mPtrVoEBase->DeleteChannel(mChannel); + mPtrVoEBase->Terminate(); + } mPtrVoEBase->Release(); } - if(mVoiceEngine) + if (mOtherDirection) { - webrtc::VoiceEngine::Delete(mVoiceEngine); + // mOtherDirection owns these now! + mOtherDirection->mOtherDirection = NULL; + // let other side we terminated the channel + mOtherDirection->mShutDown = true; + mVoiceEngine = nullptr; + } else { + // only one opener can call Delete. Have it be the last to close. + if(mVoiceEngine) + { + webrtc::VoiceEngine::Delete(mVoiceEngine); + } } } /* * WebRTCAudioConduit Implementation */ -MediaConduitErrorCode WebrtcAudioConduit::Init() +MediaConduitErrorCode WebrtcAudioConduit::Init(WebrtcAudioConduit *other) { - CSFLogDebug(logTag, "%s ", __FUNCTION__); + CSFLogDebug(logTag, "%s this=%p other=%p", __FUNCTION__, this, other); - //Per WebRTC APIs below function calls return NULL on failure - if(!(mVoiceEngine = webrtc::VoiceEngine::Create())) - { - CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__); - return kMediaConduitSessionNotInited; - } + if (other) { + MOZ_ASSERT(!other->mOtherDirection); + other->mOtherDirection = this; + mOtherDirection = other; - PRLogModuleInfo *logs = GetWebRTCLogInfo(); - if (!gWebrtcTraceLoggingOn && logs && logs->level > 0) { - // no need to a critical section or lock here - gWebrtcTraceLoggingOn = 1; - - const char *file = PR_GetEnv("WEBRTC_TRACE_FILE"); - if (!file) { - file = "WebRTC.log"; + // only one can call ::Create()/GetVoiceEngine() + MOZ_ASSERT(other->mVoiceEngine); + mVoiceEngine = other->mVoiceEngine; + } else { + //Per WebRTC APIs below function calls return NULL on failure + if(!(mVoiceEngine = webrtc::VoiceEngine::Create())) + { + CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__); + return kMediaConduitSessionNotInited; + } + + PRLogModuleInfo *logs = GetWebRTCLogInfo(); + if (!gWebrtcTraceLoggingOn && logs && logs->level > 0) { + // no need to a critical section or lock here + gWebrtcTraceLoggingOn = 1; + + const char *file = PR_GetEnv("WEBRTC_TRACE_FILE"); + if (!file) { + file = "WebRTC.log"; + } + CSFLogDebug(logTag, "%s Logging webrtc to %s level %d", __FUNCTION__, + file, logs->level); + mVoiceEngine->SetTraceFilter(logs->level); + mVoiceEngine->SetTraceFile(file); } - CSFLogDebug(logTag, "%s Logging webrtc to %s level %d", __FUNCTION__, - file, logs->level); - mVoiceEngine->SetTraceFilter(logs->level); - mVoiceEngine->SetTraceFile(file); } if(!(mPtrVoEBase = VoEBase::GetInterface(mVoiceEngine))) @@ -149,45 +181,48 @@ MediaConduitErrorCode WebrtcAudioConduit::Init() return kMediaConduitSessionNotInited; } - // init the engine with our audio device layer - if(mPtrVoEBase->Init() == -1) - { - CSFLogError(logTag, "%s VoiceEngine Base Not Initialized", __FUNCTION__); - return kMediaConduitSessionNotInited; - } + if (other) { + mChannel = other->mChannel; + } else { + // init the engine with our audio device layer + if(mPtrVoEBase->Init() == -1) + { + CSFLogError(logTag, "%s VoiceEngine Base Not Initialized", __FUNCTION__); + return kMediaConduitSessionNotInited; + } - if( (mChannel = mPtrVoEBase->CreateChannel()) == -1) - { - CSFLogError(logTag, "%s VoiceEngine Channel creation failed",__FUNCTION__); - return kMediaConduitChannelError; - } + if( (mChannel = mPtrVoEBase->CreateChannel()) == -1) + { + CSFLogError(logTag, "%s VoiceEngine Channel creation failed",__FUNCTION__); + return kMediaConduitChannelError; + } - CSFLogDebug(logTag, "%s Channel Created %d ",__FUNCTION__, mChannel); + CSFLogDebug(logTag, "%s Channel Created %d ",__FUNCTION__, mChannel); - if(mPtrVoENetwork->RegisterExternalTransport(mChannel, *this) == -1) - { - CSFLogError(logTag, "%s VoiceEngine, External Transport Failed",__FUNCTION__); - return kMediaConduitTransportRegistrationFail; - } + if(mPtrVoENetwork->RegisterExternalTransport(mChannel, *this) == -1) + { + CSFLogError(logTag, "%s VoiceEngine, External Transport Failed",__FUNCTION__); + return kMediaConduitTransportRegistrationFail; + } - if(mPtrVoEXmedia->SetExternalRecordingStatus(true) == -1) - { - CSFLogError(logTag, "%s SetExternalRecordingStatus Failed %d",__FUNCTION__, - mPtrVoEBase->LastError()); - return kMediaConduitExternalPlayoutError; - } + if(mPtrVoEXmedia->SetExternalRecordingStatus(true) == -1) + { + CSFLogError(logTag, "%s SetExternalRecordingStatus Failed %d",__FUNCTION__, + mPtrVoEBase->LastError()); + return kMediaConduitExternalPlayoutError; + } - if(mPtrVoEXmedia->SetExternalPlayoutStatus(true) == -1) - { - CSFLogError(logTag, "%s SetExternalPlayoutStatus Failed %d ",__FUNCTION__, - mPtrVoEBase->LastError()); - return kMediaConduitExternalRecordingError; + if(mPtrVoEXmedia->SetExternalPlayoutStatus(true) == -1) + { + CSFLogError(logTag, "%s SetExternalPlayoutStatus Failed %d ",__FUNCTION__, + mPtrVoEBase->LastError()); + return kMediaConduitExternalRecordingError; + } + CSFLogDebug(logTag , "%s AudioSessionConduit Initialization Done (%p)",__FUNCTION__, this); } - CSFLogDebug(logTag , "%s AudioSessionConduit Initialization Done",__FUNCTION__); return kMediaConduitNoError; } - // AudioSessionConduit Implementation MediaConduitErrorCode WebrtcAudioConduit::AttachTransport(mozilla::RefPtr aTransport) @@ -588,34 +623,53 @@ WebrtcAudioConduit::ReceivedRTCPPacket(const void *data, int len) int WebrtcAudioConduit::SendPacket(int channel, const void* data, int len) { - CSFLogDebug(logTag, "%s : channel %d",__FUNCTION__,channel); + CSFLogDebug(logTag, "%s : channel %d %s",__FUNCTION__,channel, + (mEngineReceiving && mOtherDirection) ? "(using mOtherDirection)" : ""); - if(mTransport && (mTransport->SendRtpPacket(data, len) == NS_OK)) - { + if (mEngineReceiving) + { + if (mOtherDirection) + { + return mOtherDirection->SendPacket(channel, data, len); + } + CSFLogDebug(logTag, "%s : Asked to send RTP without an RTP sender", + __FUNCTION__, channel); + return -1; + } else { + if(mTransport && (mTransport->SendRtpPacket(data, len) == NS_OK)) + { CSFLogDebug(logTag, "%s Sent RTP Packet ", __FUNCTION__); return len; - } else { - CSFLogError(logTag, "%s RTP Packet Send Failed ", __FUNCTION__); - return -1; - } - + } else { + CSFLogError(logTag, "%s RTP Packet Send Failed ", __FUNCTION__); + return -1; + } + } } int WebrtcAudioConduit::SendRTCPPacket(int channel, const void* data, int len) { CSFLogDebug(logTag, "%s : channel %d", __FUNCTION__, channel); - // can't enable this assertion, because we do. Suppress it - // NS_ASSERTION(mEngineReceiving,"We shouldn't send RTCP on the receiver side"); - if(mEngineReceiving && mTransport && mTransport->SendRtcpPacket(data, len) == NS_OK) + if (mEngineTransmitting) { - CSFLogDebug(logTag, "%s Sent RTCP Packet ", __FUNCTION__); - return len; - } else { - CSFLogError(logTag, "%s RTCP Packet Send Failed ", __FUNCTION__); + if (mOtherDirection) + { + return mOtherDirection->SendRTCPPacket(channel, data, len); + } + CSFLogDebug(logTag, "%s : Asked to send RTCP without an RTP receiver", + __FUNCTION__, channel); return -1; + } else { + if(mTransport && mTransport->SendRtcpPacket(data, len) == NS_OK) + { + CSFLogDebug(logTag, "%s Sent RTCP Packet ", __FUNCTION__); + return len; + } else { + CSFLogError(logTag, "%s RTCP Packet Send Failed ", __FUNCTION__); + return -1; + } } - } /** diff --git a/media/webrtc/signaling/src/media-conduit/AudioConduit.h b/media/webrtc/signaling/src/media-conduit/AudioConduit.h index 5e51d322998..7869b6fddfb 100755 --- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h +++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h @@ -143,6 +143,8 @@ public: WebrtcAudioConduit(): + mOtherDirection(NULL), + mShutDown(false), mVoiceEngine(NULL), mTransport(NULL), mEngineTransmitting(false), @@ -157,7 +159,7 @@ public: virtual ~WebrtcAudioConduit(); - MediaConduitErrorCode Init(); + MediaConduitErrorCode Init(WebrtcAudioConduit *other); private: WebrtcAudioConduit(const WebrtcAudioConduit& other) MOZ_DELETE; @@ -190,6 +192,12 @@ private: //Utility function to dump recv codec database void DumpCodecDB() const; + WebrtcAudioConduit* mOtherDirection; + // Other side has shut down our channel and related items already + bool mShutDown; + + // These are shared by both directions. They're released by the last + // conduit to die webrtc::VoiceEngine* mVoiceEngine; mozilla::RefPtr mTransport; webrtc::VoENetwork* mPtrVoENetwork; diff --git a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h index 7988f6b15dc..0f1437b577e 100755 --- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h +++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h @@ -226,7 +226,7 @@ public: * return: Concrete VideoSessionConduitObject or NULL in the case * of failure */ - static mozilla::RefPtr Create(); + static mozilla::RefPtr Create(AudioSessionConduit *aOther); virtual ~AudioSessionConduit() {} diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp index aa1bcdbbe62..2aaf579728c 100644 --- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp +++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp @@ -1303,12 +1303,18 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, if (CC_IS_AUDIO(mcap_id)) { std::vector configs; + // Instantiate an appropriate conduit + mozilla::RefPtr tx_conduit = + pc.impl()->media()->GetConduit(level, false); + mozilla::RefPtr conduit = - mozilla::AudioSessionConduit::Create(); + mozilla::AudioSessionConduit::Create(tx_conduit); if(!conduit) return VCM_ERROR; + pc.impl()->media()->AddConduit(level, true, conduit); + mozilla::AudioCodecConfig *config_raw; for(int i=0; i config(config_raw); // Instantiate an appropriate conduit + mozilla::RefPtr rx_conduit = + pc.impl()->media()->GetConduit(level, true); + mozilla::RefPtr conduit = - mozilla::AudioSessionConduit::Create(); + mozilla::AudioSessionConduit::Create(rx_conduit); if (!conduit || conduit->ConfigureSendMediaCodec(config)) return VCM_ERROR; + pc.impl()->media()->AddConduit(level, false, conduit); + mozilla::RefPtr pipeline = new mozilla::MediaPipelineTransmit( pc.impl()->GetHandle(), diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index cc5f776ebd0..26cd23ecbb7 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -293,9 +293,28 @@ class PeerConnectionMedia : public sigslot::has_slots<> { mozilla::RefPtr aFlow) { int index_inner = aIndex * 2 + (aRtcp ? 1 : 0); + MOZ_ASSERT(!mTransportFlows[index_inner]); mTransportFlows[index_inner] = aFlow; } + mozilla::RefPtr GetConduit(int aStreamIndex, bool aReceive) { + int index_inner = aStreamIndex * 2 + (aReceive ? 0 : 1); + + if (mAudioConduits.find(index_inner) == mAudioConduits.end()) + return NULL; + + return mAudioConduits[index_inner]; + } + + // Add a conduit + void AddConduit(int aIndex, bool aReceive, + const mozilla::RefPtr &aConduit) { + int index_inner = aIndex * 2 + (aReceive ? 0 : 1); + + MOZ_ASSERT(!mAudioConduits[index_inner]); + mAudioConduits[index_inner] = aConduit; + } + // ICE state signals sigslot::signal1 SignalIceGatheringCompleted; // Done gathering sigslot::signal1 SignalIceCompleted; // Done handshaking @@ -331,6 +350,10 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // Transport flows: even is RTP, odd is RTCP std::map > mTransportFlows; + // Conduits: even is receive, odd is transmit (for easier correlation with + // flows) + std::map > mAudioConduits; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia) }; diff --git a/media/webrtc/signaling/test/mediaconduit_unittests.cpp b/media/webrtc/signaling/test/mediaconduit_unittests.cpp index 318a0959a06..afde93e5325 100644 --- a/media/webrtc/signaling/test/mediaconduit_unittests.cpp +++ b/media/webrtc/signaling/test/mediaconduit_unittests.cpp @@ -490,11 +490,11 @@ class TransportConduitTest : public ::testing::Test { //get pointer to AudioSessionConduit int err=0; - mAudioSession = mozilla::AudioSessionConduit::Create(); + mAudioSession = mozilla::AudioSessionConduit::Create(NULL); if( !mAudioSession ) ASSERT_NE(mAudioSession, (void*)NULL); - mAudioSession2 = mozilla::AudioSessionConduit::Create(); + mAudioSession2 = mozilla::AudioSessionConduit::Create(NULL); if( !mAudioSession2 ) ASSERT_NE(mAudioSession2, (void*)NULL); diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 128423dd11d..27dccf05ac8 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -48,7 +48,7 @@ class TestAgent { audio_prsock_(new TransportLayerPrsock()), audio_dtls_(new TransportLayerDtls()), audio_config_(109, "opus", 48000, 480, 1, 64000), - audio_conduit_(mozilla::AudioSessionConduit::Create()), + audio_conduit_(mozilla::AudioSessionConduit::Create(NULL)), audio_(), audio_pipeline_(), video_flow_(new TransportFlow()), From e9d69c4af4930da11f07daf772289165a7fa18fb Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 29 Jan 2013 22:05:42 +0100 Subject: [PATCH 05/70] Bug 725587 - Firefox jumps randomly from IPv6 to IPv4 and vice versa in dual-stack environment, r=mcmanus --- netwerk/base/public/nsISocketTransport.idl | 6 +++ netwerk/base/src/nsSocketTransport2.cpp | 19 ++++--- netwerk/dns/nsDNSService2.cpp | 3 ++ netwerk/dns/nsIDNSService.idl | 5 ++ netwerk/protocol/http/nsHttpChannel.cpp | 4 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 52 +++++++++++++++++-- netwerk/protocol/http/nsHttpConnectionMgr.h | 17 ++++++ 7 files changed, 95 insertions(+), 11 deletions(-) diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index cf43807f5b8..0c8c585aadd 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -163,6 +163,12 @@ interface nsISocketTransport : nsITransport */ const unsigned long NO_PERMANENT_STORAGE = (1 << 3); + /** + * If set, we will skip all IPv4 addresses the host may have and only + * connect to IPv6 ones. + */ + const unsigned long DISABLE_IPV4 = (1 << 4); + /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 0396e75b99d..7dd872ad19c 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -926,6 +926,12 @@ nsSocketTransport::ResolveHost() dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; if (mConnectionFlags & nsSocketTransport::DISABLE_IPV6) dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6; + if (mConnectionFlags & nsSocketTransport::DISABLE_IPV4) + dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4; + + NS_ASSERTION(!(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) || + !(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4), + "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4"); SendStatus(NS_NET_STATUS_RESOLVING_HOST); rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nullptr, @@ -1267,12 +1273,12 @@ nsSocketTransport::RecoverFromError() bool tryAgain = false; - if (mConnectionFlags & DISABLE_IPV6 && + if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4) && mCondition == NS_ERROR_UNKNOWN_HOST && mState == STATE_RESOLVING && !mProxyTransparentResolvesHost) { SOCKET_LOG((" trying lookup again with both ipv4/ipv6 enabled\n")); - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } @@ -1285,14 +1291,15 @@ nsSocketTransport::RecoverFromError() SOCKET_LOG((" trying again with next ip address\n")); tryAgain = true; } - else if (mConnectionFlags & DISABLE_IPV6) { + else if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4)) { // Drop state to closed. This will trigger new round of DNS // resolving bellow. - // XXX Here should idealy be set now non-existing flag DISABLE_IPV4 - SOCKET_LOG((" failed to connect all ipv4 hosts," + // XXX Could be optimized to only switch the flags to save duplicate + // connection attempts. + SOCKET_LOG((" failed to connect all ipv4-only or ipv6-only hosts," " trying lookup/connect again with both ipv4/ipv6\n")); mState = STATE_CLOSED; - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } } diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index f1fe85b2460..05be514c72f 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -850,6 +850,9 @@ nsDNSService::GetAFForLookup(const nsACString &host, uint32_t flags) } while (*end); } + if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4)) + af = PR_AF_INET6; + return af; } diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index 6b06a194f83..183ca004422 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -134,4 +134,9 @@ interface nsIDNSService : nsISupports * asyncResolve. */ const unsigned long RESOLVE_OFFLINE = (1 << 6); + + /** + * If set, only IPv6 addresses will be returned from resolve/asyncResolve. + */ + const unsigned long RESOLVE_DISABLE_IPV4 = (1 << 7); }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 4eca5e109cd..d15af44d21e 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4484,8 +4484,10 @@ nsHttpChannel::BeginConnect() // Force-Reload should reset the persistent connection pool for this host if (mLoadFlags & LOAD_FRESH_CONNECTION) { // just the initial document resets the whole pool - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { gHttpHandler->ConnMgr()->ClosePersistentConnections(); + gHttpHandler->ConnMgr()->ResetIPFamillyPreference(mConnectionInfo); + } // each sub resource gets a fresh connection mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING); } diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index e079b15e6bd..4e6efd9e744 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -2521,8 +2521,13 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, // IPv6 on the backup connection gives them a much better user experience // with dual-stack hosts, though they still pay the 250ms delay for each new // connection. This strategy is also known as "happy eyeballs". - if (isBackup && gHttpHandler->FastFallbackToIPv4()) + if (mEnt->mPreferIPv6) { + tmpFlags |= nsISocketTransport::DISABLE_IPV4; + } + else if (mEnt->mPreferIPv4 || + (isBackup && gHttpHandler->FastFallbackToIPv4())) { tmpFlags |= nsISocketTransport::DISABLE_IPV6; + } socketTransport->SetConnectionFlags(tmpFlags); @@ -2714,6 +2719,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) LOG(("nsHalfOpenSocket::OnOutputStreamReady " "Created new nshttpconnection %p\n", conn.get())); + PRNetAddr peeraddr; nsCOMPtr callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks)); if (out == mStreamOut) { @@ -2724,6 +2730,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mStreamOut = nullptr; mStreamIn = nullptr; @@ -2737,6 +2746,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mBackupTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mBackupStreamOut = nullptr; mBackupStreamIn = nullptr; @@ -2949,6 +2961,8 @@ nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci) , mUsingSpdy(false) , mTestedSpdy(false) , mSpdyPreferred(false) + , mPreferIPv4(false) + , mPreferIPv6(false) { NS_ADDREF(mConnInfo); if (gHttpHandler->GetPipelineAggressive()) { @@ -3104,7 +3118,8 @@ nsConnectionEntry::SetYellowConnection(nsHttpConnection *conn) } void -nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() +nsHttpConnectionMgr:: +nsConnectionEntry::OnYellowComplete() { if (mPipelineState == PS_YELLOW) { if (mYellowGoodEvents && !mYellowBadEvents) { @@ -3127,7 +3142,8 @@ nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() } void -nsHttpConnectionMgr::nsConnectionEntry::CreditPenalty() +nsHttpConnectionMgr:: +nsConnectionEntry::CreditPenalty() { if (mLastCreditTime.IsNull()) return; @@ -3223,8 +3239,17 @@ nsHttpConnectionMgr::GetConnectionData(nsTArray *aA return true; } +void +nsHttpConnectionMgr::ResetIPFamillyPreference(nsHttpConnectionInfo *ci) +{ + nsConnectionEntry *ent = LookupConnectionEntry(ci, nullptr, nullptr); + if (ent) + ent->ResetIPFamilyPreference(); +} + uint32_t -nsHttpConnectionMgr::nsConnectionEntry::UnconnectedHalfOpens() +nsHttpConnectionMgr:: +nsConnectionEntry::UnconnectedHalfOpens() { uint32_t unconnectedHalfOpens = 0; for (uint32_t i = 0; i < mHalfOpens.Length(); ++i) { @@ -3250,3 +3275,22 @@ nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen) // altering the pending q vector from an arbitrary stack gHttpHandler->ConnMgr()->ProcessPendingQ(mConnInfo); } + +void +nsHttpConnectionMgr:: +nsConnectionEntry::RecordIPFamilyPreference(uint16_t family) +{ + if (family == PR_AF_INET && !mPreferIPv6) + mPreferIPv4 = true; + + if (family == PR_AF_INET6 && !mPreferIPv4) + mPreferIPv6 = true; +} + +void +nsHttpConnectionMgr:: +nsConnectionEntry::ResetIPFamilyPreference() +{ + mPreferIPv4 = false; + mPreferIPv6 = false; +} diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index a27b9598959..30d917bc6ea 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -225,6 +225,9 @@ public: bool SupportsPipelining(nsHttpConnectionInfo *); bool GetConnectionData(nsTArray *); + + void ResetIPFamillyPreference(nsHttpConnectionInfo *); + private: virtual ~nsHttpConnectionMgr(); @@ -343,6 +346,20 @@ private: bool mTestedSpdy; bool mSpdyPreferred; + + // Flags to remember our happy-eyeballs decision. + // Reset only by Ctrl-F5 reload. + // True when we've first connected an IPv4 server for this host, + // initially false. + bool mPreferIPv4 : 1; + // True when we've first connected an IPv6 server for this host, + // initially false. + bool mPreferIPv6 : 1; + + // Set the IP family preference flags according the connected family + void RecordIPFamilyPreference(uint16_t family); + // Resets all flags to their default values + void ResetIPFamilyPreference(); }; // nsConnectionHandle From f4075839690ccdbdc7b4dad123a7b0a40ddfa703 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 29 Jan 2013 22:05:43 +0100 Subject: [PATCH 06/70] Bug 794507 - make offline application cache store security info for entries, r=michal --- netwerk/cache/nsDiskCacheDeviceSQL.cpp | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/netwerk/cache/nsDiskCacheDeviceSQL.cpp b/netwerk/cache/nsDiskCacheDeviceSQL.cpp index a092a560076..88a1ff9bed3 100644 --- a/netwerk/cache/nsDiskCacheDeviceSQL.cpp +++ b/netwerk/cache/nsDiskCacheDeviceSQL.cpp @@ -26,6 +26,8 @@ #include "nsIArray.h" #include "nsIVariant.h" #include "nsThreadUtils.h" +#include "nsISerializable.h" +#include "nsSerializationHelper.h" #include "mozIStorageService.h" #include "mozIStorageStatement.h" @@ -476,6 +478,19 @@ CreateCacheEntry(nsOfflineCacheDevice *device, entry->UnflattenMetaData((const char *) rec.metaData, rec.metaDataLen); + // Restore security info, if present + const char* info = entry->GetMetaDataElement("security-info"); + if (info) { + nsCOMPtr infoObj; + rv = NS_DeserializeObject(nsDependentCString(info), + getter_AddRefs(infoObj)); + if (NS_FAILED(rv)) { + delete entry; + return nullptr; + } + entry->SetSecurityInfo(infoObj); + } + // create a binding object for this entry nsOfflineCacheBinding *binding = nsOfflineCacheBinding::Create(device->CacheDirectory(), @@ -918,6 +933,21 @@ nsOfflineCacheDevice::UpdateEntry(nsCacheEntry *entry) if (!DecomposeCacheEntryKey(entry->Key(), &cid, &key, keyBuf)) return NS_ERROR_UNEXPECTED; + // Store security info, if it is serializable + nsCOMPtr infoObj = entry->SecurityInfo(); + nsCOMPtr serializable = do_QueryInterface(infoObj); + if (infoObj && !serializable) + return NS_ERROR_UNEXPECTED; + + if (serializable) { + nsCString info; + nsresult rv = NS_SerializeToString(serializable, info); + NS_ENSURE_SUCCESS(rv, rv); + + rv = entry->SetMetaDataElement("security-info", info.get()); + NS_ENSURE_SUCCESS(rv, rv); + } + nsCString metaDataBuf; uint32_t mdSize = entry->MetaDataSize(); if (!EnsureStringLength(metaDataBuf, mdSize)) From de69ca40badee173fd57f20a7a0a5f4ac85932ca Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Tue, 29 Jan 2013 22:17:50 +0100 Subject: [PATCH 07/70] Bug 835877: Increase inline depth for small functions, r=dvander --- js/src/ion/Ion.h | 11 +++++++++++ js/src/ion/IonBuilder.cpp | 11 +++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/js/src/ion/Ion.h b/js/src/ion/Ion.h index 9a4299c7562..9ad6fb658b7 100644 --- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -112,6 +112,16 @@ struct IonOptions // Default: 3 uint32_t maxInlineDepth; + // The maximum inlining depth for functions. + // + // Inlining small functions has almost no compiling overhead + // and removes the otherwise needed call overhead. + // The value is currently very low. + // Actually it is only needed to make sure we don't blow out the stack. + // + // Default: 10 + uint32_t smallFunctionMaxInlineDepth; + // The bytecode length limit for small function. // // The default for this was arrived at empirically via benchmarking. @@ -191,6 +201,7 @@ struct IonOptions usesBeforeInlining(usesBeforeCompile), maxStackArgs(4096), maxInlineDepth(3), + smallFunctionMaxInlineDepth(10), smallFunctionMaxBytecodeLength(100), smallFunctionUsesBeforeInlining(usesBeforeInlining / 4), polyInlineMax(4), diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index 966d046272a..c528201c439 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -3097,9 +3097,6 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32_t argc) { AssertCanGC(); - if (inliningDepth >= js_IonOptions.maxInlineDepth) - return false; - // For "small" functions, we should be more aggressive about inlining. // This is based on the following intuition: // 1. The call overhead for a small function will likely be a much @@ -3115,6 +3112,7 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32_t argc) uint32_t totalSize = 0; uint32_t checkUses = js_IonOptions.usesBeforeInlining; + uint32_t maxInlineDepth = js_IonOptions.maxInlineDepth; bool allFunctionsAreSmall = true; RootedFunction target(cx); RootedScript targetScript(cx); @@ -3138,8 +3136,13 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets, uint32_t argc) return false; } } - if (allFunctionsAreSmall) + if (allFunctionsAreSmall) { checkUses = js_IonOptions.smallFunctionUsesBeforeInlining; + maxInlineDepth = js_IonOptions.smallFunctionMaxInlineDepth; + } + + if (inliningDepth >= maxInlineDepth) + return false; if (script()->getUseCount() < checkUses) { IonSpew(IonSpew_Inlining, "Not inlining, caller is not hot"); From 64ef77dfa48dc4530405a0fad5a3666cc050cd4f Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 29 Jan 2013 22:26:47 +0100 Subject: [PATCH 08/70] Backout of changeset 816f076c2c15 --- netwerk/base/public/nsISocketTransport.idl | 6 --- netwerk/base/src/nsSocketTransport2.cpp | 19 +++---- netwerk/dns/nsDNSService2.cpp | 3 -- netwerk/dns/nsIDNSService.idl | 5 -- netwerk/protocol/http/nsHttpChannel.cpp | 4 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 52 ++----------------- netwerk/protocol/http/nsHttpConnectionMgr.h | 17 ------ 7 files changed, 11 insertions(+), 95 deletions(-) diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index 0c8c585aadd..cf43807f5b8 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -163,12 +163,6 @@ interface nsISocketTransport : nsITransport */ const unsigned long NO_PERMANENT_STORAGE = (1 << 3); - /** - * If set, we will skip all IPv4 addresses the host may have and only - * connect to IPv6 ones. - */ - const unsigned long DISABLE_IPV4 = (1 << 4); - /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 7dd872ad19c..0396e75b99d 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -926,12 +926,6 @@ nsSocketTransport::ResolveHost() dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; if (mConnectionFlags & nsSocketTransport::DISABLE_IPV6) dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6; - if (mConnectionFlags & nsSocketTransport::DISABLE_IPV4) - dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4; - - NS_ASSERTION(!(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) || - !(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4), - "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4"); SendStatus(NS_NET_STATUS_RESOLVING_HOST); rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nullptr, @@ -1273,12 +1267,12 @@ nsSocketTransport::RecoverFromError() bool tryAgain = false; - if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4) && + if (mConnectionFlags & DISABLE_IPV6 && mCondition == NS_ERROR_UNKNOWN_HOST && mState == STATE_RESOLVING && !mProxyTransparentResolvesHost) { SOCKET_LOG((" trying lookup again with both ipv4/ipv6 enabled\n")); - mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); + mConnectionFlags &= ~DISABLE_IPV6; tryAgain = true; } @@ -1291,15 +1285,14 @@ nsSocketTransport::RecoverFromError() SOCKET_LOG((" trying again with next ip address\n")); tryAgain = true; } - else if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4)) { + else if (mConnectionFlags & DISABLE_IPV6) { // Drop state to closed. This will trigger new round of DNS // resolving bellow. - // XXX Could be optimized to only switch the flags to save duplicate - // connection attempts. - SOCKET_LOG((" failed to connect all ipv4-only or ipv6-only hosts," + // XXX Here should idealy be set now non-existing flag DISABLE_IPV4 + SOCKET_LOG((" failed to connect all ipv4 hosts," " trying lookup/connect again with both ipv4/ipv6\n")); mState = STATE_CLOSED; - mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); + mConnectionFlags &= ~DISABLE_IPV6; tryAgain = true; } } diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index 05be514c72f..f1fe85b2460 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -850,9 +850,6 @@ nsDNSService::GetAFForLookup(const nsACString &host, uint32_t flags) } while (*end); } - if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4)) - af = PR_AF_INET6; - return af; } diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index 183ca004422..6b06a194f83 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -134,9 +134,4 @@ interface nsIDNSService : nsISupports * asyncResolve. */ const unsigned long RESOLVE_OFFLINE = (1 << 6); - - /** - * If set, only IPv6 addresses will be returned from resolve/asyncResolve. - */ - const unsigned long RESOLVE_DISABLE_IPV4 = (1 << 7); }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index d15af44d21e..4eca5e109cd 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4484,10 +4484,8 @@ nsHttpChannel::BeginConnect() // Force-Reload should reset the persistent connection pool for this host if (mLoadFlags & LOAD_FRESH_CONNECTION) { // just the initial document resets the whole pool - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) gHttpHandler->ConnMgr()->ClosePersistentConnections(); - gHttpHandler->ConnMgr()->ResetIPFamillyPreference(mConnectionInfo); - } // each sub resource gets a fresh connection mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING); } diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 4e6efd9e744..e079b15e6bd 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -2521,13 +2521,8 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, // IPv6 on the backup connection gives them a much better user experience // with dual-stack hosts, though they still pay the 250ms delay for each new // connection. This strategy is also known as "happy eyeballs". - if (mEnt->mPreferIPv6) { - tmpFlags |= nsISocketTransport::DISABLE_IPV4; - } - else if (mEnt->mPreferIPv4 || - (isBackup && gHttpHandler->FastFallbackToIPv4())) { + if (isBackup && gHttpHandler->FastFallbackToIPv4()) tmpFlags |= nsISocketTransport::DISABLE_IPV6; - } socketTransport->SetConnectionFlags(tmpFlags); @@ -2719,7 +2714,6 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) LOG(("nsHalfOpenSocket::OnOutputStreamReady " "Created new nshttpconnection %p\n", conn.get())); - PRNetAddr peeraddr; nsCOMPtr callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks)); if (out == mStreamOut) { @@ -2730,9 +2724,6 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); - if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) - mEnt->RecordIPFamilyPreference(peeraddr.raw.family); - // The nsHttpConnection object now owns these streams and sockets mStreamOut = nullptr; mStreamIn = nullptr; @@ -2746,9 +2737,6 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); - if (NS_SUCCEEDED(mBackupTransport->GetPeerAddr(&peeraddr))) - mEnt->RecordIPFamilyPreference(peeraddr.raw.family); - // The nsHttpConnection object now owns these streams and sockets mBackupStreamOut = nullptr; mBackupStreamIn = nullptr; @@ -2961,8 +2949,6 @@ nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci) , mUsingSpdy(false) , mTestedSpdy(false) , mSpdyPreferred(false) - , mPreferIPv4(false) - , mPreferIPv6(false) { NS_ADDREF(mConnInfo); if (gHttpHandler->GetPipelineAggressive()) { @@ -3118,8 +3104,7 @@ nsConnectionEntry::SetYellowConnection(nsHttpConnection *conn) } void -nsHttpConnectionMgr:: -nsConnectionEntry::OnYellowComplete() +nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() { if (mPipelineState == PS_YELLOW) { if (mYellowGoodEvents && !mYellowBadEvents) { @@ -3142,8 +3127,7 @@ nsConnectionEntry::OnYellowComplete() } void -nsHttpConnectionMgr:: -nsConnectionEntry::CreditPenalty() +nsHttpConnectionMgr::nsConnectionEntry::CreditPenalty() { if (mLastCreditTime.IsNull()) return; @@ -3239,17 +3223,8 @@ nsHttpConnectionMgr::GetConnectionData(nsTArray *aA return true; } -void -nsHttpConnectionMgr::ResetIPFamillyPreference(nsHttpConnectionInfo *ci) -{ - nsConnectionEntry *ent = LookupConnectionEntry(ci, nullptr, nullptr); - if (ent) - ent->ResetIPFamilyPreference(); -} - uint32_t -nsHttpConnectionMgr:: -nsConnectionEntry::UnconnectedHalfOpens() +nsHttpConnectionMgr::nsConnectionEntry::UnconnectedHalfOpens() { uint32_t unconnectedHalfOpens = 0; for (uint32_t i = 0; i < mHalfOpens.Length(); ++i) { @@ -3275,22 +3250,3 @@ nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen) // altering the pending q vector from an arbitrary stack gHttpHandler->ConnMgr()->ProcessPendingQ(mConnInfo); } - -void -nsHttpConnectionMgr:: -nsConnectionEntry::RecordIPFamilyPreference(uint16_t family) -{ - if (family == PR_AF_INET && !mPreferIPv6) - mPreferIPv4 = true; - - if (family == PR_AF_INET6 && !mPreferIPv4) - mPreferIPv6 = true; -} - -void -nsHttpConnectionMgr:: -nsConnectionEntry::ResetIPFamilyPreference() -{ - mPreferIPv4 = false; - mPreferIPv6 = false; -} diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index 30d917bc6ea..a27b9598959 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -225,9 +225,6 @@ public: bool SupportsPipelining(nsHttpConnectionInfo *); bool GetConnectionData(nsTArray *); - - void ResetIPFamillyPreference(nsHttpConnectionInfo *); - private: virtual ~nsHttpConnectionMgr(); @@ -346,20 +343,6 @@ private: bool mTestedSpdy; bool mSpdyPreferred; - - // Flags to remember our happy-eyeballs decision. - // Reset only by Ctrl-F5 reload. - // True when we've first connected an IPv4 server for this host, - // initially false. - bool mPreferIPv4 : 1; - // True when we've first connected an IPv6 server for this host, - // initially false. - bool mPreferIPv6 : 1; - - // Set the IP family preference flags according the connected family - void RecordIPFamilyPreference(uint16_t family); - // Resets all flags to their default values - void ResetIPFamilyPreference(); }; // nsConnectionHandle From 96b55dfae9ef181ab7e2f76f5f98a87576c0339d Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 29 Jan 2013 16:38:37 -0500 Subject: [PATCH 09/70] Backed out changesets 50f4ba15a3c7 and cafa8ba33704 (bug 796388) for mochitest-2 orange. --- storage/src/Makefile.in | 1 + storage/src/TelemetryVFS.cpp | 531 +++++++++++++++++++ storage/src/mozStorageConnection.cpp | 5 +- storage/src/mozStorageService.cpp | 63 +-- storage/src/mozStorageService.h | 10 +- storage/test/unit/test_telemetry_vfs.js | 30 ++ storage/test/unit/xpcshell.ini | 1 + toolkit/components/telemetry/Histograms.json | 216 ++++++++ 8 files changed, 805 insertions(+), 52 deletions(-) create mode 100644 storage/src/TelemetryVFS.cpp create mode 100644 storage/test/unit/test_telemetry_vfs.js diff --git a/storage/src/Makefile.in b/storage/src/Makefile.in index 0c3b67172c6..50dd3c78285 100644 --- a/storage/src/Makefile.in +++ b/storage/src/Makefile.in @@ -63,6 +63,7 @@ CPPSRCS = \ StorageBaseStatementInternal.cpp \ SQLCollations.cpp \ VacuumManager.cpp \ + TelemetryVFS.cpp \ FileSystemModule.cpp \ $(NULL) diff --git a/storage/src/TelemetryVFS.cpp b/storage/src/TelemetryVFS.cpp new file mode 100644 index 00000000000..e4fce091f72 --- /dev/null +++ b/storage/src/TelemetryVFS.cpp @@ -0,0 +1,531 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include "mozilla/Telemetry.h" +#include "mozilla/Preferences.h" +#include "sqlite3.h" +#include "nsThreadUtils.h" +#include "mozilla/Util.h" +#include "mozilla/dom/quota/QuotaManager.h" + +/** + * This preference is a workaround to allow users/sysadmins to identify + * that the profile exists on an NFS share whose implementation + * is incompatible with SQLite's default locking implementation. + * Bug 433129 attempted to automatically identify such file-systems, + * but a reliable way was not found and it was determined that the fallback + * locking is slower than POSIX locking, so we do not want to do it by default. +*/ +#define PREF_NFS_FILESYSTEM "storage.nfs_filesystem" + +namespace { + +using namespace mozilla; +using namespace mozilla::dom::quota; + +struct Histograms { + const char *name; + const Telemetry::ID readB; + const Telemetry::ID writeB; + const Telemetry::ID readMS; + const Telemetry::ID writeMS; + const Telemetry::ID syncMS; +}; + +#define SQLITE_TELEMETRY(FILENAME, HGRAM) \ + { FILENAME, \ + Telemetry::MOZ_SQLITE_ ## HGRAM ## _READ_B, \ + Telemetry::MOZ_SQLITE_ ## HGRAM ## _WRITE_B, \ + Telemetry::MOZ_SQLITE_ ## HGRAM ## _READ_MS, \ + Telemetry::MOZ_SQLITE_ ## HGRAM ## _WRITE_MS, \ + Telemetry::MOZ_SQLITE_ ## HGRAM ## _SYNC_MS \ + } + +Histograms gHistograms[] = { + SQLITE_TELEMETRY("places.sqlite", PLACES), + SQLITE_TELEMETRY("cookies.sqlite", COOKIES), + SQLITE_TELEMETRY("webappsstore.sqlite", WEBAPPS), + SQLITE_TELEMETRY(NULL, OTHER) +}; +#undef SQLITE_TELEMETRY + +/** RAII class for measuring how long io takes on/off main thread + */ +class IOThreadAutoTimer { +public: + /** + * IOThreadAutoTimer measures time spent in IO. Additionally it + * automatically determines whether IO is happening on the main + * thread and picks an appropriate histogram. + * + * @param id takes a telemetry histogram id. The id+1 must be an + * equivalent histogram for the main thread. Eg, MOZ_SQLITE_OPEN_MS + * is followed by MOZ_SQLITE_OPEN_MAIN_THREAD_MS. + */ + IOThreadAutoTimer(Telemetry::ID id) + : start(TimeStamp::Now()), + id(id) + { + } + + ~IOThreadAutoTimer() { + uint32_t mainThread = NS_IsMainThread() ? 1 : 0; + Telemetry::AccumulateTimeDelta(static_cast(id + mainThread), + start); + } + +private: + const TimeStamp start; + const Telemetry::ID id; +}; + +struct telemetry_file { + // Base class. Must be first + sqlite3_file base; + + // histograms pertaining to this file + Histograms *histograms; + + // quota object for this file + nsRefPtr quotaObject; + + // This contains the vfs that actually does work + sqlite3_file pReal[1]; +}; + +/* +** Close a telemetry_file. +*/ +int +xClose(sqlite3_file *pFile) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xClose(p->pReal); + if( rc==SQLITE_OK ){ + delete p->base.pMethods; + p->base.pMethods = NULL; + p->quotaObject = nullptr; + } + return rc; +} + +/* +** Read data from a telemetry_file. +*/ +int +xRead(sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst) +{ + telemetry_file *p = (telemetry_file *)pFile; + IOThreadAutoTimer ioTimer(p->histograms->readMS); + int rc; + rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst); + // sqlite likes to read from empty files, this is normal, ignore it. + if (rc != SQLITE_IOERR_SHORT_READ) + Telemetry::Accumulate(p->histograms->readB, rc == SQLITE_OK ? iAmt : 0); + return rc; +} + +/* +** Write data to a telemetry_file. +*/ +int +xWrite(sqlite3_file *pFile, const void *zBuf, int iAmt, sqlite_int64 iOfst) +{ + telemetry_file *p = (telemetry_file *)pFile; + if (p->quotaObject && !p->quotaObject->MaybeAllocateMoreSpace(iOfst, iAmt)) { + return SQLITE_FULL; + } + IOThreadAutoTimer ioTimer(p->histograms->writeMS); + int rc; + rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst); + Telemetry::Accumulate(p->histograms->writeB, rc == SQLITE_OK ? iAmt : 0); + return rc; +} + +/* +** Truncate a telemetry_file. +*/ +int +xTruncate(sqlite3_file *pFile, sqlite_int64 size) +{ + IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_TRUNCATE_MS); + telemetry_file *p = (telemetry_file *)pFile; + int rc; + Telemetry::AutoTimer timer; + rc = p->pReal->pMethods->xTruncate(p->pReal, size); + if (rc == SQLITE_OK && p->quotaObject) { + p->quotaObject->UpdateSize(size); + } + return rc; +} + +/* +** Sync a telemetry_file. +*/ +int +xSync(sqlite3_file *pFile, int flags) +{ + telemetry_file *p = (telemetry_file *)pFile; + IOThreadAutoTimer ioTimer(p->histograms->syncMS); + return p->pReal->pMethods->xSync(p->pReal, flags); +} + +/* +** Return the current file-size of a telemetry_file. +*/ +int +xFileSize(sqlite3_file *pFile, sqlite_int64 *pSize) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xFileSize(p->pReal, pSize); + return rc; +} + +/* +** Lock a telemetry_file. +*/ +int +xLock(sqlite3_file *pFile, int eLock) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xLock(p->pReal, eLock); + return rc; +} + +/* +** Unlock a telemetry_file. +*/ +int +xUnlock(sqlite3_file *pFile, int eLock) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xUnlock(p->pReal, eLock); + return rc; +} + +/* +** Check if another file-handle holds a RESERVED lock on a telemetry_file. +*/ +int +xCheckReservedLock(sqlite3_file *pFile, int *pResOut) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut); + return rc; +} + +/* +** File control method. For custom operations on a telemetry_file. +*/ +int +xFileControl(sqlite3_file *pFile, int op, void *pArg) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); + return rc; +} + +/* +** Return the sector-size in bytes for a telemetry_file. +*/ +int +xSectorSize(sqlite3_file *pFile) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xSectorSize(p->pReal); + return rc; +} + +/* +** Return the device characteristic flags supported by a telemetry_file. +*/ +int +xDeviceCharacteristics(sqlite3_file *pFile) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal); + return rc; +} + +/* +** Shared-memory operations. +*/ +int +xShmLock(sqlite3_file *pFile, int ofst, int n, int flags) +{ + telemetry_file *p = (telemetry_file *)pFile; + return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); +} + +int +xShmMap(sqlite3_file *pFile, int iRegion, int szRegion, int isWrite, void volatile **pp) +{ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); + return rc; +} + +void +xShmBarrier(sqlite3_file *pFile){ + telemetry_file *p = (telemetry_file *)pFile; + p->pReal->pMethods->xShmBarrier(p->pReal); +} + +int +xShmUnmap(sqlite3_file *pFile, int delFlag){ + telemetry_file *p = (telemetry_file *)pFile; + int rc; + rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); + return rc; +} + +int +xOpen(sqlite3_vfs* vfs, const char *zName, sqlite3_file* pFile, + int flags, int *pOutFlags) +{ + IOThreadAutoTimer ioTimer(Telemetry::MOZ_SQLITE_OPEN_MS); + Telemetry::AutoTimer timer; + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + int rc; + telemetry_file *p = (telemetry_file *)pFile; + Histograms *h = NULL; + // check if the filename is one we are probing for + for(size_t i = 0;i < sizeof(gHistograms)/sizeof(gHistograms[0]);i++) { + h = &gHistograms[i]; + // last probe is the fallback probe + if (!h->name) + break; + if (!zName) + continue; + const char *match = strstr(zName, h->name); + if (!match) + continue; + char c = match[strlen(h->name)]; + // include -wal/-journal too + if (!c || c == '-') + break; + } + p->histograms = h; + + const char* origin; + if ((flags & SQLITE_OPEN_URI) && + (origin = sqlite3_uri_parameter(zName, "origin"))) { + QuotaManager* quotaManager = QuotaManager::Get(); + MOZ_ASSERT(quotaManager); + + p->quotaObject = quotaManager->GetQuotaObject(nsDependentCString(origin), + NS_ConvertUTF8toUTF16(zName)); + + } + + rc = orig_vfs->xOpen(orig_vfs, zName, p->pReal, flags, pOutFlags); + if( rc != SQLITE_OK ) + return rc; + if( p->pReal->pMethods ){ + sqlite3_io_methods *pNew = new sqlite3_io_methods; + const sqlite3_io_methods *pSub = p->pReal->pMethods; + memset(pNew, 0, sizeof(*pNew)); + pNew->iVersion = pSub->iVersion; + pNew->xClose = xClose; + pNew->xRead = xRead; + pNew->xWrite = xWrite; + pNew->xTruncate = xTruncate; + pNew->xSync = xSync; + pNew->xFileSize = xFileSize; + pNew->xLock = xLock; + pNew->xUnlock = xUnlock; + pNew->xCheckReservedLock = xCheckReservedLock; + pNew->xFileControl = xFileControl; + pNew->xSectorSize = xSectorSize; + pNew->xDeviceCharacteristics = xDeviceCharacteristics; + if( pNew->iVersion>=2 ){ + pNew->xShmMap = pSub->xShmMap ? xShmMap : 0; + pNew->xShmLock = pSub->xShmLock ? xShmLock : 0; + pNew->xShmBarrier = pSub->xShmBarrier ? xShmBarrier : 0; + pNew->xShmUnmap = pSub->xShmUnmap ? xShmUnmap : 0; + } + pFile->pMethods = pNew; + } + return rc; +} + +int +xDelete(sqlite3_vfs* vfs, const char *zName, int syncDir) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xDelete(orig_vfs, zName, syncDir); +} + +int +xAccess(sqlite3_vfs *vfs, const char *zName, int flags, int *pResOut) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xAccess(orig_vfs, zName, flags, pResOut); +} + +int +xFullPathname(sqlite3_vfs *vfs, const char *zName, int nOut, char *zOut) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xFullPathname(orig_vfs, zName, nOut, zOut); +} + +void* +xDlOpen(sqlite3_vfs *vfs, const char *zFilename) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xDlOpen(orig_vfs, zFilename); +} + +void +xDlError(sqlite3_vfs *vfs, int nByte, char *zErrMsg) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + orig_vfs->xDlError(orig_vfs, nByte, zErrMsg); +} + +void +(*xDlSym(sqlite3_vfs *vfs, void *pHdle, const char *zSym))(void){ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xDlSym(orig_vfs, pHdle, zSym); +} + +void +xDlClose(sqlite3_vfs *vfs, void *pHandle) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + orig_vfs->xDlClose(orig_vfs, pHandle); +} + +int +xRandomness(sqlite3_vfs *vfs, int nByte, char *zOut) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xRandomness(orig_vfs, nByte, zOut); +} + +int +xSleep(sqlite3_vfs *vfs, int microseconds) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xSleep(orig_vfs, microseconds); +} + +int +xCurrentTime(sqlite3_vfs *vfs, double *prNow) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xCurrentTime(orig_vfs, prNow); +} + +int +xGetLastError(sqlite3_vfs *vfs, int nBuf, char *zBuf) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xGetLastError(orig_vfs, nBuf, zBuf); +} + +int +xCurrentTimeInt64(sqlite3_vfs *vfs, sqlite3_int64 *piNow) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xCurrentTimeInt64(orig_vfs, piNow); +} + +static +int +xSetSystemCall(sqlite3_vfs *vfs, const char *zName, sqlite3_syscall_ptr pFunc) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xSetSystemCall(orig_vfs, zName, pFunc); +} + +static +sqlite3_syscall_ptr +xGetSystemCall(sqlite3_vfs *vfs, const char *zName) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xGetSystemCall(orig_vfs, zName); +} + +static +const char * +xNextSystemCall(sqlite3_vfs *vfs, const char *zName) +{ + sqlite3_vfs *orig_vfs = static_cast(vfs->pAppData); + return orig_vfs->xNextSystemCall(orig_vfs, zName); +} + +} + +namespace mozilla { +namespace storage { + +sqlite3_vfs* ConstructTelemetryVFS() +{ +#if defined(XP_WIN) +#define EXPECTED_VFS "win32" +#define EXPECTED_VFS_NFS "win32" +#else +#define EXPECTED_VFS "unix" +#define EXPECTED_VFS_NFS "unix-excl" +#endif + + bool expected_vfs; + sqlite3_vfs *vfs; + if (Preferences::GetBool(PREF_NFS_FILESYSTEM)) { + vfs = sqlite3_vfs_find(EXPECTED_VFS_NFS); + expected_vfs = (vfs != nullptr); + } + else { + vfs = sqlite3_vfs_find(NULL); + expected_vfs = vfs->zName && !strcmp(vfs->zName, EXPECTED_VFS); + } + if (!expected_vfs) { + return NULL; + } + + sqlite3_vfs *tvfs = new ::sqlite3_vfs; + memset(tvfs, 0, sizeof(::sqlite3_vfs)); + tvfs->iVersion = 3; + // If the SQLite VFS version is updated, this shim must be updated as well. + MOZ_ASSERT(vfs->iVersion == tvfs->iVersion); + tvfs->szOsFile = sizeof(telemetry_file) - sizeof(sqlite3_file) + vfs->szOsFile; + tvfs->mxPathname = vfs->mxPathname; + tvfs->zName = "telemetry-vfs"; + tvfs->pAppData = vfs; + tvfs->xOpen = xOpen; + tvfs->xDelete = xDelete; + tvfs->xAccess = xAccess; + tvfs->xFullPathname = xFullPathname; + tvfs->xDlOpen = xDlOpen; + tvfs->xDlError = xDlError; + tvfs->xDlSym = xDlSym; + tvfs->xDlClose = xDlClose; + tvfs->xRandomness = xRandomness; + tvfs->xSleep = xSleep; + tvfs->xCurrentTime = xCurrentTime; + tvfs->xGetLastError = xGetLastError; + // Added in version 2. + tvfs->xCurrentTimeInt64 = xCurrentTimeInt64; + // Added in version 3. + tvfs->xSetSystemCall = xSetSystemCall; + tvfs->xGetSystemCall = xGetSystemCall; + tvfs->xNextSystemCall = xNextSystemCall; + + return tvfs; +} + +} +} diff --git a/storage/src/mozStorageConnection.cpp b/storage/src/mozStorageConnection.cpp index 14ca2d33e08..da19f6e0154 100644 --- a/storage/src/mozStorageConnection.cpp +++ b/storage/src/mozStorageConnection.cpp @@ -502,7 +502,7 @@ Connection::initialize(nsIFile *aDatabaseFile) NS_ENSURE_SUCCESS(rv, rv); int srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, - mFlags, mStorageService->getVFSName()); + mFlags, NULL); if (srv != SQLITE_OK) { mDBConn = nullptr; return convertResultCode(srv); @@ -531,8 +531,7 @@ Connection::initialize(nsIFileURL *aFileURL) rv = aFileURL->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); - int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, - mStorageService->getVFSName()); + int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, NULL); if (srv != SQLITE_OK) { mDBConn = nullptr; return convertResultCode(srv); diff --git a/storage/src/mozStorageService.cpp b/storage/src/mozStorageService.cpp index 23aaf9d2866..51c06743563 100644 --- a/storage/src/mozStorageService.cpp +++ b/storage/src/mozStorageService.cpp @@ -39,25 +39,6 @@ #define PREF_TS_SYNCHRONOUS "toolkit.storage.synchronous" #define PREF_TS_SYNCHRONOUS_DEFAULT 1 -/** - * This preference is a workaround to allow users/sysadmins to identify - * that the profile exists on an NFS share whose implementation is - * incompatible with SQLite's default locking implementation. Bug - * 433129 attempted to automatically identify such file-systems, but a - * reliable way was not found and it was determined that the fallback - * locking is slower than POSIX locking, so we do not want to do it by - * default. - */ -#define PREF_NFS_FILESYSTEM "storage.nfs_filesystem" - -#if defined(XP_WIN) -#define STANDARD_VFS "win32" -#define NFS_VFS "win32" -#else -#define STANDARD_VFS "unix" -#define NFS_VFS "unix-excl" -#endif - namespace mozilla { namespace storage { @@ -248,13 +229,11 @@ public: ServiceMainThreadInitializer(Service *aService, nsIObserver *aObserver, nsIXPConnect **aXPConnectPtr, - int32_t *aSynchronousPrefValPtr, - const char **aVFSNamePtr) + int32_t *aSynchronousPrefValPtr) : mService(aService) , mObserver(aObserver) , mXPConnectPtr(aXPConnectPtr) , mSynchronousPrefValPtr(aSynchronousPrefValPtr) - , mVFSNamePtr(aVFSNamePtr) { } @@ -289,13 +268,6 @@ public: Preferences::GetInt(PREF_TS_SYNCHRONOUS, PREF_TS_SYNCHRONOUS_DEFAULT); ::PR_ATOMIC_SET(mSynchronousPrefValPtr, synchronous); - // Likewise for whether we're on an NFS filesystem. - if (Preferences::GetBool(PREF_NFS_FILESYSTEM)) { - *mVFSNamePtr = NFS_VFS; - } else { - *mVFSNamePtr = STANDARD_VFS; - } - // Create and register our SQLite memory reporters. Registration can only // happen on the main thread (otherwise you'll get cryptic crashes). mService->mStorageSQLiteReporter = new NS_MEMORY_REPORTER_NAME(StorageSQLite); @@ -311,7 +283,6 @@ private: nsIObserver *mObserver; nsIXPConnect **mXPConnectPtr; int32_t *mSynchronousPrefValPtr; - const char **mVFSNamePtr; }; //////////////////////////////////////////////////////////////////////////////// @@ -388,17 +359,9 @@ Service::getSynchronousPref() return sSynchronousPref; } -const char *Service::sVFSName; - -// static -const char * -Service::getVFSName() -{ - return sVFSName; -} - Service::Service() : mMutex("Service::mMutex") +, mSqliteVFS(nullptr) , mRegistrationMutex("Service::mRegistrationMutex") , mConnections() , mStorageSQLiteReporter(nullptr) @@ -411,9 +374,13 @@ Service::~Service() (void)::NS_UnregisterMemoryReporter(mStorageSQLiteReporter); (void)::NS_UnregisterMemoryMultiReporter(mStorageSQLiteMultiReporter); + int rc = sqlite3_vfs_unregister(mSqliteVFS); + if (rc != SQLITE_OK) + NS_WARNING("Failed to unregister sqlite vfs wrapper."); + // Shutdown the sqlite3 API. Warn if shutdown did not turn out okay, but // there is nothing actionable we can do in that case. - int rc = ::sqlite3_shutdown(); + rc = ::sqlite3_shutdown(); if (rc != SQLITE_OK) NS_WARNING("sqlite3 did not shutdown cleanly."); @@ -421,6 +388,8 @@ Service::~Service() NS_ASSERTION(shutdownObserved, "Shutdown was not observed!"); gService = nullptr; + delete mSqliteVFS; + mSqliteVFS = nullptr; } void @@ -462,6 +431,8 @@ Service::shutdown() NS_IF_RELEASE(sXPConnect); } +sqlite3_vfs *ConstructTelemetryVFS(); + #ifdef MOZ_STORAGE_MEMORY # include "mozmemory.h" @@ -595,14 +566,22 @@ Service::initialize() if (rc != SQLITE_OK) return convertResultCode(rc); + mSqliteVFS = ConstructTelemetryVFS(); + if (mSqliteVFS) { + rc = sqlite3_vfs_register(mSqliteVFS, 1); + if (rc != SQLITE_OK) + return convertResultCode(rc); + } else { + NS_WARNING("Failed to register telemetry VFS"); + } + // Set the default value for the toolkit.storage.synchronous pref. It will be // updated with the user preference on the main thread. sSynchronousPref = PREF_TS_SYNCHRONOUS_DEFAULT; // Run the things that need to run on the main thread there. nsCOMPtr event = - new ServiceMainThreadInitializer(this, this, &sXPConnect, &sSynchronousPref, - &sVFSName); + new ServiceMainThreadInitializer(this, this, &sXPConnect, &sSynchronousPref); if (event && ::NS_IsMainThread()) { (void)event->Run(); } diff --git a/storage/src/mozStorageService.h b/storage/src/mozStorageService.h index 448abd5b705..3f5a546695e 100644 --- a/storage/src/mozStorageService.h +++ b/storage/src/mozStorageService.h @@ -19,6 +19,7 @@ class nsIMemoryReporter; class nsIMemoryMultiReporter; class nsIXPConnect; +struct sqlite3_vfs; namespace mozilla { namespace storage { @@ -67,11 +68,6 @@ public: */ static int32_t getSynchronousPref(); - /** - * Returns the name of the sqlite3 VFS to use for file-backed databases. - */ - static const char *getVFSName(); - /** * Registers the connection with the storage service. Connections are * registered so they can be iterated over. @@ -118,6 +114,8 @@ private: */ Mutex mMutex; + sqlite3_vfs *mSqliteVFS; + /** * Protects mConnections. */ @@ -163,8 +161,6 @@ private: static int32_t sSynchronousPref; - static const char *sVFSName; - friend class ServiceMainThreadInitializer; }; diff --git a/storage/test/unit/test_telemetry_vfs.js b/storage/test/unit/test_telemetry_vfs.js new file mode 100644 index 00000000000..b8c7ff87901 --- /dev/null +++ b/storage/test/unit/test_telemetry_vfs.js @@ -0,0 +1,30 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// Make sure that there are telemetry entries created by sqlite io + +function run_sql(d, sql) { + var stmt = d.createStatement(sql) + stmt.execute() + stmt.finalize(); +} + +function new_file(name) +{ + var file = dirSvc.get("ProfD", Ci.nsIFile); + file.append(name); + return file; +} +function run_test() +{ + const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry); + let read_hgram = Telemetry.getHistogramById("MOZ_SQLITE_OTHER_READ_B"); + let old_sum = read_hgram.snapshot().sum; + const file = new_file("telemetry.sqlite"); + var d = getDatabase(file); + run_sql(d, "CREATE TABLE bloat(data varchar)"); + run_sql(d, "DROP TABLE bloat") + do_check_true(read_hgram.snapshot().sum > old_sum) +} + diff --git a/storage/test/unit/xpcshell.ini b/storage/test/unit/xpcshell.ini index 4f9b05498b9..fa996642b22 100644 --- a/storage/test/unit/xpcshell.ini +++ b/storage/test/unit/xpcshell.ini @@ -31,5 +31,6 @@ fail-if = os == "android" [test_storage_value_array.js] [test_unicode.js] [test_vacuum.js] +[test_telemetry_vfs.js] # Bug 676981: test fails consistently on Android # fail-if = os == "android" diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 7323c406e7f..5e817acb8bc 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -1478,6 +1478,222 @@ "n_buckets": 20, "description": "Time spent shutting down plugins (ms)" }, + "MOZ_SQLITE_OPEN_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite open() (ms)" + }, + "MOZ_SQLITE_OPEN_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite open() (ms)" + }, + "MOZ_SQLITE_TRUNCATE_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite truncate() (ms)" + }, + "MOZ_SQLITE_TRUNCATE_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite truncate() (ms)" + }, + "MOZ_SQLITE_OTHER_READ_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_OTHER_READ_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_PLACES_READ_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_PLACES_READ_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_COOKIES_READ_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_COOKIES_READ_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_WEBAPPS_READ_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_WEBAPPS_READ_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite read() (ms)" + }, + "MOZ_SQLITE_OTHER_WRITE_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_OTHER_WRITE_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_PLACES_WRITE_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_PLACES_WRITE_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_COOKIES_WRITE_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_COOKIES_WRITE_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_WEBAPPS_WRITE_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_WEBAPPS_WRITE_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite write() (ms)" + }, + "MOZ_SQLITE_OTHER_SYNC_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_OTHER_SYNC_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_PLACES_SYNC_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_PLACES_SYNC_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_COOKIES_SYNC_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_COOKIES_SYNC_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_WEBAPPS_SYNC_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_WEBAPPS_SYNC_MAIN_THREAD_MS": { + "kind": "exponential", + "high": "3000", + "n_buckets": 10, + "description": "Time spent on SQLite fsync() (ms)" + }, + "MOZ_SQLITE_OTHER_READ_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite read() (bytes)" + }, + "MOZ_SQLITE_PLACES_READ_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite read() (bytes)" + }, + "MOZ_SQLITE_COOKIES_READ_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite read() (bytes)" + }, + "MOZ_SQLITE_WEBAPPS_READ_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite read() (bytes)" + }, + "MOZ_SQLITE_PLACES_WRITE_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite write (bytes)" + }, + "MOZ_SQLITE_COOKIES_WRITE_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite write (bytes)" + }, + "MOZ_SQLITE_WEBAPPS_WRITE_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite write (bytes)" + }, + "MOZ_SQLITE_OTHER_WRITE_B": { + "kind": "linear", + "high": "32768", + "n_buckets": 3, + "description": "SQLite write (bytes)" + }, "MOZ_STORAGE_ASYNC_REQUESTS_MS": { "kind": "exponential", "high": "32768", From f9a3d75fd5a73c2d50e65afd01e75ff0cfb6a694 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 29 Jan 2013 22:44:58 +0100 Subject: [PATCH 10/70] Bug 725587 - Firefox jumps randomly from IPv6 to IPv4 and vice versa in dual-stack environment, r=mcmanus --- netwerk/base/public/nsISocketTransport.idl | 6 +++ netwerk/base/src/nsSocketTransport2.cpp | 19 ++++--- netwerk/dns/nsDNSService2.cpp | 3 ++ netwerk/dns/nsIDNSService.idl | 5 ++ netwerk/protocol/http/nsHttpChannel.cpp | 4 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 52 +++++++++++++++++-- netwerk/protocol/http/nsHttpConnectionMgr.h | 17 ++++++ 7 files changed, 95 insertions(+), 11 deletions(-) diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index cf43807f5b8..0c8c585aadd 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -163,6 +163,12 @@ interface nsISocketTransport : nsITransport */ const unsigned long NO_PERMANENT_STORAGE = (1 << 3); + /** + * If set, we will skip all IPv4 addresses the host may have and only + * connect to IPv6 ones. + */ + const unsigned long DISABLE_IPV4 = (1 << 4); + /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 0396e75b99d..7dd872ad19c 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -926,6 +926,12 @@ nsSocketTransport::ResolveHost() dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; if (mConnectionFlags & nsSocketTransport::DISABLE_IPV6) dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6; + if (mConnectionFlags & nsSocketTransport::DISABLE_IPV4) + dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4; + + NS_ASSERTION(!(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) || + !(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4), + "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4"); SendStatus(NS_NET_STATUS_RESOLVING_HOST); rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nullptr, @@ -1267,12 +1273,12 @@ nsSocketTransport::RecoverFromError() bool tryAgain = false; - if (mConnectionFlags & DISABLE_IPV6 && + if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4) && mCondition == NS_ERROR_UNKNOWN_HOST && mState == STATE_RESOLVING && !mProxyTransparentResolvesHost) { SOCKET_LOG((" trying lookup again with both ipv4/ipv6 enabled\n")); - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } @@ -1285,14 +1291,15 @@ nsSocketTransport::RecoverFromError() SOCKET_LOG((" trying again with next ip address\n")); tryAgain = true; } - else if (mConnectionFlags & DISABLE_IPV6) { + else if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4)) { // Drop state to closed. This will trigger new round of DNS // resolving bellow. - // XXX Here should idealy be set now non-existing flag DISABLE_IPV4 - SOCKET_LOG((" failed to connect all ipv4 hosts," + // XXX Could be optimized to only switch the flags to save duplicate + // connection attempts. + SOCKET_LOG((" failed to connect all ipv4-only or ipv6-only hosts," " trying lookup/connect again with both ipv4/ipv6\n")); mState = STATE_CLOSED; - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } } diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index f1fe85b2460..05be514c72f 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -850,6 +850,9 @@ nsDNSService::GetAFForLookup(const nsACString &host, uint32_t flags) } while (*end); } + if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4)) + af = PR_AF_INET6; + return af; } diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index 6b06a194f83..183ca004422 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -134,4 +134,9 @@ interface nsIDNSService : nsISupports * asyncResolve. */ const unsigned long RESOLVE_OFFLINE = (1 << 6); + + /** + * If set, only IPv6 addresses will be returned from resolve/asyncResolve. + */ + const unsigned long RESOLVE_DISABLE_IPV4 = (1 << 7); }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 4eca5e109cd..d15af44d21e 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4484,8 +4484,10 @@ nsHttpChannel::BeginConnect() // Force-Reload should reset the persistent connection pool for this host if (mLoadFlags & LOAD_FRESH_CONNECTION) { // just the initial document resets the whole pool - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { gHttpHandler->ConnMgr()->ClosePersistentConnections(); + gHttpHandler->ConnMgr()->ResetIPFamillyPreference(mConnectionInfo); + } // each sub resource gets a fresh connection mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING); } diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index e079b15e6bd..4e6efd9e744 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -2521,8 +2521,13 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, // IPv6 on the backup connection gives them a much better user experience // with dual-stack hosts, though they still pay the 250ms delay for each new // connection. This strategy is also known as "happy eyeballs". - if (isBackup && gHttpHandler->FastFallbackToIPv4()) + if (mEnt->mPreferIPv6) { + tmpFlags |= nsISocketTransport::DISABLE_IPV4; + } + else if (mEnt->mPreferIPv4 || + (isBackup && gHttpHandler->FastFallbackToIPv4())) { tmpFlags |= nsISocketTransport::DISABLE_IPV6; + } socketTransport->SetConnectionFlags(tmpFlags); @@ -2714,6 +2719,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) LOG(("nsHalfOpenSocket::OnOutputStreamReady " "Created new nshttpconnection %p\n", conn.get())); + PRNetAddr peeraddr; nsCOMPtr callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks)); if (out == mStreamOut) { @@ -2724,6 +2730,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mStreamOut = nullptr; mStreamIn = nullptr; @@ -2737,6 +2746,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mBackupTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mBackupStreamOut = nullptr; mBackupStreamIn = nullptr; @@ -2949,6 +2961,8 @@ nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci) , mUsingSpdy(false) , mTestedSpdy(false) , mSpdyPreferred(false) + , mPreferIPv4(false) + , mPreferIPv6(false) { NS_ADDREF(mConnInfo); if (gHttpHandler->GetPipelineAggressive()) { @@ -3104,7 +3118,8 @@ nsConnectionEntry::SetYellowConnection(nsHttpConnection *conn) } void -nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() +nsHttpConnectionMgr:: +nsConnectionEntry::OnYellowComplete() { if (mPipelineState == PS_YELLOW) { if (mYellowGoodEvents && !mYellowBadEvents) { @@ -3127,7 +3142,8 @@ nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() } void -nsHttpConnectionMgr::nsConnectionEntry::CreditPenalty() +nsHttpConnectionMgr:: +nsConnectionEntry::CreditPenalty() { if (mLastCreditTime.IsNull()) return; @@ -3223,8 +3239,17 @@ nsHttpConnectionMgr::GetConnectionData(nsTArray *aA return true; } +void +nsHttpConnectionMgr::ResetIPFamillyPreference(nsHttpConnectionInfo *ci) +{ + nsConnectionEntry *ent = LookupConnectionEntry(ci, nullptr, nullptr); + if (ent) + ent->ResetIPFamilyPreference(); +} + uint32_t -nsHttpConnectionMgr::nsConnectionEntry::UnconnectedHalfOpens() +nsHttpConnectionMgr:: +nsConnectionEntry::UnconnectedHalfOpens() { uint32_t unconnectedHalfOpens = 0; for (uint32_t i = 0; i < mHalfOpens.Length(); ++i) { @@ -3250,3 +3275,22 @@ nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen) // altering the pending q vector from an arbitrary stack gHttpHandler->ConnMgr()->ProcessPendingQ(mConnInfo); } + +void +nsHttpConnectionMgr:: +nsConnectionEntry::RecordIPFamilyPreference(uint16_t family) +{ + if (family == PR_AF_INET && !mPreferIPv6) + mPreferIPv4 = true; + + if (family == PR_AF_INET6 && !mPreferIPv4) + mPreferIPv6 = true; +} + +void +nsHttpConnectionMgr:: +nsConnectionEntry::ResetIPFamilyPreference() +{ + mPreferIPv4 = false; + mPreferIPv6 = false; +} diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index a27b9598959..30d917bc6ea 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -225,6 +225,9 @@ public: bool SupportsPipelining(nsHttpConnectionInfo *); bool GetConnectionData(nsTArray *); + + void ResetIPFamillyPreference(nsHttpConnectionInfo *); + private: virtual ~nsHttpConnectionMgr(); @@ -343,6 +346,20 @@ private: bool mTestedSpdy; bool mSpdyPreferred; + + // Flags to remember our happy-eyeballs decision. + // Reset only by Ctrl-F5 reload. + // True when we've first connected an IPv4 server for this host, + // initially false. + bool mPreferIPv4 : 1; + // True when we've first connected an IPv6 server for this host, + // initially false. + bool mPreferIPv6 : 1; + + // Set the IP family preference flags according the connected family + void RecordIPFamilyPreference(uint16_t family); + // Resets all flags to their default values + void ResetIPFamilyPreference(); }; // nsConnectionHandle From 083b32590b97bc8ef065dbedb3f7d224cf04fcf0 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Tue, 29 Jan 2013 14:59:42 -0700 Subject: [PATCH 11/70] Bug 826385 - Reduce pause/resume notifications to gecko; r=mfinkle --- mobile/android/base/GeckoActivity.java.in | 44 ++++++++++++++++++++++- mobile/android/base/GeckoApplication.java | 20 ++++++++--- mobile/android/base/GeckoPreferences.java | 24 ++++++++++++- 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/mobile/android/base/GeckoActivity.java.in b/mobile/android/base/GeckoActivity.java.in index 1b8c2d9b0fa..f8fb7cdbe1f 100644 --- a/mobile/android/base/GeckoActivity.java.in +++ b/mobile/android/base/GeckoActivity.java.in @@ -2,11 +2,23 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#filter substitution + package org.mozilla.gecko; import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; + +interface GeckoActivityStatus { + public boolean isGeckoActivityOpened(); + public boolean isFinishing(); // typically from android.app.Activity +}; + +public class GeckoActivity extends Activity implements GeckoActivityStatus { + // has this activity recently started another Gecko activity? + private boolean mGeckoActivityOpened = false; -public class GeckoActivity extends Activity { @Override public void onPause() { super.onPause(); @@ -22,9 +34,39 @@ public class GeckoActivity extends Activity { if (getApplication() instanceof GeckoApplication) { ((GeckoApplication) getApplication()).onActivityResume(this); + mGeckoActivityOpened = false; } } + @Override + public void startActivity(Intent intent) { + checkIfGeckoActivity(intent); + super.startActivity(intent); + } + + @Override + public void startActivityForResult(Intent intent, int request) { + checkIfGeckoActivity(intent); + super.startActivityForResult(intent, request); + } + + private void checkIfGeckoActivity(Intent intent) { + // Whenever we call our own activity, the component and it's package name is set. + // If we call an activity from another package, or an open intent (leaving android to resolve) + // component has a different package name or it is null. + ComponentName component = intent.getComponent(); + mGeckoActivityOpened = false; + if (component != null && + component.getPackageName() != null && + component.getPackageName().equals("@ANDROID_PACKAGE_NAME@")) { + mGeckoActivityOpened = true; + } + } + + public boolean isGeckoActivityOpened() { + return mGeckoActivityOpened; + } + public boolean isApplicationInBackground() { return ((GeckoApplication) getApplication()).isApplicationInBackground(); } diff --git a/mobile/android/base/GeckoApplication.java b/mobile/android/base/GeckoApplication.java index c2d094e445f..d47df61821e 100644 --- a/mobile/android/base/GeckoApplication.java +++ b/mobile/android/base/GeckoApplication.java @@ -10,6 +10,7 @@ public class GeckoApplication extends Application { private boolean mInited; private boolean mInBackground; + private boolean mPausedGecko; private LightweightTheme mLightweightTheme; @@ -32,17 +33,28 @@ public class GeckoApplication extends Application { mInited = true; } - protected void onActivityPause(GeckoActivity activity) { + protected void onActivityPause(GeckoActivityStatus activity) { mInBackground = true; - GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true)); + if ((activity.isFinishing() == false) && + (activity.isGeckoActivityOpened() == false)) { + // Notify Gecko that we are pausing; the cache service will be + // shutdown, closing the disk cache cleanly. If the android + // low memory killer subsequently kills us, the disk cache will + // be left in a consistent state, avoiding costly cleanup and + // re-creation. + GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true)); + mPausedGecko = true; + } GeckoConnectivityReceiver.getInstance().stop(); GeckoNetworkManager.getInstance().stop(); } - protected void onActivityResume(GeckoActivity activity) { - if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) + protected void onActivityResume(GeckoActivityStatus activity) { + if (mPausedGecko) { GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true)); + mPausedGecko = false; + } GeckoConnectivityReceiver.getInstance().start(); GeckoNetworkManager.getInstance().start(); diff --git a/mobile/android/base/GeckoPreferences.java b/mobile/android/base/GeckoPreferences.java index ed9e75db76b..6432ffed38d 100644 --- a/mobile/android/base/GeckoPreferences.java +++ b/mobile/android/base/GeckoPreferences.java @@ -43,7 +43,7 @@ import java.util.ArrayList; public class GeckoPreferences extends PreferenceActivity - implements OnPreferenceChangeListener, GeckoEventListener + implements OnPreferenceChangeListener, GeckoEventListener, GeckoActivityStatus { private static final String LOGTAG = "GeckoPreferences"; @@ -85,6 +85,24 @@ public class GeckoPreferences unregisterEventListener("Sanitize:Finished"); } + @Override + public void onPause() { + super.onPause(); + + if (getApplication() instanceof GeckoApplication) { + ((GeckoApplication) getApplication()).onActivityPause(this); + } + } + + @Override + public void onResume() { + super.onResume(); + + if (getApplication() instanceof GeckoApplication) { + ((GeckoApplication) getApplication()).onActivityResume(this); + } + } + public void handleMessage(String event, JSONObject message) { try { if (event.equals("Sanitize:Finished")) { @@ -445,4 +463,8 @@ public class GeckoPreferences private void unregisterEventListener(String event) { GeckoAppShell.getEventDispatcher().unregisterEventListener(event, this); } + + public boolean isGeckoActivityOpened() { + return false; + } } From 477f66a61efef5283a9a7031d4be6f8a97d03ed6 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 29 Jan 2013 17:01:10 -0500 Subject: [PATCH 12/70] Backed out changeset 0aea65518be3 (bug 725587) for bustage. --- netwerk/base/public/nsISocketTransport.idl | 6 --- netwerk/base/src/nsSocketTransport2.cpp | 19 +++---- netwerk/dns/nsDNSService2.cpp | 3 -- netwerk/dns/nsIDNSService.idl | 5 -- netwerk/protocol/http/nsHttpChannel.cpp | 4 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 52 ++----------------- netwerk/protocol/http/nsHttpConnectionMgr.h | 17 ------ 7 files changed, 11 insertions(+), 95 deletions(-) diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index 0c8c585aadd..cf43807f5b8 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -163,12 +163,6 @@ interface nsISocketTransport : nsITransport */ const unsigned long NO_PERMANENT_STORAGE = (1 << 3); - /** - * If set, we will skip all IPv4 addresses the host may have and only - * connect to IPv6 ones. - */ - const unsigned long DISABLE_IPV4 = (1 << 4); - /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 7dd872ad19c..0396e75b99d 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -926,12 +926,6 @@ nsSocketTransport::ResolveHost() dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; if (mConnectionFlags & nsSocketTransport::DISABLE_IPV6) dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6; - if (mConnectionFlags & nsSocketTransport::DISABLE_IPV4) - dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4; - - NS_ASSERTION(!(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) || - !(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4), - "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4"); SendStatus(NS_NET_STATUS_RESOLVING_HOST); rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nullptr, @@ -1273,12 +1267,12 @@ nsSocketTransport::RecoverFromError() bool tryAgain = false; - if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4) && + if (mConnectionFlags & DISABLE_IPV6 && mCondition == NS_ERROR_UNKNOWN_HOST && mState == STATE_RESOLVING && !mProxyTransparentResolvesHost) { SOCKET_LOG((" trying lookup again with both ipv4/ipv6 enabled\n")); - mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); + mConnectionFlags &= ~DISABLE_IPV6; tryAgain = true; } @@ -1291,15 +1285,14 @@ nsSocketTransport::RecoverFromError() SOCKET_LOG((" trying again with next ip address\n")); tryAgain = true; } - else if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4)) { + else if (mConnectionFlags & DISABLE_IPV6) { // Drop state to closed. This will trigger new round of DNS // resolving bellow. - // XXX Could be optimized to only switch the flags to save duplicate - // connection attempts. - SOCKET_LOG((" failed to connect all ipv4-only or ipv6-only hosts," + // XXX Here should idealy be set now non-existing flag DISABLE_IPV4 + SOCKET_LOG((" failed to connect all ipv4 hosts," " trying lookup/connect again with both ipv4/ipv6\n")); mState = STATE_CLOSED; - mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); + mConnectionFlags &= ~DISABLE_IPV6; tryAgain = true; } } diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index 05be514c72f..f1fe85b2460 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -850,9 +850,6 @@ nsDNSService::GetAFForLookup(const nsACString &host, uint32_t flags) } while (*end); } - if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4)) - af = PR_AF_INET6; - return af; } diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index 183ca004422..6b06a194f83 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -134,9 +134,4 @@ interface nsIDNSService : nsISupports * asyncResolve. */ const unsigned long RESOLVE_OFFLINE = (1 << 6); - - /** - * If set, only IPv6 addresses will be returned from resolve/asyncResolve. - */ - const unsigned long RESOLVE_DISABLE_IPV4 = (1 << 7); }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index d15af44d21e..4eca5e109cd 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4484,10 +4484,8 @@ nsHttpChannel::BeginConnect() // Force-Reload should reset the persistent connection pool for this host if (mLoadFlags & LOAD_FRESH_CONNECTION) { // just the initial document resets the whole pool - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) gHttpHandler->ConnMgr()->ClosePersistentConnections(); - gHttpHandler->ConnMgr()->ResetIPFamillyPreference(mConnectionInfo); - } // each sub resource gets a fresh connection mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING); } diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index 4e6efd9e744..e079b15e6bd 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -2521,13 +2521,8 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, // IPv6 on the backup connection gives them a much better user experience // with dual-stack hosts, though they still pay the 250ms delay for each new // connection. This strategy is also known as "happy eyeballs". - if (mEnt->mPreferIPv6) { - tmpFlags |= nsISocketTransport::DISABLE_IPV4; - } - else if (mEnt->mPreferIPv4 || - (isBackup && gHttpHandler->FastFallbackToIPv4())) { + if (isBackup && gHttpHandler->FastFallbackToIPv4()) tmpFlags |= nsISocketTransport::DISABLE_IPV6; - } socketTransport->SetConnectionFlags(tmpFlags); @@ -2719,7 +2714,6 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) LOG(("nsHalfOpenSocket::OnOutputStreamReady " "Created new nshttpconnection %p\n", conn.get())); - PRNetAddr peeraddr; nsCOMPtr callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks)); if (out == mStreamOut) { @@ -2730,9 +2724,6 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); - if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) - mEnt->RecordIPFamilyPreference(peeraddr.raw.family); - // The nsHttpConnection object now owns these streams and sockets mStreamOut = nullptr; mStreamIn = nullptr; @@ -2746,9 +2737,6 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); - if (NS_SUCCEEDED(mBackupTransport->GetPeerAddr(&peeraddr))) - mEnt->RecordIPFamilyPreference(peeraddr.raw.family); - // The nsHttpConnection object now owns these streams and sockets mBackupStreamOut = nullptr; mBackupStreamIn = nullptr; @@ -2961,8 +2949,6 @@ nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci) , mUsingSpdy(false) , mTestedSpdy(false) , mSpdyPreferred(false) - , mPreferIPv4(false) - , mPreferIPv6(false) { NS_ADDREF(mConnInfo); if (gHttpHandler->GetPipelineAggressive()) { @@ -3118,8 +3104,7 @@ nsConnectionEntry::SetYellowConnection(nsHttpConnection *conn) } void -nsHttpConnectionMgr:: -nsConnectionEntry::OnYellowComplete() +nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() { if (mPipelineState == PS_YELLOW) { if (mYellowGoodEvents && !mYellowBadEvents) { @@ -3142,8 +3127,7 @@ nsConnectionEntry::OnYellowComplete() } void -nsHttpConnectionMgr:: -nsConnectionEntry::CreditPenalty() +nsHttpConnectionMgr::nsConnectionEntry::CreditPenalty() { if (mLastCreditTime.IsNull()) return; @@ -3239,17 +3223,8 @@ nsHttpConnectionMgr::GetConnectionData(nsTArray *aA return true; } -void -nsHttpConnectionMgr::ResetIPFamillyPreference(nsHttpConnectionInfo *ci) -{ - nsConnectionEntry *ent = LookupConnectionEntry(ci, nullptr, nullptr); - if (ent) - ent->ResetIPFamilyPreference(); -} - uint32_t -nsHttpConnectionMgr:: -nsConnectionEntry::UnconnectedHalfOpens() +nsHttpConnectionMgr::nsConnectionEntry::UnconnectedHalfOpens() { uint32_t unconnectedHalfOpens = 0; for (uint32_t i = 0; i < mHalfOpens.Length(); ++i) { @@ -3275,22 +3250,3 @@ nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen) // altering the pending q vector from an arbitrary stack gHttpHandler->ConnMgr()->ProcessPendingQ(mConnInfo); } - -void -nsHttpConnectionMgr:: -nsConnectionEntry::RecordIPFamilyPreference(uint16_t family) -{ - if (family == PR_AF_INET && !mPreferIPv6) - mPreferIPv4 = true; - - if (family == PR_AF_INET6 && !mPreferIPv4) - mPreferIPv6 = true; -} - -void -nsHttpConnectionMgr:: -nsConnectionEntry::ResetIPFamilyPreference() -{ - mPreferIPv4 = false; - mPreferIPv6 = false; -} diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index 30d917bc6ea..a27b9598959 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -225,9 +225,6 @@ public: bool SupportsPipelining(nsHttpConnectionInfo *); bool GetConnectionData(nsTArray *); - - void ResetIPFamillyPreference(nsHttpConnectionInfo *); - private: virtual ~nsHttpConnectionMgr(); @@ -346,20 +343,6 @@ private: bool mTestedSpdy; bool mSpdyPreferred; - - // Flags to remember our happy-eyeballs decision. - // Reset only by Ctrl-F5 reload. - // True when we've first connected an IPv4 server for this host, - // initially false. - bool mPreferIPv4 : 1; - // True when we've first connected an IPv6 server for this host, - // initially false. - bool mPreferIPv6 : 1; - - // Set the IP family preference flags according the connected family - void RecordIPFamilyPreference(uint16_t family); - // Resets all flags to their default values - void ResetIPFamilyPreference(); }; // nsConnectionHandle From 87b09ed812dfd26ff1f3325f9fbd32353194b4b2 Mon Sep 17 00:00:00 2001 From: Tim Abraldes Date: Tue, 29 Jan 2013 14:05:22 -0800 Subject: [PATCH 13/70] bug 834434. Configure should ignore anything after the first minor version number and before the "-Unicode" in the NSIS version string. e.g. "major.minor[ignore everything here]-Unicode". r=ted --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 4cdc011c866..11b1405b0b5 100644 --- a/configure.in +++ b/configure.in @@ -6180,7 +6180,7 @@ if test "$OS_ARCH" = "WINNT"; then if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then AC_MSG_RESULT([yes]) changequote(,) - MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'` + MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\).*\-Unicode$/\1/g'` changequote([,]) if test ! "$MAKENSISU_VER" = ""; then MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'` From 78a93845b95a4207581a91a87f8ffdef44c47e59 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Thu, 17 Jan 2013 17:24:11 -0500 Subject: [PATCH 14/70] Bug 834024. Add -include $(DEPTH)/mozilla-config.h to ASFLAGS In order to be able use stuff mozilla-config.h in files included by .S files we need this. I specifically ran into this in pixman with the neon files including pixman-private.h which was customized on MOZ_GFX_OPTIMIZE_MOBILE. --HG-- extra : rebase_source : 93fd47d98ea63450e57a9cfc1e7c637366894914 --- configure.in | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.in b/configure.in index 11b1405b0b5..d01f8102980 100644 --- a/configure.in +++ b/configure.in @@ -1436,6 +1436,7 @@ if test "$GNU_CC"; then _DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT' _USE_CPP_INCLUDE_FLAG=1 + ASFLAGS="$ASFLAGS $_DEFINES_CFLAGS" elif test "$SOLARIS_SUNPRO_CC"; then DSO_CFLAGS='' From fc4b49e6bd174a99fa15640d06458b55bd59d5fa Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 29 Jan 2013 17:11:44 -0500 Subject: [PATCH 15/70] Bug 831561 - SVGClipPathElement should inherit from SVGElement r=longsonr --- content/svg/content/src/crashtests/831561.html | 10 ++++++++++ content/svg/content/src/crashtests/crashtests.list | 1 + dom/webidl/SVGClipPathElement.webidl | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 content/svg/content/src/crashtests/831561.html diff --git a/content/svg/content/src/crashtests/831561.html b/content/svg/content/src/crashtests/831561.html new file mode 100644 index 00000000000..d86a8cb5bd6 --- /dev/null +++ b/content/svg/content/src/crashtests/831561.html @@ -0,0 +1,10 @@ + + + + + + diff --git a/content/svg/content/src/crashtests/crashtests.list b/content/svg/content/src/crashtests/crashtests.list index ee12a17d40e..c27bb832d91 100644 --- a/content/svg/content/src/crashtests/crashtests.list +++ b/content/svg/content/src/crashtests/crashtests.list @@ -61,3 +61,4 @@ load zero-size-image.svg load 723441-1.html load 751515-1.svg load 761507-1.svg +load 831561.html diff --git a/dom/webidl/SVGClipPathElement.webidl b/dom/webidl/SVGClipPathElement.webidl index 0a207df1204..aba8f52fbf6 100644 --- a/dom/webidl/SVGClipPathElement.webidl +++ b/dom/webidl/SVGClipPathElement.webidl @@ -12,8 +12,9 @@ interface SVGAnimatedEnumeration; -interface SVGClipPathElement : SVGTransformableElement { +interface SVGClipPathElement : SVGElement { readonly attribute SVGAnimatedEnumeration clipPathUnits; + readonly attribute SVGAnimatedTransformList transform; }; SVGClipPathElement implements SVGUnitTypes; From 5ca7ffc965bab1f328dcea6402c2dca25ac5104c Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 29 Jan 2013 17:11:44 -0500 Subject: [PATCH 16/70] Bug 832154: Move SVGMarkerElement to mozilla::dom r=bz,longsonr --HG-- rename : content/svg/content/src/nsSVGMarkerElement.cpp => content/svg/content/src/SVGMarkerElement.cpp rename : content/svg/content/src/nsSVGMarkerElement.h => content/svg/content/src/SVGMarkerElement.h --- content/svg/content/src/Makefile.in | 3 +- ...MarkerElement.cpp => SVGMarkerElement.cpp} | 116 +++++++++--------- ...sSVGMarkerElement.h => SVGMarkerElement.h} | 41 ++++--- content/svg/content/src/nsSVGAngle.cpp | 4 +- content/svg/content/src/nsSVGAngle.h | 6 +- layout/svg/nsSVGMarkerFrame.cpp | 10 +- 6 files changed, 97 insertions(+), 83 deletions(-) rename content/svg/content/src/{nsSVGMarkerElement.cpp => SVGMarkerElement.cpp} (75%) rename content/svg/content/src/{nsSVGMarkerElement.h => SVGMarkerElement.h} (82%) diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in index 04fd7cf1584..6f4868c3cda 100644 --- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -49,7 +49,6 @@ CPPSRCS = \ nsSVGInteger.cpp \ nsSVGIntegerPair.cpp \ nsSVGLength2.cpp \ - nsSVGMarkerElement.cpp \ nsSVGNumber2.cpp \ nsSVGNumberPair.cpp \ nsSVGPathDataParser.cpp \ @@ -94,6 +93,7 @@ CPPSRCS = \ SVGLengthListSMILType.cpp \ SVGLineElement.cpp \ SVGLocatableElement.cpp \ + SVGMarkerElement.cpp \ SVGMaskElement.cpp \ SVGMatrix.cpp \ SVGMetadataElement.cpp \ @@ -177,6 +177,7 @@ EXPORTS_mozilla/dom = \ SVGImageElement.h \ SVGLineElement.h \ SVGLocatableElement.h \ + SVGMarkerElement.h \ SVGMaskElement.h \ SVGMatrix.h \ SVGMetadataElement.h \ diff --git a/content/svg/content/src/nsSVGMarkerElement.cpp b/content/svg/content/src/SVGMarkerElement.cpp similarity index 75% rename from content/svg/content/src/nsSVGMarkerElement.cpp rename to content/svg/content/src/SVGMarkerElement.cpp index 51f56351105..7b66ccbcb4e 100644 --- a/content/svg/content/src/nsSVGMarkerElement.cpp +++ b/content/svg/content/src/SVGMarkerElement.cpp @@ -9,16 +9,20 @@ #include "nsCOMPtr.h" #include "SVGAnimatedPreserveAspectRatio.h" #include "nsError.h" -#include "nsSVGMarkerElement.h" +#include "mozilla/dom/SVGMarkerElement.h" #include "gfxMatrix.h" #include "nsContentUtils.h" // NS_ENSURE_FINITE #include "SVGContentUtils.h" #include "SVGAngle.h" -using namespace mozilla; -using namespace mozilla::dom; +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Marker) -nsSVGElement::LengthInfo nsSVGMarkerElement::sLengthInfo[4] = +DOMCI_NODE_DATA(SVGMarkerElement, mozilla::dom::SVGMarkerElement) + +namespace mozilla { +namespace dom { + +nsSVGElement::LengthInfo SVGMarkerElement::sLengthInfo[4] = { { &nsGkAtoms::refX, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, { &nsGkAtoms::refY, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, @@ -26,13 +30,13 @@ nsSVGElement::LengthInfo nsSVGMarkerElement::sLengthInfo[4] = { &nsGkAtoms::markerHeight, 3, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, }; -nsSVGEnumMapping nsSVGMarkerElement::sUnitsMap[] = { +nsSVGEnumMapping SVGMarkerElement::sUnitsMap[] = { {&nsGkAtoms::strokeWidth, nsIDOMSVGMarkerElement::SVG_MARKERUNITS_STROKEWIDTH}, {&nsGkAtoms::userSpaceOnUse, nsIDOMSVGMarkerElement::SVG_MARKERUNITS_USERSPACEONUSE}, {nullptr, 0} }; -nsSVGElement::EnumInfo nsSVGMarkerElement::sEnumInfo[1] = +nsSVGElement::EnumInfo SVGMarkerElement::sEnumInfo[1] = { { &nsGkAtoms::markerUnits, sUnitsMap, @@ -40,13 +44,11 @@ nsSVGElement::EnumInfo nsSVGMarkerElement::sEnumInfo[1] = } }; -nsSVGElement::AngleInfo nsSVGMarkerElement::sAngleInfo[1] = +nsSVGElement::AngleInfo SVGMarkerElement::sAngleInfo[1] = { { &nsGkAtoms::orient, 0, SVG_ANGLETYPE_UNSPECIFIED } }; -NS_IMPL_NS_NEW_SVG_ELEMENT(Marker) - //---------------------------------------------------------------------- // nsISupports methods @@ -61,17 +63,15 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGOrientType::DOMAnimatedEnum) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedEnumeration) NS_INTERFACE_MAP_END -NS_IMPL_ADDREF_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase) -NS_IMPL_RELEASE_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase) +NS_IMPL_ADDREF_INHERITED(SVGMarkerElement,SVGMarkerElementBase) +NS_IMPL_RELEASE_INHERITED(SVGMarkerElement,SVGMarkerElementBase) -DOMCI_NODE_DATA(SVGMarkerElement, nsSVGMarkerElement) - -NS_INTERFACE_TABLE_HEAD(nsSVGMarkerElement) - NS_NODE_INTERFACE_TABLE5(nsSVGMarkerElement, nsIDOMNode, nsIDOMElement, +NS_INTERFACE_TABLE_HEAD(SVGMarkerElement) + NS_NODE_INTERFACE_TABLE5(SVGMarkerElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, nsIDOMSVGFitToViewBox, nsIDOMSVGMarkerElement) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGMarkerElement) -NS_INTERFACE_MAP_END_INHERITING(nsSVGMarkerElementBase) +NS_INTERFACE_MAP_END_INHERITING(SVGMarkerElementBase) //---------------------------------------------------------------------- // Implementation @@ -105,29 +105,29 @@ nsSVGOrientType::ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult, return NS_OK; } -nsSVGMarkerElement::nsSVGMarkerElement(already_AddRefed aNodeInfo) - : nsSVGMarkerElementBase(aNodeInfo), mCoordCtx(nullptr) +SVGMarkerElement::SVGMarkerElement(already_AddRefed aNodeInfo) + : SVGMarkerElementBase(aNodeInfo), mCoordCtx(nullptr) { } //---------------------------------------------------------------------- // nsIDOMNode methods -NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGMarkerElement) +NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMarkerElement) //---------------------------------------------------------------------- // nsIDOMSVGFitToViewBox methods /* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ - NS_IMETHODIMP nsSVGMarkerElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) + NS_IMETHODIMP SVGMarkerElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) { return mViewBox.ToDOMAnimatedRect(aViewBox, this); } /* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ NS_IMETHODIMP -nsSVGMarkerElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) +SVGMarkerElement::GetPreserveAspectRatio(nsISupports + **aPreserveAspectRatio) { nsRefPtr ratio; mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), this); @@ -139,49 +139,49 @@ nsSVGMarkerElement::GetPreserveAspectRatio(nsISupports // nsIDOMSVGMarkerElement methods /* readonly attribute nsIDOMSVGAnimatedLength refX; */ -NS_IMETHODIMP nsSVGMarkerElement::GetRefX(nsIDOMSVGAnimatedLength * *aRefX) +NS_IMETHODIMP SVGMarkerElement::GetRefX(nsIDOMSVGAnimatedLength * *aRefX) { return mLengthAttributes[REFX].ToDOMAnimatedLength(aRefX, this); } /* readonly attribute nsIDOMSVGAnimatedLength refY; */ -NS_IMETHODIMP nsSVGMarkerElement::GetRefY(nsIDOMSVGAnimatedLength * *aRefY) +NS_IMETHODIMP SVGMarkerElement::GetRefY(nsIDOMSVGAnimatedLength * *aRefY) { return mLengthAttributes[REFY].ToDOMAnimatedLength(aRefY, this); } /* readonly attribute nsIDOMSVGAnimatedEnumeration markerUnits; */ -NS_IMETHODIMP nsSVGMarkerElement::GetMarkerUnits(nsIDOMSVGAnimatedEnumeration * *aMarkerUnits) +NS_IMETHODIMP SVGMarkerElement::GetMarkerUnits(nsIDOMSVGAnimatedEnumeration * *aMarkerUnits) { return mEnumAttributes[MARKERUNITS].ToDOMAnimatedEnum(aMarkerUnits, this); } /* readonly attribute nsIDOMSVGAnimatedLength markerWidth; */ -NS_IMETHODIMP nsSVGMarkerElement::GetMarkerWidth(nsIDOMSVGAnimatedLength * *aMarkerWidth) +NS_IMETHODIMP SVGMarkerElement::GetMarkerWidth(nsIDOMSVGAnimatedLength * *aMarkerWidth) { return mLengthAttributes[MARKERWIDTH].ToDOMAnimatedLength(aMarkerWidth, this); } /* readonly attribute nsIDOMSVGAnimatedLength markerHeight; */ -NS_IMETHODIMP nsSVGMarkerElement::GetMarkerHeight(nsIDOMSVGAnimatedLength * *aMarkerHeight) +NS_IMETHODIMP SVGMarkerElement::GetMarkerHeight(nsIDOMSVGAnimatedLength * *aMarkerHeight) { return mLengthAttributes[MARKERHEIGHT].ToDOMAnimatedLength(aMarkerHeight, this); } /* readonly attribute nsIDOMSVGAnimatedEnumeration orientType; */ -NS_IMETHODIMP nsSVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType) +NS_IMETHODIMP SVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType) { return mOrientType.ToDOMAnimatedEnum(aOrientType, this); } /* readonly attribute SVGAnimatedAngle orientAngle; */ -NS_IMETHODIMP nsSVGMarkerElement::GetOrientAngle(nsISupports * *aOrientAngle) +NS_IMETHODIMP SVGMarkerElement::GetOrientAngle(nsISupports * *aOrientAngle) { return mAngleAttributes[ORIENT].ToDOMAnimatedAngle(aOrientAngle, this); } /* void setOrientToAuto (); */ -NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAuto() +NS_IMETHODIMP SVGMarkerElement::SetOrientToAuto() { SetAttr(kNameSpaceID_None, nsGkAtoms::orient, nullptr, NS_LITERAL_STRING("auto"), true); @@ -189,7 +189,7 @@ NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAuto() } /* void setOrientToAngle (in SVGAngle angle); */ -NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAngle(nsISupports *aAngle) +NS_IMETHODIMP SVGMarkerElement::SetOrientToAngle(nsISupports *aAngle) { nsCOMPtr angle = do_QueryInterface(aAngle); if (!angle) @@ -206,7 +206,7 @@ NS_IMETHODIMP nsSVGMarkerElement::SetOrientToAngle(nsISupports *aAngle) // nsIContent methods NS_IMETHODIMP_(bool) -nsSVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const +SVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const { static const MappedAttributeEntry* const map[] = { sFEFloodMap, @@ -216,19 +216,22 @@ nsSVGMarkerElement::IsAttributeMapped(const nsIAtom* name) const sLightingEffectsMap, sMarkersMap, sTextContentElementsMap, - sViewportsMap + sViewportsMap, + sColorMap, + sFillStrokeMap, + sGraphicsMap }; return FindAttributeDependence(name, map) || - nsSVGMarkerElementBase::IsAttributeMapped(name); + SVGMarkerElementBase::IsAttributeMapped(name); } //---------------------------------------------------------------------- // nsSVGElement methods bool -nsSVGMarkerElement::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, - nsAString &aResult) const +SVGMarkerElement::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, + nsAString &aResult) const { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient && @@ -236,13 +239,13 @@ nsSVGMarkerElement::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, aResult.AssignLiteral("auto"); return true; } - return nsSVGMarkerElementBase::GetAttr(aNameSpaceID, aName, aResult); + return SVGMarkerElementBase::GetAttr(aNameSpaceID, aName, aResult); } bool -nsSVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, - const nsAString& aValue, - nsAttrValue& aResult) +SVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, + const nsAString& aValue, + nsAttrValue& aResult) { if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient) { if (aValue.EqualsLiteral("auto")) { @@ -252,13 +255,13 @@ nsSVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, } mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE); } - return nsSVGMarkerElementBase::ParseAttribute(aNameSpaceID, aName, - aValue, aResult); + return SVGMarkerElementBase::ParseAttribute(aNameSpaceID, aName, + aValue, aResult); } nsresult -nsSVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName, - bool aNotify) +SVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName, + bool aNotify) { if (aNamespaceID == kNameSpaceID_None) { if (aName == nsGkAtoms::orient) { @@ -273,14 +276,14 @@ nsSVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName, // nsSVGElement methods void -nsSVGMarkerElement::SetParentCoordCtxProvider(SVGSVGElement *aContext) +SVGMarkerElement::SetParentCoordCtxProvider(SVGSVGElement *aContext) { mCoordCtx = aContext; mViewBoxToViewportTransform = nullptr; } /* virtual */ bool -nsSVGMarkerElement::HasValidDimensions() const +SVGMarkerElement::HasValidDimensions() const { return (!mLengthAttributes[MARKERWIDTH].IsExplicitlySet() || mLengthAttributes[MARKERWIDTH].GetAnimValInSpecifiedUnits() > 0) && @@ -289,34 +292,34 @@ nsSVGMarkerElement::HasValidDimensions() const } nsSVGElement::LengthAttributesInfo -nsSVGMarkerElement::GetLengthInfo() +SVGMarkerElement::GetLengthInfo() { return LengthAttributesInfo(mLengthAttributes, sLengthInfo, ArrayLength(sLengthInfo)); } nsSVGElement::AngleAttributesInfo -nsSVGMarkerElement::GetAngleInfo() +SVGMarkerElement::GetAngleInfo() { return AngleAttributesInfo(mAngleAttributes, sAngleInfo, ArrayLength(sAngleInfo)); } nsSVGElement::EnumAttributesInfo -nsSVGMarkerElement::GetEnumInfo() +SVGMarkerElement::GetEnumInfo() { return EnumAttributesInfo(mEnumAttributes, sEnumInfo, ArrayLength(sEnumInfo)); } nsSVGViewBox * -nsSVGMarkerElement::GetViewBox() +SVGMarkerElement::GetViewBox() { return &mViewBox; } SVGAnimatedPreserveAspectRatio * -nsSVGMarkerElement::GetPreserveAspectRatio() +SVGMarkerElement::GetPreserveAspectRatio() { return &mPreserveAspectRatio; } @@ -325,8 +328,8 @@ nsSVGMarkerElement::GetPreserveAspectRatio() // public helpers gfxMatrix -nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth, - float aX, float aY, float aAutoAngle) +SVGMarkerElement::GetMarkerTransform(float aStrokeWidth, + float aX, float aY, float aAutoAngle) { gfxFloat scale = mEnumAttributes[MARKERUNITS].GetAnimValue() == SVG_MARKERUNITS_STROKEWIDTH ? aStrokeWidth : 1.0; @@ -341,7 +344,7 @@ nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth, } nsSVGViewBoxRect -nsSVGMarkerElement::GetViewBoxRect() +SVGMarkerElement::GetViewBoxRect() { if (mViewBox.IsExplicitlySet()) { return mViewBox.GetAnimValue(); @@ -353,7 +356,7 @@ nsSVGMarkerElement::GetViewBoxRect() } gfxMatrix -nsSVGMarkerElement::GetViewBoxTransform() +SVGMarkerElement::GetViewBoxTransform() { if (!mViewBoxToViewportTransform) { float viewportWidth = @@ -386,4 +389,5 @@ nsSVGMarkerElement::GetViewBoxTransform() return *mViewBoxToViewportTransform; } - +} // namespace dom +} // namespace mozilla diff --git a/content/svg/content/src/nsSVGMarkerElement.h b/content/svg/content/src/SVGMarkerElement.h similarity index 82% rename from content/svg/content/src/nsSVGMarkerElement.h rename to content/svg/content/src/SVGMarkerElement.h index 50fc788c40c..a50abd5dc25 100644 --- a/content/svg/content/src/nsSVGMarkerElement.h +++ b/content/svg/content/src/SVGMarkerElement.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef __NS_SVGMARKERELEMENT_H__ -#define __NS_SVGMARKERELEMENT_H__ +#ifndef mozilla_dom_SVGMarkerElement_h +#define mozilla_dom_SVGMarkerElement_h #include "gfxMatrix.h" #include "nsIDOMSVGFitToViewBox.h" @@ -14,9 +14,17 @@ #include "nsSVGLength2.h" #include "nsSVGViewBox.h" #include "SVGAnimatedPreserveAspectRatio.h" -#include "SVGGraphicsElement.h" +#include "nsSVGElement.h" #include "mozilla/Attributes.h" +class nsSVGMarkerFrame; + +nsresult NS_NewSVGMarkerElement(nsIContent **aResult, + already_AddRefed aNodeInfo); + +namespace mozilla { +namespace dom { + class nsSVGOrientType { public: @@ -68,22 +76,20 @@ private: }; }; -typedef mozilla::dom::SVGGraphicsElement nsSVGMarkerElementBase; +typedef nsSVGElement SVGMarkerElementBase; -class nsSVGMarkerElement : public nsSVGMarkerElementBase, - public nsIDOMSVGMarkerElement, - public nsIDOMSVGFitToViewBox +class SVGMarkerElement : public SVGMarkerElementBase, + public nsIDOMSVGMarkerElement, + public nsIDOMSVGFitToViewBox { - friend class nsSVGMarkerFrame; + friend class ::nsSVGMarkerFrame; protected: - friend nsresult NS_NewSVGMarkerElement(nsIContent **aResult, - already_AddRefed aNodeInfo); - nsSVGMarkerElement(already_AddRefed aNodeInfo); + friend nsresult (::NS_NewSVGMarkerElement(nsIContent **aResult, + already_AddRefed aNodeInfo)); + SVGMarkerElement(already_AddRefed aNodeInfo); public: - typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio; - // interfaces: NS_DECL_ISUPPORTS_INHERITED @@ -125,7 +131,7 @@ protected: const nsAString& aValue, nsAttrValue& aResult); - void SetParentCoordCtxProvider(mozilla::dom::SVGSVGElement *aContext); + void SetParentCoordCtxProvider(SVGSVGElement *aContext); virtual LengthAttributesInfo GetLengthInfo(); virtual AngleAttributesInfo GetAngleInfo(); @@ -152,8 +158,11 @@ protected: // derived properties (from 'orient') handled separately nsSVGOrientType mOrientType; - mozilla::dom::SVGSVGElement *mCoordCtx; + SVGSVGElement *mCoordCtx; nsAutoPtr mViewBoxToViewportTransform; }; -#endif +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_SVGMarkerElement_h diff --git a/content/svg/content/src/nsSVGAngle.cpp b/content/svg/content/src/nsSVGAngle.cpp index a67899b884e..fcc3d043ab5 100644 --- a/content/svg/content/src/nsSVGAngle.cpp +++ b/content/svg/content/src/nsSVGAngle.cpp @@ -9,7 +9,7 @@ #include "prdtoa.h" #include "nsTextFormatter.h" #include "nsSVGAttrTearoffTable.h" -#include "nsSVGMarkerElement.h" +#include "mozilla/dom/SVGMarkerElement.h" #include "nsMathUtils.h" #include "nsContentUtils.h" // NS_ENSURE_FINITE #include "nsSMILValue.h" @@ -366,7 +366,7 @@ nsISMILAttr* nsSVGAngle::ToSMILAttr(nsSVGElement *aSVGElement) { if (aSVGElement->NodeInfo()->Equals(nsGkAtoms::marker, kNameSpaceID_SVG)) { - nsSVGMarkerElement *marker = static_cast(aSVGElement); + SVGMarkerElement *marker = static_cast(aSVGElement); return new SMILOrient(marker->GetOrientType(), this, aSVGElement); } // SMILOrient would not be useful for general angle attributes (also, diff --git a/content/svg/content/src/nsSVGAngle.h b/content/svg/content/src/nsSVGAngle.h index 6a9bd5c887e..5a31fdb46ef 100644 --- a/content/svg/content/src/nsSVGAngle.h +++ b/content/svg/content/src/nsSVGAngle.h @@ -16,7 +16,6 @@ class nsISMILAnimationElement; class nsSMILValue; -class nsSVGOrientType; namespace mozilla { @@ -28,6 +27,7 @@ static const unsigned short SVG_ANGLETYPE_RAD = 3; static const unsigned short SVG_ANGLETYPE_GRAD = 4; namespace dom { +class nsSVGOrientType; class SVGAngle; class SVGAnimatedAngle; } @@ -100,7 +100,7 @@ public: struct SMILOrient MOZ_FINAL : public nsISMILAttr { public: - SMILOrient(nsSVGOrientType* aOrientType, + SMILOrient(mozilla::dom::nsSVGOrientType* aOrientType, nsSVGAngle* aAngle, nsSVGElement* aSVGElement) : mOrientType(aOrientType) @@ -111,7 +111,7 @@ public: // These will stay alive because a nsISMILAttr only lives as long // as the Compositing step, and DOM elements don't get a chance to // die during that. - nsSVGOrientType* mOrientType; + mozilla::dom::nsSVGOrientType* mOrientType; nsSVGAngle* mAngle; nsSVGElement* mSVGElement; diff --git a/layout/svg/nsSVGMarkerFrame.cpp b/layout/svg/nsSVGMarkerFrame.cpp index 065e456a27e..cebe817f433 100644 --- a/layout/svg/nsSVGMarkerFrame.cpp +++ b/layout/svg/nsSVGMarkerFrame.cpp @@ -10,7 +10,7 @@ #include "gfxContext.h" #include "nsRenderingContext.h" #include "nsSVGEffects.h" -#include "nsSVGMarkerElement.h" +#include "mozilla/dom/SVGMarkerElement.h" #include "nsSVGPathGeometryElement.h" #include "nsSVGPathGeometryFrame.h" @@ -80,7 +80,7 @@ nsSVGMarkerFrame::GetCanvasTM(uint32_t aFor) return gfxMatrix(); } - nsSVGMarkerElement *content = static_cast(mContent); + SVGMarkerElement *content = static_cast(mContent); mInUse2 = true; gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor); @@ -106,7 +106,7 @@ nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext, AutoMarkerReferencer markerRef(this, aMarkedFrame); - nsSVGMarkerElement *marker = static_cast(mContent); + SVGMarkerElement *marker = static_cast(mContent); const nsSVGViewBoxRect viewBox = marker->GetViewBoxRect(); @@ -164,7 +164,7 @@ nsSVGMarkerFrame::GetMarkBBoxContribution(const gfxMatrix &aToBBoxUserspace, AutoMarkerReferencer markerRef(this, aMarkedFrame); - nsSVGMarkerElement *content = static_cast(mContent); + SVGMarkerElement *content = static_cast(mContent); const nsSVGViewBoxRect viewBox = content->GetViewBoxRect(); @@ -204,7 +204,7 @@ nsSVGMarkerFrame::GetMarkBBoxContribution(const gfxMatrix &aToBBoxUserspace, void nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGSVGElement *aContext) { - nsSVGMarkerElement *marker = static_cast(mContent); + SVGMarkerElement *marker = static_cast(mContent); marker->SetParentCoordCtxProvider(aContext); } From 95099a92e52d3ca3c3dd67dda00d5d6a8a940521 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 29 Jan 2013 17:11:44 -0500 Subject: [PATCH 17/70] Bug 832154: Convert SVGMarkerElement to WebIDL r=bz --- content/svg/content/src/SVGMarkerElement.cpp | 127 +++++++++++++++---- content/svg/content/src/SVGMarkerElement.h | 19 ++- content/svg/content/src/nsSVGAngle.cpp | 8 +- content/svg/content/src/nsSVGAngle.h | 4 +- dom/webidl/SVGMarkerElement.webidl | 41 ++++++ dom/webidl/WebIDL.mk | 1 + 6 files changed, 167 insertions(+), 33 deletions(-) create mode 100644 dom/webidl/SVGMarkerElement.webidl diff --git a/content/svg/content/src/SVGMarkerElement.cpp b/content/svg/content/src/SVGMarkerElement.cpp index 7b66ccbcb4e..32e537be7bf 100644 --- a/content/svg/content/src/SVGMarkerElement.cpp +++ b/content/svg/content/src/SVGMarkerElement.cpp @@ -9,11 +9,14 @@ #include "nsCOMPtr.h" #include "SVGAnimatedPreserveAspectRatio.h" #include "nsError.h" +#include "mozilla/dom/SVGAngle.h" +#include "mozilla/dom/SVGAnimatedAngle.h" +#include "mozilla/dom/SVGAnimatedLength.h" #include "mozilla/dom/SVGMarkerElement.h" +#include "mozilla/dom/SVGMarkerElementBinding.h" #include "gfxMatrix.h" #include "nsContentUtils.h" // NS_ENSURE_FINITE #include "SVGContentUtils.h" -#include "SVGAngle.h" NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Marker) @@ -22,6 +25,12 @@ DOMCI_NODE_DATA(SVGMarkerElement, mozilla::dom::SVGMarkerElement) namespace mozilla { namespace dom { +JSObject* +SVGMarkerElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) +{ + return SVGMarkerElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); +} + nsSVGElement::LengthInfo SVGMarkerElement::sLengthInfo[4] = { { &nsGkAtoms::refX, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, @@ -93,21 +102,18 @@ nsSVGOrientType::SetBaseValue(uint16_t aValue, return NS_ERROR_DOM_SYNTAX_ERR; } -nsresult -nsSVGOrientType::ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult, - nsSVGElement *aSVGElement) +already_AddRefed +nsSVGOrientType::ToDOMAnimatedEnum(nsSVGElement *aSVGElement) { - *aResult = new DOMAnimatedEnum(this, aSVGElement); - if (!*aResult) - return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF(*aResult); - return NS_OK; + nsCOMPtr toReturn = + new DOMAnimatedEnum(this, aSVGElement); + return toReturn.forget(); } SVGMarkerElement::SVGMarkerElement(already_AddRefed aNodeInfo) : SVGMarkerElementBase(aNodeInfo), mCoordCtx(nullptr) { + SetIsDOMBinding(); } //---------------------------------------------------------------------- @@ -121,18 +127,33 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMarkerElement) /* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ NS_IMETHODIMP SVGMarkerElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) { - return mViewBox.ToDOMAnimatedRect(aViewBox, this); + *aViewBox = ViewBox().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::ViewBox() +{ + nsCOMPtr rect; + mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this); + return rect.forget(); } /* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ NS_IMETHODIMP SVGMarkerElement::GetPreserveAspectRatio(nsISupports **aPreserveAspectRatio) +{ + *aPreserveAspectRatio = PreserveAspectRatio().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::PreserveAspectRatio() { nsRefPtr ratio; mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), this); - ratio.forget(aPreserveAspectRatio); - return NS_OK; + return ratio.forget(); } //---------------------------------------------------------------------- @@ -141,43 +162,92 @@ SVGMarkerElement::GetPreserveAspectRatio(nsISupports /* readonly attribute nsIDOMSVGAnimatedLength refX; */ NS_IMETHODIMP SVGMarkerElement::GetRefX(nsIDOMSVGAnimatedLength * *aRefX) { - return mLengthAttributes[REFX].ToDOMAnimatedLength(aRefX, this); + *aRefX = RefX().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::RefX() +{ + return mLengthAttributes[REFX].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedLength refY; */ NS_IMETHODIMP SVGMarkerElement::GetRefY(nsIDOMSVGAnimatedLength * *aRefY) { - return mLengthAttributes[REFY].ToDOMAnimatedLength(aRefY, this); + *aRefY = RefY().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::RefY() +{ + return mLengthAttributes[REFY].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedEnumeration markerUnits; */ NS_IMETHODIMP SVGMarkerElement::GetMarkerUnits(nsIDOMSVGAnimatedEnumeration * *aMarkerUnits) { - return mEnumAttributes[MARKERUNITS].ToDOMAnimatedEnum(aMarkerUnits, this); + *aMarkerUnits = MarkerUnits().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::MarkerUnits() +{ + return mEnumAttributes[MARKERUNITS].ToDOMAnimatedEnum(this); } /* readonly attribute nsIDOMSVGAnimatedLength markerWidth; */ NS_IMETHODIMP SVGMarkerElement::GetMarkerWidth(nsIDOMSVGAnimatedLength * *aMarkerWidth) { - return mLengthAttributes[MARKERWIDTH].ToDOMAnimatedLength(aMarkerWidth, this); + *aMarkerWidth = MarkerWidth().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::MarkerWidth() +{ + return mLengthAttributes[MARKERWIDTH].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedLength markerHeight; */ NS_IMETHODIMP SVGMarkerElement::GetMarkerHeight(nsIDOMSVGAnimatedLength * *aMarkerHeight) { - return mLengthAttributes[MARKERHEIGHT].ToDOMAnimatedLength(aMarkerHeight, this); + *aMarkerHeight = MarkerHeight().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::MarkerHeight() +{ + return mLengthAttributes[MARKERHEIGHT].ToDOMAnimatedLength(this); } /* readonly attribute nsIDOMSVGAnimatedEnumeration orientType; */ NS_IMETHODIMP SVGMarkerElement::GetOrientType(nsIDOMSVGAnimatedEnumeration * *aOrientType) { - return mOrientType.ToDOMAnimatedEnum(aOrientType, this); + *aOrientType = OrientType().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::OrientType() +{ + return mOrientType.ToDOMAnimatedEnum(this); } /* readonly attribute SVGAnimatedAngle orientAngle; */ NS_IMETHODIMP SVGMarkerElement::GetOrientAngle(nsISupports * *aOrientAngle) { - return mAngleAttributes[ORIENT].ToDOMAnimatedAngle(aOrientAngle, this); + *aOrientAngle = OrientAngle().get(); + return NS_OK; +} + +already_AddRefed +SVGMarkerElement::OrientAngle() +{ + return mAngleAttributes[ORIENT].ToDOMAnimatedAngle(this); } /* void setOrientToAuto (); */ @@ -195,11 +265,20 @@ NS_IMETHODIMP SVGMarkerElement::SetOrientToAngle(nsISupports *aAngle) if (!angle) return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR; - float f = angle->Value(); - NS_ENSURE_FINITE(f, NS_ERROR_DOM_SVG_WRONG_TYPE_ERR); - mAngleAttributes[ORIENT].SetBaseValue(f, this, true); + ErrorResult rv; + SetOrientToAngle(*angle, rv); + return rv.ErrorCode(); +} - return NS_OK; +void +SVGMarkerElement::SetOrientToAngle(SVGAngle& angle, ErrorResult& rv) +{ + float f = angle.Value(); + if (!NS_finite(f)) { + rv.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR); + return; + } + mAngleAttributes[ORIENT].SetBaseValue(f, this, true); } //---------------------------------------------------------------------- diff --git a/content/svg/content/src/SVGMarkerElement.h b/content/svg/content/src/SVGMarkerElement.h index a50abd5dc25..fd66547f13f 100644 --- a/content/svg/content/src/SVGMarkerElement.h +++ b/content/svg/content/src/SVGMarkerElement.h @@ -48,8 +48,8 @@ public: uint16_t GetAnimValue() const { return mAnimVal; } - nsresult ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult, - nsSVGElement* aSVGElement); + already_AddRefed + ToDOMAnimatedEnum(nsSVGElement* aSVGElement); private: nsSVGEnumValue mAnimVal; @@ -88,6 +88,7 @@ protected: friend nsresult (::NS_NewSVGMarkerElement(nsIContent **aResult, already_AddRefed aNodeInfo)); SVGMarkerElement(already_AddRefed aNodeInfo); + virtual JSObject* WrapNode(JSContext *cx, JSObject *scope, bool *triedToWrap) MOZ_OVERRIDE; public: // interfaces: @@ -125,6 +126,20 @@ public: virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } + + // WebIDL + already_AddRefed ViewBox(); + already_AddRefed PreserveAspectRatio(); + already_AddRefed RefX(); + already_AddRefed RefY(); + already_AddRefed MarkerUnits(); + already_AddRefed MarkerWidth(); + already_AddRefed MarkerHeight(); + already_AddRefed OrientType(); + already_AddRefed OrientAngle(); + // We can use the XPIDL SetOrientToAuto + void SetOrientToAngle(SVGAngle& angle, ErrorResult& rv); + protected: virtual bool ParseAttribute(int32_t aNameSpaceID, nsIAtom* aName, diff --git a/content/svg/content/src/nsSVGAngle.cpp b/content/svg/content/src/nsSVGAngle.cpp index fcc3d043ab5..526c5e2b949 100644 --- a/content/svg/content/src/nsSVGAngle.cpp +++ b/content/svg/content/src/nsSVGAngle.cpp @@ -342,9 +342,8 @@ nsSVGAngle::SetAnimValue(float aValue, uint8_t aUnit, nsSVGElement *aSVGElement) aSVGElement->DidAnimateAngle(mAttrEnum); } -nsresult -nsSVGAngle::ToDOMAnimatedAngle(nsISupports **aResult, - nsSVGElement *aSVGElement) +already_AddRefed +nsSVGAngle::ToDOMAnimatedAngle(nsSVGElement *aSVGElement) { nsRefPtr domAnimatedAngle = sSVGAnimatedAngleTearoffTable.GetTearoff(this); @@ -353,8 +352,7 @@ nsSVGAngle::ToDOMAnimatedAngle(nsISupports **aResult, sSVGAnimatedAngleTearoffTable.AddTearoff(this, domAnimatedAngle); } - domAnimatedAngle.forget(aResult); - return NS_OK; + return domAnimatedAngle.forget(); } SVGAnimatedAngle::~SVGAnimatedAngle() diff --git a/content/svg/content/src/nsSVGAngle.h b/content/svg/content/src/nsSVGAngle.h index 5a31fdb46ef..5d26c2ac083 100644 --- a/content/svg/content/src/nsSVGAngle.h +++ b/content/svg/content/src/nsSVGAngle.h @@ -68,8 +68,8 @@ public: float GetAnimValInSpecifiedUnits() const { return mAnimVal; } static nsresult ToDOMSVGAngle(nsISupports **aResult); - nsresult ToDOMAnimatedAngle(nsISupports **aResult, - nsSVGElement* aSVGElement); + already_AddRefed + ToDOMAnimatedAngle(nsSVGElement* aSVGElement); // Returns a new nsISMILAttr object that the caller must delete nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement); diff --git a/dom/webidl/SVGMarkerElement.webidl b/dom/webidl/SVGMarkerElement.webidl new file mode 100644 index 00000000000..f80ef0d159c --- /dev/null +++ b/dom/webidl/SVGMarkerElement.webidl @@ -0,0 +1,41 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://www.w3.org/TR/SVG2/ + * + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +interface SVGAnimatedEnumeration; + +interface SVGMarkerElement : SVGElement { + + // Marker Unit Types + const unsigned short SVG_MARKERUNITS_UNKNOWN = 0; + const unsigned short SVG_MARKERUNITS_USERSPACEONUSE = 1; + const unsigned short SVG_MARKERUNITS_STROKEWIDTH = 2; + + // Marker Orientation Types + const unsigned short SVG_MARKER_ORIENT_UNKNOWN = 0; + const unsigned short SVG_MARKER_ORIENT_AUTO = 1; + const unsigned short SVG_MARKER_ORIENT_ANGLE = 2; + + readonly attribute SVGAnimatedLength refX; + readonly attribute SVGAnimatedLength refY; + readonly attribute SVGAnimatedEnumeration markerUnits; + readonly attribute SVGAnimatedLength markerWidth; + readonly attribute SVGAnimatedLength markerHeight; + readonly attribute SVGAnimatedEnumeration orientType; + readonly attribute SVGAnimatedAngle orientAngle; + + void setOrientToAuto(); + [Throws] + void setOrientToAngle(SVGAngle angle); +}; + +SVGMarkerElement implements SVGFitToViewBox; + diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 7cc3d220d2e..b91a5616d6a 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -133,6 +133,7 @@ webidl_files = \ SVGLinearGradientElement.webidl \ SVGLineElement.webidl \ SVGLocatableElement.webidl \ + SVGMarkerElement.webidl \ SVGMaskElement.webidl \ SVGMatrix.webidl \ SVGMetadataElement.webidl \ From a63a685d7ce67bf37e80262ce51b124d48aafe4c Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 29 Jan 2013 17:11:45 -0500 Subject: [PATCH 18/70] Bug 835195: Remove nsIDOMSVGTests r=bz --- content/svg/content/src/DOMSVGTests.cpp | 34 +------------------ content/svg/content/src/DOMSVGTests.h | 12 +++++-- .../svg/content/src/SVGAnimationElement.cpp | 2 +- .../svg/content/src/SVGGraphicsElement.cpp | 2 +- content/svg/content/src/SVGSymbolElement.cpp | 2 +- dom/base/nsDOMClassInfo.cpp | 7 ---- dom/interfaces/svg/Makefile.in | 1 - dom/interfaces/svg/nsIDOMSVGTests.idl | 17 ---------- 8 files changed, 13 insertions(+), 64 deletions(-) delete mode 100644 dom/interfaces/svg/nsIDOMSVGTests.idl diff --git a/content/svg/content/src/DOMSVGTests.cpp b/content/svg/content/src/DOMSVGTests.cpp index 12c23186749..7f9af2a57a3 100644 --- a/content/svg/content/src/DOMSVGTests.cpp +++ b/content/svg/content/src/DOMSVGTests.cpp @@ -13,7 +13,7 @@ using namespace mozilla; -NS_IMPL_ISUPPORTS1(DOMSVGTests, nsIDOMSVGTests) +NS_IMPL_ISUPPORTS0(DOMSVGTests) nsIAtom** DOMSVGTests::sStringListNames[3] = { @@ -27,14 +27,6 @@ DOMSVGTests::DOMSVGTests() mStringListAttributes[LANGUAGE].SetIsCommaSeparated(true); } -/* readonly attribute nsIDOMSVGStringList requiredFeatures; */ -NS_IMETHODIMP -DOMSVGTests::GetRequiredFeatures(nsIDOMSVGStringList * *aRequiredFeatures) -{ - *aRequiredFeatures = RequiredFeatures().get(); - return NS_OK; -} - already_AddRefed DOMSVGTests::RequiredFeatures() { @@ -43,14 +35,6 @@ DOMSVGTests::RequiredFeatures() &mStringListAttributes[FEATURES], element, true, FEATURES).get(); } -/* readonly attribute nsIDOMSVGStringList requiredExtensions; */ -NS_IMETHODIMP -DOMSVGTests::GetRequiredExtensions(nsIDOMSVGStringList * *aRequiredExtensions) -{ - *aRequiredExtensions = RequiredExtensions().get(); - return NS_OK; -} - already_AddRefed DOMSVGTests::RequiredExtensions() { @@ -59,14 +43,6 @@ DOMSVGTests::RequiredExtensions() &mStringListAttributes[EXTENSIONS], element, true, EXTENSIONS).get(); } -/* readonly attribute nsIDOMSVGStringList systemLanguage; */ -NS_IMETHODIMP -DOMSVGTests::GetSystemLanguage(nsIDOMSVGStringList * *aSystemLanguage) -{ - *aSystemLanguage = SystemLanguage().get(); - return NS_OK; -} - already_AddRefed DOMSVGTests::SystemLanguage() { @@ -75,14 +51,6 @@ DOMSVGTests::SystemLanguage() &mStringListAttributes[LANGUAGE], element, true, LANGUAGE).get(); } -/* boolean hasExtension (in DOMString extension); */ -NS_IMETHODIMP -DOMSVGTests::HasExtension(const nsAString & extension, bool *_retval) -{ - *_retval = HasExtension(extension); - return NS_OK; -} - bool DOMSVGTests::HasExtension(const nsAString& aExtension) { diff --git a/content/svg/content/src/DOMSVGTests.h b/content/svg/content/src/DOMSVGTests.h index 4add8b70e28..2f07c1a20d1 100644 --- a/content/svg/content/src/DOMSVGTests.h +++ b/content/svg/content/src/DOMSVGTests.h @@ -6,24 +6,28 @@ #ifndef MOZILLA_DOMSVGTESTS_H__ #define MOZILLA_DOMSVGTESTS_H__ -#include "nsIDOMSVGTests.h" #include "nsStringFwd.h" #include "SVGStringList.h" #include "nsCOMPtr.h" class nsAttrValue; class nsIAtom; +class nsIDOMSVGStringList; class nsString; namespace mozilla { class DOMSVGStringList; } -class DOMSVGTests : public nsIDOMSVGTests +#define MOZILLA_DOMSVGTESTS_IID \ + { 0x92370da8, 0xda28, 0x4895, \ + {0x9b, 0x1b, 0xe0, 0x06, 0x0d, 0xb7, 0x3f, 0xc3 } } + +class DOMSVGTests : public nsISupports { public: + NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGTESTS_IID) NS_DECL_ISUPPORTS - NS_DECL_NSIDOMSVGTESTS DOMSVGTests(); virtual ~DOMSVGTests() {} @@ -97,4 +101,6 @@ private: static nsIAtom** sStringListNames[3]; }; +NS_DEFINE_STATIC_IID_ACCESSOR(DOMSVGTests, MOZILLA_DOMSVGTESTS_IID) + #endif // MOZILLA_DOMSVGTESTS_H__ diff --git a/content/svg/content/src/SVGAnimationElement.cpp b/content/svg/content/src/SVGAnimationElement.cpp index a9ca16eef74..06c2863ec7c 100644 --- a/content/svg/content/src/SVGAnimationElement.cpp +++ b/content/svg/content/src/SVGAnimationElement.cpp @@ -23,7 +23,7 @@ NS_IMPL_RELEASE_INHERITED(SVGAnimationElement, SVGAnimationElementBase) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGAnimationElement) NS_INTERFACE_MAP_ENTRY(nsISMILAnimationElement) NS_INTERFACE_MAP_ENTRY(nsIDOMElementTimeControl) - NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests) + NS_INTERFACE_MAP_ENTRY(DOMSVGTests) NS_INTERFACE_MAP_END_INHERITING(SVGAnimationElementBase) // Cycle collection magic -- based on nsSVGUseElement diff --git a/content/svg/content/src/SVGGraphicsElement.cpp b/content/svg/content/src/SVGGraphicsElement.cpp index a8308e80ad8..b014d40a6df 100644 --- a/content/svg/content/src/SVGGraphicsElement.cpp +++ b/content/svg/content/src/SVGGraphicsElement.cpp @@ -16,7 +16,7 @@ NS_IMPL_ADDREF_INHERITED(SVGGraphicsElement, SVGGraphicsElementBase) NS_IMPL_RELEASE_INHERITED(SVGGraphicsElement, SVGGraphicsElementBase) NS_INTERFACE_MAP_BEGIN(SVGGraphicsElement) - NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests) + NS_INTERFACE_MAP_ENTRY(DOMSVGTests) NS_INTERFACE_MAP_END_INHERITING(SVGGraphicsElementBase) //---------------------------------------------------------------------- diff --git a/content/svg/content/src/SVGSymbolElement.cpp b/content/svg/content/src/SVGSymbolElement.cpp index b34ce9a5f69..83c2e706aa0 100644 --- a/content/svg/content/src/SVGSymbolElement.cpp +++ b/content/svg/content/src/SVGSymbolElement.cpp @@ -28,7 +28,7 @@ NS_IMPL_RELEASE_INHERITED(SVGSymbolElement,SVGSymbolElementBase) NS_INTERFACE_TABLE_HEAD(SVGSymbolElement) NS_NODE_INTERFACE_TABLE6(SVGSymbolElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, nsIDOMSVGFitToViewBox, - nsIDOMSVGSymbolElement, nsIDOMSVGTests) + nsIDOMSVGSymbolElement, DOMSVGTests) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSymbolElement) NS_INTERFACE_MAP_END_INHERITING(SVGSymbolElementBase) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index a6eda9a3591..fa22e5f7c6a 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -358,7 +358,6 @@ #include "nsIDOMSVGSVGElement.h" #include "nsIDOMSVGSwitchElement.h" #include "nsIDOMSVGSymbolElement.h" -#include "nsIDOMSVGTests.h" #include "nsIDOMSVGTextElement.h" #include "nsIDOMSVGTextPathElement.h" #include "nsIDOMSVGTitleElement.h" @@ -2992,7 +2991,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES #define DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES \ - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) \ DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES // XXX - the proto chain stuff is sort of hackish, because of the MI in @@ -3026,7 +3024,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGAnimateElement, nsIDOMSVGAnimateElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3035,7 +3032,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGAnimateTransformElement, nsIDOMSVGAnimateTransformElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateTransformElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3044,7 +3040,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGAnimateMotionElement, nsIDOMSVGAnimateMotionElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateMotionElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3053,7 +3048,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGSetElement, nsIDOMSVGSetElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSetElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3353,7 +3347,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGSymbolElement, nsIDOMSVGSymbolElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSymbolElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END diff --git a/dom/interfaces/svg/Makefile.in b/dom/interfaces/svg/Makefile.in index 5249d1b865e..9d5acf75009 100644 --- a/dom/interfaces/svg/Makefile.in +++ b/dom/interfaces/svg/Makefile.in @@ -65,7 +65,6 @@ XPIDLSRCS = \ nsIDOMSVGStyleElement.idl \ nsIDOMSVGSwitchElement.idl \ nsIDOMSVGSymbolElement.idl \ - nsIDOMSVGTests.idl \ nsIDOMSVGTextContentElement.idl \ nsIDOMSVGTextElement.idl \ nsIDOMSVGTextPathElement.idl \ diff --git a/dom/interfaces/svg/nsIDOMSVGTests.idl b/dom/interfaces/svg/nsIDOMSVGTests.idl deleted file mode 100644 index 0dd35852010..00000000000 --- a/dom/interfaces/svg/nsIDOMSVGTests.idl +++ /dev/null @@ -1,17 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsIDOMSVGStringList.idl" - -[scriptable, uuid(b6186ed0-0861-11e1-be50-0800200c9a66)] -interface nsIDOMSVGTests : nsISupports -{ - readonly attribute nsIDOMSVGStringList requiredFeatures; - readonly attribute nsIDOMSVGStringList requiredExtensions; - readonly attribute nsIDOMSVGStringList systemLanguage; - - boolean hasExtension(in DOMString extension); -}; - From 614b4ac1bcc7ef8da83f51b610e6c2d584a0e423 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 29 Jan 2013 17:11:45 -0500 Subject: [PATCH 19/70] Bug 835195: Remove nsIDOMSVGFitToViewBox r=bz --- content/svg/content/src/SVGMarkerElement.cpp | 21 ++--------------- content/svg/content/src/SVGMarkerElement.h | 5 +--- content/svg/content/src/SVGPatternElement.cpp | 20 ++-------------- content/svg/content/src/SVGPatternElement.h | 7 +----- content/svg/content/src/SVGSVGElement.cpp | 23 ++----------------- content/svg/content/src/SVGSVGElement.h | 5 +--- content/svg/content/src/SVGSymbolElement.cpp | 21 ++--------------- content/svg/content/src/SVGSymbolElement.h | 5 +--- content/svg/content/src/SVGViewElement.cpp | 23 ++----------------- content/svg/content/src/SVGViewElement.h | 5 +--- dom/base/nsDOMClassInfo.cpp | 6 ----- dom/interfaces/svg/Makefile.in | 1 - dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl | 15 ------------ 13 files changed, 15 insertions(+), 142 deletions(-) delete mode 100644 dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl diff --git a/content/svg/content/src/SVGMarkerElement.cpp b/content/svg/content/src/SVGMarkerElement.cpp index 32e537be7bf..21839e33a07 100644 --- a/content/svg/content/src/SVGMarkerElement.cpp +++ b/content/svg/content/src/SVGMarkerElement.cpp @@ -76,8 +76,8 @@ NS_IMPL_ADDREF_INHERITED(SVGMarkerElement,SVGMarkerElementBase) NS_IMPL_RELEASE_INHERITED(SVGMarkerElement,SVGMarkerElementBase) NS_INTERFACE_TABLE_HEAD(SVGMarkerElement) - NS_NODE_INTERFACE_TABLE5(SVGMarkerElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, nsIDOMSVGFitToViewBox, + NS_NODE_INTERFACE_TABLE4(SVGMarkerElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement, nsIDOMSVGMarkerElement) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGMarkerElement) NS_INTERFACE_MAP_END_INHERITING(SVGMarkerElementBase) @@ -122,14 +122,6 @@ SVGMarkerElement::SVGMarkerElement(already_AddRefed aNodeInfo) NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMarkerElement) //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ - NS_IMETHODIMP SVGMarkerElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGMarkerElement::ViewBox() @@ -139,15 +131,6 @@ SVGMarkerElement::ViewBox() return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGMarkerElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGMarkerElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGMarkerElement.h b/content/svg/content/src/SVGMarkerElement.h index fd66547f13f..d99b7284c8b 100644 --- a/content/svg/content/src/SVGMarkerElement.h +++ b/content/svg/content/src/SVGMarkerElement.h @@ -7,7 +7,6 @@ #define mozilla_dom_SVGMarkerElement_h #include "gfxMatrix.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsIDOMSVGMarkerElement.h" #include "nsSVGAngle.h" #include "nsSVGEnum.h" @@ -79,8 +78,7 @@ private: typedef nsSVGElement SVGMarkerElementBase; class SVGMarkerElement : public SVGMarkerElementBase, - public nsIDOMSVGMarkerElement, - public nsIDOMSVGFitToViewBox + public nsIDOMSVGMarkerElement { friend class ::nsSVGMarkerFrame; @@ -95,7 +93,6 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGMARKERELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx I wish we could use virtual inheritance NS_FORWARD_NSIDOMNODE_TO_NSINODE diff --git a/content/svg/content/src/SVGPatternElement.cpp b/content/svg/content/src/SVGPatternElement.cpp index 62a03cf2175..fb2c56ff4e2 100644 --- a/content/svg/content/src/SVGPatternElement.cpp +++ b/content/svg/content/src/SVGPatternElement.cpp @@ -60,9 +60,9 @@ NS_IMPL_ADDREF_INHERITED(SVGPatternElement,SVGPatternElementBase) NS_IMPL_RELEASE_INHERITED(SVGPatternElement,SVGPatternElementBase) NS_INTERFACE_TABLE_HEAD(SVGPatternElement) - NS_NODE_INTERFACE_TABLE7(SVGPatternElement, nsIDOMNode, nsIDOMElement, + NS_NODE_INTERFACE_TABLE6(SVGPatternElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGFitToViewBox, nsIDOMSVGURIReference, + nsIDOMSVGURIReference, nsIDOMSVGPatternElement, nsIDOMSVGUnitTypes) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPatternElement) NS_INTERFACE_MAP_END_INHERITING(SVGPatternElementBase) @@ -82,14 +82,6 @@ SVGPatternElement::SVGPatternElement(already_AddRefed aNodeInfo) NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPatternElement) //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP SVGPatternElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGPatternElement::ViewBox() @@ -99,14 +91,6 @@ SVGPatternElement::ViewBox() return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGPatternElement::GetPreserveAspectRatio(nsISupports **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGPatternElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGPatternElement.h b/content/svg/content/src/SVGPatternElement.h index f4a34be5b61..2b70b1c857c 100644 --- a/content/svg/content/src/SVGPatternElement.h +++ b/content/svg/content/src/SVGPatternElement.h @@ -6,7 +6,6 @@ #ifndef mozilla_dom_SVGPatternElement_h #define mozilla_dom_SVGPatternElement_h -#include "nsIDOMSVGFitToViewBox.h" #include "nsIDOMSVGPatternElement.h" #include "nsIDOMSVGUnitTypes.h" #include "nsIDOMSVGURIReference.h" @@ -33,7 +32,6 @@ typedef nsSVGElement SVGPatternElementBase; class SVGPatternElement MOZ_FINAL : public SVGPatternElementBase, public nsIDOMSVGPatternElement, public nsIDOMSVGURIReference, - public nsIDOMSVGFitToViewBox, public nsIDOMSVGUnitTypes { friend class ::nsSVGPatternFrame; @@ -56,9 +54,6 @@ public: // URI Reference NS_DECL_NSIDOMSVGURIREFERENCE - // FitToViewbox - NS_DECL_NSIDOMSVGFITTOVIEWBOX - NS_FORWARD_NSIDOMNODE_TO_NSINODE NS_FORWARD_NSIDOMELEMENT_TO_GENERIC NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::) @@ -117,7 +112,7 @@ protected: nsSVGString mStringAttributes[1]; static StringInfo sStringInfo[1]; - // nsIDOMSVGFitToViewbox properties + // SVGFitToViewbox properties nsSVGViewBox mViewBox; SVGAnimatedPreserveAspectRatio mPreserveAspectRatio; }; diff --git a/content/svg/content/src/SVGSVGElement.cpp b/content/svg/content/src/SVGSVGElement.cpp index bd8a20292d8..a4964781813 100644 --- a/content/svg/content/src/SVGSVGElement.cpp +++ b/content/svg/content/src/SVGSVGElement.cpp @@ -146,10 +146,9 @@ NS_IMPL_ADDREF_INHERITED(SVGSVGElement,SVGSVGElementBase) NS_IMPL_RELEASE_INHERITED(SVGSVGElement,SVGSVGElementBase) NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGSVGElement) - NS_NODE_INTERFACE_TABLE5(SVGSVGElement, nsIDOMNode, nsIDOMElement, + NS_NODE_INTERFACE_TABLE4(SVGSVGElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, - nsIDOMSVGSVGElement, - nsIDOMSVGFitToViewBox) + nsIDOMSVGSVGElement) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSVGElement) NS_INTERFACE_MAP_END_INHERITING(SVGSVGElementBase) @@ -675,15 +674,6 @@ SVGSVGElement::GetElementById(const nsAString& elementId, ErrorResult& rv) } //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP -SVGSVGElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGSVGElement::ViewBox() @@ -693,15 +683,6 @@ SVGSVGElement::ViewBox() return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGSVGElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGSVGElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGSVGElement.h b/content/svg/content/src/SVGSVGElement.h index d184569f9f9..d1b4b157c18 100644 --- a/content/svg/content/src/SVGSVGElement.h +++ b/content/svg/content/src/SVGSVGElement.h @@ -7,7 +7,6 @@ #define mozilla_dom_SVGSVGElement_h #include "mozilla/dom/FromParser.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsISVGPoint.h" #include "nsIDOMSVGSVGElement.h" #include "nsSVGEnum.h" @@ -80,8 +79,7 @@ public: typedef SVGGraphicsElement SVGSVGElementBase; class SVGSVGElement MOZ_FINAL : public SVGSVGElementBase, - public nsIDOMSVGSVGElement, - public nsIDOMSVGFitToViewBox + public nsIDOMSVGSVGElement { friend class ::nsSVGOuterSVGFrame; friend class ::nsSVGInnerSVGFrame; @@ -101,7 +99,6 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSVGElement, SVGSVGElementBase) NS_DECL_NSIDOMSVGSVGELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx I wish we could use virtual inheritance NS_FORWARD_NSIDOMNODE_TO_NSINODE diff --git a/content/svg/content/src/SVGSymbolElement.cpp b/content/svg/content/src/SVGSymbolElement.cpp index 83c2e706aa0..38741eacbbd 100644 --- a/content/svg/content/src/SVGSymbolElement.cpp +++ b/content/svg/content/src/SVGSymbolElement.cpp @@ -26,8 +26,8 @@ NS_IMPL_ADDREF_INHERITED(SVGSymbolElement,SVGSymbolElementBase) NS_IMPL_RELEASE_INHERITED(SVGSymbolElement,SVGSymbolElementBase) NS_INTERFACE_TABLE_HEAD(SVGSymbolElement) - NS_NODE_INTERFACE_TABLE6(SVGSymbolElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, nsIDOMSVGFitToViewBox, + NS_NODE_INTERFACE_TABLE5(SVGSymbolElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement, nsIDOMSVGSymbolElement, DOMSVGTests) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSymbolElement) NS_INTERFACE_MAP_END_INHERITING(SVGSymbolElementBase) @@ -48,14 +48,6 @@ SVGSymbolElement::SVGSymbolElement(already_AddRefed aNodeInfo) NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSymbolElement) //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP SVGSymbolElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGSymbolElement::ViewBox() @@ -65,15 +57,6 @@ SVGSymbolElement::ViewBox() return rect.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGSymbolElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGSymbolElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGSymbolElement.h b/content/svg/content/src/SVGSymbolElement.h index f016bc88353..95b7a3690a1 100644 --- a/content/svg/content/src/SVGSymbolElement.h +++ b/content/svg/content/src/SVGSymbolElement.h @@ -11,7 +11,6 @@ #include "nsSVGElement.h" #include "nsSVGViewBox.h" #include "SVGAnimatedPreserveAspectRatio.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsGkAtoms.h" nsresult NS_NewSVGSymbolElement(nsIContent **aResult, @@ -24,8 +23,7 @@ typedef nsSVGElement SVGSymbolElementBase; class SVGSymbolElement MOZ_FINAL : public SVGSymbolElementBase, public nsIDOMSVGSymbolElement, - public DOMSVGTests, - public nsIDOMSVGFitToViewBox + public DOMSVGTests { protected: friend nsresult (::NS_NewSVGSymbolElement(nsIContent **aResult, @@ -38,7 +36,6 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGSYMBOLELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx I wish we could use virtual inheritance NS_FORWARD_NSIDOMNODE_TO_NSINODE diff --git a/content/svg/content/src/SVGViewElement.cpp b/content/svg/content/src/SVGViewElement.cpp index 303dbeb931a..07acc04bcba 100644 --- a/content/svg/content/src/SVGViewElement.cpp +++ b/content/svg/content/src/SVGViewElement.cpp @@ -46,9 +46,8 @@ NS_IMPL_ADDREF_INHERITED(SVGViewElement,SVGViewElementBase) NS_IMPL_RELEASE_INHERITED(SVGViewElement,SVGViewElementBase) NS_INTERFACE_TABLE_HEAD(SVGViewElement) - NS_NODE_INTERFACE_TABLE5(SVGViewElement, nsIDOMNode, nsIDOMElement, - nsIDOMSVGElement, nsIDOMSVGViewElement, - nsIDOMSVGFitToViewBox) + NS_NODE_INTERFACE_TABLE4(SVGViewElement, nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement, nsIDOMSVGViewElement) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGViewElement) NS_INTERFACE_MAP_END_INHERITING(SVGViewElementBase) @@ -78,15 +77,6 @@ SVGViewElement::SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv) } //---------------------------------------------------------------------- -// nsIDOMSVGFitToViewBox methods - -/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */ -NS_IMETHODIMP -SVGViewElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox) -{ - *aViewBox = ViewBox().get(); - return NS_OK; -} already_AddRefed SVGViewElement::ViewBox() @@ -96,15 +86,6 @@ SVGViewElement::ViewBox() return box.forget(); } -/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */ -NS_IMETHODIMP -SVGViewElement::GetPreserveAspectRatio(nsISupports - **aPreserveAspectRatio) -{ - *aPreserveAspectRatio = PreserveAspectRatio().get(); - return NS_OK; -} - already_AddRefed SVGViewElement::PreserveAspectRatio() { diff --git a/content/svg/content/src/SVGViewElement.h b/content/svg/content/src/SVGViewElement.h index abdd8485bbf..dd0526c8e04 100644 --- a/content/svg/content/src/SVGViewElement.h +++ b/content/svg/content/src/SVGViewElement.h @@ -7,7 +7,6 @@ #define mozilla_dom_SVGViewElement_h #include "nsIDOMSVGViewElement.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsSVGElement.h" #include "nsSVGEnum.h" #include "nsSVGViewBox.h" @@ -32,8 +31,7 @@ namespace dom { class SVGSVGElement; class SVGViewElement : public SVGViewElementBase, - public nsIDOMSVGViewElement, - public nsIDOMSVGFitToViewBox + public nsIDOMSVGViewElement { protected: friend class mozilla::SVGFragmentIdentifier; @@ -49,7 +47,6 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMSVGVIEWELEMENT - NS_DECL_NSIDOMSVGFITTOVIEWBOX // xxx If xpcom allowed virtual inheritance we wouldn't need to // forward here :-( diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index fa22e5f7c6a..b0cdc05a539 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -335,7 +335,6 @@ #include "nsIDOMSVGEvent.h" #include "nsIDOMSVGFilterElement.h" #include "nsIDOMSVGFilters.h" -#include "nsIDOMSVGFitToViewBox.h" #include "nsIDOMSVGForeignObjectElem.h" #include "nsIDOMSVGGElement.h" #include "nsIDOMSVGGradientElement.h" @@ -3265,7 +3264,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGMarkerElement, nsIDOMSVGMarkerElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMarkerElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END @@ -3287,7 +3285,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGPatternElement, nsIDOMSVGPatternElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPatternElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES @@ -3335,7 +3332,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGSVGElement, nsIDOMSVGSVGElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSVGElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END @@ -3347,7 +3343,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(SVGSymbolElement, nsIDOMSVGSymbolElement) DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSymbolElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END @@ -3383,7 +3378,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(SVGViewElement, nsIDOMSVGViewElement) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox) DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END diff --git a/dom/interfaces/svg/Makefile.in b/dom/interfaces/svg/Makefile.in index 9d5acf75009..cf25cab7192 100644 --- a/dom/interfaces/svg/Makefile.in +++ b/dom/interfaces/svg/Makefile.in @@ -39,7 +39,6 @@ XPIDLSRCS = \ nsIDOMSVGEvent.idl \ nsIDOMSVGFilterElement.idl \ nsIDOMSVGFilters.idl \ - nsIDOMSVGFitToViewBox.idl \ nsIDOMSVGForeignObjectElem.idl \ nsIDOMSVGGElement.idl \ nsIDOMSVGGradientElement.idl \ diff --git a/dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl b/dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl deleted file mode 100644 index bf5f87e7caf..00000000000 --- a/dom/interfaces/svg/nsIDOMSVGFitToViewBox.idl +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "domstubs.idl" - -interface nsIDOMSVGAnimatedRect; - -[scriptable, uuid(089410F3-9777-44f1-A882-AB4225696434)] -interface nsIDOMSVGFitToViewBox : nsISupports -{ - readonly attribute nsIDOMSVGAnimatedRect viewBox; - readonly attribute nsISupports preserveAspectRatio; -}; From 129a025deea1d55421c0c242958685ad89cf7a89 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Mon, 28 Jan 2013 16:33:17 -0800 Subject: [PATCH 20/70] Bug 835648 - Move typed enum support to a new header. r=Ms2ger --HG-- extra : rebase_source : 8c912fba889c1c5435e3619714071502fbfb30a3 --- content/events/src/nsEventStateManager.h | 2 + content/media/webaudio/AudioEventTimeline.h | 4 +- content/media/webaudio/BiquadFilterNode.h | 2 +- content/media/webaudio/PannerNode.h | 2 +- .../svg/content/src/SVGPreserveAspectRatio.h | 2 + editor/libeditor/base/nsEditor.h | 3 +- layout/generic/nsIFrame.h | 2 +- mfbt/Attributes.h | 174 -------------- mfbt/TypedEnum.h | 212 ++++++++++++++++++ mfbt/exported_headers.mk | 3 +- 10 files changed, 226 insertions(+), 180 deletions(-) create mode 100644 mfbt/TypedEnum.h diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index 642d8e99d7a..4659e024482 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -6,6 +6,8 @@ #ifndef nsEventStateManager_h__ #define nsEventStateManager_h__ +#include "mozilla/TypedEnum.h" + #include "nsEvent.h" #include "nsGUIEvent.h" #include "nsIContent.h" diff --git a/content/media/webaudio/AudioEventTimeline.h b/content/media/webaudio/AudioEventTimeline.h index d931975087e..4b49ebf9bec 100644 --- a/content/media/webaudio/AudioEventTimeline.h +++ b/content/media/webaudio/AudioEventTimeline.h @@ -7,8 +7,10 @@ #ifndef AudioEventTimeline_h_ #define AudioEventTimeline_h_ -#include "mozilla/Attributes.h" +#include "mozilla/Assertions.h" #include "mozilla/FloatingPoint.h" +#include "mozilla/TypedEnum.h" + #include "nsTArray.h" #include "math.h" diff --git a/content/media/webaudio/BiquadFilterNode.h b/content/media/webaudio/BiquadFilterNode.h index da77897be1f..fa4ef74e941 100644 --- a/content/media/webaudio/BiquadFilterNode.h +++ b/content/media/webaudio/BiquadFilterNode.h @@ -9,8 +9,8 @@ #include "AudioNode.h" #include "AudioParam.h" -#include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" +#include "mozilla/TypedEnum.h" namespace mozilla { namespace dom { diff --git a/content/media/webaudio/PannerNode.h b/content/media/webaudio/PannerNode.h index 7be68b192c0..8dc27eb7fc7 100644 --- a/content/media/webaudio/PannerNode.h +++ b/content/media/webaudio/PannerNode.h @@ -9,8 +9,8 @@ #include "AudioNode.h" #include "AudioParam.h" -#include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" +#include "mozilla/TypedEnum.h" #include "ThreeDPoint.h" namespace mozilla { diff --git a/content/svg/content/src/SVGPreserveAspectRatio.h b/content/svg/content/src/SVGPreserveAspectRatio.h index ebe724eceea..e1d4e64d2ef 100644 --- a/content/svg/content/src/SVGPreserveAspectRatio.h +++ b/content/svg/content/src/SVGPreserveAspectRatio.h @@ -5,6 +5,8 @@ #pragma once +#include "mozilla/TypedEnum.h" + #include "nsWrapperCache.h" #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index a47bbbb8d2a..3eb2866deb4 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -6,7 +6,8 @@ #ifndef __editor_h__ #define __editor_h__ -#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc. +#include "mozilla/TypedEnum.h" // for MOZ_BEGIN_ENUM_CLASS, etc. #include "nsAutoPtr.h" // for nsRefPtr #include "nsCOMArray.h" // for nsCOMArray #include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 3cb52232f03..f7742bf7da4 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -31,7 +31,7 @@ #include "nsAlgorithm.h" #include "mozilla/layout/FrameChildList.h" #include "FramePropertyTable.h" -#include "mozilla/Attributes.h" +#include "mozilla/TypedEnum.h" #include #ifdef ACCESSIBILITY diff --git a/mfbt/Attributes.h b/mfbt/Attributes.h index d227b906e5d..ca18d6e9e5f 100644 --- a/mfbt/Attributes.h +++ b/mfbt/Attributes.h @@ -73,10 +73,6 @@ # define MOZ_HAVE_CXX11_OVERRIDE # define MOZ_HAVE_CXX11_FINAL final # endif -# if __has_extension(cxx_strong_enums) -# define MOZ_HAVE_CXX11_ENUM_TYPE -# define MOZ_HAVE_CXX11_STRONG_ENUMS -# endif # if __has_attribute(noinline) # define MOZ_HAVE_NEVER_INLINE __attribute__((noinline)) # endif @@ -98,10 +94,6 @@ # define MOZ_HAVE_CXX11_CONSTEXPR # endif # define MOZ_HAVE_CXX11_DELETE -# if __GNUC_MINOR__ >= 5 -# define MOZ_HAVE_CXX11_ENUM_TYPE -# define MOZ_HAVE_CXX11_STRONG_ENUMS -# endif # endif # else /* __final is a non-C++11 GCC synonym for 'final', per GCC r176655. */ @@ -118,13 +110,11 @@ #elif defined(_MSC_VER) # if _MSC_VER >= 1700 # define MOZ_HAVE_CXX11_FINAL final -# define MOZ_HAVE_CXX11_STRONG_ENUMS # else /* MSVC <= 10 used to spell "final" as "sealed". */ # define MOZ_HAVE_CXX11_FINAL sealed # endif # define MOZ_HAVE_CXX11_OVERRIDE -# define MOZ_HAVE_CXX11_ENUM_TYPE # define MOZ_HAVE_NEVER_INLINE __declspec(noinline) # define MOZ_HAVE_NORETURN __declspec(noreturn) #endif @@ -325,170 +315,6 @@ # define MOZ_FINAL /* no support */ #endif -/** - * MOZ_ENUM_TYPE specifies the underlying numeric type for an enum. It's - * specified by placing MOZ_ENUM_TYPE(type) immediately after the enum name in - * its declaration, and before the opening curly brace, like - * - * enum MyEnum MOZ_ENUM_TYPE(uint16_t) - * { - * A, - * B = 7, - * C - * }; - * - * In supporting compilers, the macro will expand to ": uint16_t". The - * compiler will allocate exactly two bytes for MyEnum, and will require all - * enumerators to have values between 0 and 65535. (Thus specifying "B = - * 100000" instead of "B = 7" would fail to compile.) In old compilers, the - * macro expands to the empty string, and the underlying type is generally - * undefined. - */ -#ifdef MOZ_HAVE_CXX11_ENUM_TYPE -# define MOZ_ENUM_TYPE(type) : type -#else -# define MOZ_ENUM_TYPE(type) /* no support */ -#endif - -/** - * MOZ_BEGIN_ENUM_CLASS and MOZ_END_ENUM_CLASS provide access to the - * strongly-typed enumeration feature of C++11 ("enum class"). If supported - * by the compiler, an enum defined using these macros will not be implicitly - * converted to any other type, and its enumerators will be scoped using the - * enumeration name. Place MOZ_BEGIN_ENUM_CLASS(EnumName, type) in place of - * "enum EnumName {", and MOZ_END_ENUM_CLASS(EnumName) in place of the closing - * "};". For example, - * - * MOZ_BEGIN_ENUM_CLASS(Enum, int32_t) - * A, B = 6 - * MOZ_END_ENUM_CLASS(Enum) - * - * This will make "Enum::A" and "Enum::B" appear in the global scope, but "A" - * and "B" will not. In compilers that support C++11 strongly-typed - * enumerations, implicit conversions of Enum values to numeric types will - * fail. In other compilers, Enum itself will actually be defined as a class, - * and some implicit conversions will fail while others will succeed. - * - * The type argument specifies the underlying type for the enum where - * supported, as with MOZ_ENUM_TYPE(). For simplicity, it is currently - * mandatory. As with MOZ_ENUM_TYPE(), it will do nothing on compilers that do - * not support it. - * - * Note that the workaround implemented here is not compatible with enums - * nested inside a class. - */ -#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) - /* All compilers that support strong enums also support an explicit - * underlying type, so no extra check is needed */ -# define MOZ_BEGIN_ENUM_CLASS(Name, type) enum class Name : type { -# define MOZ_END_ENUM_CLASS(Name) }; -#else - /** - * We need Name to both name a type, and scope the provided enumerator - * names. Namespaces and classes both provide scoping, but namespaces - * aren't types, so we need to use a class that wraps the enum values. We - * have an implicit conversion from the inner enum type to the class, so - * statements like - * - * Enum x = Enum::A; - * - * will still work. We need to define an implicit conversion from the class - * to the inner enum as well, so that (for instance) switch statements will - * work. This means that the class can be implicitly converted to a numeric - * value as well via the enum type, since C++ allows an implicit - * user-defined conversion followed by a standard conversion to still be - * implicit. - * - * We have an explicit constructor from int defined, so that casts like - * (Enum)7 will still work. We also have a zero-argument constructor with - * no arguments, so declaration without initialization (like "Enum foo;") - * will work. - * - * Additionally, we'll delete as many operators as possible for the inner - * enum type, so statements like this will still fail: - * - * f(5 + Enum::B); // deleted operator+ - * - * But we can't prevent things like this, because C++ doesn't allow - * overriding conversions or assignment operators for enums: - * - * int x = Enum::A; - * int f() - * { - * return Enum::A; - * } - */ -# define MOZ_BEGIN_ENUM_CLASS(Name, type) \ - class Name \ - { \ - public: \ - enum Enum MOZ_ENUM_TYPE(type) \ - { -# define MOZ_END_ENUM_CLASS(Name) \ - }; \ - Name() {} \ - Name(Enum aEnum) : mEnum(aEnum) {} \ - explicit Name(int num) : mEnum((Enum)num) {} \ - operator Enum() const { return mEnum; } \ - private: \ - Enum mEnum; \ - }; \ - inline int operator+(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator+(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator-(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator-(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator*(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator*(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator/(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator/(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator%(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator%(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator+(const Name::Enum&) MOZ_DELETE; \ - inline int operator-(const Name::Enum&) MOZ_DELETE; \ - inline int& operator++(Name::Enum&) MOZ_DELETE; \ - inline int operator++(Name::Enum&, int) MOZ_DELETE; \ - inline int& operator--(Name::Enum&) MOZ_DELETE; \ - inline int operator--(Name::Enum&, int) MOZ_DELETE; \ - inline bool operator==(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator==(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator!=(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator!=(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator>(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator>(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator<(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator<(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator>=(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator>=(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator<=(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator<=(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator!(const Name::Enum&) MOZ_DELETE; \ - inline bool operator&&(const bool&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator&&(const Name::Enum&, const bool&) MOZ_DELETE; \ - inline bool operator||(const bool&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator||(const Name::Enum&, const bool&) MOZ_DELETE; \ - inline int operator~(const Name::Enum&) MOZ_DELETE; \ - inline int operator&(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator&(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator|(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator|(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator^(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator^(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator<<(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator<<(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator>>(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator>>(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int& operator+=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator-=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator*=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator/=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator%=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator&=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator|=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator^=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator<<=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE; -#endif - /** * MOZ_WARN_UNUSED_RESULT tells the compiler to emit a warning if a function's * return value is not used by the caller. diff --git a/mfbt/TypedEnum.h b/mfbt/TypedEnum.h new file mode 100644 index 00000000000..b94f1279662 --- /dev/null +++ b/mfbt/TypedEnum.h @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Macros to emulate C++11 typed enums and enum classes. */ + +#ifndef mozilla_TypedEnum_h_ +#define mozilla_TypedEnum_h_ + +#if defined(__clang__) + /* + * Per Clang documentation, "Note that marketing version numbers should not + * be used to check for language features, as different vendors use different + * numbering schemes. Instead, use the feature checking macros." + */ +# ifndef __has_extension +# define __has_extension __has_feature /* compatibility, for older versions of clang */ +# endif +# if __has_extension(cxx_strong_enums) +# define MOZ_HAVE_CXX11_ENUM_TYPE +# define MOZ_HAVE_CXX11_STRONG_ENUMS +# endif +#elif defined(__GNUC__) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L +# if __GNUC__ > 4 +# define MOZ_HAVE_CXX11_ENUM_TYPE +# define MOZ_HAVE_CXX11_STRONG_ENUMS +# elif __GNUC__ == 4 +# if __GNUC_MINOR__ >= 5 +# define MOZ_HAVE_CXX11_ENUM_TYPE +# define MOZ_HAVE_CXX11_STRONG_ENUMS +# endif +# endif +# endif +#elif defined(_MSC_VER) +# if _MSC_VER >= 1400 +# define MOZ_HAVE_CXX11_ENUM_TYPE +# endif +# if _MSC_VER >= 1700 +# define MOZ_HAVE_CXX11_STRONG_ENUMS +# endif +#endif + +/** + * MOZ_ENUM_TYPE specifies the underlying numeric type for an enum. It's + * specified by placing MOZ_ENUM_TYPE(type) immediately after the enum name in + * its declaration, and before the opening curly brace, like + * + * enum MyEnum MOZ_ENUM_TYPE(uint16_t) + * { + * A, + * B = 7, + * C + * }; + * + * In supporting compilers, the macro will expand to ": uint16_t". The + * compiler will allocate exactly two bytes for MyEnum and will require all + * enumerators to have values between 0 and 65535. (Thus specifying "B = + * 100000" instead of "B = 7" would fail to compile.) In old compilers the + * macro expands to the empty string, and the underlying type is generally + * undefined. + */ +#ifdef MOZ_HAVE_CXX11_ENUM_TYPE +# define MOZ_ENUM_TYPE(type) : type +#else +# define MOZ_ENUM_TYPE(type) /* no support */ +#endif + +/** + * MOZ_BEGIN_ENUM_CLASS and MOZ_END_ENUM_CLASS provide access to the + * strongly-typed enumeration feature of C++11 ("enum class"). If supported + * by the compiler, an enum defined using these macros will not be implicitly + * converted to any other type, and its enumerators will be scoped using the + * enumeration name. Place MOZ_BEGIN_ENUM_CLASS(EnumName, type) in place of + * "enum EnumName {", and MOZ_END_ENUM_CLASS(EnumName) in place of the closing + * "};". For example, + * + * MOZ_BEGIN_ENUM_CLASS(Enum, int32_t) + * A, + * B = 6 + * MOZ_END_ENUM_CLASS(Enum) + * + * This will make "Enum::A" and "Enum::B" appear in the global scope, but "A" + * and "B" will not. In compilers that support C++11 strongly-typed + * enumerations, implicit conversions of Enum values to numeric types will + * fail. In other compilers, Enum itself will actually be defined as a class, + * and some implicit conversions will fail while others will succeed. + * + * The type argument specifies the underlying type for the enum where + * supported, as with MOZ_ENUM_TYPE(). For simplicity, it is currently + * mandatory. As with MOZ_ENUM_TYPE(), it will do nothing on compilers that do + * not support it. + * + * Note that the workaround implemented here is not compatible with enums + * nested inside a class. + */ +#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) + /* + * All compilers that support strong enums also support an explicit + * underlying type, so no extra check is needed. + */ +# define MOZ_BEGIN_ENUM_CLASS(Name, type) enum class Name : type { +# define MOZ_END_ENUM_CLASS(Name) }; +#else + /** + * We need Name to both name a type, and scope the provided enumerator + * names. Namespaces and classes both provide scoping, but namespaces + * aren't types, so we need to use a class that wraps the enum values. We + * have an implicit conversion from the inner enum type to the class, so + * statements like + * + * Enum x = Enum::A; + * + * will still work. We need to define an implicit conversion from the class + * to the inner enum as well, so that (for instance) switch statements will + * work. This means that the class can be implicitly converted to a numeric + * value as well via the enum type, since C++ allows an implicit + * user-defined conversion followed by a standard conversion to still be + * implicit. + * + * We have an explicit constructor from int defined, so that casts like + * (Enum)7 will still work. We also have a zero-argument constructor with + * no arguments, so declaration without initialization (like "Enum foo;") + * will work. + * + * Additionally, we'll delete as many operators as possible for the inner + * enum type, so statements like this will still fail: + * + * f(5 + Enum::B); // deleted operator+ + * + * But we can't prevent things like this, because C++ doesn't allow + * overriding conversions or assignment operators for enums: + * + * int x = Enum::A; + * int f() + * { + * return Enum::A; + * } + */ +# define MOZ_BEGIN_ENUM_CLASS(Name, type) \ + class Name \ + { \ + public: \ + enum Enum MOZ_ENUM_TYPE(type) \ + { +# define MOZ_END_ENUM_CLASS(Name) \ + }; \ + Name() {} \ + Name(Enum aEnum) : mEnum(aEnum) {} \ + explicit Name(int num) : mEnum((Enum)num) {} \ + operator Enum() const { return mEnum; } \ + private: \ + Enum mEnum; \ + }; \ + inline int operator+(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator+(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator-(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator-(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator*(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator*(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator/(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator/(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator%(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator%(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator+(const Name::Enum&) MOZ_DELETE; \ + inline int operator-(const Name::Enum&) MOZ_DELETE; \ + inline int& operator++(Name::Enum&) MOZ_DELETE; \ + inline int operator++(Name::Enum&, int) MOZ_DELETE; \ + inline int& operator--(Name::Enum&) MOZ_DELETE; \ + inline int operator--(Name::Enum&, int) MOZ_DELETE; \ + inline bool operator==(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator==(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator!=(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator!=(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator>(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator>(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator<(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator<(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator>=(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator>=(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator<=(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator<=(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator!(const Name::Enum&) MOZ_DELETE; \ + inline bool operator&&(const bool&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator&&(const Name::Enum&, const bool&) MOZ_DELETE; \ + inline bool operator||(const bool&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator||(const Name::Enum&, const bool&) MOZ_DELETE; \ + inline int operator~(const Name::Enum&) MOZ_DELETE; \ + inline int operator&(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator&(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator|(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator|(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator^(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator^(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator<<(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator<<(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator>>(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator>>(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int& operator+=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator-=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator*=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator/=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator%=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator&=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator|=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator^=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator<<=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE; +#endif + +#endif /* mozilla_TypedEnum_h_ */ diff --git a/mfbt/exported_headers.mk b/mfbt/exported_headers.mk index ad0324b8b3b..d1d3ecf2753 100644 --- a/mfbt/exported_headers.mk +++ b/mfbt/exported_headers.mk @@ -33,8 +33,9 @@ EXPORTS_mozilla += \ SplayTree.h \ StandardInteger.h \ ThreadLocal.h \ - TypeTraits.h \ + TypedEnum.h \ Types.h \ + TypeTraits.h \ Util.h \ WeakPtr.h \ $(NULL) From 47e5125519e3ebea8c97a66340b2c29da40ff846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Tue, 29 Jan 2013 23:16:04 +0100 Subject: [PATCH 21/70] Bug 835892 - Provide No Video & No Audio options when both camera and microphone access are requested. r=gavin --- .../en-US/chrome/browser/browser.properties | 2 + browser/modules/webrtcUI.jsm | 37 ++++++++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties index 0d377686d6f..7d2a78bf021 100644 --- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -426,6 +426,8 @@ identity.loggedIn.signOut.accessKey = O getUserMedia.shareCamera.message = Would you like to share your camera with %S? getUserMedia.shareMicrophone.message = Would you like to share your microphone with %S? getUserMedia.shareCameraAndMicrophone.message = Would you like to share your camera and microphone with %S? +getUserMedia.noVideo.label = No Video +getUserMedia.noAudio.label = No Audio getUserMedia.shareSelectedDevices.label = Share Selected Device;Share Selected Devices getUserMedia.shareSelectedDevices.accesskey = S getUserMedia.denyRequest.label = Don't Share diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm index c84347bf51e..53733d1f3a3 100644 --- a/browser/modules/webrtcUI.jsm +++ b/browser/modules/webrtcUI.jsm @@ -118,19 +118,30 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) { let deviceIndex = 0; for (let device of devices) { - let menuitem = chromeDoc.createElement("menuitem"); - menuitem.setAttribute("value", deviceIndex); - menuitem.setAttribute("label", device.name); - menuitem.setAttribute("tooltiptext", device.name); - menupopup.appendChild(menuitem); + addDeviceToList(menupopup, device.name, deviceIndex); deviceIndex++; } } + function addDeviceToList(menupopup, deviceName, deviceIndex) { + let menuitem = chromeDoc.createElement("menuitem"); + menuitem.setAttribute("value", deviceIndex); + menuitem.setAttribute("label", deviceName); + menuitem.setAttribute("tooltiptext", deviceName); + menupopup.appendChild(menuitem); + } + chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length; chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length; - listDevices(chromeDoc.getElementById("webRTC-selectCamera-menupopup"), videoDevices); - listDevices(chromeDoc.getElementById("webRTC-selectMicrophone-menupopup"), audioDevices); + + let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup"); + let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup"); + listDevices(camMenupopup, videoDevices); + listDevices(micMenupopup, audioDevices); + if (requestType == "CameraAndMicrophone") { + addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1"); + addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1"); + } let mainAction = { label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1, @@ -141,12 +152,20 @@ function prompt(aBrowser, aCallID, aAudioRequested, aVideoRequested, aDevices) { .createInstance(Ci.nsISupportsArray); if (videoDevices.length) { let videoDeviceIndex = chromeDoc.getElementById("webRTC-selectCamera-menulist").value; - allowedDevices.AppendElement(videoDevices[videoDeviceIndex]); + if (videoDeviceIndex != "-1") + allowedDevices.AppendElement(videoDevices[videoDeviceIndex]); } if (audioDevices.length) { let audioDeviceIndex = chromeDoc.getElementById("webRTC-selectMicrophone-menulist").value; - allowedDevices.AppendElement(audioDevices[audioDeviceIndex]); + if (audioDeviceIndex != "-1") + allowedDevices.AppendElement(audioDevices[audioDeviceIndex]); } + + if (allowedDevices.Count() == 0) { + Services.obs.notifyObservers(null, "getUserMedia:response:deny", aCallID); + return; + } + Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID); // Show browser-specific indicator for the active camera/mic access. From 775587776aba4a9d3bf8dd6b433491d51a43cca3 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 29 Jan 2013 17:17:37 -0500 Subject: [PATCH 22/70] Back out bug 829867 (rev 2a0424e177c1) on suspicion of Ts regression --- dom/bindings/Bindings.conf | 2 ++ js/xpconnect/src/dom_quickstubs.qsconf | 23 ++++++++++++++++++++ js/xpconnect/src/nsCSSPropertiesQS.h | 30 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 js/xpconnect/src/nsCSSPropertiesQS.h diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 58044c17bb8..d68094b5817 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -562,6 +562,7 @@ DOMInterfaces = { 'PaintRequest': { 'nativeType': 'nsPaintRequest', + 'prefable': True }, 'PaintRequestList': { @@ -612,6 +613,7 @@ DOMInterfaces = { 'Screen': { 'nativeType': 'nsScreen', + 'prefable': True, }, 'SVGAElement': { diff --git a/js/xpconnect/src/dom_quickstubs.qsconf b/js/xpconnect/src/dom_quickstubs.qsconf index 9eea0a43b37..53a12ba58dd 100644 --- a/js/xpconnect/src/dom_quickstubs.qsconf +++ b/js/xpconnect/src/dom_quickstubs.qsconf @@ -46,7 +46,12 @@ members = [ 'nsIDOMWindow.onmouseleave', 'nsIDOMWindowPerformance.performance', 'nsIDOMJSWindow.dump', + 'nsIDOMScreen.top', + 'nsIDOMScreen.height', + 'nsIDOMScreen.width', + 'nsIDOMScreen.left', 'nsIDOMClientRect.*', + 'nsIDOMPaintRequest.*', # nsLocationSH has ~ALLOW_PROP_MODS_TO_PROTOTYPE, so don't try. #'nsIDOMLocation.hostname', #'nsIDOMLocation.href', @@ -59,11 +64,17 @@ members = [ 'nsIDOMCanvasPattern.*', # dom/interfaces/core + 'nsIDOMCharacterData.data', + 'nsIDOMCharacterData.length', 'nsIDOMNamedNodeMap.item', 'nsIDOMNamedNodeMap.length', + 'nsIDOMText.splitText', 'nsIDOMDOMStringList.*', 'nsIDOMXULDocument.getBoxObjectFor', + # dom/interfaces/css + 'nsIDOMRect.*', + 'nsIDOMEvent.type', 'nsIDOMEvent.target', 'nsIDOMEvent.currentTarget', @@ -296,8 +307,20 @@ irregularFilenames = { } customIncludes = [ + 'nsINode.h', + 'nsIContent.h', + 'nsIDocument.h', + 'nsCSSPropertiesQS.h', + 'nsDOMTokenList.h', + 'nsGenericDOMDataNode.h', + 'mozilla/dom/Element.h', + 'nsGenericHTMLElement.h', + 'nsSVGElement.h', 'nsDOMQS.h', + 'nsDOMStringMap.h', + 'HTMLPropertiesCollection.h', 'nsHTMLMenuElement.h', + 'nsICSSDeclaration.h', 'mozilla/dom/NodeBinding.h', 'mozilla/dom/ElementBinding.h', 'mozilla/dom/HTMLElementBinding.h', diff --git a/js/xpconnect/src/nsCSSPropertiesQS.h b/js/xpconnect/src/nsCSSPropertiesQS.h new file mode 100644 index 00000000000..c52fa07bb38 --- /dev/null +++ b/js/xpconnect/src/nsCSSPropertiesQS.h @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsCSSPropertiesQS_h__ +#define nsCSSPropertiesQS_h__ + +#include "nsICSSDeclaration.h" + +#define CSS_PROP_DOMPROP_PREFIXED(prop_) Moz ## prop_ +#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, kwtable_, \ + stylestruct_, stylestructoffset_, animtype_) \ +static const nsCSSProperty QS_CSS_PROP_##method_ = eCSSProperty_##id_; + +#define CSS_PROP_LIST_EXCLUDE_INTERNAL +#define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, pref_) \ + CSS_PROP(name_, id_, method_, flags_, pref_, X, X, X, X, X) +#include "nsCSSPropList.h" + +#define CSS_PROP_ALIAS(aliasname_, propid_, aliasmethod_, pref_) \ + CSS_PROP(X, propid_, aliasmethod_, X, pref_, X, X, X, X, X) +#include "nsCSSPropAliasList.h" +#undef CSS_PROP_ALIAS + +#undef CSS_PROP_SHORTHAND +#undef CSS_PROP_LIST_EXCLUDE_INTERNAL +#undef CSS_PROP +#undef CSS_PROP_DOMPROP_PREFIXED + +#endif /* nsCSSPropertiesQS_h__ */ From 66e49b02aae88578a104eb944170c9696b93ead7 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 29 Jan 2013 17:18:06 -0500 Subject: [PATCH 23/70] Back out bug 824589 (rev 22695cac3896) on suspicion of Ts regression --- browser/base/content/browser.js | 2 +- content/base/public/nsINode.h | 1 - .../canvas/src/CanvasRenderingContext2D.cpp | 6 +- content/canvas/src/CanvasRenderingContext2D.h | 4 +- content/canvas/src/Makefile.in | 1 - content/xul/content/src/nsXULElement.cpp | 233 ++++++------------ content/xul/content/src/nsXULElement.h | 174 +------------ dom/base/nsDOMClassInfo.cpp | 1 - dom/base/nsWrapperCache.h | 2 - dom/bindings/BindingUtils.cpp | 4 +- dom/bindings/Bindings.conf | 14 +- dom/bindings/Makefile.in | 1 - dom/interfaces/xul/nsIDOMXULElement.idl | 3 +- dom/webidl/CanvasRenderingContext2D.webidl | 1 + dom/webidl/HTMLElement.webidl | 31 +-- dom/webidl/SVGElement.webidl | 14 +- dom/webidl/WebIDL.mk | 1 - dom/webidl/XULElement.webidl | 134 ---------- js/xpconnect/src/XPCJSID.cpp | 16 +- js/xpconnect/src/dom_quickstubs.qsconf | 13 + xpfe/appshell/src/nsXULWindow.cpp | 4 +- 21 files changed, 143 insertions(+), 517 deletions(-) delete mode 100644 dom/webidl/XULElement.webidl diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 9f6fe17ca48..1dea8f5699c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1265,7 +1265,7 @@ var gBrowserInit = { gBrowser.addEventListener("pageshow", function(event) { // Filter out events that are not about the document load we are interested in - if (content && event.target == content.document) + if (event.target == content.document) setTimeout(pageShowEventHandlers, 0, event); }, true); diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index f533c87f7ac..9c221d222b9 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -388,7 +388,6 @@ protected: virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) { - MOZ_ASSERT(!IsDOMBinding(), "Someone forgot to override WrapNode"); *aTriedToWrap = false; return nullptr; } diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp index bfcd4c4e922..abe77e2f634 100644 --- a/content/canvas/src/CanvasRenderingContext2D.cpp +++ b/content/canvas/src/CanvasRenderingContext2D.cpp @@ -6,7 +6,7 @@ #include "base/basictypes.h" #include "CanvasRenderingContext2D.h" -#include "nsXULElement.h" +#include "nsIDOMXULElement.h" #include "prenv.h" @@ -3234,7 +3234,7 @@ CanvasRenderingContext2D::DrawWindow(nsIDOMWindow* window, double x, } void -CanvasRenderingContext2D::AsyncDrawXULElement(nsXULElement& elem, +CanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w, double h, const nsAString& bgColor, @@ -3255,7 +3255,7 @@ CanvasRenderingContext2D::AsyncDrawXULElement(nsXULElement& elem, } #if 0 - nsCOMPtr loaderOwner = do_QueryInterface(&elem); + nsCOMPtr loaderOwner = do_QueryInterface(elem); if (!loaderOwner) { error.Throw(NS_ERROR_FAILURE); return; diff --git a/content/canvas/src/CanvasRenderingContext2D.h b/content/canvas/src/CanvasRenderingContext2D.h index 90a3e903f80..67f8630abee 100644 --- a/content/canvas/src/CanvasRenderingContext2D.h +++ b/content/canvas/src/CanvasRenderingContext2D.h @@ -24,7 +24,7 @@ #define NS_CANVASPATTERNAZURE_PRIVATE_IID \ {0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}} -class nsXULElement; +class nsIDOMXULElement; namespace mozilla { namespace gfx { @@ -438,7 +438,7 @@ public: void DrawWindow(nsIDOMWindow* window, double x, double y, double w, double h, const nsAString& bgColor, uint32_t flags, mozilla::ErrorResult& error); - void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w, + void AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w, double h, const nsAString& bgColor, uint32_t flags, mozilla::ErrorResult& error); diff --git a/content/canvas/src/Makefile.in b/content/canvas/src/Makefile.in index b46aefec544..b8029ec8e9e 100644 --- a/content/canvas/src/Makefile.in +++ b/content/canvas/src/Makefile.in @@ -68,7 +68,6 @@ CPPSRCS += \ LOCAL_INCLUDES += \ -I$(topsrcdir)/js/xpconnect/wrappers \ - -I$(topsrcdir)/content/xul/content/src \ $(NULL) else diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index b0dd707c8dd..0f18a707614 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -104,9 +104,8 @@ #include "nsCCUncollectableMarker.h" #include "nsICSSDeclaration.h" -#include "mozilla/dom/XULElementBinding.h" - -using namespace mozilla; +namespace css = mozilla::css; +namespace dom = mozilla::dom; //---------------------------------------------------------------------- @@ -167,8 +166,6 @@ nsXULElement::nsXULElement(already_AddRefed aNodeInfo) { XUL_PROTOTYPE_ATTRIBUTE_METER(gNumElements); - SetIsDOMBinding(); - // We may be READWRITE by default; check. if (IsReadWriteTextElement()) { AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); @@ -402,18 +399,12 @@ NS_IMETHODIMP nsXULElement::GetElementsByAttribute(const nsAString& aAttribute, const nsAString& aValue, nsIDOMNodeList** aReturn) -{ - *aReturn = GetElementsByAttribute(aAttribute, aValue).get(); - return NS_OK; -} - -already_AddRefed -nsXULElement::GetElementsByAttribute(const nsAString& aAttribute, - const nsAString& aValue) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); + NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); void* attrValue = new nsString(aValue); - nsRefPtr list = + NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY); + nsContentList *list = new nsContentList(this, nsXULDocument::MatchAttribute, nsContentUtils::DestroyMatchString, @@ -421,7 +412,10 @@ nsXULElement::GetElementsByAttribute(const nsAString& aAttribute, true, attrAtom, kNameSpaceID_Unknown); - return list.forget(); + NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(*aReturn = list); + return NS_OK; } NS_IMETHODIMP @@ -429,33 +423,22 @@ nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI, const nsAString& aAttribute, const nsAString& aValue, nsIDOMNodeList** aReturn) -{ - ErrorResult rv; - *aReturn = - GetElementsByAttributeNS(aNamespaceURI, aAttribute, aValue, rv).get(); - return rv.ErrorCode(); -} - -already_AddRefed -nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI, - const nsAString& aAttribute, - const nsAString& aValue, - ErrorResult& rv) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); + NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); int32_t nameSpaceId = kNameSpaceID_Wildcard; if (!aNamespaceURI.EqualsLiteral("*")) { - rv = + nsresult rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, nameSpaceId); - if (rv.Failed()) { - return nullptr; - } + NS_ENSURE_SUCCESS(rv, rv); } void* attrValue = new nsString(aValue); - nsRefPtr list = + NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY); + + nsContentList *list = new nsContentList(this, nsXULDocument::MatchAttribute, nsContentUtils::DestroyMatchString, @@ -463,8 +446,10 @@ nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI, true, attrAtom, nameSpaceId); + NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - return list.forget(); + NS_ADDREF(*aReturn = list); + return NS_OK; } nsEventListenerManager* @@ -1190,14 +1175,6 @@ nsXULElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) // XXX This _should_ be an implementation method, _not_ publicly exposed :-( NS_IMETHODIMP nsXULElement::GetResource(nsIRDFResource** aResource) -{ - ErrorResult rv; - *aResource = GetResource(rv).get(); - return rv.ErrorCode(); -} - -already_AddRefed -nsXULElement::GetResource(ErrorResult& rv) { nsAutoString id; GetAttr(kNameSpaceID_None, nsGkAtoms::ref, id); @@ -1205,57 +1182,44 @@ nsXULElement::GetResource(ErrorResult& rv) GetAttr(kNameSpaceID_None, nsGkAtoms::id, id); } - if (id.IsEmpty()) { - return nullptr; + if (!id.IsEmpty()) { + return nsXULContentUtils::RDFService()-> + GetUnicodeResource(id, aResource); } + *aResource = nullptr; - nsCOMPtr resource; - rv = nsXULContentUtils::RDFService()-> - GetUnicodeResource(id, getter_AddRefs(resource)); - return resource.forget(); + return NS_OK; } + NS_IMETHODIMP nsXULElement::GetDatabase(nsIRDFCompositeDataSource** aDatabase) { - *aDatabase = GetDatabase().get(); + nsCOMPtr builder; + GetBuilder(getter_AddRefs(builder)); + + if (builder) + builder->GetDatabase(aDatabase); + else + *aDatabase = nullptr; + return NS_OK; } -already_AddRefed -nsXULElement::GetDatabase() -{ - nsCOMPtr builder = GetBuilder(); - if (!builder) { - return nullptr; - } - - nsCOMPtr database; - builder->GetDatabase(getter_AddRefs(database)); - return database.forget(); -} - NS_IMETHODIMP nsXULElement::GetBuilder(nsIXULTemplateBuilder** aBuilder) { - *aBuilder = GetBuilder().get(); + *aBuilder = nullptr; + + // XXX sXBL/XBL2 issue! Owner or current document? + nsCOMPtr xuldoc = do_QueryInterface(GetCurrentDoc()); + if (xuldoc) + xuldoc->GetTemplateBuilderFor(this, aBuilder); + return NS_OK; } -already_AddRefed -nsXULElement::GetBuilder() -{ - // XXX sXBL/XBL2 issue! Owner or current document? - nsCOMPtr xuldoc = do_QueryInterface(GetCurrentDoc()); - if (!xuldoc) { - return nullptr; - } - - nsCOMPtr builder; - xuldoc->GetTemplateBuilderFor(this, getter_AddRefs(builder)); - return builder.forget(); -} //---------------------------------------------------------------------- // Implementation methods @@ -1304,46 +1268,30 @@ nsXULElement::IsAttributeMapped(const nsIAtom* aAttribute) const // Controllers Methods NS_IMETHODIMP nsXULElement::GetControllers(nsIControllers** aResult) -{ - ErrorResult rv; - NS_IF_ADDREF(*aResult = GetControllers(rv)); - return rv.ErrorCode(); -} - -nsIControllers* -nsXULElement::GetControllers(ErrorResult& rv) { if (! Controllers()) { nsDOMSlots* slots = DOMSlots(); + nsresult rv; rv = NS_NewXULControllers(nullptr, NS_GET_IID(nsIControllers), reinterpret_cast(&slots->mControllers)); - NS_ASSERTION(NS_SUCCEEDED(rv.ErrorCode()), - "unable to create a controllers"); - if (rv.Failed()) { - return nullptr; - } + NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a controllers"); + if (NS_FAILED(rv)) return rv; } - return Controllers(); + *aResult = Controllers(); + NS_IF_ADDREF(*aResult); + return NS_OK; } NS_IMETHODIMP nsXULElement::GetBoxObject(nsIBoxObject** aResult) { - ErrorResult rv; - *aResult = GetBoxObject(rv).get(); - return rv.ErrorCode(); -} + *aResult = nullptr; -already_AddRefed -nsXULElement::GetBoxObject(ErrorResult& rv) -{ - nsCOMPtr boxObject; - // XXX sXBL/XBL2 issue! Owner or current document? - rv = OwnerDoc()->GetBoxObjectFor(this, getter_AddRefs(boxObject)); - return boxObject.forget(); + // XXX sXBL/XBL2 issue! Owner or current document? + return OwnerDoc()->GetBoxObjectFor(this, aResult); } // Methods for setting/getting attributes from nsIDOMXULElement @@ -1363,19 +1311,26 @@ nsXULElement::GetBoxObject(ErrorResult& rv) #define NS_IMPL_XUL_BOOL_ATTR(_method, _atom) \ NS_IMETHODIMP \ - nsXULElement::Get##_method(bool* aResult) \ + nsXULElement::Get##_method(bool* aResult) \ { \ - *aResult = _method(); \ + *aResult = BoolAttrIsTrue(nsGkAtoms::_atom); \ + \ return NS_OK; \ } \ NS_IMETHODIMP \ - nsXULElement::Set##_method(bool aValue) \ + nsXULElement::Set##_method(bool aValue) \ { \ - SetXULBoolAttr(nsGkAtoms::_atom, aValue); \ - return NS_OK; \ + if (aValue) \ + SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, \ + NS_LITERAL_STRING("true"), true); \ + else \ + UnsetAttr(kNameSpaceID_None, nsGkAtoms::_atom, true); \ + \ + return NS_OK; \ } +NS_IMPL_XUL_STRING_ATTR(Id, id) NS_IMPL_XUL_STRING_ATTR(ClassName, _class) NS_IMPL_XUL_STRING_ATTR(Align, align) NS_IMPL_XUL_STRING_ATTR(Dir, dir) @@ -1463,32 +1418,24 @@ nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner) nsXULElement* otherEl = FromContent(otherContent); NS_ENSURE_TRUE(otherEl, NS_ERROR_NOT_IMPLEMENTED); - ErrorResult rv; - SwapFrameLoaders(*otherEl, rv); - return rv.ErrorCode(); -} - -void -nsXULElement::SwapFrameLoaders(nsXULElement& aOtherElement, ErrorResult& rv) -{ - if (&aOtherElement == this) { + if (otherEl == this) { // nothing to do - return; + return NS_OK; } nsXULSlots *ourSlots = static_cast(GetExistingDOMSlots()); nsXULSlots *otherSlots = - static_cast(aOtherElement.GetExistingDOMSlots()); + static_cast(otherEl->GetExistingDOMSlots()); if (!ourSlots || !ourSlots->mFrameLoader || !otherSlots || !otherSlots->mFrameLoader) { // Can't handle swapping when there is nothing to swap... yet. - rv.Throw(NS_ERROR_NOT_IMPLEMENTED); - return; + return NS_ERROR_NOT_IMPLEMENTED; } - rv = ourSlots->mFrameLoader->SwapWithOtherLoader(otherSlots->mFrameLoader, - ourSlots->mFrameLoader, - otherSlots->mFrameLoader); + return + ourSlots->mFrameLoader->SwapWithOtherLoader(otherSlots->mFrameLoader, + ourSlots->mFrameLoader, + otherSlots->mFrameLoader); } NS_IMETHODIMP @@ -1511,45 +1458,27 @@ nsXULElement::GetParentTree(nsIDOMXULMultiSelectControlElement** aTreeElement) NS_IMETHODIMP nsXULElement::Focus() -{ - ErrorResult rv; - Focus(rv); - return rv.ErrorCode(); -} - -void -nsXULElement::Focus(ErrorResult& rv) { nsIFocusManager* fm = nsFocusManager::GetFocusManager(); nsCOMPtr elem = do_QueryObject(this); - if (fm) { - rv = fm->SetFocus(this, 0); - } + return fm ? fm->SetFocus(this, 0) : NS_OK; } NS_IMETHODIMP nsXULElement::Blur() -{ - ErrorResult rv; - Blur(rv); - return rv.ErrorCode(); -} - -void -nsXULElement::Blur(ErrorResult& rv) { if (!ShouldBlur(this)) - return; + return NS_OK; nsIDocument* doc = GetCurrentDoc(); if (!doc) - return; + return NS_OK; nsIDOMWindow* win = doc->GetWindow(); nsIFocusManager* fm = nsFocusManager::GetFocusManager(); - if (win && fm) { - rv = fm->ClearFocus(win); - } + if (win && fm) + return fm->ClearFocus(win); + return NS_OK; } NS_IMETHODIMP @@ -1558,12 +1487,6 @@ nsXULElement::Click() return ClickWithInputSource(nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN); } -void -nsXULElement::Click(ErrorResult& rv) -{ - rv = Click(); -} - nsresult nsXULElement::ClickWithInputSource(uint16_t aInputSource) { @@ -1869,7 +1792,7 @@ nsXULElement::ResetChromeMargins() } bool -nsXULElement::BoolAttrIsTrue(nsIAtom* aName) const +nsXULElement::BoolAttrIsTrue(nsIAtom* aName) { const nsAttrValue* attr = GetAttrInfo(kNameSpaceID_None, aName).mValue; @@ -1907,12 +1830,6 @@ nsXULElement::IsEventAttributeName(nsIAtom *aName) return nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL); } -JSObject* -nsXULElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap) -{ - return dom::XULElementBinding::Wrap(aCx, aScope, this, aTriedToWrap); -} - NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeNode) if (tmp->mType == nsXULPrototypeNode::eType_Element) { static_cast(tmp)->Unlink(); diff --git a/content/xul/content/src/nsXULElement.h b/content/xul/content/src/nsXULElement.h index c8d08481aa0..9c8baa38f43 100644 --- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -37,8 +37,6 @@ #include "nsDOMScriptObjectHolder.h" #include "nsIFrameLoader.h" #include "jspubtd.h" -#include "nsGenericHTMLElement.h" -#include "nsFrameLoader.h" class nsIDocument; class nsString; @@ -395,9 +393,6 @@ public: // nsIDOMNode NS_FORWARD_NSIDOMNODE_TO_NSINODE - // And since that shadowed GetParentElement with the XPCOM - // signature, pull in the one we care about. - using nsStyledElement::GetParentElement; // nsIDOMElement NS_FORWARD_NSIDOMELEMENT_TO_GENERIC @@ -409,6 +404,7 @@ public: virtual nsEventStates IntrinsicState() const; nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader); + already_AddRefed GetFrameLoader(); nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner); virtual void RecompileScriptEventListeners(); @@ -427,169 +423,6 @@ public: virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE; - void SetXULAttr(nsIAtom* aName, const nsAString& aValue, - mozilla::ErrorResult& aError) - { - aError = SetAttr(kNameSpaceID_None, aName, aValue, true); - } - void SetXULBoolAttr(nsIAtom* aName, bool aValue) - { - if (aValue) { - SetAttr(kNameSpaceID_None, aName, NS_LITERAL_STRING("true"), true); - } else { - UnsetAttr(kNameSpaceID_None, aName, true); - } - } - - // WebIDL API - // The XPCOM getter is fine for our string attributes. - // The XPCOM setter is fine for our bool attributes. - void SetClassName(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::_class, aValue, rv); - } - void SetAlign(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::align, aValue, rv); - } - void SetDir(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::dir, aValue, rv); - } - void SetFlex(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::flex, aValue, rv); - } - void SetFlexGroup(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::flexgroup, aValue, rv); - } - void SetOrdinal(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::ordinal, aValue, rv); - } - void SetOrient(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::orient, aValue, rv); - } - void SetPack(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::pack, aValue, rv); - } - bool Hidden() const - { - return BoolAttrIsTrue(nsGkAtoms::hidden); - } - bool Collapsed() const - { - return BoolAttrIsTrue(nsGkAtoms::collapsed); - } - void SetObserves(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::observes, aValue, rv); - } - void SetMenu(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::menu, aValue, rv); - } - void SetContextMenu(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::contextmenu, aValue, rv); - } - void SetTooltip(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::tooltip, aValue, rv); - } - void SetWidth(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::width, aValue, rv); - } - void SetHeight(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::height, aValue, rv); - } - void SetMinWidth(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::minwidth, aValue, rv); - } - void SetMinHeight(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::minheight, aValue, rv); - } - void SetMaxWidth(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::maxwidth, aValue, rv); - } - void SetMaxHeight(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::maxheight, aValue, rv); - } - void SetPersist(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::persist, aValue, rv); - } - void SetLeft(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::left, aValue, rv); - } - void SetTop(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::top, aValue, rv); - } - void SetDatasources(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::datasources, aValue, rv); - } - void SetRef(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::ref, aValue, rv); - } - void SetTooltipText(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::tooltiptext, aValue, rv); - } - void SetStatusText(const nsAString& aValue, mozilla::ErrorResult& rv) - { - SetXULAttr(nsGkAtoms::statustext, aValue, rv); - } - bool AllowEvents() const - { - return BoolAttrIsTrue(nsGkAtoms::allowevents); - } - already_AddRefed GetDatabase(); - already_AddRefed GetBuilder(); - already_AddRefed GetResource(mozilla::ErrorResult& rv); - nsIControllers* GetControllers(mozilla::ErrorResult& rv); - already_AddRefed GetBoxObject(mozilla::ErrorResult& rv); - void Focus(mozilla::ErrorResult& rv); - void Blur(mozilla::ErrorResult& rv); - void Click(mozilla::ErrorResult& rv); - // The XPCOM DoCommand never fails, so it's OK for us. - already_AddRefed - GetElementsByAttribute(const nsAString& aAttribute, - const nsAString& aValue); - already_AddRefed - GetElementsByAttributeNS(const nsAString& aNamespaceURI, - const nsAString& aAttribute, - const nsAString& aValue, - mozilla::ErrorResult& rv); - // Style() inherited from nsStyledElement - already_AddRefed GetFrameLoader(); - void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& rv); - - // For XUL, the parent is the parent element, if any - nsINode* GetParentObject() const - { - Element* parent = GetParentElement(); - if (parent) { - return parent; - } - return nsStyledElement::GetParentObject(); - } - static bool PrefEnabled() - { - return nsGenericHTMLElement::PrefEnabled(); - } protected: // This can be removed if EnsureContentsGenerated dies. @@ -678,7 +511,7 @@ protected: } void UnregisterAccessKey(const nsAString& aOldValue); - bool BoolAttrIsTrue(nsIAtom* aName) const; + bool BoolAttrIsTrue(nsIAtom* aName); friend nsresult NS_NewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo); @@ -697,9 +530,6 @@ protected: (tag == nsGkAtoms::textbox || tag == nsGkAtoms::textarea) && !HasAttr(kNameSpaceID_None, nsGkAtoms::readonly); } - - virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope, - bool *aTriedToWrap) MOZ_OVERRIDE; }; #endif // nsXULElement_h__ diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index b0cdc05a539..6f8868923c9 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -2945,7 +2945,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(XULTreeBuilder, nsIXULTreeBuilder) DOM_CLASSINFO_MAP_ENTRY(nsIXULTreeBuilder) - DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder) DOM_CLASSINFO_MAP_ENTRY(nsITreeView) DOM_CLASSINFO_MAP_END #endif diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index 452ab1e05e2..44e358a1cc4 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -7,7 +7,6 @@ #define nsWrapperCache_h___ #include "nsCycleCollectionParticipant.h" -#include "mozilla/Assertions.h" class JSObject; struct JSContext; @@ -162,7 +161,6 @@ public: virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap) { - MOZ_ASSERT(!IsDOMBinding(), "Someone forgot to override WrapObject"); *triedToWrap = false; return nullptr; } diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index aee9594ebb1..3971fc40cb3 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -575,9 +575,9 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp) return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS); } - nsIJSID* iid; + nsIJSIID* iid; xpc_qsSelfRef iidRef; - if (NS_FAILED(xpc_qsUnwrapArg(cx, argv[0], &iid, &iidRef.ptr, + if (NS_FAILED(xpc_qsUnwrapArg(cx, argv[0], &iid, &iidRef.ptr, &argv[0]))) { return Throw(cx, NS_ERROR_XPC_BAD_CONVERT_JS); } diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index d68094b5817..39a8ea13106 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1013,12 +1013,6 @@ DOMInterfaces = { 'wrapperCache': False }, -'XULElement': { - 'nativeType': 'nsXULElement', - 'resultNotAddRefed': [ 'controllers', 'style' ], - 'hasInstanceInterface': 'nsIDOMXULElement', -}, - #################################### # Test Interfaces of various sorts # #################################### @@ -1222,13 +1216,6 @@ addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserve addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True) addExternalIface('LockedFile') addExternalIface('MediaStream') -addExternalIface('MozBoxObject', nativeType='nsIBoxObject') -addExternalIface('MozControllers', nativeType='nsIControllers') -addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True) -addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource', - notflattened=True) -addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True) -addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder') addExternalIface('NamedNodeMap') addExternalIface('NodeIterator') addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True) @@ -1257,3 +1244,4 @@ addExternalIface('WindowProxy', nativeType='nsIDOMWindow') addExternalIface('XPathResult', nativeType='nsISupports') addExternalIface('XPathExpression') addExternalIface('XPathNSResolver') +addExternalIface('XULElement') diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index ca93381593f..2a7842d1723 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -86,7 +86,6 @@ LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \ -I$(topsrcdir)/content/xslt/src/base \ -I$(topsrcdir)/content/xslt/src/xpath \ -I$(topsrcdir)/content/xml/content/src \ - -I$(topsrcdir)/content/xul/content/src \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/interfaces/xul/nsIDOMXULElement.idl b/dom/interfaces/xul/nsIDOMXULElement.idl index de52acc82d5..dffd1ac1468 100644 --- a/dom/interfaces/xul/nsIDOMXULElement.idl +++ b/dom/interfaces/xul/nsIDOMXULElement.idl @@ -12,9 +12,10 @@ interface nsIControllers; interface nsIBoxObject; -[scriptable, uuid(bece5b0b-6e59-4de5-98d0-088adfd1cadc)] +[scriptable, uuid(3a07dead-39e5-4dad-bc68-6ef369994126)] interface nsIDOMXULElement : nsIDOMElement { + attribute DOMString id; attribute DOMString className; // Layout properties diff --git a/dom/webidl/CanvasRenderingContext2D.webidl b/dom/webidl/CanvasRenderingContext2D.webidl index 8711b330a83..046952ceb54 100644 --- a/dom/webidl/CanvasRenderingContext2D.webidl +++ b/dom/webidl/CanvasRenderingContext2D.webidl @@ -18,6 +18,7 @@ interface HTMLCanvasElement; interface HTMLVideoElement; interface TextMetrics; interface Window; +interface XULElement; enum CanvasWindingRule { "nonzero", "evenodd" }; diff --git a/dom/webidl/HTMLElement.webidl b/dom/webidl/HTMLElement.webidl index 96be9ec85dd..6b298b94597 100644 --- a/dom/webidl/HTMLElement.webidl +++ b/dom/webidl/HTMLElement.webidl @@ -15,7 +15,6 @@ interface DOMStringMap; interface HTMLMenuElement; -// Hack to make sure that we initialize the touch prefs properly [PrefControlled] interface HTMLElement : Element { // metadata attributes @@ -81,6 +80,19 @@ interface HTMLElement : Element { // FIXME Bug 810677 Move className from HTMLElement to Element attribute DOMString className; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchstart; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchend; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchmove; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchenter; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchleave; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchcancel; + [SetterThrows] attribute EventHandler oncopy; [SetterThrows] @@ -98,24 +110,7 @@ partial interface HTMLElement { readonly attribute long offsetHeight; }; -[NoInterfaceObject] -interface TouchEventHandlers { - [SetterThrows,Pref="dom.w3c_touch_events.expose"] - attribute EventHandler ontouchstart; - [SetterThrows,Pref="dom.w3c_touch_events.expose"] - attribute EventHandler ontouchend; - [SetterThrows,Pref="dom.w3c_touch_events.expose"] - attribute EventHandler ontouchmove; - [SetterThrows,Pref="dom.w3c_touch_events.expose"] - attribute EventHandler ontouchenter; - [SetterThrows,Pref="dom.w3c_touch_events.expose"] - attribute EventHandler ontouchleave; - [SetterThrows,Pref="dom.w3c_touch_events.expose"] - attribute EventHandler ontouchcancel; -}; - HTMLElement implements GlobalEventHandlers; HTMLElement implements NodeEventHandlers; -HTMLElement implements TouchEventHandlers; interface HTMLUnknownElement : HTMLElement {}; diff --git a/dom/webidl/SVGElement.webidl b/dom/webidl/SVGElement.webidl index 4afdd550803..fe7a522e4fe 100644 --- a/dom/webidl/SVGElement.webidl +++ b/dom/webidl/SVGElement.webidl @@ -34,6 +34,19 @@ interface SVGElement : Element { readonly attribute SVGSVGElement? ownerSVGElement; readonly attribute SVGElement? viewportElement; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchstart; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchend; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchmove; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchenter; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchleave; + [SetterThrows,Pref="dom.w3c_touch_events.expose"] + attribute EventHandler ontouchcancel; + [SetterThrows] attribute EventHandler oncopy; [SetterThrows] @@ -44,4 +57,3 @@ interface SVGElement : Element { SVGElement implements GlobalEventHandlers; SVGElement implements NodeEventHandlers; -SVGElement implements TouchEventHandlers; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index b91a5616d6a..1971d5ef667 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -185,7 +185,6 @@ webidl_files = \ XMLHttpRequestUpload.webidl \ XMLSerializer.webidl \ XPathEvaluator.webidl \ - XULElement.webidl \ $(NULL) ifdef MOZ_WEBGL diff --git a/dom/webidl/XULElement.webidl b/dom/webidl/XULElement.webidl deleted file mode 100644 index 9288a4a00a7..00000000000 --- a/dom/webidl/XULElement.webidl +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -interface MozBoxObject; -interface MozControllers; -interface MozFrameLoader; -interface MozRDFCompositeDataSource; -interface MozRDFResource; -interface MozXULTemplateBuilder; - -// Hack to make sure that we initialize the touch prefs properly -[PrefControlled] -interface XULElement : Element { - [SetterThrows] - attribute DOMString className; - - // Layout properties - [SetterThrows] - attribute DOMString align; - [SetterThrows] - attribute DOMString dir; - [SetterThrows] - attribute DOMString flex; - [SetterThrows] - attribute DOMString flexGroup; - [SetterThrows] - attribute DOMString ordinal; - [SetterThrows] - attribute DOMString orient; - [SetterThrows] - attribute DOMString pack; - - // Properties for hiding elements. - attribute boolean hidden; - attribute boolean collapsed; - - // Property for hooking up to broadcasters - [SetterThrows] - attribute DOMString observes; - - // Properties for hooking up to popups - [SetterThrows] - attribute DOMString menu; - [SetterThrows] - attribute DOMString contextMenu; - [SetterThrows] - attribute DOMString tooltip; - - // Width/height properties - [SetterThrows] - attribute DOMString width; - [SetterThrows] - attribute DOMString height; - [SetterThrows] - attribute DOMString minWidth; - [SetterThrows] - attribute DOMString minHeight; - [SetterThrows] - attribute DOMString maxWidth; - [SetterThrows] - attribute DOMString maxHeight; - - // Persistence - [SetterThrows] - attribute DOMString persist; - - // Position properties for - // * popups - these are screen coordinates - // * other elements - these are client coordinates relative to parent stack. - [SetterThrows] - attribute DOMString left; - [SetterThrows] - attribute DOMString top; - - // XUL Template Builder - [SetterThrows] - attribute DOMString datasources; - [SetterThrows] - attribute DOMString ref; - - // Tooltip and status info - [SetterThrows] - attribute DOMString tooltipText; - [SetterThrows] - attribute DOMString statusText; - - attribute boolean allowEvents; - - readonly attribute MozRDFCompositeDataSource? database; - readonly attribute MozXULTemplateBuilder? builder; - [Throws] - readonly attribute MozRDFResource? resource; - [Throws] - readonly attribute MozControllers controllers; - [Throws] - readonly attribute MozBoxObject? boxObject; - - [Throws] - void focus(); - [Throws] - void blur(); - [Throws] - void click(); - void doCommand(); - - // XXXbz this isn't really a nodelist! See bug 818548 - NodeList getElementsByAttribute(DOMString name, - DOMString value); - // XXXbz this isn't really a nodelist! See bug 818548 - [Throws] - NodeList getElementsByAttributeNS(DOMString namespaceURI, - DOMString name, - DOMString value); - [Constant] - readonly attribute CSSStyleDeclaration style; -}; - -// And the things from nsIFrameLoaderOwner -[NoInterfaceObject] -interface MozFrameLoaderOwner { - [ChromeOnly] - readonly attribute MozFrameLoader? frameLoader; - - [ChromeOnly, Throws] - void swapFrameLoaders(XULElement aOtherOwner); -}; - -XULElement implements GlobalEventHandlers; -XULElement implements NodeEventHandlers; -XULElement implements TouchEventHandlers; -XULElement implements MozFrameLoaderOwner; diff --git a/js/xpconnect/src/XPCJSID.cpp b/js/xpconnect/src/XPCJSID.cpp index 6970676adf9..b07d2102969 100644 --- a/js/xpconnect/src/XPCJSID.cpp +++ b/js/xpconnect/src/XPCJSID.cpp @@ -486,9 +486,19 @@ nsJSIID::HasInstance(nsIXPConnectWrappedNative *wrapper, JSObject* cur = unsafeObj ? unsafeObj : obj; nsISupports *identity; if (mozilla::dom::UnwrapDOMObjectToISupports(cur, identity)) { - nsCOMPtr supp; - identity->QueryInterface(*iid, getter_AddRefs(supp)); - *bp = supp; + nsCOMPtr ci = do_QueryInterface(identity); + if (!ci) { + // No classinfo means we're not implementing interfaces and all + return NS_OK; + } + + XPCCallContext ccx(JS_CALLER, cx); + + AutoMarkingNativeSetPtr set(ccx); + set = XPCNativeSet::GetNewOrUsed(ccx, ci); + if (!set) + return NS_ERROR_FAILURE; + *bp = set->HasInterfaceWithAncestor(iid); return NS_OK; } } diff --git a/js/xpconnect/src/dom_quickstubs.qsconf b/js/xpconnect/src/dom_quickstubs.qsconf index 53a12ba58dd..266f7d176c6 100644 --- a/js/xpconnect/src/dom_quickstubs.qsconf +++ b/js/xpconnect/src/dom_quickstubs.qsconf @@ -73,6 +73,7 @@ members = [ 'nsIDOMXULDocument.getBoxObjectFor', # dom/interfaces/css + 'nsIDOMElementCSSInlineStyle.*', 'nsIDOMRect.*', 'nsIDOMEvent.type', @@ -240,6 +241,9 @@ members = [ 'nsIDOMXPathResult.singleNodeValue', 'nsIDOMNSXPathExpression.evaluateWithContext', + # dom/interfaces/xul + 'nsIDOMXULElement.*', + # layout/xul/base/public 'nsIBoxObject.x', 'nsIBoxObject.y', @@ -346,6 +350,15 @@ customMethodCalls = { 'nsIDOMStorage_Clear': { 'code': nsIDOMStorage_Clear_customMethodCallCode }, + 'nsIDOMElementCSSInlineStyle_GetStyle': { + 'thisType': 'nsStyledElement', + 'code': ' /* XXXbz MathML elements inherit from nsStyledElement but\n' + ' don\'t actually implement GetStyle. */\n' + ' if (self->GetNameSpaceID() == kNameSpaceID_MathML)\n' + ' return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n' + ' nsIDOMCSSStyleDeclaration* result = self->Style();', + 'canFail': False + }, 'nsIDOMWindow_GetOnmouseenter' : { 'thisType' : 'nsIDOMWindow', 'unwrapThisFailureFatal' : False diff --git a/xpfe/appshell/src/nsXULWindow.cpp b/xpfe/appshell/src/nsXULWindow.cpp index e4e05f16ea1..194d80d9423 100644 --- a/xpfe/appshell/src/nsXULWindow.cpp +++ b/xpfe/appshell/src/nsXULWindow.cpp @@ -1494,8 +1494,8 @@ NS_IMETHODIMP nsXULWindow::SavePersistentAttributes() nsCOMPtr ownerDoc; docShellElement->GetOwnerDocument(getter_AddRefs(ownerDoc)); ownerXULDoc = do_QueryInterface(ownerDoc); - nsCOMPtr XULElement(do_QueryInterface(docShellElement)); - if (XULElement && XULElement->IsXUL()) + nsCOMPtr XULElement(do_QueryInterface(docShellElement)); + if (XULElement) XULElement->GetId(windowElementId); } From d051501ede83da8bfb68f621f56cc1ee8f8a7c69 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Tue, 8 Jan 2013 14:09:48 -0500 Subject: [PATCH 24/70] Bug 828789. Update to pixman 0.27.2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alan Coopersmith (2): Make mmx code compatible with Solaris Studio 12.3 compilers Just use xmmintrin.h when building with Solaris Studio compilers Andrea Canciani (7): Remove useless checks for NULL before freeing test: Cleanup includes Use the ARRAY_LENGTH() macro when possible test: Reuse the ARRAY_LENGTH() macro demos: Consistently use G_N_ELEMENTS() test: Produce autotools-looking report in the win32 build system build: Fix compilation on win32 Antti S. Lankila (5): Faster unorm_to_unorm for wide processing. Remove unnecessary dst initialization Add support for sRGB surfaces Add sRGB blending demo program Add tests to validate new sRGB behavior Bobby Salazar (2): Android Runtime Detection Support For ARM NEON iOS Runtime Detection Support For ARM NEON Chun-wei Fan (1): Just include xmmintrin.h on MSVC as well Colin Walters (1): autogen.sh: Support GNOME Build API Ingmar Runge (1): Fix MSVC compilation Jeremy Huddleston (7): configure.ac: Add an --enable-libpng option Revert "Disable MMX when Clang is being used." Silence a warning about unused pixman_have_mmx Disable MMX when incompatible clang is being used. Expand TLS support beyond __thread to __declspec(thread) Fix a false-negative in MMX check configure.ac: Fix a copy-paste-o in TLS detection Matt Turner (60): Use AC_LANG_SOURCE for iwMMXt configure program Make sure to run AC_SUBST IWMMXT_CFLAGS Convert while (w) to if (w) when possible autoconf: use #error instead of error mmx: enable over_x888_8_8888 on ARM/iwMMXt mmx: Use _mm_mulhi_pu16 mmx: Use _mm_shuffle_pi16 mmx: fix typo in pix_add_mul on MSVC Update .gitignore with more demos and tests mmx: make store8888 take uint32_t *dest as argument mmx: make load8888 take a pointer to data instead of the data itself lowlevel-blt: add over_8888_8888 lowlevel-blt: add over_x888_n_8888 lowlevel-blt-bench: add in_8_8 and in_n_8_8 Use AC_LANG_SOURCE for DSPr2 configure program mmx: enable over_n_0565 for b5g6r5 mmx: Use force_inline instead of __inline__ (bug 46906) configure.ac: require >= gcc-4.5 for ARM iwMMXt mmx: fix _mm_shuffle_pi16 function when compiling without optimization configure.ac: fix iwMMXt/gcc version error message mmx: add store function and use it in add_8888_8888 mmx: add load function and use it in add_8888_8888 mmx: make ldq_u take __m64* directly mmx: compile on MIPS for Loongson MMI optimizations mmx: remove unnecessary uint64_t<->__m64 conversions mmx: simplify srcsrcsrcsrc calculation in over_n_8_0565 mmx: introduce is_equal, is_opaque, and is_zero functions mmx: don't pack and unpack src unnecessarily mmx: Use Loongson pinsrh instruction in pack_565 mmx: Use Loongson pextrh instruction in expand565 mmx: add r5g6b5 fetcher mmx: add a8 fetcher mmx: add x8f8g8b8 fetcher mmx: add src_8888_0565 mmx: Use wpackhus in src_x888_0565 on iwMMXt .gitignore: add demos/checkerboard and demos/quad2quad configure.ac: make -march=loongson2f come before CFLAGS mmx: add and use pack_4x565 function configure.ac: Fix loongson-mmi out-of-tree builds configure.ac: Rename loongson -> loongson-mmi configure.ac: Fail the ARM/iwMMXt test if not compiling with -march=iwmmxt mmx: add and use expand_4xpacked565 function mmx: implement expand_4x565 in terms of expand_4xpacked565 fast: add add_0565_0565 function mmx: add add_0565_0565 mmx: add over_reverse_n_8888 mmx: add missing _mm_empty calls autotools: use custom build rule to build iwMMXt code configure.ac: add iwmmxt2 configure flag .gitignore: add test/glyph-test sse2: enable over_n_0565 for b5g6r5 sse2: add src_x888_0565 Fix distcheck due to custom iwMMXt rules mmx: Use expand_alpha instead of mask/shift mmx: add scaled bilinear src_8888_8888 mmx: add scaled bilinear over_8888_8888 mmx: add scaled bilinear over_8888_8_8888 mmx: optimize bilinear function when using 7-bit precision loongson: optimize _mm_set_pi* functions with shuffle instructions sse2: add missing ABGR entires for bilinear src_8888_8888 Naohiro Aota (1): Don't use non-POSIX test Nemanja Lukic (9): MIPS: DSPr2: Basic infrastructure for MIPS architecture MIPS: DSPr2: Added fast-paths for SRC operation. MIPS: DSPr2: Added mips_dspr2_blt and mips_dspr2_fill routines. MIPS: DSPr2: Added over_n_8888_8888_ca and over_n_8888_0565_ca fast paths. MIPS: DSPr2: Added over_n_8_8888 and over_n_8_0565 fast paths. MIPS: DSPr2: Fix bug in over_n_8888_8888_ca/over_n_8888_0565_ca routines MIPS: DSPr2: Added bilinear over_8888_8_8888 fast path. MIPS: DSPr2: Added several bilinear fast paths with a8 mask MIPS: DSPr2: Added more bilinear fast paths (without mask) Sebastian Bauer (4): Qualify the static variables in pixman_f_transform_invert() with the const keyword. Changed the style of two function headers Added HAVE_CONFIG_H check before including config.h Use angle brackets form of including config.h Siarhei Siamashka (8): test: OpenMP 2.5 requires signed loop iteration variables test: fix bisecting issue in fuzzer-find-diff.pl test: Fix for strict aliasing issue in 'get_random_seed' test: support nearest/bilinear scaling in lowlevel-blt-bench sse2: faster bilinear scaling (use _mm_loadl_epi64) Bilinear interpolation precision is now configurable at compile time sse2: _mm_madd_epi16 for faster bilinear scaling with 7-bit precision Change default bilinear interpolation precision to 7 bits Søren Sandmann Pedersen (81): Post-release version bump to 0.25.1 region: Add pixman_region{,32}_clear() functions. Modify gradient-test to show a bug in NONE processing gradient-walker: For NONE repeats, when x < 0 or x > 1, set both colors to 0 pixman-image.c: Fix typo in pixman_image_set_transform() Fix some signed overflow bugs Add missing cast in _pixman_edge_multi_init() Fix a bunch of signed overflow issues In MUL_UNc() cast to comp2_t Reject trapezoids where top (botttom) is above (below) the edges Fix rounding for DIV_UNc() test: In the alphamap test, also test that we get the right red value Fix bugs with alpha maps test/alphamap.c: Make dst and orig_dst more independent of each other Get rid of delegates for combiners Move the color_correct() function from composite.c to utils.c Rename color_correct() to round_color() test: Add a new "pixel_checker_t" object. test: Port composite test over to use new pixel_checker_t object. Revert "Reject trapezoids where top (botttom) is above (below) the edges" mmx: Enable over_x888_8_8888() for x86 as well mmx: Delete unused function in_over_full_src_alpha() Disable MMX when Clang is being used. Disable implementations mentioned in the PIXMAN_DISABLE environment variable. Move fetching for solid bits images to pixman-noop.c pixman-accessors.h: Delete unused macros pixman-access.c: Remove some unused macros mmx: Squash a warning by making the argument to ldl_u() const Pre-release version bump to 0.25.2 Post-release version bump to 0.25.3 Use "=a" and "=d" constraints for rdtsc inline assembly demos: Add quad2quad program demos: Add checkerboard demo composite-test.c: Use similar gradient to the one in the PDF spec. composite-test.c: Add a parrot image Add the original parrot image. Rename fast_composite_add_1000_1000 to _add_1_1() gtk-utils.c: Don't include pixman-private.h test/utils.c: Rename and export the pngify_pixels() function. gtk-utils.c: In pixbuf_from_argb32() use a8r8g8b8_to_rgba_np() test/utils.c: Clip values to the [0, 255] interval bits_image_fetch_pixel_convolution(): Make sure channels are signed Add Makefile.win32 and Makefile.win32.common to EXTRA_DIST demos/Makefile.am: Add parrot.c to EXTRA_DIST Pre-release version bump to 0.25.6 Post-release version bump to 0.25.7 demos: Add parrot.jpg to EXTRA_DIST test: Composite with solid images instead of using pixman_image_fill_* Pre-release version bump to 0.26.0 Post-release version bump to 0.27.1 Pass the full image flags to iterators Make use of image flags in mmx and sse2 iterators Add doubly linked lists Add pixman_glyph_cache_t API Move CRC32 computation from blitters-test.c into utils.c Add support for alpha maps to compute_crc32_for_image(). test: Add glyph-test Speed up pixman_composite_glyphs() Speed up _pixman_composite_glyphs_no_mask() Speed up _pixman_image_get_solid() in common cases bits-image: Turn all the fetchers into iterator getters test: Make glyph test pass on big endian test: Add missing break in stress-test.c test: Make stress-test more likely to actually composite something In fast_composite_tiled_repeat() don't clone images with a palette Use a compile-time constant for the "K" constraint in the MMX detection. pixman-cpu.c: Rename disabled to _pixman_disabled() and export it Move x86 specific CPU detection to a new file pixman-x86.c Move ARM specific CPU detection to a new file pixman-arm.c Move PowerPC specific CPU detection to its own file pixman-ppc.c Move MIPS specific CPU detection to its own file, pixman-mips.c Move the remaining bits of pixman-cpu into pixman-implementation.c Simplify MIPS CPU detection Simplifications to ARM CPU detection Simplify CPU detection on PPC. Cleanups and simplifications in x86 CPU feature detection Make pixman-mmx.c compile on x86-32 without optimization Add make-srgb.pl to EXTRA_DIST stress-test: Avoid overflows in clip rectangles glyph-test: Avoid setting solid images as alpha maps. Pre-release version bump to 0.27.2 * * * --HG-- extra : rebase_source : d5b871a3b10fe0123f6e50cf98c3621532e5d914 --- gfx/cairo/libpixman/src/Makefile.in | 7 +- gfx/cairo/libpixman/src/pixman-access.c | 134 +- .../src/pixman-arm-neon-asm-bilinear.S | 119 +- gfx/cairo/libpixman/src/pixman-arm-neon-asm.S | 159 +- gfx/cairo/libpixman/src/pixman-arm.c | 229 +++ gfx/cairo/libpixman/src/pixman-bits-image.c | 255 +-- gfx/cairo/libpixman/src/pixman-combine32.c | 20 +- gfx/cairo/libpixman/src/pixman-combine32.h | 4 +- gfx/cairo/libpixman/src/pixman-combine64.c | 20 +- gfx/cairo/libpixman/src/pixman-combine64.h | 4 +- gfx/cairo/libpixman/src/pixman-compiler.h | 4 + .../libpixman/src/pixman-conical-gradient.c | 2 +- gfx/cairo/libpixman/src/pixman-fast-path.c | 65 +- gfx/cairo/libpixman/src/pixman-general.c | 12 +- gfx/cairo/libpixman/src/pixman-glyph.c | 676 ++++++++ gfx/cairo/libpixman/src/pixman-image.c | 34 +- .../libpixman/src/pixman-implementation.c | 63 +- gfx/cairo/libpixman/src/pixman-inlines.h | 52 +- .../libpixman/src/pixman-linear-gradient.c | 8 +- gfx/cairo/libpixman/src/pixman-matrix.c | 6 +- .../libpixman/src/pixman-mips-dspr2-asm.S | 1521 +++++++++++++++++ .../libpixman/src/pixman-mips-dspr2-asm.h | 659 +++++++ gfx/cairo/libpixman/src/pixman-mips-dspr2.c | 326 ++++ gfx/cairo/libpixman/src/pixman-mips-dspr2.h | 231 +++ .../libpixman/src/pixman-mips-memcpy-asm.S | 382 +++++ gfx/cairo/libpixman/src/pixman-mips.c | 84 + gfx/cairo/libpixman/src/pixman-mmx.c | 1164 +++++++++++-- gfx/cairo/libpixman/src/pixman-noop.c | 14 +- gfx/cairo/libpixman/src/pixman-ppc.c | 155 ++ gfx/cairo/libpixman/src/pixman-private.h | 148 +- .../libpixman/src/pixman-radial-gradient.c | 4 +- gfx/cairo/libpixman/src/pixman-region.c | 14 +- gfx/cairo/libpixman/src/pixman-solid-fill.c | 2 +- gfx/cairo/libpixman/src/pixman-srgb.c | 455 +++++ gfx/cairo/libpixman/src/pixman-sse2.c | 160 +- gfx/cairo/libpixman/src/pixman-utils.c | 31 +- gfx/cairo/libpixman/src/pixman-version.h | 6 +- gfx/cairo/libpixman/src/pixman-vmx.c | 3 - gfx/cairo/libpixman/src/pixman-x86.c | 237 +++ gfx/cairo/libpixman/src/pixman.c | 43 +- gfx/cairo/libpixman/src/pixman.h | 63 + 41 files changed, 6981 insertions(+), 594 deletions(-) create mode 100644 gfx/cairo/libpixman/src/pixman-arm.c create mode 100644 gfx/cairo/libpixman/src/pixman-glyph.c create mode 100644 gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S create mode 100644 gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h create mode 100644 gfx/cairo/libpixman/src/pixman-mips-dspr2.c create mode 100644 gfx/cairo/libpixman/src/pixman-mips-dspr2.h create mode 100644 gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S create mode 100644 gfx/cairo/libpixman/src/pixman-mips.c create mode 100644 gfx/cairo/libpixman/src/pixman-ppc.c create mode 100644 gfx/cairo/libpixman/src/pixman-srgb.c create mode 100644 gfx/cairo/libpixman/src/pixman-x86.c diff --git a/gfx/cairo/libpixman/src/Makefile.in b/gfx/cairo/libpixman/src/Makefile.in index 9b4873ede42..fcb0369cf61 100644 --- a/gfx/cairo/libpixman/src/Makefile.in +++ b/gfx/cairo/libpixman/src/Makefile.in @@ -83,29 +83,34 @@ endif CSRCS = \ pixman-access.c \ pixman-access-accessors.c \ + pixman-arm.c \ pixman-bits-image.c \ pixman.c \ pixman-combine16.c \ pixman-combine32.c \ pixman-combine64.c \ pixman-conical-gradient.c \ - pixman-cpu.c \ pixman-edge.c \ pixman-edge-accessors.c \ pixman-fast-path.c \ pixman-general.c \ pixman-gradient-walker.c \ + pixman-glyph.c \ pixman-image.c \ pixman-implementation.c \ pixman-linear-gradient.c \ pixman-matrix.c \ + pixman-mips.c \ pixman-noop.c \ + pixman-ppc.c \ pixman-radial-gradient.c \ pixman-region16.c \ pixman-region32.c \ pixman-solid-fill.c \ + pixman-srgb.c \ pixman-trap.c \ pixman-utils.c \ + pixman-x86.c \ $(NULL) ifdef USE_MMX diff --git a/gfx/cairo/libpixman/src/pixman-access.c b/gfx/cairo/libpixman/src/pixman-access.c index 91ce793cacc..521ad405742 100644 --- a/gfx/cairo/libpixman/src/pixman-access.c +++ b/gfx/cairo/libpixman/src/pixman-access.c @@ -32,8 +32,8 @@ #include #include -#include "pixman-private.h" #include "pixman-accessor.h" +#include "pixman-private.h" #define CONVERT_RGB24_TO_Y15(s) \ (((((s) >> 16) & 0xff) * 153 + \ @@ -210,6 +210,7 @@ get_shifts (pixman_format_code_t format, break; case PIXMAN_TYPE_ARGB: + case PIXMAN_TYPE_ARGB_SRGB: *b = 0; *g = *b + PIXMAN_FORMAT_B (format); *r = *g + PIXMAN_FORMAT_G (format); @@ -1065,6 +1066,130 @@ fetch_pixel_generic_64 (bits_image_t *image, return result; } +/* The 32_sRGB paths should be deleted after narrow processing + * is no longer invoked for formats that are considered wide. + * (Also see fetch_pixel_generic_lossy_32) */ +static void +fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image, + int x, + int y, + int width, + uint32_t *buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint32_t tmp; + + while (pixel < end) + { + tmp = READ (image, pixel++); + *buffer++ = (tmp >> 24) << 24 + | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 + | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 + | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; + } +} + +static void +fetch_scanline_a8r8g8b8_64_sRGB (pixman_image_t *image, + int x, + int y, + int width, + uint32_t *b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint64_t *buffer = (uint64_t *)b; + uint32_t tmp; + + while (pixel < end) + { + tmp = READ (image, pixel++); + *buffer++ = (uint64_t) ((tmp >> 24) * 257) << 48 + | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 + | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 + | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; + } +} + +static uint32_t +fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t tmp = READ (image, bits + offset); + return (tmp >> 24) << 24 + | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 + | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 + | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; +} + +static uint64_t +fetch_pixel_a8r8g8b8_64_sRGB (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t tmp = READ (image, bits + offset); + return (uint64_t) ((tmp >> 24) * 257) << 48 + | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 + | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 + | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; +} + +static void +store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + uint64_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + tmp = values[i]; + WRITE (image, pixel++, + ((uint32_t) (tmp >> 24 ) << 24) + | (linear_to_srgb[(tmp >> 16 << 4) & 0xfff] << 16) + | (linear_to_srgb[(tmp >> 8 << 4) & 0xfff] << 8) + | (linear_to_srgb[(tmp >> 0 << 4) & 0xfff] << 0)); + } +} + +static void +store_scanline_a8r8g8b8_64_sRGB (bits_image_t *image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + uint64_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + tmp = values[i]; + WRITE (image, pixel++, + ((uint32_t) (tmp >> 56) << 24) + | (linear_to_srgb[(tmp >> 36) & 0xfff] << 16) + | (linear_to_srgb[(tmp >> 20) & 0xfff] << 8) + | (linear_to_srgb[(tmp >> 4) & 0xfff] << 0)); + } +} + /* * XXX: The transformed fetch path only works at 32-bpp so far. When all * paths have wide versions, this can be removed. @@ -1132,6 +1257,13 @@ static const format_info_t accessors[] = FORMAT_INFO (r8g8b8x8), FORMAT_INFO (x14r6g6b6), +/* sRGB formats */ + { PIXMAN_a8r8g8b8_sRGB, + fetch_scanline_a8r8g8b8_32_sRGB, + fetch_scanline_a8r8g8b8_64_sRGB, + fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB, + store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB }, + /* 24bpp formats */ FORMAT_INFO (r8g8b8), FORMAT_INFO (b8g8r8), diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S index f7913adb71b..e37b5c298e4 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S +++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.S @@ -64,6 +64,7 @@ .altmacro .p2align 2 +#include "pixman-private.h" #include "pixman-arm-neon-asm.h" /* @@ -488,12 +489,12 @@ fname: vmull.u8 q1, d0, d28 vmlal.u8 q1, d1, d29 /* 5 cycles bubble */ - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 /* 5 cycles bubble */ bilinear_duplicate_mask mask_fmt, 1, d4 - vshrn.u32 d0, q0, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) /* 3 cycles bubble */ vmovn.u16 d0, q0 /* 1 cycle bubble */ @@ -514,16 +515,16 @@ fname: q1, q11, d0, d1, d20, d21, d22, d23 bilinear_load_mask mask_fmt, 2, d4 bilinear_load_dst dst_fmt, op, 2, d18, d19, q9 - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) bilinear_duplicate_mask mask_fmt, 2, d4 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vmovn.u16 d0, q0 bilinear_interleave_src_dst \ @@ -544,29 +545,29 @@ fname: q3, q9, d4, d5, d16, d17, d18, d19 pld [TMP1, PF_OFFS] sub TMP1, TMP1, STRIDE - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d6, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d6, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d6, d30 vmlal.u16 q2, d7, d30 - vshll.u16 q8, d18, #8 + vshll.u16 q8, d18, #BILINEAR_INTERPOLATION_BITS bilinear_load_mask mask_fmt, 4, d22 bilinear_load_dst dst_fmt, op, 4, d2, d3, q1 pld [TMP1, PF_OFFS] vmlsl.u16 q8, d18, d31 vmlal.u16 q8, d19, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 - vshrn.u32 d4, q2, #16 - vshrn.u32 d5, q8, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q8, #(2 * BILINEAR_INTERPOLATION_BITS) bilinear_duplicate_mask mask_fmt, 4, d22 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vmovn.u16 d0, q0 vmovn.u16 d1, q2 vadd.u16 q12, q12, q13 @@ -694,13 +695,13 @@ pixman_asm_function fname blt 0f tst OUT, #(1 << dst_bpp_shift) beq 0f - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 bilinear_process_last_pixel sub WIDTH, WIDTH, #1 0: vadd.u16 q13, q13, q13 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 cmp WIDTH, #2 @@ -921,7 +922,7 @@ pixman_asm_function fname vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -932,27 +933,27 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 .endm .macro bilinear_over_8888_8888_process_pixblock_tail - vshll.u16 q2, d20, #8 + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d2, d3}, [OUT, :128] pld [OUT, #(prefetch_offset * 4)] - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 - vshrn.u32 d5, q3, #16 + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d6, q0 vmovn.u16 d7, q2 vuzp.8 d6, d7 @@ -975,7 +976,7 @@ pixman_asm_function fname .endm .macro bilinear_over_8888_8888_process_pixblock_tail_head - vshll.u16 q2, d20, #8 + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS mov TMP1, X, asr #16 add X, X, UX add TMP1, TOP, TMP1, asl #2 @@ -984,21 +985,21 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d2, d3}, [OUT, :128] pld [OUT, PF_OFFS] - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d6, q0 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -1022,7 +1023,7 @@ pixman_asm_function fname vmlal.u8 q10, d23, d29 vmull.u8 q11, d2, d4 vmull.u8 q2, d3, d4 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vrshr.u16 q1, q11, #8 vmlal.u16 q0, d17, d30 @@ -1037,12 +1038,12 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 vuzp.8 d6, d7 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vuzp.8 d6, d7 vmlsl.u16 q1, d18, d31 vadd.u16 q12, q12, q13 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vst1.32 {d6, d7}, [OUT, :128]! .endm @@ -1081,14 +1082,14 @@ pixman_asm_function fname vmull.u8 q3, d2, d28 vmlal.u8 q2, d1, d29 vmlal.u8 q3, d3, d29 - vshll.u16 q0, d4, #8 - vshll.u16 q1, d6, #8 + vshll.u16 q0, d4, #BILINEAR_INTERPOLATION_BITS + vshll.u16 q1, d6, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d4, d30 vmlsl.u16 q1, d6, d31 vmlal.u16 q0, d5, d30 vmlal.u16 q1, d7, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d2}, [TMP3], STRIDE vld1.32 {d3}, [TMP3] pld [TMP4, PF_OFFS] @@ -1099,7 +1100,7 @@ pixman_asm_function fname vmlal.u8 q3, d3, d29 vmull.u8 q1, d4, d28 vmlal.u8 q1, d5, d29 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d22[0]}, [MASK]! pld [MASK, #prefetch_offset] vadd.u16 q12, q12, q13 @@ -1107,17 +1108,17 @@ pixman_asm_function fname .endm .macro bilinear_over_8888_8_8888_process_pixblock_tail - vshll.u16 q9, d6, #8 - vshll.u16 q10, d2, #8 + vshll.u16 q9, d6, #BILINEAR_INTERPOLATION_BITS + vshll.u16 q10, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q9, d6, d30 vmlsl.u16 q10, d2, d31 vmlal.u16 q9, d7, d30 vmlal.u16 q10, d3, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vdup.32 d22, d22[0] - vshrn.u32 d18, q9, #16 - vshrn.u32 d19, q10, #16 + vshrn.u32 d18, q9, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d19, q10, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d17, q9 vld1.32 {d18, d19}, [OUT, :128] pld [OUT, PF_OFFS] @@ -1146,11 +1147,11 @@ pixman_asm_function fname .endm .macro bilinear_over_8888_8_8888_process_pixblock_tail_head - vshll.u16 q9, d6, #8 + vshll.u16 q9, d6, #BILINEAR_INTERPOLATION_BITS mov TMP1, X, asr #16 add X, X, UX add TMP1, TOP, TMP1, asl #2 - vshll.u16 q10, d2, #8 + vshll.u16 q10, d2, #BILINEAR_INTERPOLATION_BITS vld1.32 {d0}, [TMP1], STRIDE mov TMP2, X, asr #16 add X, X, UX @@ -1167,12 +1168,12 @@ pixman_asm_function fname mov TMP4, X, asr #16 add X, X, UX add TMP4, TOP, TMP4, asl #2 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d3}, [TMP2] vdup.32 d22, d22[0] - vshrn.u32 d18, q9, #16 - vshrn.u32 d19, q10, #16 + vshrn.u32 d18, q9, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d19, q10, #(2 * BILINEAR_INTERPOLATION_BITS) vmull.u8 q2, d0, d28 vmull.u8 q3, d2, d28 vmovn.u16 d17, q9 @@ -1182,8 +1183,8 @@ pixman_asm_function fname vmlal.u8 q3, d3, d29 vuzp.8 d16, d17 vuzp.8 d18, d19 - vshll.u16 q0, d4, #8 - vshll.u16 q1, d6, #8 + vshll.u16 q0, d4, #BILINEAR_INTERPOLATION_BITS + vshll.u16 q1, d6, #BILINEAR_INTERPOLATION_BITS vuzp.8 d16, d17 vuzp.8 d18, d19 vmlsl.u16 q0, d4, d30 @@ -1194,8 +1195,8 @@ pixman_asm_function fname vmlal.u16 q1, d7, d31 vrsra.u16 q10, q10, #8 vrsra.u16 q11, q11, #8 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vrshrn.u16 d16, q10, #8 vrshrn.u16 d17, q11, #8 vld1.32 {d2}, [TMP3], STRIDE @@ -1216,7 +1217,7 @@ pixman_asm_function fname vraddhn.u16 d18, q9, q10 vraddhn.u16 d19, q15, q11 vmlal.u8 q1, d5, d29 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vqadd.u8 q9, q8, q9 vld1.32 {d22[0]}, [MASK]! vuzp.8 d18, d19 diff --git a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S index 87aae1d552d..187197dc31d 100644 --- a/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S +++ b/gfx/cairo/libpixman/src/pixman-arm-neon-asm.S @@ -49,6 +49,7 @@ .altmacro .p2align 2 +#include "pixman-private.h" #include "pixman-arm-neon-asm.h" /* Global configuration options and preferences */ @@ -2986,11 +2987,11 @@ fname: vmull.u8 q1, d0, d28 vmlal.u8 q1, d1, d29 /* 5 cycles bubble */ - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 /* 5 cycles bubble */ - vshrn.u32 d0, q0, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) /* 3 cycles bubble */ vmovn.u16 d0, q0 /* 1 cycle bubble */ @@ -3000,15 +3001,15 @@ fname: .macro bilinear_interpolate_two_pixels src_fmt, dst_fmt bilinear_load_and_vertical_interpolate_two_&src_fmt \ q1, q11, d0, d1, d20, d21, d22, d23 - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 - vshr.u16 q15, q12, #8 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vmovn.u16 d0, q0 bilinear_store_&dst_fmt 2, q2, q3 @@ -3020,26 +3021,26 @@ fname: q3, q9, d4, d5, d16, d17, d18, d19 pld [TMP1, PF_OFFS] sub TMP1, TMP1, STRIDE - vshll.u16 q0, d2, #8 + vshll.u16 q0, d2, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d2, d30 vmlal.u16 q0, d3, d30 - vshll.u16 q10, d22, #8 + vshll.u16 q10, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q10, d22, d31 vmlal.u16 q10, d23, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d6, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d6, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d6, d30 vmlal.u16 q2, d7, d30 - vshll.u16 q8, d18, #8 + vshll.u16 q8, d18, #BILINEAR_INTERPOLATION_BITS pld [TMP2, PF_OFFS] vmlsl.u16 q8, d18, d31 vmlal.u16 q8, d19, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q10, #16 - vshrn.u32 d4, q2, #16 - vshrn.u32 d5, q8, #16 - vshr.u16 q15, q12, #8 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q10, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q8, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vmovn.u16 d0, q0 vmovn.u16 d1, q2 vadd.u16 q12, q12, q13 @@ -3158,13 +3159,13 @@ pixman_asm_function fname blt 0f tst OUT, #(1 << dst_bpp_shift) beq 0f - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 bilinear_interpolate_last_pixel src_fmt, dst_fmt sub WIDTH, WIDTH, #1 0: vadd.u16 q13, q13, q13 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 cmp WIDTH, #2 @@ -3282,7 +3283,7 @@ pixman_asm_function fname vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3293,25 +3294,25 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 .endm .macro bilinear_interpolate_four_pixels_8888_8888_tail vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 - vshrn.u32 d5, q3, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d6, q0 vmovn.u16 d7, q2 vadd.u16 q12, q12, q13 @@ -3326,22 +3327,22 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3353,12 +3354,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d6, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d7, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3370,7 +3371,7 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 vst1.32 {d6, d7}, [OUT, :128]! - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 .endm @@ -3403,7 +3404,7 @@ pixman_asm_function fname vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 pld [TMP4, PF_OFFS] @@ -3412,7 +3413,7 @@ pixman_asm_function fname pld [TMP4, PF_OFFS] vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 mov TMP1, X, asr #16 @@ -3422,22 +3423,22 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3449,12 +3450,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d8, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d9, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3465,25 +3466,25 @@ pixman_asm_function fname pld [TMP4, PF_OFFS] vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 .endm .macro bilinear_interpolate_eight_pixels_8888_0565_tail vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vadd.u16 q12, q12, q13 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 - vshr.u16 q15, q12, #8 - vshrn.u32 d5, q3, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vmovn.u16 d10, q0 vmovn.u16 d11, q2 vadd.u16 q12, q12, q13 @@ -3508,23 +3509,23 @@ pixman_asm_function fname add X, X, UX add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vuzp.u8 d8, d9 - vshll.u16 q2, d20, #8 + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 vld1.32 {d21}, [TMP1] vmull.u8 q8, d20, d28 vmlal.u8 q8, d21, d29 - vshrn.u32 d0, q0, #16 - vshrn.u32 d1, q1, #16 - vshrn.u32 d4, q2, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3536,12 +3537,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d10, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d11, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3553,7 +3554,7 @@ pixman_asm_function fname vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 vuzp.u8 d10, d11 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vmlsl.u16 q1, d18, d31 mov TMP1, X, asr #16 @@ -3564,12 +3565,12 @@ pixman_asm_function fname add TMP2, TOP, TMP2, asl #2 vmlal.u16 q1, d19, d31 vuzp.u8 d9, d11 - vshr.u16 q15, q12, #8 - vshll.u16 q2, d20, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) + vshll.u16 q2, d20, #BILINEAR_INTERPOLATION_BITS vuzp.u8 d8, d10 vmlsl.u16 q2, d20, d30 vmlal.u16 q2, d21, d30 - vshll.u16 q3, d22, #8 + vshll.u16 q3, d22, #BILINEAR_INTERPOLATION_BITS vld1.32 {d20}, [TMP1], STRIDE vmlsl.u16 q3, d22, d31 vmlal.u16 q3, d23, d31 @@ -3579,13 +3580,13 @@ pixman_asm_function fname vshll.u8 q6, d9, #8 vshll.u8 q5, d10, #8 vshll.u8 q7, d8, #8 - vshrn.u32 d0, q0, #16 + vshrn.u32 d0, q0, #(2 * BILINEAR_INTERPOLATION_BITS) vsri.u16 q5, q6, #5 - vshrn.u32 d1, q1, #16 + vshrn.u32 d1, q1, #(2 * BILINEAR_INTERPOLATION_BITS) vsri.u16 q5, q7, #11 - vshrn.u32 d4, q2, #16 + vshrn.u32 d4, q2, #(2 * BILINEAR_INTERPOLATION_BITS) vld1.32 {d22}, [TMP2], STRIDE - vshrn.u32 d5, q3, #16 + vshrn.u32 d5, q3, #(2 * BILINEAR_INTERPOLATION_BITS) vadd.u16 q12, q12, q13 vld1.32 {d23}, [TMP2] vmull.u8 q9, d22, d28 @@ -3597,12 +3598,12 @@ pixman_asm_function fname add TMP4, TOP, TMP4, asl #2 vmlal.u8 q9, d23, d29 vld1.32 {d22}, [TMP3], STRIDE - vshr.u16 q15, q12, #8 + vshr.u16 q15, q12, #(16 - BILINEAR_INTERPOLATION_BITS) vld1.32 {d23}, [TMP3] vmull.u8 q10, d22, d28 vmlal.u8 q10, d23, d29 vmovn.u16 d8, q0 - vshll.u16 q0, d16, #8 + vshll.u16 q0, d16, #BILINEAR_INTERPOLATION_BITS vmovn.u16 d9, q2 vmlsl.u16 q0, d16, d30 vmlal.u16 q0, d17, d30 @@ -3613,7 +3614,7 @@ pixman_asm_function fname pld [TMP4, PF_OFFS] vmull.u8 q11, d16, d28 vmlal.u8 q11, d17, d29 - vshll.u16 q1, d18, #8 + vshll.u16 q1, d18, #BILINEAR_INTERPOLATION_BITS vst1.32 {d10, d11}, [OUT, :128]! vmlsl.u16 q1, d18, d31 .endm diff --git a/gfx/cairo/libpixman/src/pixman-arm.c b/gfx/cairo/libpixman/src/pixman-arm.c new file mode 100644 index 00000000000..145bd9050b7 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-arm.c @@ -0,0 +1,229 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +typedef enum +{ + ARM_V7 = (1 << 0), + ARM_V6 = (1 << 1), + ARM_VFP = (1 << 2), + ARM_NEON = (1 << 3), + ARM_IWMMXT = (1 << 4) +} arm_cpu_features_t; + +#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) + +#if defined(_MSC_VER) + +/* Needed for EXCEPTION_ILLEGAL_INSTRUCTION */ +#include + +extern int pixman_msvc_try_arm_neon_op (); +extern int pixman_msvc_try_arm_simd_op (); + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + + __try + { + pixman_msvc_try_arm_simd_op (); + features |= ARM_V6; + } + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) + { + } + + __try + { + pixman_msvc_try_arm_neon_op (); + features |= ARM_NEON; + } + __except (GetExceptionCode () == EXCEPTION_ILLEGAL_INSTRUCTION) + { + } + + return features; +} + +#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) /* iOS */ + +#include "TargetConditionals.h" + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + + features |= ARM_V6; + + /* Detection of ARM NEON on iOS is fairly simple because iOS binaries + * contain separate executable images for each processor architecture. + * So all we have to do is detect the armv7 architecture build. The + * operating system automatically runs the armv7 binary for armv7 devices + * and the armv6 binary for armv6 devices. + */ +#if defined(__ARM_NEON__) + features |= ARM_NEON; +#endif + + return features; +} + +#elif defined(__ANDROID__) || defined(ANDROID) /* Android */ + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + char buf[1024]; + char* pos; + const char* ver_token = "CPU architecture: "; + FILE* f = fopen("/proc/cpuinfo", "r"); + if (!f) { + return features; + } + + fread(buf, sizeof(char), sizeof(buf), f); + fclose(f); + pos = strstr(buf, ver_token); + if (pos) { + char vchar = *(pos + strlen(ver_token)); + if (vchar >= '0' && vchar <= '9') { + int ver = vchar - '0'; + if (ver >= 7) + features |= ARM_V7; + } + } + if (strstr(buf, "neon") != NULL) + features |= ARM_NEON; + if (strstr(buf, "vfp") != NULL) + features |= ARM_VFP; + + return features; +} + +#elif defined (__linux__) /* linux ELF */ + +#include +#include +#include +#include +#include +#include +#include + +static arm_cpu_features_t +detect_cpu_features (void) +{ + arm_cpu_features_t features = 0; + Elf32_auxv_t aux; + int fd; + + fd = open ("/proc/self/auxv", O_RDONLY); + if (fd >= 0) + { + while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) + { + if (aux.a_type == AT_HWCAP) + { + uint32_t hwcap = aux.a_un.a_val; + + /* hardcode these values to avoid depending on specific + * versions of the hwcap header, e.g. HWCAP_NEON + */ + if ((hwcap & 64) != 0) + features |= ARM_VFP; + if ((hwcap & 512) != 0) + features |= ARM_IWMMXT; + /* this flag is only present on kernel 2.6.29 */ + if ((hwcap & 4096) != 0) + features |= ARM_NEON; + } + else if (aux.a_type == AT_PLATFORM) + { + const char *plat = (const char*) aux.a_un.a_val; + + if (strncmp (plat, "v7l", 3) == 0) + features |= (ARM_V7 | ARM_V6); + else if (strncmp (plat, "v6l", 3) == 0) + features |= ARM_V6; + } + } + close (fd); + } + + return features; +} + +#else /* Unknown */ + +static arm_cpu_features_t +detect_cpu_features (void) +{ + return 0; +} + +#endif /* Linux elf */ + +static pixman_bool_t +have_feature (arm_cpu_features_t feature) +{ + static pixman_bool_t initialized; + static arm_cpu_features_t features; + + if (!initialized) + { + features = detect_cpu_features(); + initialized = TRUE; + } + + return (features & feature) == feature; +} + +#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ + +pixman_implementation_t * +_pixman_arm_get_implementations (pixman_implementation_t *imp) +{ +#ifdef USE_ARM_SIMD + if (!_pixman_disabled ("arm-simd") && have_feature (ARM_V6)) + imp = _pixman_implementation_create_arm_simd (imp); +#endif + +#ifdef USE_ARM_IWMMXT + if (!_pixman_disabled ("arm-iwmmxt") && have_feature (ARM_IWMMXT)) + imp = _pixman_implementation_create_mmx (imp); +#endif + +#ifdef USE_ARM_NEON + if (!_pixman_disabled ("arm-neon") && have_feature (ARM_NEON)) + imp = _pixman_implementation_create_arm_neon (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-bits-image.c b/gfx/cairo/libpixman/src/pixman-bits-image.c index 61f1c485c2b..c859b69a577 100644 --- a/gfx/cairo/libpixman/src/pixman-bits-image.c +++ b/gfx/cairo/libpixman/src/pixman-bits-image.c @@ -42,14 +42,14 @@ * we could produce smoother gradients by evaluating them at higher color * depth, but that's a project for the future. */ -static void -_pixman_image_get_scanline_generic_64 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +_pixman_image_get_scanline_generic_64 (pixman_iter_t * iter, + const uint32_t *mask) { + int width = iter->width; + uint32_t * buffer = iter->buffer; + + pixman_iter_get_scanline_t fetch_32 = iter->data; uint32_t *mask8 = NULL; /* Contract the mask image, if one exists, so that the 32-bit fetch @@ -59,18 +59,20 @@ _pixman_image_get_scanline_generic_64 (pixman_image_t * image, { mask8 = pixman_malloc_ab (width, sizeof(uint32_t)); if (!mask8) - return; + return buffer; pixman_contract (mask8, (uint64_t *)mask, width); } /* Fetch the source image into the first half of buffer. */ - image->bits.get_scanline_32 (image, x, y, width, (uint32_t*)buffer, mask8); + fetch_32 (iter, mask8); /* Expand from 32bpp to 64bpp in place. */ pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width); free (mask8); + + return buffer; } /* Fetch functions */ @@ -129,8 +131,8 @@ bits_image_fetch_pixel_bilinear (bits_image_t *image, x1 = x - pixman_fixed_1 / 2; y1 = y - pixman_fixed_1 / 2; - distx = interpolation_coord(x1); - disty = interpolation_coord(y1); + distx = pixman_fixed_to_bilinear_weight (x1); + disty = pixman_fixed_to_bilinear_weight (y1); x1 = pixman_fixed_to_int (x1); y1 = pixman_fixed_to_int (y1); @@ -160,14 +162,17 @@ bits_image_fetch_pixel_bilinear (bits_image_t *image, return bilinear_interpolation (tl, tr, bl, br, distx, disty); } -static void -bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, - int offset, - int line, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter, + const uint32_t *mask) { + + pixman_image_t * ima = iter->image; + int offset = iter->x; + int line = iter->y++; + int width = iter->width; + uint32_t * buffer = iter->buffer; + bits_image_t *bits = &ima->bits; pixman_fixed_t x_top, x_bottom, x; pixman_fixed_t ux_top, ux_bottom, ux; @@ -189,13 +194,13 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, v.vector[2] = pixman_fixed_1; if (!pixman_transform_point_3d (bits->common.transform, &v)) - return; + return iter->buffer; ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0]; x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2; y = v.vector[1] - pixman_fixed_1/2; - disty = interpolation_coord(y); + disty = pixman_fixed_to_bilinear_weight (y); /* Load the pointers to the first and second lines from the source * image that bilinear code must read. @@ -256,7 +261,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, if (top_row == zero && bottom_row == zero) { memset (buffer, 0, width * sizeof (uint32_t)); - return; + return iter->buffer; } else if (bits->format == PIXMAN_x8r8g8b8) { @@ -304,7 +309,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask; br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; - distx = interpolation_coord(x); + distx = pixman_fixed_to_bilinear_weight (x); *buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty); @@ -329,7 +334,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask; - distx = interpolation_coord(x); + distx = pixman_fixed_to_bilinear_weight (x); *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty); } @@ -353,7 +358,7 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, tl = top_row [pixman_fixed_to_int (x_top)] | top_mask; bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask; - distx = interpolation_coord(x); + distx = pixman_fixed_to_bilinear_weight (x); *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty); } @@ -368,6 +373,8 @@ bits_image_fetch_bilinear_no_repeat_8888 (pixman_image_t * ima, /* Zero fill to the left of the image */ while (buffer < end) *buffer++ = 0; + + return iter->buffer; } static force_inline uint32_t @@ -381,11 +388,11 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, int y_off = (params[1] - pixman_fixed_1) >> 1; int32_t cwidth = pixman_fixed_to_int (params[0]); int32_t cheight = pixman_fixed_to_int (params[1]); - int32_t srtot, sgtot, sbtot, satot; int32_t i, j, x1, x2, y1, y2; pixman_repeat_t repeat_mode = image->common.repeat; int width = image->width; int height = image->height; + int srtot, sgtot, sbtot, satot; params += 2; @@ -421,10 +428,10 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, pixel = get_pixel (image, rx, ry, TRUE); } - srtot += RED_8 (pixel) * f; - sgtot += GREEN_8 (pixel) * f; - sbtot += BLUE_8 (pixel) * f; - satot += ALPHA_8 (pixel) * f; + srtot += (int)RED_8 (pixel) * f; + sgtot += (int)GREEN_8 (pixel) * f; + sbtot += (int)BLUE_8 (pixel) * f; + satot += (int)ALPHA_8 (pixel) * f; } params++; @@ -474,14 +481,16 @@ bits_image_fetch_pixel_filtered (bits_image_t *image, return 0; } -static void -bits_image_fetch_affine_no_alpha (pixman_image_t * image, - int offset, - int line, - int width, - uint32_t * buffer, +static uint32_t * +bits_image_fetch_affine_no_alpha (pixman_iter_t * iter, const uint32_t * mask) { + pixman_image_t *image = iter->image; + int offset = iter->x; + int line = iter->y++; + int width = iter->width; + uint32_t * buffer = iter->buffer; + pixman_fixed_t x, y; pixman_fixed_t ux, uy; pixman_vector_t v; @@ -495,7 +504,7 @@ bits_image_fetch_affine_no_alpha (pixman_image_t * image, if (image->common.transform) { if (!pixman_transform_point_3d (image->common.transform, &v)) - return; + return iter->buffer; ux = image->common.transform->matrix[0][0]; uy = image->common.transform->matrix[1][0]; @@ -520,6 +529,8 @@ bits_image_fetch_affine_no_alpha (pixman_image_t * image, x += ux; y += uy; } + + return buffer; } /* General fetcher */ @@ -563,14 +574,16 @@ fetch_pixel_general (bits_image_t *image, int x, int y, pixman_bool_t check_boun return pixel; } -static void -bits_image_fetch_general (pixman_image_t * image, - int offset, - int line, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +bits_image_fetch_general (pixman_iter_t *iter, + const uint32_t *mask) { + pixman_image_t *image = iter->image; + int offset = iter->x; + int line = iter->y++; + int width = iter->width; + uint32_t * buffer = iter->buffer; + pixman_fixed_t x, y, w; pixman_fixed_t ux, uy, uw; pixman_vector_t v; @@ -584,7 +597,7 @@ bits_image_fetch_general (pixman_image_t * image, if (image->common.transform) { if (!pixman_transform_point_3d (image->common.transform, &v)) - return; + return buffer; ux = image->common.transform->matrix[0][0]; uy = image->common.transform->matrix[1][0]; @@ -626,6 +639,8 @@ bits_image_fetch_general (pixman_image_t * image, y += uy; w += uw; } + + return buffer; } static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -680,8 +695,8 @@ bits_image_fetch_bilinear_affine (pixman_image_t * image, x1 = x - pixman_fixed_1 / 2; y1 = y - pixman_fixed_1 / 2; - distx = interpolation_coord(x1); - disty = interpolation_coord(y1); + distx = pixman_fixed_to_bilinear_weight (x1); + disty = pixman_fixed_to_bilinear_weight (y1); y1 = pixman_fixed_to_int (y1); y2 = y1 + 1; @@ -882,35 +897,33 @@ convert_r5g6b5 (const uint8_t *row, int x) } #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \ - static void \ - bits_image_fetch_bilinear_affine_ ## name (pixman_image_t *image, \ - int offset, \ - int line, \ - int width, \ - uint32_t * buffer, \ + static uint32_t * \ + bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \ const uint32_t * mask) \ { \ - bits_image_fetch_bilinear_affine (image, offset, line, \ - width, buffer, mask, \ + bits_image_fetch_bilinear_affine (iter->image, \ + iter->x, iter->y++, \ + iter->width, \ + iter->buffer, mask, \ convert_ ## format, \ PIXMAN_ ## format, \ repeat_mode); \ + return iter->buffer; \ } #define MAKE_NEAREST_FETCHER(name, format, repeat_mode) \ - static void \ - bits_image_fetch_nearest_affine_ ## name (pixman_image_t *image, \ - int offset, \ - int line, \ - int width, \ - uint32_t * buffer, \ + static uint32_t * \ + bits_image_fetch_nearest_affine_ ## name (pixman_iter_t *iter, \ const uint32_t * mask) \ { \ - bits_image_fetch_nearest_affine (image, offset, line, \ - width, buffer, mask, \ + bits_image_fetch_nearest_affine (iter->image, \ + iter->x, iter->y++, \ + iter->width, \ + iter->buffer, mask, \ convert_ ## format, \ PIXMAN_ ## format, \ repeat_mode); \ + return iter->buffer; \ } #define MAKE_FETCHERS(name, format, repeat_mode) \ @@ -1059,14 +1072,16 @@ bits_image_fetch_untransformed_repeat_normal (bits_image_t *image, } } -static void -bits_image_fetch_untransformed_32 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t * mask) +static uint32_t * +bits_image_fetch_untransformed_32 (pixman_iter_t * iter, + const uint32_t *mask) { + pixman_image_t *image = iter->image; + int x = iter->x; + int y = iter->y; + int width = iter->width; + uint32_t * buffer = iter->buffer; + if (image->common.repeat == PIXMAN_REPEAT_NONE) { bits_image_fetch_untransformed_repeat_none ( @@ -1077,16 +1092,22 @@ bits_image_fetch_untransformed_32 (pixman_image_t * image, bits_image_fetch_untransformed_repeat_normal ( &image->bits, FALSE, x, y, width, buffer); } + + iter->y++; + return buffer; } -static void -bits_image_fetch_untransformed_64 (pixman_image_t * image, - int x, - int y, - int width, - uint32_t * buffer, - const uint32_t * unused) +static uint32_t * +bits_image_fetch_untransformed_64 (pixman_iter_t * iter, + const uint32_t *mask) + { + pixman_image_t *image = iter->image; + int x = iter->x; + int y = iter->y; + int width = iter->width; + uint32_t * buffer = iter->buffer; + if (image->common.repeat == PIXMAN_REPEAT_NONE) { bits_image_fetch_untransformed_repeat_none ( @@ -1097,14 +1118,21 @@ bits_image_fetch_untransformed_64 (pixman_image_t * image, bits_image_fetch_untransformed_repeat_normal ( &image->bits, TRUE, x, y, width, buffer); } + + iter->y++; + return buffer; } +static uint32_t * +_pixman_image_get_scanline_generic_64 (pixman_iter_t *iter, + const uint32_t * mask); + typedef struct { pixman_format_code_t format; uint32_t flags; - fetch_scanline_t fetch_32; - fetch_scanline_t fetch_64; + pixman_iter_get_scanline_t get_scanline_32; + pixman_iter_get_scanline_t get_scanline_64; } fetcher_info_t; static const fetcher_info_t fetcher_info[] = @@ -1206,53 +1234,36 @@ static const fetcher_info_t fetcher_info[] = static void bits_image_property_changed (pixman_image_t *image) { - uint32_t flags = image->common.flags; - pixman_format_code_t format = image->common.extended_format_code; - const fetcher_info_t *info; - _pixman_bits_image_setup_accessors (&image->bits); - - info = fetcher_info; - while (info->format != PIXMAN_null) - { - if ((info->format == format || info->format == PIXMAN_any) && - (info->flags & flags) == info->flags) - { - image->bits.get_scanline_32 = info->fetch_32; - image->bits.get_scanline_64 = info->fetch_64; - break; - } - - info++; - } -} - -static uint32_t * -src_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask) -{ - iter->image->bits.get_scanline_32 ( - iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask); - - return iter->buffer; -} - -static uint32_t * -src_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) -{ - iter->image->bits.get_scanline_64 ( - iter->image, iter->x, iter->y++, iter->width, iter->buffer, mask); - - return iter->buffer; } void _pixman_bits_image_src_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_NARROW) - iter->get_scanline = src_get_scanline_narrow; - else - iter->get_scanline = src_get_scanline_wide; + pixman_format_code_t format = image->common.extended_format_code; + uint32_t flags = image->common.flags; + const fetcher_info_t *info; + for (info = fetcher_info; info->format != PIXMAN_null; ++info) + { + if ((info->format == format || info->format == PIXMAN_any) && + (info->flags & flags) == info->flags) + { + if (iter->iter_flags & ITER_NARROW) + { + iter->get_scanline = info->get_scanline_32; + } + else + { + iter->data = info->get_scanline_32; + iter->get_scanline = info->get_scanline_64; + } + return; + } + } + + /* Just in case we somehow didn't find a scanline function */ + iter->get_scanline = _pixman_iter_get_scanline_noop; } static uint32_t * @@ -1409,9 +1420,9 @@ dest_write_back_wide (pixman_iter_t *iter) void _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) { - if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == + if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) { iter->get_scanline = _pixman_iter_get_scanline_noop; @@ -1422,9 +1433,9 @@ _pixman_bits_image_dest_iter_init (pixman_image_t *image, pixman_iter_t *iter) } iter->write_back = dest_write_back_16; } - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) { - if ((iter->flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == + if ((iter->iter_flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) == (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) { iter->get_scanline = _pixman_iter_get_scanline_noop; diff --git a/gfx/cairo/libpixman/src/pixman-combine32.c b/gfx/cairo/libpixman/src/pixman-combine32.c index d98d3f8383d..c23f49df9f0 100644 --- a/gfx/cairo/libpixman/src/pixman-combine32.c +++ b/gfx/cairo/libpixman/src/pixman-combine32.c @@ -441,7 +441,7 @@ combine_saturate_u (pixman_implementation_t *imp, * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an * argument. Note that this implementation operates on premultiplied colors, * while the PDF specification does not. Therefore the code uses the formula - * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) + * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) */ /* @@ -526,7 +526,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (result, isa, s, ida); \ \ *(dest + i) = result + \ - (DIV_ONE_UN8 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \ (blend_ ## name (RED_8 (d), da, RED_8 (s), sa) << R_SHIFT) + \ (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa) << G_SHIFT) + \ (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa)); \ @@ -556,7 +556,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (result, ~m, s, ida); \ \ result += \ - (DIV_ONE_UN8 (ALPHA_8 (m) * da) << A_SHIFT) + \ + (DIV_ONE_UN8 (ALPHA_8 (m) * (uint32_t)da) << A_SHIFT) + \ (blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)) << R_SHIFT) + \ (blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)) << G_SHIFT) + \ (blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m))); \ @@ -853,7 +853,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * r * set_sat (C, s) = set_sat (x * C, r * s) * - * The above holds for all non-zero x, because they x'es in the fraction for + * The above holds for all non-zero x, because the x'es in the fraction for * C_mid cancel out. Specifically, it holds for x = r: * * r * set_sat (C, s) = set_sat (r_c, rs) @@ -889,8 +889,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * a_s * a_d * B(s, d) * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) - * = a_s * a_d * set_lum (set_sat (a_d * S, a_s * SAT (D)), - * a_s * LUM (D), a_s * a_d) + * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) * */ @@ -931,7 +930,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) blend_ ## name (c, dc, da, sc, sa); \ \ *(dest + i) = result + \ - (DIV_ONE_UN8 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN8 (sa * (uint32_t)da) << A_SHIFT) + \ (DIV_ONE_UN8 (c[0]) << R_SHIFT) + \ (DIV_ONE_UN8 (c[1]) << G_SHIFT) + \ (DIV_ONE_UN8 (c[2])); \ @@ -1148,9 +1147,7 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) #undef CH_MIN #undef PDF_NON_SEPARABLE_BLEND_MODE -/* Overlay - * - * All of the disjoint composing functions +/* All of the disjoint/conjoint composing functions * * The four entries in the first column indicate what source contributions * come from each of the four areas of the picture -- areas covered by neither @@ -1171,6 +1168,9 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + * + * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more + * information about these operators. */ #define COMBINE_A_OUT 1 diff --git a/gfx/cairo/libpixman/src/pixman-combine32.h b/gfx/cairo/libpixman/src/pixman-combine32.h index 68bde4281a9..b5e157a1de3 100644 --- a/gfx/cairo/libpixman/src/pixman-combine32.h +++ b/gfx/cairo/libpixman/src/pixman-combine32.h @@ -29,10 +29,10 @@ */ #define MUL_UN8(a, b, t) \ - ((t) = (a) * (b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) + ((t) = (a) * (uint16_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) #define DIV_UN8(a, b) \ - (((uint16_t) (a) * MASK) / (b)) + (((uint16_t) (a) * MASK + ((b) / 2)) / (b)) #define ADD_UN8(x, y, t) \ ((t) = (x) + (y), \ diff --git a/gfx/cairo/libpixman/src/pixman-combine64.c b/gfx/cairo/libpixman/src/pixman-combine64.c index 850afba6ad1..1c85af8eec6 100644 --- a/gfx/cairo/libpixman/src/pixman-combine64.c +++ b/gfx/cairo/libpixman/src/pixman-combine64.c @@ -441,7 +441,7 @@ combine_saturate_u (pixman_implementation_t *imp, * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an * argument. Note that this implementation operates on premultiplied colors, * while the PDF specification does not. Therefore the code uses the formula - * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) + * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) */ /* @@ -526,7 +526,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN16x4_MUL_UN16_ADD_UN16x4_MUL_UN16 (result, isa, s, ida); \ \ *(dest + i) = result + \ - (DIV_ONE_UN16 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN16 (sa * (uint64_t)da) << A_SHIFT) + \ (blend_ ## name (RED_16 (d), da, RED_16 (s), sa) << R_SHIFT) + \ (blend_ ## name (GREEN_16 (d), da, GREEN_16 (s), sa) << G_SHIFT) + \ (blend_ ## name (BLUE_16 (d), da, BLUE_16 (s), sa)); \ @@ -556,7 +556,7 @@ combine_multiply_ca (pixman_implementation_t *imp, UN16x4_MUL_UN16x4_ADD_UN16x4_MUL_UN16 (result, ~m, s, ida); \ \ result += \ - (DIV_ONE_UN16 (ALPHA_16 (m) * da) << A_SHIFT) + \ + (DIV_ONE_UN16 (ALPHA_16 (m) * (uint64_t)da) << A_SHIFT) + \ (blend_ ## name (RED_16 (d), da, RED_16 (s), RED_16 (m)) << R_SHIFT) + \ (blend_ ## name (GREEN_16 (d), da, GREEN_16 (s), GREEN_16 (m)) << G_SHIFT) + \ (blend_ ## name (BLUE_16 (d), da, BLUE_16 (s), BLUE_16 (m))); \ @@ -853,7 +853,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * r * set_sat (C, s) = set_sat (x * C, r * s) * - * The above holds for all non-zero x, because they x'es in the fraction for + * The above holds for all non-zero x, because the x'es in the fraction for * C_mid cancel out. Specifically, it holds for x = r: * * r * set_sat (C, s) = set_sat (r_c, rs) @@ -889,8 +889,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) * * a_s * a_d * B(s, d) * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) - * = a_s * a_d * set_lum (set_sat (a_d * S, a_s * SAT (D)), - * a_s * LUM (D), a_s * a_d) + * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) * */ @@ -931,7 +930,7 @@ PDF_SEPARABLE_BLEND_MODE (exclusion) blend_ ## name (c, dc, da, sc, sa); \ \ *(dest + i) = result + \ - (DIV_ONE_UN16 (sa * da) << A_SHIFT) + \ + (DIV_ONE_UN16 (sa * (uint64_t)da) << A_SHIFT) + \ (DIV_ONE_UN16 (c[0]) << R_SHIFT) + \ (DIV_ONE_UN16 (c[1]) << G_SHIFT) + \ (DIV_ONE_UN16 (c[2])); \ @@ -1148,9 +1147,7 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) #undef CH_MIN #undef PDF_NON_SEPARABLE_BLEND_MODE -/* Overlay - * - * All of the disjoint composing functions +/* All of the disjoint/conjoint composing functions * * The four entries in the first column indicate what source contributions * come from each of the four areas of the picture -- areas covered by neither @@ -1171,6 +1168,9 @@ PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + * + * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more + * information about these operators. */ #define COMBINE_A_OUT 1 diff --git a/gfx/cairo/libpixman/src/pixman-combine64.h b/gfx/cairo/libpixman/src/pixman-combine64.h index ed9ffebf6c3..00413a85f6a 100644 --- a/gfx/cairo/libpixman/src/pixman-combine64.h +++ b/gfx/cairo/libpixman/src/pixman-combine64.h @@ -29,10 +29,10 @@ */ #define MUL_UN16(a, b, t) \ - ((t) = (a) * (b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) + ((t) = (a) * (uint32_t)(b) + ONE_HALF, ((((t) >> G_SHIFT ) + (t) ) >> G_SHIFT )) #define DIV_UN16(a, b) \ - (((uint32_t) (a) * MASK) / (b)) + (((uint32_t) (a) * MASK + ((b) / 2)) / (b)) #define ADD_UN16(x, y, t) \ ((t) = (x) + (y), \ diff --git a/gfx/cairo/libpixman/src/pixman-compiler.h b/gfx/cairo/libpixman/src/pixman-compiler.h index 81be529a891..adcd777af3a 100644 --- a/gfx/cairo/libpixman/src/pixman-compiler.h +++ b/gfx/cairo/libpixman/src/pixman-compiler.h @@ -96,6 +96,10 @@ #endif +/* member offsets */ +#define CONTAINER_OF(type, member, data) \ + ((type *)(((uint8_t *)data) - offsetof (type, member))) + /* TLS */ #if defined(PIXMAN_NO_TLS) diff --git a/gfx/cairo/libpixman/src/pixman-conical-gradient.c b/gfx/cairo/libpixman/src/pixman-conical-gradient.c index 791d4f34402..8b52176e4fb 100644 --- a/gfx/cairo/libpixman/src/pixman-conical-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-conical-gradient.c @@ -173,7 +173,7 @@ conical_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) void _pixman_conical_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_NARROW) + if (iter->iter_flags & ITER_NARROW) iter->get_scanline = conical_get_scanline_narrow; else iter->get_scanline = conical_get_scanline_wide; diff --git a/gfx/cairo/libpixman/src/pixman-fast-path.c b/gfx/cairo/libpixman/src/pixman-fast-path.c index b5198e048a9..bcf43d7feaa 100644 --- a/gfx/cairo/libpixman/src/pixman-fast-path.c +++ b/gfx/cairo/libpixman/src/pixman-fast-path.c @@ -809,6 +809,48 @@ fast_composite_add_8_8 (pixman_implementation_t *imp, } } +static void +fast_composite_add_0565_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t d; + uint16_t *src_line, *src; + uint32_t s; + int dst_stride, src_stride; + int32_t w; + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint16_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w--) + { + s = *src++; + if (s) + { + d = *dst; + s = CONVERT_0565_TO_8888 (s); + if (d) + { + d = CONVERT_0565_TO_8888 (d); + UN8x4_ADD_UN8x4 (s, d); + } + *dst = CONVERT_8888_TO_0565 (s); + } + dst++; + } + } +} + static void fast_composite_add_8888_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) @@ -1215,8 +1257,8 @@ scaled_bilinear_scanline_8888_565_OVER (uint16_t * dst, d = *dst; src = bilinear_interpolation (tl, tr, bl, br, - interpolation_coord(vx), - wb >> (8 - INTERPOLATION_PRECISION_BITS)); + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; result = over (src, CONVERT_0565_TO_0888 (d)); *dst++ = CONVERT_8888_TO_0565(result); @@ -1248,8 +1290,8 @@ scaled_bilinear_scanline_8888_8888_OVER (uint32_t * dst, d = *dst; src = bilinear_interpolation (tl, tr, bl, br, - interpolation_coord(vx), - wb >> (8 - INTERPOLATION_PRECISION_BITS)); + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; *dst++ = over (src, d); } @@ -1281,8 +1323,8 @@ scaled_bilinear_scanline_565_565_SRC (uint16_t * dst, CONVERT_0565_TO_8888(tr), CONVERT_0565_TO_8888(bl), CONVERT_0565_TO_8888(br), - interpolation_coord(vx), - wb >> (8 - INTERPOLATION_PRECISION_BITS)); + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; *dst++ = CONVERT_8888_TO_0565(d); } @@ -1352,7 +1394,9 @@ scaled_bilinear_scanline_565_565_SRC (uint16_t * dst, uint16_t bl = src_bottom [pixman_fixed_to_int (vx)]; uint16_t br = src_bottom [pixman_fixed_to_int (vx) + 1]; - uint16_t d = bilinear_interpolation_565 (tl, tr, bl, br, (vx >> 12) & 0xf, wb >> 4); + uint16_t d = bilinear_interpolation_565 (tl, tr, bl, br, + pixman_fixed_to_bilinear_weight(vx), + wb); vx += unit_x; *dst++ = d; } @@ -1458,8 +1502,9 @@ fast_composite_tiled_repeat (pixman_implementation_t *imp, src_bpp = PIXMAN_FORMAT_BPP (src_image->bits.format); - if (src_image->bits.width < REPEAT_MIN_WIDTH && - (src_bpp == 32 || src_bpp == 16 || src_bpp == 8)) + if (src_image->bits.width < REPEAT_MIN_WIDTH && + (src_bpp == 32 || src_bpp == 16 || src_bpp == 8) && + !src_image->bits.indexed) { sx = src_x; sx = MOD (sx, src_image->bits.width); @@ -2056,6 +2101,8 @@ static const pixman_fast_path_t c_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, fast_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, fast_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, fast_composite_over_8888_0565), + PIXMAN_STD_FAST_PATH (ADD, r5g6b5, null, r5g6b5, fast_composite_add_0565_0565), + PIXMAN_STD_FAST_PATH (ADD, b5g6r5, null, b5g6r5, fast_composite_add_0565_0565), PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, fast_composite_add_8888_8888), PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, fast_composite_add_8888_8888), PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, fast_composite_add_8_8), diff --git a/gfx/cairo/libpixman/src/pixman-general.c b/gfx/cairo/libpixman/src/pixman-general.c index 013609995f8..b6b68789883 100644 --- a/gfx/cairo/libpixman/src/pixman-general.c +++ b/gfx/cairo/libpixman/src/pixman-general.c @@ -110,7 +110,7 @@ general_composite_rect (pixman_implementation_t *imp, pixman_iter_t src_iter, mask_iter, dest_iter; pixman_combine_32_func_t compose; pixman_bool_t component_alpha; - iter_flags_t narrow, src_flags; + iter_flags_t narrow, src_iter_flags; iter_flags_t rgb16; int Bpp; int i; @@ -155,14 +155,14 @@ general_composite_rect (pixman_implementation_t *imp, dest_buffer = mask_buffer + width * Bpp; /* src iter */ - src_flags = narrow | op_flags[op].src | rgb16; + src_iter_flags = narrow | op_flags[op].src | rgb16; _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src_image, src_x, src_y, width, height, - src_buffer, src_flags); + src_buffer, src_iter_flags, info->src_flags); /* mask iter */ - if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == + if ((src_iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) { /* If it doesn't matter what the source is, then it doesn't matter @@ -179,12 +179,12 @@ general_composite_rect (pixman_implementation_t *imp, _pixman_implementation_src_iter_init ( imp->toplevel, &mask_iter, mask_image, mask_x, mask_y, width, height, - mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB)); + mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB), info->mask_flags); /* dest iter */ _pixman_implementation_dest_iter_init ( imp->toplevel, &dest_iter, dest_image, dest_x, dest_y, width, height, - dest_buffer, narrow | op_flags[op].dst | rgb16); + dest_buffer, narrow | op_flags[op].dst | rgb16, info->dest_flags); compose = _pixman_implementation_lookup_combiner ( imp->toplevel, op, component_alpha, narrow, !!rgb16); diff --git a/gfx/cairo/libpixman/src/pixman-glyph.c b/gfx/cairo/libpixman/src/pixman-glyph.c new file mode 100644 index 00000000000..cbc3637fa9d --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-glyph.c @@ -0,0 +1,676 @@ +/* + * Copyright 2010, 2012, Soren Sandmann + * Copyright 2010, 2011, 2012, Red Hat, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "pixman-private.h" + +#include + +typedef struct glyph_metrics_t glyph_metrics_t; +typedef struct glyph_t glyph_t; + +#define TOMBSTONE ((glyph_t *)0x1) + +/* XXX: These numbers are arbitrary---we've never done any measurements. + */ +#define N_GLYPHS_HIGH_WATER (16384) +#define N_GLYPHS_LOW_WATER (8192) +#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER) +#define HASH_MASK (HASH_SIZE - 1) + +struct glyph_t +{ + void * font_key; + void * glyph_key; + int origin_x; + int origin_y; + pixman_image_t * image; + pixman_link_t mru_link; +}; + +struct pixman_glyph_cache_t +{ + int n_glyphs; + int n_tombstones; + int freeze_count; + pixman_list_t mru; + glyph_t * glyphs[HASH_SIZE]; +}; + +static void +free_glyph (glyph_t *glyph) +{ + pixman_list_unlink (&glyph->mru_link); + pixman_image_unref (glyph->image); + free (glyph); +} + +static unsigned int +hash (const void *font_key, const void *glyph_key) +{ + size_t key = (size_t)font_key + (size_t)glyph_key; + + /* This hash function is based on one found on Thomas Wang's + * web page at + * + * http://www.concentric.net/~Ttwang/tech/inthash.htm + * + */ + key = (key << 15) - key - 1; + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key + (key << 3) + (key << 11); + key = key ^ (key >> 16); + + return key; +} + +static glyph_t * +lookup_glyph (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + unsigned idx; + glyph_t *g; + + idx = hash (font_key, glyph_key); + while ((g = cache->glyphs[idx++ & HASH_MASK])) + { + if (g != TOMBSTONE && + g->font_key == font_key && + g->glyph_key == glyph_key) + { + return g; + } + } + + return NULL; +} + +static void +insert_glyph (pixman_glyph_cache_t *cache, + glyph_t *glyph) +{ + unsigned idx; + glyph_t **loc; + + idx = hash (glyph->font_key, glyph->glyph_key); + + /* Note: we assume that there is room in the table. If there isn't, + * this will be an infinite loop. + */ + do + { + loc = &cache->glyphs[idx++ & HASH_MASK]; + } while (*loc && *loc != TOMBSTONE); + + if (*loc == TOMBSTONE) + cache->n_tombstones--; + cache->n_glyphs++; + + *loc = glyph; +} + +static void +remove_glyph (pixman_glyph_cache_t *cache, + glyph_t *glyph) +{ + unsigned idx; + + idx = hash (glyph->font_key, glyph->glyph_key); + while (cache->glyphs[idx & HASH_MASK] != glyph) + idx++; + + cache->glyphs[idx & HASH_MASK] = TOMBSTONE; + cache->n_tombstones++; + cache->n_glyphs--; + + /* Eliminate tombstones if possible */ + if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL) + { + while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE) + { + cache->glyphs[idx & HASH_MASK] = NULL; + cache->n_tombstones--; + idx--; + } + } +} + +static void +clear_table (pixman_glyph_cache_t *cache) +{ + int i; + + for (i = 0; i < HASH_SIZE; ++i) + { + glyph_t *glyph = cache->glyphs[i]; + + if (glyph && glyph != TOMBSTONE) + free_glyph (glyph); + + cache->glyphs[i] = NULL; + } + + cache->n_glyphs = 0; + cache->n_tombstones = 0; +} + +PIXMAN_EXPORT pixman_glyph_cache_t * +pixman_glyph_cache_create (void) +{ + pixman_glyph_cache_t *cache; + + if (!(cache = malloc (sizeof *cache))) + return NULL; + + memset (cache->glyphs, 0, sizeof (cache->glyphs)); + cache->n_glyphs = 0; + cache->n_tombstones = 0; + cache->freeze_count = 0; + + pixman_list_init (&cache->mru); + + return cache; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache) +{ + return_if_fail (cache->freeze_count == 0); + + clear_table (cache); + + free (cache); +} + +PIXMAN_EXPORT void +pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache) +{ + cache->freeze_count++; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache) +{ + if (--cache->freeze_count == 0 && + cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER) + { + if (cache->n_tombstones > N_GLYPHS_HIGH_WATER) + { + /* More than half the entries are + * tombstones. Just dump the whole table. + */ + clear_table (cache); + } + + while (cache->n_glyphs > N_GLYPHS_LOW_WATER) + { + glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail); + + remove_glyph (cache, glyph); + free_glyph (glyph); + } + } +} + +PIXMAN_EXPORT const void * +pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + return lookup_glyph (cache, font_key, glyph_key); +} + +PIXMAN_EXPORT const void * +pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key, + int origin_x, + int origin_y, + pixman_image_t *image) +{ + glyph_t *glyph; + int32_t width, height; + + return_val_if_fail (cache->freeze_count > 0, NULL); + return_val_if_fail (image->type == BITS, NULL); + + width = image->bits.width; + height = image->bits.height; + + if (cache->n_glyphs >= HASH_SIZE) + return NULL; + + if (!(glyph = malloc (sizeof *glyph))) + return NULL; + + glyph->font_key = font_key; + glyph->glyph_key = glyph_key; + glyph->origin_x = origin_x; + glyph->origin_y = origin_y; + + if (!(glyph->image = pixman_image_create_bits ( + image->bits.format, width, height, NULL, -1))) + { + free (glyph); + return NULL; + } + + pixman_image_composite32 (PIXMAN_OP_SRC, + image, NULL, glyph->image, 0, 0, 0, 0, 0, 0, + width, height); + + if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 && + PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0) + { + pixman_image_set_component_alpha (glyph->image, TRUE); + } + + pixman_list_prepend (&cache->mru, &glyph->mru_link); + + _pixman_image_validate (glyph->image); + insert_glyph (cache, glyph); + + return glyph; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + glyph_t *glyph; + + if ((glyph = lookup_glyph (cache, font_key, glyph_key))) + { + remove_glyph (cache, glyph); + + free_glyph (glyph); + } +} + +PIXMAN_EXPORT void +pixman_glyph_get_extents (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs, + pixman_box32_t *extents) +{ + int i; + + extents->x1 = extents->y1 = INT32_MAX; + extents->x2 = extents->y2 = INT32_MIN; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + int x1, y1, x2, y2; + + x1 = glyphs[i].x - glyph->origin_x; + y1 = glyphs[i].y - glyph->origin_y; + x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width; + y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height; + + if (x1 < extents->x1) + extents->x1 = x1; + if (y1 < extents->y1) + extents->y1 = y1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y2 > extents->y2) + extents->y2 = y2; + } +} + +/* This function returns a format that is suitable for use as a mask for the + * set of glyphs in question. + */ +PIXMAN_EXPORT pixman_format_code_t +pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t * glyphs) +{ + pixman_format_code_t format = PIXMAN_a1; + int i; + + for (i = 0; i < n_glyphs; ++i) + { + const glyph_t *glyph = glyphs[i].glyph; + pixman_format_code_t glyph_format = glyph->image->bits.format; + + if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A) + { + if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format)) + format = glyph_format; + } + else + { + return PIXMAN_a8r8g8b8; + } + } + + return format; +} + +static pixman_bool_t +box32_intersect (pixman_box32_t *dest, + const pixman_box32_t *box1, + const pixman_box32_t *box2) +{ + dest->x1 = MAX (box1->x1, box2->x1); + dest->y1 = MAX (box1->y1, box2->y1); + dest->x2 = MIN (box1->x2, box2->x2); + dest->y2 = MIN (box1->y2, box2->y2); + + return dest->x2 > dest->x1 && dest->y2 > dest->y1; +} + +PIXMAN_EXPORT void +pixman_composite_glyphs_no_mask (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t dest_x, + int32_t dest_y, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs) +{ + pixman_region32_t region; + pixman_format_code_t glyph_format = PIXMAN_null; + uint32_t glyph_flags = 0; + pixman_format_code_t dest_format; + uint32_t dest_flags; + pixman_composite_func_t func = NULL; + pixman_implementation_t *implementation = NULL; + pixman_composite_info_t info; + int i; + + _pixman_image_validate (src); + _pixman_image_validate (dest); + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + + pixman_region32_init (®ion); + if (!_pixman_compute_composite_region32 ( + ®ion, + src, NULL, dest, + src_x - dest_x, src_y - dest_y, 0, 0, 0, 0, + dest->bits.width, dest->bits.height)) + { + goto out; + } + + info.op = op; + info.src_image = src; + info.dest_image = dest; + info.src_flags = src->common.flags; + info.dest_flags = dest->common.flags; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + pixman_image_t *glyph_img = glyph->image; + pixman_box32_t glyph_box; + pixman_box32_t *pbox; + uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + pixman_box32_t composite_box; + int n; + + glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x; + glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y; + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; + + pbox = pixman_region32_rectangles (®ion, &n); + + info.mask_image = glyph_img; + + while (n--) + { + if (box32_intersect (&composite_box, pbox, &glyph_box)) + { + if (glyph_img->common.extended_format_code != glyph_format || + glyph_img->common.flags != glyph_flags) + { + glyph_format = glyph_img->common.extended_format_code; + glyph_flags = glyph_img->common.flags; + + _pixman_lookup_composite_function ( + get_implementation(), op, + src->common.extended_format_code, src->common.flags, + glyph_format, glyph_flags | extra, + dest_format, dest_flags, + &implementation, &func); + + if (!func) + goto out; + } + + info.src_x = src_x + composite_box.x1 - dest_x; + info.src_y = src_y + composite_box.y1 - dest_y; + info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x); + info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y); + info.dest_x = composite_box.x1; + info.dest_y = composite_box.y1; + info.width = composite_box.x2 - composite_box.x1; + info.height = composite_box.y2 - composite_box.y1; + + info.mask_flags = glyph_flags; + + func (implementation, &info); + } + + pbox++; + } + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + } + +out: + pixman_region32_fini (®ion); +} + +static void +add_glyphs (pixman_glyph_cache_t *cache, + pixman_image_t *dest, + int off_x, int off_y, + int n_glyphs, pixman_glyph_t *glyphs) +{ + pixman_format_code_t glyph_format = PIXMAN_null; + uint32_t glyph_flags = 0; + pixman_composite_func_t func = NULL; + pixman_implementation_t *implementation = NULL; + uint32_t dest_format; + uint32_t dest_flags; + pixman_box32_t dest_box; + pixman_composite_info_t info; + pixman_image_t *white_img = NULL; + pixman_bool_t white_src = FALSE; + int i; + + _pixman_image_validate (dest); + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + + info.op = PIXMAN_OP_ADD; + info.dest_image = dest; + info.src_x = 0; + info.src_y = 0; + info.dest_flags = dest_flags; + + dest_box.x1 = 0; + dest_box.y1 = 0; + dest_box.x2 = dest->bits.width; + dest_box.y2 = dest->bits.height; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + pixman_image_t *glyph_img = glyph->image; + pixman_box32_t glyph_box; + pixman_box32_t composite_box; + + if (glyph_img->common.extended_format_code != glyph_format || + glyph_img->common.flags != glyph_flags) + { + pixman_format_code_t src_format, mask_format; + + glyph_format = glyph_img->common.extended_format_code; + glyph_flags = glyph_img->common.flags; + + if (glyph_format == dest->bits.format) + { + src_format = glyph_format; + mask_format = PIXMAN_null; + info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + info.mask_flags = FAST_PATH_IS_OPAQUE; + info.mask_image = NULL; + white_src = FALSE; + } + else + { + if (!white_img) + { + pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; + + if (!(white_img = pixman_image_create_solid_fill (&white))) + goto out; + + _pixman_image_validate (white_img); + } + + src_format = PIXMAN_solid; + mask_format = glyph_format; + info.src_flags = white_img->common.flags; + info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + info.src_image = white_img; + white_src = TRUE; + } + + _pixman_lookup_composite_function ( + get_implementation(), PIXMAN_OP_ADD, + src_format, info.src_flags, + mask_format, info.mask_flags, + dest_format, dest_flags, + &implementation, &func); + + if (!func) + goto out; + } + + glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x; + glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y; + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; + + if (box32_intersect (&composite_box, &glyph_box, &dest_box)) + { + int src_x = composite_box.x1 - glyph_box.x1; + int src_y = composite_box.y1 - glyph_box.y1; + + if (white_src) + info.mask_image = glyph_img; + else + info.src_image = glyph_img; + + info.mask_x = info.src_x = src_x; + info.mask_y = info.src_y = src_y; + info.dest_x = composite_box.x1; + info.dest_y = composite_box.y1; + info.width = composite_box.x2 - composite_box.x1; + info.height = composite_box.y2 - composite_box.y1; + + func (implementation, &info); + + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + } + } + +out: + if (white_img) + pixman_image_unref (white_img); +} + +/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an + * infinitely big mask image at the position such that the glyph origin point + * is positioned at the (glyphs[i].x, glyphs[i].y) point. + * + * Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source + * image are both aligned with (dest_x, dest_y) in the destination image. Then + * these three images are composited within the + * + * (dest_x, dest_y, dst_x + width, dst_y + height) + * + * rectangle. + * + * TODO: + * - Trim the mask to the destination clip/image? + * - Trim composite region based on sources, when the op ignores 0s. + */ +PIXMAN_EXPORT void +pixman_composite_glyphs (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + pixman_format_code_t mask_format, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs) +{ + pixman_image_t *mask; + + if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1))) + return; + + if (PIXMAN_FORMAT_A (mask_format) != 0 && + PIXMAN_FORMAT_RGB (mask_format) != 0) + { + pixman_image_set_component_alpha (mask, TRUE); + } + + add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs); + + pixman_image_composite32 (op, src, mask, dest, + src_x, src_y, + 0, 0, + dest_x, dest_y, + width, height); + + pixman_image_unref (mask); +} diff --git a/gfx/cairo/libpixman/src/pixman-image.c b/gfx/cairo/libpixman/src/pixman-image.c index 97421c498f9..d2e75978c2d 100644 --- a/gfx/cairo/libpixman/src/pixman-image.c +++ b/gfx/cairo/libpixman/src/pixman-image.c @@ -883,16 +883,38 @@ _pixman_image_get_solid (pixman_implementation_t *imp, pixman_format_code_t format) { uint32_t result; - pixman_iter_t iter; - _pixman_implementation_src_iter_init ( - imp, &iter, image, 0, 0, 1, 1, - (uint8_t *)&result, ITER_NARROW); + if (image->type == SOLID) + { + result = image->solid.color_32; + } + else if (image->type == BITS) + { + if (image->bits.format == PIXMAN_a8r8g8b8) + result = image->bits.bits[0]; + else if (image->bits.format == PIXMAN_x8r8g8b8) + result = image->bits.bits[0] | 0xff000000; + else if (image->bits.format == PIXMAN_a8) + result = (*(uint8_t *)image->bits.bits) << 24; + else + goto otherwise; + } + else + { + pixman_iter_t iter; - result = *iter.get_scanline (&iter, NULL); + otherwise: + _pixman_implementation_src_iter_init ( + imp, &iter, image, 0, 0, 1, 1, + (uint8_t *)&result, + ITER_NARROW, image->common.flags); + + result = *iter.get_scanline (&iter, NULL); + } /* If necessary, convert RGB <--> BGR. */ - if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB) + if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB + && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB) { result = (((result & 0xff000000) >> 0) | ((result & 0x00ff0000) >> 16) | diff --git a/gfx/cairo/libpixman/src/pixman-implementation.c b/gfx/cairo/libpixman/src/pixman-implementation.c index 7d6103dd4fb..887a149ef72 100644 --- a/gfx/cairo/libpixman/src/pixman-implementation.c +++ b/gfx/cairo/libpixman/src/pixman-implementation.c @@ -191,7 +191,8 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags) + iter_flags_t iter_flags, + uint32_t image_flags) { iter->image = image; iter->buffer = (uint32_t *)buffer; @@ -199,7 +200,8 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, iter->y = y; iter->width = width; iter->height = height; - iter->flags = flags; + iter->iter_flags = iter_flags; + iter->image_flags = image_flags; (*imp->src_iter_init) (imp, iter); } @@ -213,7 +215,8 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags) + iter_flags_t iter_flags, + uint32_t image_flags) { iter->image = image; iter->buffer = (uint32_t *)buffer; @@ -221,7 +224,59 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, iter->y = y; iter->width = width; iter->height = height; - iter->flags = flags; + iter->iter_flags = iter_flags; + iter->image_flags = image_flags; (*imp->dest_iter_init) (imp, iter); } + +pixman_bool_t +_pixman_disabled (const char *name) +{ + const char *env; + + if ((env = getenv ("PIXMAN_DISABLE"))) + { + do + { + const char *end; + int len; + + if ((end = strchr (env, ' '))) + len = end - env; + else + len = strlen (env); + + if (strlen (name) == len && strncmp (name, env, len) == 0) + { + printf ("pixman: Disabled %s implementation\n", name); + return TRUE; + } + + env += len; + } + while (*env++); + } + + return FALSE; +} + +pixman_implementation_t * +_pixman_choose_implementation (void) +{ + pixman_implementation_t *imp; + + imp = _pixman_implementation_create_general(); + + if (!_pixman_disabled ("fast")) + imp = _pixman_implementation_create_fast_path (imp); + + imp = _pixman_x86_get_implementations (imp); + imp = _pixman_arm_get_implementations (imp); + imp = _pixman_ppc_get_implementations (imp); + imp = _pixman_mips_get_implementations (imp); + + imp = _pixman_implementation_create_noop (imp); + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-inlines.h b/gfx/cairo/libpixman/src/pixman-inlines.h index 6790f0fa2ec..a9a65812dec 100644 --- a/gfx/cairo/libpixman/src/pixman-inlines.h +++ b/gfx/cairo/libpixman/src/pixman-inlines.h @@ -81,27 +81,13 @@ repeat (pixman_repeat_t repeat, int *c, int size) return TRUE; } -#ifdef MOZ_GFX_OPTIMIZE_MOBILE -#define LOW_QUALITY_INTERPOLATION -#define LOWER_QUALITY_INTERPOLATION -#endif - -#ifdef LOW_QUALITY_INTERPOLATION -#define INTERPOLATION_PRECISION_BITS 4 -#else -#define INTERPOLATION_PRECISION_BITS 8 -#endif -static force_inline int32_t -interpolation_coord(pixman_fixed_t t) +static force_inline int +pixman_fixed_to_bilinear_weight (pixman_fixed_t x) { -#ifdef LOW_QUALITY_INTERPOLATION - return (t >> 12) & 0xf; -#else - return (t >> 8) & 0xff; -#endif + return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) & + ((1 << BILINEAR_INTERPOLATION_BITS) - 1); } - #if SIZEOF_LONG > 4 static force_inline uint32_t @@ -113,6 +99,9 @@ bilinear_interpolation (uint32_t tl, uint32_t tr, uint64_t tl64, tr64, bl64, br64; uint64_t f, r; + distx <<= (8 - BILINEAR_INTERPOLATION_BITS); + disty <<= (8 - BILINEAR_INTERPOLATION_BITS); + distxy = distx * disty; distxiy = distx * (256 - disty); distixy = (256 - distx) * disty; @@ -184,6 +173,9 @@ bilinear_interpolation (uint32_t tl, uint32_t tr, int distxy, distxiy, distixy, distixiy; uint32_t f, r; + distx <<= (8 - BILINEAR_INTERPOLATION_BITS); + disty <<= (8 - BILINEAR_INTERPOLATION_BITS); + distxy = distx * disty; distxiy = (distx << 8) - distxy; /* distx * (256 - disty) */ distixy = (disty << 8) - distxy; /* disty * (256 - distx) */ @@ -814,12 +806,14 @@ bilinear_pad_repeat_get_scanline_bounds (int32_t source_image_width, * all source pixels are fetched from zero padding * zone for NONE repeat * - * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to 256, - * but sometimes it may be less than that for NONE repeat when handling - * fuzzy antialiased top or bottom image edges. Also both top and - * bottom weight variables are guaranteed to have value in 0-255 - * range and can fit into unsigned byte or be used with 8-bit SIMD - * multiplication instructions. + * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to + * BILINEAR_INTERPOLATION_RANGE, but sometimes it may be less than that + * for NONE repeat when handling fuzzy antialiased top or bottom image + * edges. Also both top and bottom weight variables are guaranteed to + * have value, which is less than BILINEAR_INTERPOLATION_RANGE. + * For example, the weights can fit into unsigned byte or be used + * with 8-bit SIMD multiplication instructions for 8-bit interpolation + * precision. */ /* Replace a single "scanline_func" with "fetch_func" & "op_func" to allow optional @@ -974,18 +968,18 @@ fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, } \ \ y1 = pixman_fixed_to_int (vy); \ - weight2 = (vy >> 8) & 0xff; \ + weight2 = pixman_fixed_to_bilinear_weight (vy); \ if (weight2) \ { \ - /* normal case, both row weights are in 0-255 range and fit unsigned byte */ \ + /* both weight1 and weight2 are smaller than BILINEAR_INTERPOLATION_RANGE */ \ y2 = y1 + 1; \ - weight1 = 256 - weight2; \ + weight1 = BILINEAR_INTERPOLATION_RANGE - weight2; \ } \ else \ { \ - /* set both top and bottom row to the same scanline, and weights to 128+128 */ \ + /* set both top and bottom row to the same scanline and tweak weights */ \ y2 = y1; \ - weight1 = weight2 = 128; \ + weight1 = weight2 = BILINEAR_INTERPOLATION_RANGE / 2; \ } \ vy += unit_y; \ if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ diff --git a/gfx/cairo/libpixman/src/pixman-linear-gradient.c b/gfx/cairo/libpixman/src/pixman-linear-gradient.c index 20f94f7934c..148f6a30d7f 100644 --- a/gfx/cairo/libpixman/src/pixman-linear-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-linear-gradient.c @@ -398,9 +398,9 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) if (0 && linear_gradient_is_horizontal ( iter->image, iter->x, iter->y, iter->width, iter->height)) { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) linear_get_scanline_16 (iter, NULL); - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) linear_get_scanline_narrow (iter, NULL); else linear_get_scanline_wide (iter, NULL); @@ -409,9 +409,9 @@ _pixman_linear_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) } else { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) iter->get_scanline = linear_get_scanline_16; - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) iter->get_scanline = linear_get_scanline_narrow; else iter->get_scanline = linear_get_scanline_wide; diff --git a/gfx/cairo/libpixman/src/pixman-matrix.c b/gfx/cairo/libpixman/src/pixman-matrix.c index 8d0d9732533..a029ab75753 100644 --- a/gfx/cairo/libpixman/src/pixman-matrix.c +++ b/gfx/cairo/libpixman/src/pixman-matrix.c @@ -25,7 +25,7 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif #include @@ -471,8 +471,8 @@ pixman_f_transform_invert (struct pixman_f_transform * dst, { double det; int i, j; - static int a[3] = { 2, 2, 1 }; - static int b[3] = { 1, 0, 0 }; + static const int a[3] = { 2, 2, 1 }; + static const int b[3] = { 1, 0, 0 }; det = 0; for (i = 0; i < 3; i++) diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S new file mode 100644 index 00000000000..a8fccd5ad7a --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.S @@ -0,0 +1,1521 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#include "pixman-private.h" +#include "pixman-mips-dspr2-asm.h" + +LEAF_MIPS_DSPR2(pixman_fill_buff16_mips) +/* + * a0 - *dest + * a1 - count (bytes) + * a2 - value to fill buffer with + */ + + beqz a1, 3f + andi t1, a0, 0x0002 + beqz t1, 0f /* check if address is 4-byte aligned */ + nop + sh a2, 0(a0) + addiu a0, a0, 2 + addiu a1, a1, -2 +0: + srl t1, a1, 5 /* t1 how many multiples of 32 bytes */ + replv.ph a2, a2 /* replicate fill value (16bit) in a2 */ + beqz t1, 2f + nop +1: + addiu t1, t1, -1 + beqz t1, 11f + addiu a1, a1, -32 + pref 30, 32(a0) + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + b 1b + addiu a0, a0, 32 +11: + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + addiu a0, a0, 32 +2: + blez a1, 3f + addiu a1, a1, -2 + sh a2, 0(a0) + b 2b + addiu a0, a0, 2 +3: + jr ra + nop + +END(pixman_fill_buff16_mips) + +LEAF_MIPS32R2(pixman_fill_buff32_mips) +/* + * a0 - *dest + * a1 - count (bytes) + * a2 - value to fill buffer with + */ + + beqz a1, 3f + nop + srl t1, a1, 5 /* t1 how many multiples of 32 bytes */ + beqz t1, 2f + nop +1: + addiu t1, t1, -1 + beqz t1, 11f + addiu a1, a1, -32 + pref 30, 32(a0) + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + b 1b + addiu a0, a0, 32 +11: + sw a2, 0(a0) + sw a2, 4(a0) + sw a2, 8(a0) + sw a2, 12(a0) + sw a2, 16(a0) + sw a2, 20(a0) + sw a2, 24(a0) + sw a2, 28(a0) + addiu a0, a0, 32 +2: + blez a1, 3f + addiu a1, a1, -4 + sw a2, 0(a0) + b 2b + addiu a0, a0, 4 +3: + jr ra + nop + +END(pixman_fill_buff32_mips) + +LEAF_MIPS_DSPR2(pixman_composite_src_8888_0565_asm_mips) +/* + * a0 - dst (r5g6b5) + * a1 - src (a8r8g8b8) + * a2 - w + */ + + beqz a2, 3f + nop + addiu t1, a2, -1 + beqz t1, 2f + nop + li t4, 0xf800f800 + li t5, 0x07e007e0 + li t6, 0x001f001f +1: + lw t0, 0(a1) + lw t1, 4(a1) + addiu a1, a1, 8 + addiu a2, a2, -2 + + CONVERT_2x8888_TO_2x0565 t0, t1, t2, t3, t4, t5, t6, t7, t8 + + sh t2, 0(a0) + sh t3, 2(a0) + + addiu t2, a2, -1 + bgtz t2, 1b + addiu a0, a0, 4 +2: + beqz a2, 3f + nop + lw t0, 0(a1) + + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + sh t1, 0(a0) +3: + j ra + nop + +END(pixman_composite_src_8888_0565_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_src_0565_8888_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (r5g6b5) + * a2 - w + */ + + beqz a2, 3f + nop + addiu t1, a2, -1 + beqz t1, 2f + nop + li t4, 0x07e007e0 + li t5, 0x001F001F +1: + lhu t0, 0(a1) + lhu t1, 2(a1) + addiu a1, a1, 4 + addiu a2, a2, -2 + + CONVERT_2x0565_TO_2x8888 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 + + sw t2, 0(a0) + sw t3, 4(a0) + + addiu t2, a2, -1 + bgtz t2, 1b + addiu a0, a0, 8 +2: + beqz a2, 3f + nop + lhu t0, 0(a1) + + CONVERT_1x0565_TO_1x8888 t0, t1, t2, t3 + + sw t1, 0(a0) +3: + j ra + nop + +END(pixman_composite_src_0565_8888_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_src_x888_8888_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (x8r8g8b8) + * a2 - w + */ + + beqz a2, 4f + nop + li t9, 0xff000000 + srl t8, a2, 3 /* t1 = how many multiples of 8 src pixels */ + beqz t8, 3f /* branch if less than 8 src pixels */ + nop +1: + addiu t8, t8, -1 + beqz t8, 2f + addiu a2, a2, -8 + pref 0, 32(a1) + lw t0, 0(a1) + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a1, a1, 32 + or t0, t0, t9 + or t1, t1, t9 + or t2, t2, t9 + or t3, t3, t9 + or t4, t4, t9 + or t5, t5, t9 + or t6, t6, t9 + or t7, t7, t9 + pref 30, 32(a0) + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + b 1b + addiu a0, a0, 32 +2: + lw t0, 0(a1) + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a1, a1, 32 + or t0, t0, t9 + or t1, t1, t9 + or t2, t2, t9 + or t3, t3, t9 + or t4, t4, t9 + or t5, t5, t9 + or t6, t6, t9 + or t7, t7, t9 + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + beqz a2, 4f + addiu a0, a0, 32 +3: + lw t0, 0(a1) + addiu a1, a1, 4 + addiu a2, a2, -1 + or t1, t0, t9 + sw t1, 0(a0) + bnez a2, 3b + addiu a0, a0, 4 +4: + jr ra + nop + +END(pixman_composite_src_x888_8888_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8888_8888_ca_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (32bit constant) + * a2 - mask (a8r8g8b8) + * a3 - w + */ + + SAVE_REGS_ON_STACK 8, s0, s1, s2, s3, s4, s5 + beqz a3, 4f + nop + li t6, 0xff + addiu t7, zero, -1 /* t7 = 0xffffffff */ + srl t8, a1, 24 /* t8 = srca */ + li t9, 0x00ff00ff + addiu t1, a3, -1 + beqz t1, 3f /* last pixel */ + nop + beq t8, t6, 2f /* if (srca == 0xff) */ + nop +1: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 12f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 8 + and t3, t0, t1 + move t4, a1 /* t4 = src */ + move t5, a1 /* t5 = src */ + lw t2, 0(a0) /* t2 = dst */ + beq t3, t7, 11f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + lw t3, 4(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, t4, t5, t9, s0, s1, s2, s3, s4, s5 + MIPS_2xUN8x4_MUL_2xUN8 t0, t1, t8, t8, t0, t1, t9, s0, s1, s2, s3, s4, s5 +11: + not t0, t0 + not t1, t1 + MIPS_2xUN8x4_MUL_2xUN8x4 t2, t3, t0, t1, t2, t3, t9, s0, s1, s2, s3, s4, s5 + addu_s.qb t2, t4, t2 + addu_s.qb t3, t5, t3 + sw t2, 0(a0) + sw t3, 4(a0) +12: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 1b + addiu a0, a0, 8 + b 3f + nop +2: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 22f /* if (t0 == 0) & (t1 == 0) */ + addiu a2, a2, 8 + and t2, t0, t1 + move t4, a1 + beq t2, t7, 21f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + move t5, a1 + lw t2, 0(a0) /* t2 = dst */ + lw t3, 4(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, t4, t5, t9, s0, s1, s2, s3, s4, s5 + not t0, t0 + not t1, t1 + MIPS_2xUN8x4_MUL_2xUN8x4 t2, t3, t0, t1, t2, t3, t9, s0, s1, s2, s3, s4, s5 + addu_s.qb t4, t4, t2 + addu_s.qb t5, t5, t3 +21: + sw t4, 0(a0) + sw t5, 4(a0) +22: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 2b + addiu a0, a0, 8 +3: + blez a3, 4f + nop + /* a1 = src */ + lw t1, 0(a2) /* t1 = mask */ + beqz t1, 4f + nop + move t2, a1 /* t2 = src */ + beq t1, t7, 31f + lw t0, 0(a0) /* t0 = dst */ + + MIPS_UN8x4_MUL_UN8x4 a1, t1, t2, t9, t3, t4, t5, t6 + MIPS_UN8x4_MUL_UN8 t1, t8, t1, t9, t3, t4, t5 +31: + not t1, t1 + MIPS_UN8x4_MUL_UN8x4 t0, t1, t0, t9, t3, t4, t5, t6 + addu_s.qb t0, t2, t0 + sw t0, 0(a0) +4: + RESTORE_REGS_FROM_STACK 8, s0, s1, s2, s3, s4, s5 + j ra + nop + +END(pixman_composite_over_n_8888_8888_ca_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8888_0565_ca_asm_mips) +/* + * a0 - dst (r5g6b5) + * a1 - src (32bit constant) + * a2 - mask (a8r8g8b8) + * a3 - w + */ + + SAVE_REGS_ON_STACK 20, s0, s1, s2, s3, s4, s5, s6, s7, s8 + beqz a3, 4f + nop + li t5, 0xf800f800 + li t6, 0x07e007e0 + li t7, 0x001F001F + li t9, 0x00ff00ff + + srl t8, a1, 24 /* t8 = srca */ + addiu t1, a3, -1 + beqz t1, 3f /* last pixel */ + nop + li s0, 0xff /* s0 = 0xff */ + addiu s1, zero, -1 /* s1 = 0xffffffff */ + + beq t8, s0, 2f /* if (srca == 0xff) */ + nop +1: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 12f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 8 + and t3, t0, t1 + move s2, a1 /* s2 = src */ + move s3, a1 /* s3 = src */ + lhu t2, 0(a0) /* t2 = dst */ + beq t3, s1, 11f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + lhu t3, 2(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, s2, s3, t9, t4, s4, s5, s6, s7, s8 + MIPS_2xUN8x4_MUL_2xUN8 t0, t1, t8, t8, t0, t1, t9, t4, s4, s5, s6, s7, s8 +11: + not t0, t0 + not t1, t1 + CONVERT_2x0565_TO_2x8888 t2, t3, s4, s5, t6, t7, t4, s6, s7, s8 + MIPS_2xUN8x4_MUL_2xUN8x4 s4, s5, t0, t1, s4, s5, t9, t4, s6, s7, s8, t0, t1 + addu_s.qb s2, s2, s4 + addu_s.qb s3, s3, s5 + CONVERT_2x8888_TO_2x0565 s2, s3, t2, t3, t5, t6, t7, s4, s5 + sh t2, 0(a0) + sh t3, 2(a0) +12: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 1b + addiu a0, a0, 4 + b 3f + nop +2: + /* a1 = src */ + lw t0, 0(a2) /* t0 = mask */ + lw t1, 4(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 22f /* if (t0 == 0) & (t1 == 0) */ + addiu a2, a2, 8 + and t3, t0, t1 + move t2, a1 + beq t3, s1, 21f /* if (t0 == 0xffffffff) && (t1 == 0xffffffff) */ + move t3, a1 + lhu t2, 0(a0) /* t2 = dst */ + lhu t3, 2(a0) /* t3 = dst */ + MIPS_2xUN8x4_MUL_2xUN8x4 a1, a1, t0, t1, s2, s3, t9, t4, s4, s5, s6, s7, s8 + not t0, t0 + not t1, t1 + CONVERT_2x0565_TO_2x8888 t2, t3, s4, s5, t6, t7, t4, s6, s7, s8 + MIPS_2xUN8x4_MUL_2xUN8x4 s4, s5, t0, t1, s4, s5, t9, t4, s6, s7, s8, t2, t3 + addu_s.qb t2, s2, s4 + addu_s.qb t3, s3, s5 +21: + CONVERT_2x8888_TO_2x0565 t2, t3, t0, t1, t5, t6, t7, s2, s3 + sh t0, 0(a0) + sh t1, 2(a0) +22: + addiu a3, a3, -2 + addiu t1, a3, -1 + bgtz t1, 2b + addiu a0, a0, 4 +3: + blez a3, 4f + nop + /* a1 = src */ + lw t1, 0(a2) /* t1 = mask */ + beqz t1, 4f + nop + move t2, a1 /* t2 = src */ + beq t1, t7, 31f + lhu t0, 0(a0) /* t0 = dst */ + + MIPS_UN8x4_MUL_UN8x4 a1, t1, t2, t9, t3, t4, t5, t6 + MIPS_UN8x4_MUL_UN8 t1, t8, t1, t9, t3, t4, t5 +31: + not t1, t1 + CONVERT_1x0565_TO_1x8888 t0, s1, s2, s3 + MIPS_UN8x4_MUL_UN8x4 s1, t1, t3, t9, t4, t5, t6, t7 + addu_s.qb t0, t2, t3 + CONVERT_1x8888_TO_1x0565 t0, s1, s2, s3 + sh s1, 0(a0) +4: + RESTORE_REGS_FROM_STACK 20, s0, s1, s2, s3, s4, s5, s6, s7, s8 + j ra + nop + +END(pixman_composite_over_n_8888_0565_ca_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8_8888_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - src (32bit constant) + * a2 - mask (a8) + * a3 - w + */ + + SAVE_REGS_ON_STACK 4, s0, s1, s2, s3, s4 + beqz a3, 4f + nop + li t4, 0x00ff00ff + li t5, 0xff + addiu t0, a3, -1 + beqz t0, 3f /* last pixel */ + srl t6, a1, 24 /* t6 = srca */ + not s4, a1 + beq t5, t6, 2f /* if (srca == 0xff) */ + srl s4, s4, 24 +1: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 111f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + and t3, t0, t1 + + lw t2, 0(a0) /* t2 = dst */ + beq t3, t5, 11f /* if (t0 == 0xff) && (t1 == 0xff) */ + lw t3, 4(a0) /* t3 = dst */ + + MIPS_2xUN8x4_MUL_2xUN8 a1, a1, t0, t1, s0, s1, t4, t6, t7, t8, t9, s2, s3 + not s2, s0 + not s3, s1 + srl s2, s2, 24 + srl s3, s3, 24 + MIPS_2xUN8x4_MUL_2xUN8 t2, t3, s2, s3, t2, t3, t4, t0, t1, t6, t7, t8, t9 + addu_s.qb s2, t2, s0 + addu_s.qb s3, t3, s1 + sw s2, 0(a0) + b 111f + sw s3, 4(a0) +11: + MIPS_2xUN8x4_MUL_2xUN8 t2, t3, s4, s4, t2, t3, t4, t0, t1, t6, t7, t8, t9 + addu_s.qb s2, t2, a1 + addu_s.qb s3, t3, a1 + sw s2, 0(a0) + sw s3, 4(a0) + +111: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 1b + addiu a0, a0, 8 + b 3f + nop +2: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 222f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + and t3, t0, t1 + beq t3, t5, 22f /* if (t0 == 0xff) && (t1 == 0xff) */ + nop + lw t2, 0(a0) /* t2 = dst */ + lw t3, 4(a0) /* t3 = dst */ + + OVER_2x8888_2x8_2x8888 a1, a1, t0, t1, t2, t3, \ + t6, t7, t4, t8, t9, s0, s1, s2, s3 + sw t6, 0(a0) + b 222f + sw t7, 4(a0) +22: + sw a1, 0(a0) + sw a1, 4(a0) +222: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 2b + addiu a0, a0, 8 +3: + blez a3, 4f + nop + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + beqz t0, 4f /* if (t0 == 0) */ + addiu a2, a2, 1 + move t3, a1 + beq t0, t5, 31f /* if (t0 == 0xff) */ + lw t1, 0(a0) /* t1 = dst */ + + MIPS_UN8x4_MUL_UN8 a1, t0, t3, t4, t6, t7, t8 +31: + not t2, t3 + srl t2, t2, 24 + MIPS_UN8x4_MUL_UN8 t1, t2, t1, t4, t6, t7, t8 + addu_s.qb t2, t1, t3 + sw t2, 0(a0) +4: + RESTORE_REGS_FROM_STACK 4, s0, s1, s2, s3, s4 + j ra + nop + +END(pixman_composite_over_n_8_8888_asm_mips) + +LEAF_MIPS_DSPR2(pixman_composite_over_n_8_0565_asm_mips) +/* + * a0 - dst (r5g6b5) + * a1 - src (32bit constant) + * a2 - mask (a8) + * a3 - w + */ + SAVE_REGS_ON_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 + beqz a3, 4f + nop + li t4, 0x00ff00ff + li t5, 0xff + li t6, 0xf800f800 + li t7, 0x07e007e0 + li t8, 0x001F001F + addiu t1, a3, -1 + beqz t1, 3f /* last pixel */ + srl t0, a1, 24 /* t0 = srca */ + not v0, a1 + beq t0, t5, 2f /* if (srca == 0xff) */ + srl v0, v0, 24 +1: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 111f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + lhu t2, 0(a0) /* t2 = dst */ + lhu t3, 2(a0) /* t3 = dst */ + CONVERT_2x0565_TO_2x8888 t2, t3, s0, s1, t7, t8, t9, s2, s3, s4 + and t9, t0, t1 + beq t9, t5, 11f /* if (t0 == 0xff) && (t1 == 0xff) */ + nop + + MIPS_2xUN8x4_MUL_2xUN8 a1, a1, t0, t1, s2, s3, t4, t9, s4, s5, s6, s7, s8 + not s4, s2 + not s5, s3 + srl s4, s4, 24 + srl s5, s5, 24 + MIPS_2xUN8x4_MUL_2xUN8 s0, s1, s4, s5, s0, s1, t4, t9, t0, t1, s6, s7, s8 + addu_s.qb s4, s2, s0 + addu_s.qb s5, s3, s1 + CONVERT_2x8888_TO_2x0565 s4, s5, t2, t3, t6, t7, t8, s0, s1 + sh t2, 0(a0) + b 111f + sh t3, 2(a0) +11: + MIPS_2xUN8x4_MUL_2xUN8 s0, s1, v0, v0, s0, s1, t4, t9, t0, t1, s6, s7, s8 + addu_s.qb s4, a1, s0 + addu_s.qb s5, a1, s1 + CONVERT_2x8888_TO_2x0565 s4, s5, t2, t3, t6, t7, t8, s0, s1 + sh t2, 0(a0) + sh t3, 2(a0) +111: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 1b + addiu a0, a0, 4 + b 3f + nop +2: + CONVERT_1x8888_TO_1x0565 a1, s0, s1, s2 +21: + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + lbu t1, 1(a2) /* t1 = mask */ + or t2, t0, t1 + beqz t2, 222f /* if (t0 == 0) && (t1 == 0) */ + addiu a2, a2, 2 + and t9, t0, t1 + move s2, s0 + beq t9, t5, 22f /* if (t0 == 0xff) && (t2 == 0xff) */ + move s3, s0 + lhu t2, 0(a0) /* t2 = dst */ + lhu t3, 2(a0) /* t3 = dst */ + + CONVERT_2x0565_TO_2x8888 t2, t3, s2, s3, t7, t8, s4, s5, s6, s7 + OVER_2x8888_2x8_2x8888 a1, a1, t0, t1, s2, s3, \ + t2, t3, t4, t9, s4, s5, s6, s7, s8 + CONVERT_2x8888_TO_2x0565 t2, t3, s2, s3, t6, t7, t8, s4, s5 +22: + sh s2, 0(a0) + sh s3, 2(a0) +222: + addiu a3, a3, -2 + addiu t0, a3, -1 + bgtz t0, 21b + addiu a0, a0, 4 +3: + blez a3, 4f + nop + /* a1 = src */ + lbu t0, 0(a2) /* t0 = mask */ + beqz t0, 4f /* if (t0 == 0) */ + nop + lhu t1, 0(a0) /* t1 = dst */ + CONVERT_1x0565_TO_1x8888 t1, t2, t3, t7 + beq t0, t5, 31f /* if (t0 == 0xff) */ + move t3, a1 + + MIPS_UN8x4_MUL_UN8 a1, t0, t3, t4, t7, t8, t9 +31: + not t6, t3 + srl t6, t6, 24 + MIPS_UN8x4_MUL_UN8 t2, t6, t2, t4, t7, t8, t9 + addu_s.qb t1, t2, t3 + CONVERT_1x8888_TO_1x0565 t1, t2, t3, t7 + sh t2, 0(a0) +4: + RESTORE_REGS_FROM_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 + j ra + nop + +END(pixman_composite_over_n_8_0565_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 + + lw s0, 36(sp) /* s0 = wt */ + lw s1, 40(sp) /* s1 = wb */ + lw s2, 44(sp) /* s2 = vx */ + lw s3, 48(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 + + lw s0, 36(sp) /* s0 = wt */ + lw s1, 40(sp) /* s1 = wb */ + lw s2, 44(sp) /* s2 = vx */ + lw s3, 48(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez a3, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_8888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a1) /* t0 = tl */ + lhx t1, t8(a1) /* t1 = tr */ + andi t1, t1, 0xffff + addiu a3, a3, -1 + lhx t2, t9(a2) /* t2 = bl */ + lhx t3, t8(a2) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_8888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a1) /* t0 = tl */ + lhx t1, t8(a1) /* t1 = tr */ + andi t1, t1, 0xffff + addiu a3, a3, -1 + lhx t2, t9(a2) /* t2 = bl */ + lhx t3, t8(a2) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez a3, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_OVER_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 40(sp) /* s0 = wt */ + lw s1, 44(sp) /* s1 = wb */ + lw s2, 48(sp) /* s2 = vx */ + lw s3, 52(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lw t1, 0(a0) /* t1 = dest */ + OVER_8888_8888 t0, t1, t2, s8, t3, t4, t5, t6 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t2, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 24, v0, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8888_OVER_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8888_ADD_asm_mips) +/* + * a0 - *dst + * a1 - *src_top + * a2 - *src_bottom + * a3 - w + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + */ + + beqz a3, 1f + nop + + SAVE_REGS_ON_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 + + lw s0, 36(sp) /* s0 = wt */ + lw s1, 40(sp) /* s1 = wb */ + lw s2, 44(sp) /* s2 = vx */ + lw s3, 48(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a1) /* t0 = tl */ + lwx t1, t8(a1) /* t1 = tr */ + addiu a3, a3, -1 + lwx t2, t9(a2) /* t2 = bl */ + lwx t3, t8(a2) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lw t1, 0(a0) + addu_s.qb t2, t0, t1 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t2, 0(a0) + bnez a3, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 20, v0, s0, s1, s2, s3, s4, s5, s6, s7 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8888_ADD_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_8888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw v1, 32(sp) + beqz v1, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, s8, t2, t3, t4 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez v1, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_8888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw v1, 32(sp) + beqz v1, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, s8, t2, t3, t4 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez v1, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_8_x888_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw t0, 32(sp) + beqz t0, 1f + nop + + SAVE_REGS_ON_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra + + lw s0, 48(sp) /* s0 = wt */ + lw s1, 52(sp) /* s1 = wb */ + lw s2, 56(sp) /* s2 = vx */ + lw s3, 60(sp) /* s3 = unit_x */ + lw ra, 64(sp) /* ra = w */ + li v0, 0x00ff00ff + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + li t5, BILINEAR_INTERPOLATION_RANGE + subu t5, t5, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a2) /* t0 = tl */ + lhx t1, t8(a2) /* t1 = tr */ + andi t1, t1, 0xffff + addiu ra, ra, -1 + lhx t2, t9(a3) /* t2 = bl */ + lhx t3, t8(a3) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, v0, t2, t3, t4 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez ra, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_8_x888_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_0565_8_0565_SRC_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw t0, 32(sp) + beqz t0, 1f + nop + + SAVE_REGS_ON_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra + + lw s0, 48(sp) /* s0 = wt */ + lw s1, 52(sp) /* s1 = wb */ + lw s2, 56(sp) /* s2 = vx */ + lw s3, 60(sp) /* s3 = unit_x */ + lw ra, 64(sp) /* ra = w */ + li v0, 0x00ff00ff + li v1, 0x07e007e0 + li s8, 0x001f001f + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + li t5, BILINEAR_INTERPOLATION_RANGE + subu t5, t5, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 1 + addiu t8, t9, 2 + lhx t0, t9(a2) /* t0 = tl */ + lhx t1, t8(a2) /* t1 = tr */ + andi t1, t1, 0xffff + addiu ra, ra, -1 + lhx t2, t9(a3) /* t2 = bl */ + lhx t3, t8(a3) /* t3 = br */ + andi t3, t3, 0xffff + + CONVERT_2x0565_TO_2x8888 t0, t1, t0, t1, v1, s8, t4, t5, t6, t7 + CONVERT_2x0565_TO_2x8888 t2, t3, t2, t3, v1, s8, t4, t5, t6, t7 + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8 t0, t1, t0, v0, t2, t3, t4 + CONVERT_1x8888_TO_1x0565 t0, t1, t2, t3 + + addu s2, s2, s3 /* vx += unit_x; */ + sh t1, 0(a0) + bnez ra, 0b + addiu a0, a0, 2 + + RESTORE_REGS_FROM_STACK 32, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8, ra +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_0565_8_0565_SRC_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_8888_OVER_asm_mips) +/* + * a0 - dst (a8r8g8b8) + * a1 - mask (a8) + * a2 - src_top (a8r8g8b8) + * a3 - src_bottom (a8r8g8b8) + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw v1, 60(sp) /* v1 = w(sp + 32 + 28 save regs stack offset)*/ + beqz v1, 1f + nop + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, \ + t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + lw t2, 0(a0) /* t2 = dst */ + addiu a1, a1, 1 + OVER_8888_8_8888 t0, t1, t2, t0, s8, t3, t4, t5, t6 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez v1, 0b + addiu a0, a0, 4 + +1: + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_8888_OVER_asm_mips) + +LEAF_MIPS_DSPR2(pixman_scaled_bilinear_scanline_8888_8_8888_ADD_asm_mips) +/* + * a0 - *dst + * a1 - *mask + * a2 - *src_top + * a3 - *src_bottom + * 16(sp) - wt + * 20(sp) - wb + * 24(sp) - vx + * 28(sp) - unit_x + * 32(sp) - w + */ + + lw v1, 32(sp) + beqz v1, 1f + nop + + SAVE_REGS_ON_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 + + lw s0, 44(sp) /* s0 = wt */ + lw s1, 48(sp) /* s1 = wb */ + lw s2, 52(sp) /* s2 = vx */ + lw s3, 56(sp) /* s3 = unit_x */ + li v0, BILINEAR_INTERPOLATION_RANGE + li s8, 0x00ff00ff + + sll s0, s0, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) + sll s1, s1, (2 * (8 - BILINEAR_INTERPOLATION_BITS)) +0: + andi t4, s2, 0xffff /* t4 = (short)vx */ + srl t4, t4, (16 - BILINEAR_INTERPOLATION_BITS) /* t4 = vx >> 8 */ + subu t5, v0, t4 /* t5 = ( 256 - (vx>>8)) */ + + mul s4, s0, t5 /* s4 = wt*(256-(vx>>8)) */ + mul s5, s0, t4 /* s5 = wt*(vx>>8) */ + mul s6, s1, t5 /* s6 = wb*(256-(vx>>8)) */ + mul s7, s1, t4 /* s7 = wb*(vx>>8) */ + + sra t9, s2, 16 + sll t9, t9, 2 + addiu t8, t9, 4 + lwx t0, t9(a2) /* t0 = tl */ + lwx t1, t8(a2) /* t1 = tr */ + addiu v1, v1, -1 + lwx t2, t9(a3) /* t2 = bl */ + lwx t3, t8(a3) /* t3 = br */ + + BILINEAR_INTERPOLATE_SINGLE_PIXEL t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, s4, s5, s6, s7 + lbu t1, 0(a1) /* t1 = mask */ + lw t2, 0(a0) /* t2 = dst */ + addiu a1, a1, 1 + MIPS_UN8x4_MUL_UN8_ADD_UN8x4 t0, t1, t2, t0, s8, t3, t4, t5 + + addu s2, s2, s3 /* vx += unit_x; */ + sw t0, 0(a0) + bnez v1, 0b + addiu a0, a0, 4 + + RESTORE_REGS_FROM_STACK 28, v0, v1, s0, s1, s2, s3, s4, s5, s6, s7, s8 +1: + j ra + nop + +END(pixman_scaled_bilinear_scanline_8888_8_8888_ADD_asm_mips) diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h new file mode 100644 index 00000000000..7327dc6dc01 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2-asm.h @@ -0,0 +1,659 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#ifndef PIXMAN_MIPS_DSPR2_ASM_H +#define PIXMAN_MIPS_DSPR2_ASM_H + +#define zero $0 +#define AT $1 +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define s8 $30 +#define ra $31 + +/* + * LEAF_MIPS32R2 - declare leaf routine for MIPS32r2 + */ +#define LEAF_MIPS32R2(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol, 0; \ +symbol: .frame sp, 0, ra; \ + .set push; \ + .set arch=mips32r2; \ + .set noreorder; \ + .set noat; + +/* + * LEAF_MIPS32R2 - declare leaf routine for MIPS DSPr2 + */ +#define LEAF_MIPS_DSPR2(symbol) \ +LEAF_MIPS32R2(symbol) \ + .set dspr2; + +/* + * END - mark end of function + */ +#define END(function) \ + .set pop; \ + .end function; \ + .size function,.-function + +/* + * Checks if stack offset is big enough for storing/restoring regs_num + * number of register to/from stack. Stack offset must be greater than + * or equal to the number of bytes needed for storing registers (regs_num*4). + * Since MIPS ABI allows usage of first 16 bytes of stack frame (this is + * preserved for input arguments of the functions, already stored in a0-a3), + * stack size can be further optimized by utilizing this space. + */ +.macro CHECK_STACK_OFFSET regs_num, stack_offset +.if \stack_offset < \regs_num * 4 - 16 +.error "Stack offset too small." +.endif +.endm + +/* + * Saves set of registers on stack. Maximum number of registers that + * can be saved on stack is limitted to 14 (a0-a3, v0-v1 and s0-s7). + * Stack offset is number of bytes that are added to stack pointer (sp) + * before registers are pushed in order to provide enough space on stack + * (offset must be multiple of 4, and must be big enough, as described by + * CHECK_STACK_OFFSET macro). This macro is intended to be used in + * combination with RESTORE_REGS_FROM_STACK macro. Example: + * SAVE_REGS_ON_STACK 4, v0, v1, s0, s1 + * RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1 + */ +.macro SAVE_REGS_ON_STACK stack_offset = 0, r1, \ + r2 = 0, r3 = 0, r4 = 0, \ + r5 = 0, r6 = 0, r7 = 0, \ + r8 = 0, r9 = 0, r10 = 0, \ + r11 = 0, r12 = 0, r13 = 0, \ + r14 = 0 + .if (\stack_offset < 0) || (\stack_offset - (\stack_offset / 4) * 4) + .error "Stack offset must be pozitive and multiple of 4." + .endif + .if \stack_offset != 0 + addiu sp, sp, -\stack_offset + .endif + sw \r1, 0(sp) + .if \r2 != 0 + sw \r2, 4(sp) + .endif + .if \r3 != 0 + sw \r3, 8(sp) + .endif + .if \r4 != 0 + sw \r4, 12(sp) + .endif + .if \r5 != 0 + CHECK_STACK_OFFSET 5, \stack_offset + sw \r5, 16(sp) + .endif + .if \r6 != 0 + CHECK_STACK_OFFSET 6, \stack_offset + sw \r6, 20(sp) + .endif + .if \r7 != 0 + CHECK_STACK_OFFSET 7, \stack_offset + sw \r7, 24(sp) + .endif + .if \r8 != 0 + CHECK_STACK_OFFSET 8, \stack_offset + sw \r8, 28(sp) + .endif + .if \r9 != 0 + CHECK_STACK_OFFSET 9, \stack_offset + sw \r9, 32(sp) + .endif + .if \r10 != 0 + CHECK_STACK_OFFSET 10, \stack_offset + sw \r10, 36(sp) + .endif + .if \r11 != 0 + CHECK_STACK_OFFSET 11, \stack_offset + sw \r11, 40(sp) + .endif + .if \r12 != 0 + CHECK_STACK_OFFSET 12, \stack_offset + sw \r12, 44(sp) + .endif + .if \r13 != 0 + CHECK_STACK_OFFSET 13, \stack_offset + sw \r13, 48(sp) + .endif + .if \r14 != 0 + CHECK_STACK_OFFSET 14, \stack_offset + sw \r14, 52(sp) + .endif +.endm + +/* + * Restores set of registers from stack. Maximum number of registers that + * can be restored from stack is limitted to 14 (a0-a3, v0-v1 and s0-s7). + * Stack offset is number of bytes that are added to stack pointer (sp) + * after registers are restored (offset must be multiple of 4, and must + * be big enough, as described by CHECK_STACK_OFFSET macro). This macro is + * intended to be used in combination with RESTORE_REGS_FROM_STACK macro. + * Example: + * SAVE_REGS_ON_STACK 4, v0, v1, s0, s1 + * RESTORE_REGS_FROM_STACK 4, v0, v1, s0, s1 + */ +.macro RESTORE_REGS_FROM_STACK stack_offset = 0, r1, \ + r2 = 0, r3 = 0, r4 = 0, \ + r5 = 0, r6 = 0, r7 = 0, \ + r8 = 0, r9 = 0, r10 = 0, \ + r11 = 0, r12 = 0, r13 = 0, \ + r14 = 0 + .if (\stack_offset < 0) || (\stack_offset - (\stack_offset/4)*4) + .error "Stack offset must be pozitive and multiple of 4." + .endif + lw \r1, 0(sp) + .if \r2 != 0 + lw \r2, 4(sp) + .endif + .if \r3 != 0 + lw \r3, 8(sp) + .endif + .if \r4 != 0 + lw \r4, 12(sp) + .endif + .if \r5 != 0 + CHECK_STACK_OFFSET 5, \stack_offset + lw \r5, 16(sp) + .endif + .if \r6 != 0 + CHECK_STACK_OFFSET 6, \stack_offset + lw \r6, 20(sp) + .endif + .if \r7 != 0 + CHECK_STACK_OFFSET 7, \stack_offset + lw \r7, 24(sp) + .endif + .if \r8 != 0 + CHECK_STACK_OFFSET 8, \stack_offset + lw \r8, 28(sp) + .endif + .if \r9 != 0 + CHECK_STACK_OFFSET 9, \stack_offset + lw \r9, 32(sp) + .endif + .if \r10 != 0 + CHECK_STACK_OFFSET 10, \stack_offset + lw \r10, 36(sp) + .endif + .if \r11 != 0 + CHECK_STACK_OFFSET 11, \stack_offset + lw \r11, 40(sp) + .endif + .if \r12 != 0 + CHECK_STACK_OFFSET 12, \stack_offset + lw \r12, 44(sp) + .endif + .if \r13 != 0 + CHECK_STACK_OFFSET 13, \stack_offset + lw \r13, 48(sp) + .endif + .if \r14 != 0 + CHECK_STACK_OFFSET 14, \stack_offset + lw \r14, 52(sp) + .endif + .if \stack_offset != 0 + addiu sp, sp, \stack_offset + .endif +.endm + +/* + * Conversion of single r5g6b5 pixel (in_565) to single a8r8g8b8 pixel + * returned in (out_8888) register. Requires two temporary registers + * (scratch1 and scratch2). + */ +.macro CONVERT_1x0565_TO_1x8888 in_565, \ + out_8888, \ + scratch1, scratch2 + lui \out_8888, 0xff00 + sll \scratch1, \in_565, 0x3 + andi \scratch2, \scratch1, 0xff + ext \scratch1, \in_565, 0x2, 0x3 + or \scratch1, \scratch2, \scratch1 + or \out_8888, \out_8888, \scratch1 + + sll \scratch1, \in_565, 0x5 + andi \scratch1, \scratch1, 0xfc00 + srl \scratch2, \in_565, 0x1 + andi \scratch2, \scratch2, 0x300 + or \scratch2, \scratch1, \scratch2 + or \out_8888, \out_8888, \scratch2 + + andi \scratch1, \in_565, 0xf800 + srl \scratch2, \scratch1, 0x5 + andi \scratch2, \scratch2, 0xff00 + or \scratch1, \scratch1, \scratch2 + sll \scratch1, \scratch1, 0x8 + or \out_8888, \out_8888, \scratch1 +.endm + +/* + * Conversion of two r5g6b5 pixels (in1_565 and in2_565) to two a8r8g8b8 pixels + * returned in (out1_8888 and out2_8888) registers. Requires four scratch + * registers (scratch1 ... scratch4). It also requires maskG and maskB for + * color component extractions. These masks must have following values: + * li maskG, 0x07e007e0 + * li maskB, 0x001F001F + */ +.macro CONVERT_2x0565_TO_2x8888 in1_565, in2_565, \ + out1_8888, out2_8888, \ + maskG, maskB, \ + scratch1, scratch2, scratch3, scratch4 + sll \scratch1, \in1_565, 16 + or \scratch1, \scratch1, \in2_565 + lui \out2_8888, 0xff00 + ori \out2_8888, \out2_8888, 0xff00 + shrl.ph \scratch2, \scratch1, 11 + and \scratch3, \scratch1, \maskG + shra.ph \scratch4, \scratch2, 2 + shll.ph \scratch2, \scratch2, 3 + shll.ph \scratch3, \scratch3, 5 + or \scratch2, \scratch2, \scratch4 + shrl.qb \scratch4, \scratch3, 6 + or \out2_8888, \out2_8888, \scratch2 + or \scratch3, \scratch3, \scratch4 + and \scratch1, \scratch1, \maskB + shll.ph \scratch2, \scratch1, 3 + shra.ph \scratch4, \scratch1, 2 + or \scratch2, \scratch2, \scratch4 + or \scratch3, \scratch2, \scratch3 + precrq.ph.w \out1_8888, \out2_8888, \scratch3 + precr_sra.ph.w \out2_8888, \scratch3, 0 +.endm + +/* + * Conversion of single a8r8g8b8 pixel (in_8888) to single r5g6b5 pixel + * returned in (out_565) register. Requires two temporary registers + * (scratch1 and scratch2). + */ +.macro CONVERT_1x8888_TO_1x0565 in_8888, \ + out_565, \ + scratch1, scratch2 + ext \out_565, \in_8888, 0x3, 0x5 + srl \scratch1, \in_8888, 0x5 + andi \scratch1, \scratch1, 0x07e0 + srl \scratch2, \in_8888, 0x8 + andi \scratch2, \scratch2, 0xf800 + or \out_565, \out_565, \scratch1 + or \out_565, \out_565, \scratch2 +.endm + +/* + * Conversion of two a8r8g8b8 pixels (in1_8888 and in2_8888) to two r5g6b5 + * pixels returned in (out1_565 and out2_565) registers. Requires two temporary + * registers (scratch1 and scratch2). It also requires maskR, maskG and maskB + * for color component extractions. These masks must have following values: + * li maskR, 0xf800f800 + * li maskG, 0x07e007e0 + * li maskB, 0x001F001F + * Value of input register in2_8888 is lost. + */ +.macro CONVERT_2x8888_TO_2x0565 in1_8888, in2_8888, \ + out1_565, out2_565, \ + maskR, maskG, maskB, \ + scratch1, scratch2 + precrq.ph.w \scratch1, \in2_8888, \in1_8888 + precr_sra.ph.w \in2_8888, \in1_8888, 0 + shll.ph \scratch1, \scratch1, 8 + srl \in2_8888, \in2_8888, 3 + and \scratch2, \in2_8888, \maskB + and \scratch1, \scratch1, \maskR + srl \in2_8888, \in2_8888, 2 + and \out2_565, \in2_8888, \maskG + or \out2_565, \out2_565, \scratch2 + or \out1_565, \out2_565, \scratch1 + srl \out2_565, \out1_565, 16 +.endm + +/* + * Multiply pixel (a8) with single pixel (a8r8g8b8). It requires maskLSR needed + * for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro MIPS_UN8x4_MUL_UN8 s_8888, \ + m_8, \ + d_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3 + replv.ph \m_8, \m_8 /* 0 | M | 0 | M */ + muleu_s.ph.qbl \scratch1, \s_8888, \m_8 /* A*M | R*M */ + muleu_s.ph.qbr \scratch2, \s_8888, \m_8 /* G*M | B*M */ + shra_r.ph \scratch3, \scratch1, 8 + shra_r.ph \d_8888, \scratch2, 8 + and \scratch3, \scratch3, \maskLSR /* 0 |A*M| 0 |R*M */ + and \d_8888, \d_8888, \maskLSR /* 0 |G*M| 0 |B*M */ + addq.ph \scratch1, \scratch1, \scratch3 /* A*M+A*M | R*M+R*M */ + addq.ph \scratch2, \scratch2, \d_8888 /* G*M+G*M | B*M+B*M */ + shra_r.ph \scratch1, \scratch1, 8 + shra_r.ph \scratch2, \scratch2, 8 + precr.qb.ph \d_8888, \scratch1, \scratch2 +.endm + +/* + * Multiply two pixels (a8) with two pixels (a8r8g8b8). It requires maskLSR + * needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro MIPS_2xUN8x4_MUL_2xUN8 s1_8888, \ + s2_8888, \ + m1_8, \ + m2_8, \ + d1_8888, \ + d2_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, \ + scratch4, scratch5, scratch6 + replv.ph \m1_8, \m1_8 /* 0 | M1 | 0 | M1 */ + replv.ph \m2_8, \m2_8 /* 0 | M2 | 0 | M2 */ + muleu_s.ph.qbl \scratch1, \s1_8888, \m1_8 /* A1*M1 | R1*M1 */ + muleu_s.ph.qbr \scratch2, \s1_8888, \m1_8 /* G1*M1 | B1*M1 */ + muleu_s.ph.qbl \scratch3, \s2_8888, \m2_8 /* A2*M2 | R2*M2 */ + muleu_s.ph.qbr \scratch4, \s2_8888, \m2_8 /* G2*M2 | B2*M2 */ + shra_r.ph \scratch5, \scratch1, 8 + shra_r.ph \d1_8888, \scratch2, 8 + shra_r.ph \scratch6, \scratch3, 8 + shra_r.ph \d2_8888, \scratch4, 8 + and \scratch5, \scratch5, \maskLSR /* 0 |A1*M1| 0 |R1*M1 */ + and \d1_8888, \d1_8888, \maskLSR /* 0 |G1*M1| 0 |B1*M1 */ + and \scratch6, \scratch6, \maskLSR /* 0 |A2*M2| 0 |R2*M2 */ + and \d2_8888, \d2_8888, \maskLSR /* 0 |G2*M2| 0 |B2*M2 */ + addq.ph \scratch1, \scratch1, \scratch5 + addq.ph \scratch2, \scratch2, \d1_8888 + addq.ph \scratch3, \scratch3, \scratch6 + addq.ph \scratch4, \scratch4, \d2_8888 + shra_r.ph \scratch1, \scratch1, 8 + shra_r.ph \scratch2, \scratch2, 8 + shra_r.ph \scratch3, \scratch3, 8 + shra_r.ph \scratch4, \scratch4, 8 + precr.qb.ph \d1_8888, \scratch1, \scratch2 + precr.qb.ph \d2_8888, \scratch3, \scratch4 +.endm + +/* + * Multiply pixel (a8r8g8b8) with single pixel (a8r8g8b8). It requires maskLSR + * needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro MIPS_UN8x4_MUL_UN8x4 s_8888, \ + m_8888, \ + d_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, scratch4 + preceu.ph.qbl \scratch1, \m_8888 /* 0 | A | 0 | R */ + preceu.ph.qbr \scratch2, \m_8888 /* 0 | G | 0 | B */ + muleu_s.ph.qbl \scratch3, \s_8888, \scratch1 /* A*A | R*R */ + muleu_s.ph.qbr \scratch4, \s_8888, \scratch2 /* G*G | B*B */ + shra_r.ph \scratch1, \scratch3, 8 + shra_r.ph \scratch2, \scratch4, 8 + and \scratch1, \scratch1, \maskLSR /* 0 |A*A| 0 |R*R */ + and \scratch2, \scratch2, \maskLSR /* 0 |G*G| 0 |B*B */ + addq.ph \scratch1, \scratch1, \scratch3 + addq.ph \scratch2, \scratch2, \scratch4 + shra_r.ph \scratch1, \scratch1, 8 + shra_r.ph \scratch2, \scratch2, 8 + precr.qb.ph \d_8888, \scratch1, \scratch2 +.endm + +/* + * Multiply two pixels (a8r8g8b8) with two pixels (a8r8g8b8). It requires + * maskLSR needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ + +.macro MIPS_2xUN8x4_MUL_2xUN8x4 s1_8888, \ + s2_8888, \ + m1_8888, \ + m2_8888, \ + d1_8888, \ + d2_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, \ + scratch4, scratch5, scratch6 + preceu.ph.qbl \scratch1, \m1_8888 /* 0 | A | 0 | R */ + preceu.ph.qbr \scratch2, \m1_8888 /* 0 | G | 0 | B */ + preceu.ph.qbl \scratch3, \m2_8888 /* 0 | A | 0 | R */ + preceu.ph.qbr \scratch4, \m2_8888 /* 0 | G | 0 | B */ + muleu_s.ph.qbl \scratch5, \s1_8888, \scratch1 /* A*A | R*R */ + muleu_s.ph.qbr \scratch6, \s1_8888, \scratch2 /* G*G | B*B */ + muleu_s.ph.qbl \scratch1, \s2_8888, \scratch3 /* A*A | R*R */ + muleu_s.ph.qbr \scratch2, \s2_8888, \scratch4 /* G*G | B*B */ + shra_r.ph \scratch3, \scratch5, 8 + shra_r.ph \scratch4, \scratch6, 8 + shra_r.ph \d1_8888, \scratch1, 8 + shra_r.ph \d2_8888, \scratch2, 8 + and \scratch3, \scratch3, \maskLSR /* 0 |A*A| 0 |R*R */ + and \scratch4, \scratch4, \maskLSR /* 0 |G*G| 0 |B*B */ + and \d1_8888, \d1_8888, \maskLSR /* 0 |A*A| 0 |R*R */ + and \d2_8888, \d2_8888, \maskLSR /* 0 |G*G| 0 |B*B */ + addq.ph \scratch3, \scratch3, \scratch5 + addq.ph \scratch4, \scratch4, \scratch6 + addq.ph \d1_8888, \d1_8888, \scratch1 + addq.ph \d2_8888, \d2_8888, \scratch2 + shra_r.ph \scratch3, \scratch3, 8 + shra_r.ph \scratch4, \scratch4, 8 + shra_r.ph \scratch5, \d1_8888, 8 + shra_r.ph \scratch6, \d2_8888, 8 + precr.qb.ph \d1_8888, \scratch3, \scratch4 + precr.qb.ph \d2_8888, \scratch5, \scratch6 +.endm + +/* + * OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8 + * destination pixel (d_8888) using a8 mask (m_8). It also requires maskLSR + * needed for rounding process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro OVER_8888_8_8888 s_8888, \ + m_8, \ + d_8888, \ + out_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, scratch4 + MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \ + \scratch1, \maskLSR, \ + \scratch2, \scratch3, \scratch4 + + not \scratch2, \scratch1 + srl \scratch2, \scratch2, 24 + + MIPS_UN8x4_MUL_UN8 \d_8888, \scratch2, \ + \d_8888, \maskLSR, \ + \scratch3, \scratch4, \out_8888 + + addu_s.qb \out_8888, \d_8888, \scratch1 +.endm + +/* + * OVER operation on two a8r8g8b8 source pixels (s1_8888 and s2_8888) and two + * a8r8g8b8 destination pixels (d1_8888 and d2_8888) using a8 masks (m1_8 and + * m2_8). It also requires maskLSR needed for rounding process. maskLSR must + * have following value: + * li maskLSR, 0x00ff00ff + */ +.macro OVER_2x8888_2x8_2x8888 s1_8888, \ + s2_8888, \ + m1_8, \ + m2_8, \ + d1_8888, \ + d2_8888, \ + out1_8888, \ + out2_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, \ + scratch4, scratch5, scratch6 + MIPS_2xUN8x4_MUL_2xUN8 \s1_8888, \s2_8888, \ + \m1_8, \m2_8, \ + \scratch1, \scratch2, \ + \maskLSR, \ + \scratch3, \scratch4, \out1_8888, \ + \out2_8888, \scratch5, \scratch6 + + not \scratch3, \scratch1 + srl \scratch3, \scratch3, 24 + not \scratch4, \scratch2 + srl \scratch4, \scratch4, 24 + + MIPS_2xUN8x4_MUL_2xUN8 \d1_8888, \d2_8888, \ + \scratch3, \scratch4, \ + \d1_8888, \d2_8888, \ + \maskLSR, \ + \scratch5, \scratch6, \out1_8888, \ + \out2_8888, \scratch3, \scratch4 + + addu_s.qb \out1_8888, \d1_8888, \scratch1 + addu_s.qb \out2_8888, \d2_8888, \scratch2 +.endm + +/* + * OVER operation on single a8r8g8b8 source pixel (s_8888) and single a8r8g8b8 + * destination pixel (d_8888). It also requires maskLSR needed for rounding + * process. maskLSR must have following value: + * li maskLSR, 0x00ff00ff + */ +.macro OVER_8888_8888 s_8888, \ + d_8888, \ + out_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3, scratch4 + not \scratch1, \s_8888 + srl \scratch1, \scratch1, 24 + + MIPS_UN8x4_MUL_UN8 \d_8888, \scratch1, \ + \out_8888, \maskLSR, \ + \scratch2, \scratch3, \scratch4 + + addu_s.qb \out_8888, \out_8888, \s_8888 +.endm + +.macro MIPS_UN8x4_MUL_UN8_ADD_UN8x4 s_8888, \ + m_8, \ + d_8888, \ + out_8888, \ + maskLSR, \ + scratch1, scratch2, scratch3 + MIPS_UN8x4_MUL_UN8 \s_8888, \m_8, \ + \out_8888, \maskLSR, \ + \scratch1, \scratch2, \scratch3 + + addu_s.qb \out_8888, \out_8888, \d_8888 +.endm + +.macro BILINEAR_INTERPOLATE_SINGLE_PIXEL tl, tr, bl, br, \ + scratch1, scratch2, \ + alpha, red, green, blue \ + wt1, wt2, wb1, wb2 + andi \scratch1, \tl, 0xff + andi \scratch2, \tr, 0xff + andi \alpha, \bl, 0xff + andi \red, \br, 0xff + + multu $ac0, \wt1, \scratch1 + maddu $ac0, \wt2, \scratch2 + maddu $ac0, \wb1, \alpha + maddu $ac0, \wb2, \red + + ext \scratch1, \tl, 8, 8 + ext \scratch2, \tr, 8, 8 + ext \alpha, \bl, 8, 8 + ext \red, \br, 8, 8 + + multu $ac1, \wt1, \scratch1 + maddu $ac1, \wt2, \scratch2 + maddu $ac1, \wb1, \alpha + maddu $ac1, \wb2, \red + + ext \scratch1, \tl, 16, 8 + ext \scratch2, \tr, 16, 8 + ext \alpha, \bl, 16, 8 + ext \red, \br, 16, 8 + + mflo \blue, $ac0 + + multu $ac2, \wt1, \scratch1 + maddu $ac2, \wt2, \scratch2 + maddu $ac2, \wb1, \alpha + maddu $ac2, \wb2, \red + + ext \scratch1, \tl, 24, 8 + ext \scratch2, \tr, 24, 8 + ext \alpha, \bl, 24, 8 + ext \red, \br, 24, 8 + + mflo \green, $ac1 + + multu $ac3, \wt1, \scratch1 + maddu $ac3, \wt2, \scratch2 + maddu $ac3, \wb1, \alpha + maddu $ac3, \wb2, \red + + mflo \red, $ac2 + mflo \alpha, $ac3 + + precr.qb.ph \alpha, \alpha, \red + precr.qb.ph \scratch1, \green, \blue + precrq.qb.ph \tl, \alpha, \scratch1 +.endm + +#endif //PIXMAN_MIPS_DSPR2_ASM_H diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2.c b/gfx/cairo/libpixman/src/pixman-mips-dspr2.c new file mode 100644 index 00000000000..63a0225a2e7 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" +#include "pixman-mips-dspr2.h" + +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_x888_8888, + uint32_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_8888_0565, + uint32_t, 1, uint16_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (0, src_0565_8888, + uint16_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0565_0565, + uint16_t, 1, uint16_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_8888_8888, + uint32_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST (DO_FAST_MEMCPY, src_0888_0888, + uint8_t, 3, uint8_t, 3) + +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_8888_ca, + uint32_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8888_0565_ca, + uint32_t, 1, uint16_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_8888, + uint8_t, 1, uint32_t, 1) +PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST (SKIP_ZERO_SRC, over_n_8_0565, + uint8_t, 1, uint16_t, 1) + +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_8888, SRC, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 8888_0565, SRC, + uint32_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_8888, SRC, + uint16_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (0, 0565_0565, SRC, + uint16_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, OVER, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST (SKIP_ZERO_SRC, 8888_8888, ADD, + uint32_t, uint32_t) + +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_8888, SRC, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 8888_8_0565, SRC, + uint32_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_x888, SRC, + uint16_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (0, 0565_8_0565, SRC, + uint16_t, uint16_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, OVER, + uint32_t, uint32_t) +PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST (SKIP_ZERO_SRC, 8888_8_8888, ADD, + uint32_t, uint32_t) + +static pixman_bool_t +pixman_fill_mips (uint32_t *bits, + int stride, + int bpp, + int x, + int y, + int width, + int height, + uint32_t _xor) +{ + uint8_t *byte_line; + uint32_t byte_width; + switch (bpp) + { + case 16: + stride = stride * (int) sizeof (uint32_t) / 2; + byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x); + byte_width = width * 2; + stride *= 2; + + while (height--) + { + uint8_t *dst = byte_line; + byte_line += stride; + pixman_fill_buff16_mips (dst, byte_width, _xor & 0xffff); + } + return TRUE; + case 32: + stride = stride * (int) sizeof (uint32_t) / 4; + byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x); + byte_width = width * 4; + stride *= 4; + + while (height--) + { + uint8_t *dst = byte_line; + byte_line += stride; + pixman_fill_buff32_mips (dst, byte_width, _xor); + } + return TRUE; + default: + return FALSE; + } +} + +static pixman_bool_t +pixman_blt_mips (uint32_t *src_bits, + uint32_t *dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dest_x, + int dest_y, + int width, + int height) +{ + if (src_bpp != dst_bpp) + return FALSE; + + uint8_t *src_bytes; + uint8_t *dst_bytes; + uint32_t byte_width; + + switch (src_bpp) + { + case 16: + src_stride = src_stride * (int) sizeof (uint32_t) / 2; + dst_stride = dst_stride * (int) sizeof (uint32_t) / 2; + src_bytes =(uint8_t *)(((uint16_t *)src_bits) + + src_stride * (src_y) + (src_x)); + dst_bytes = (uint8_t *)(((uint16_t *)dst_bits) + + dst_stride * (dest_y) + (dest_x)); + byte_width = width * 2; + src_stride *= 2; + dst_stride *= 2; + + while (height--) + { + uint8_t *src = src_bytes; + uint8_t *dst = dst_bytes; + src_bytes += src_stride; + dst_bytes += dst_stride; + pixman_mips_fast_memcpy (dst, src, byte_width); + } + return TRUE; + case 32: + src_stride = src_stride * (int) sizeof (uint32_t) / 4; + dst_stride = dst_stride * (int) sizeof (uint32_t) / 4; + src_bytes = (uint8_t *)(((uint32_t *)src_bits) + + src_stride * (src_y) + (src_x)); + dst_bytes = (uint8_t *)(((uint32_t *)dst_bits) + + dst_stride * (dest_y) + (dest_x)); + byte_width = width * 4; + src_stride *= 4; + dst_stride *= 4; + + while (height--) + { + uint8_t *src = src_bytes; + uint8_t *dst = dst_bytes; + src_bytes += src_stride; + dst_bytes += dst_stride; + pixman_mips_fast_memcpy (dst, src, byte_width); + } + return TRUE; + default: + return FALSE; + } +} + +static const pixman_fast_path_t mips_dspr2_fast_paths[] = +{ + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, r5g6b5, mips_composite_src_0565_0565), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, b5g6r5, mips_composite_src_0565_0565), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, mips_composite_src_8888_0565), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, a8r8g8b8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, r5g6b5, null, x8r8g8b8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, a8b8g8r8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, b5g6r5, null, x8b8g8r8, mips_composite_src_0565_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, x8r8g8b8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, x8b8g8r8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, a8b8g8r8, mips_composite_src_8888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, mips_composite_src_x888_8888), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, mips_composite_src_x888_8888), + PIXMAN_STD_FAST_PATH (SRC, r8g8b8, null, r8g8b8, mips_composite_src_0888_0888), + + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, a8r8g8b8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, x8r8g8b8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, a8b8g8r8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, x8b8g8r8, mips_composite_over_n_8888_8888_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8r8g8b8, r5g6b5, mips_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH_CA (OVER, solid, a8b8g8r8, b5g6r5, mips_composite_over_n_8888_0565_ca), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8r8g8b8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8r8g8b8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, a8b8g8r8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, x8b8g8r8, mips_composite_over_n_8_8888), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mips_composite_over_n_8_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, a8, b5g6r5, mips_composite_over_n_8_0565), + + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8888), + + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_0565), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_0565), + + SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_0565), + + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8888), + + SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8888), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mips_8888_8_8888), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, a8r8g8b8, r5g6b5, mips_8888_8_0565), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, x8r8g8b8, r5g6b5, mips_8888_8_0565), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, x8r8g8b8, mips_0565_8_x888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (SRC, r5g6b5, r5g6b5, mips_0565_8_0565), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mips_8888_8_8888), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, a8r8g8b8, mips_8888_8_8888), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (ADD, a8r8g8b8, x8r8g8b8, mips_8888_8_8888), + { PIXMAN_OP_NONE }, +}; + +static pixman_bool_t +mips_dspr2_blt (pixman_implementation_t *imp, + uint32_t * src_bits, + uint32_t * dst_bits, + int src_stride, + int dst_stride, + int src_bpp, + int dst_bpp, + int src_x, + int src_y, + int dest_x, + int dest_y, + int width, + int height) +{ + if (!pixman_blt_mips ( + src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, + src_x, src_y, dest_x, dest_y, width, height)) + + { + return _pixman_implementation_blt ( + imp->delegate, + src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp, + src_x, src_y, dest_x, dest_y, width, height); + } + + return TRUE; +} + +static pixman_bool_t +mips_dspr2_fill (pixman_implementation_t *imp, + uint32_t * bits, + int stride, + int bpp, + int x, + int y, + int width, + int height, + uint32_t xor) +{ + if (pixman_fill_mips (bits, stride, bpp, x, y, width, height, xor)) + return TRUE; + + return _pixman_implementation_fill ( + imp->delegate, bits, stride, bpp, x, y, width, height, xor); +} + +pixman_implementation_t * +_pixman_implementation_create_mips_dspr2 (pixman_implementation_t *fallback) +{ + pixman_implementation_t *imp = + _pixman_implementation_create (fallback, mips_dspr2_fast_paths); + + imp->blt = mips_dspr2_blt; + imp->fill = mips_dspr2_fill; + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-mips-dspr2.h b/gfx/cairo/libpixman/src/pixman-mips-dspr2.h new file mode 100644 index 00000000000..a3d774fcbc3 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-dspr2.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Nemanja Lukic (nlukic@mips.com) + */ + +#ifndef PIXMAN_MIPS_DSPR2_H +#define PIXMAN_MIPS_DSPR2_H + +#include "pixman-private.h" +#include "pixman-inlines.h" + +#define SKIP_ZERO_SRC 1 +#define SKIP_ZERO_MASK 2 +#define DO_FAST_MEMCPY 3 + +void +pixman_mips_fast_memcpy (void *dst, void *src, uint32_t n_bytes); +void +pixman_fill_buff16_mips (void *dst, uint32_t n_bytes, uint16_t value); +void +pixman_fill_buff32_mips (void *dst, uint32_t n_bytes, uint32_t value); + +/****************************************************************/ + +#define PIXMAN_MIPS_BIND_FAST_PATH_SRC_DST(flags, name, \ + src_type, src_cnt, \ + dst_type, dst_cnt) \ +void \ +pixman_composite_##name##_asm_mips (dst_type *dst, \ + src_type *src, \ + int32_t w); \ + \ +static void \ +mips_composite_##name (pixman_implementation_t *imp, \ + pixman_composite_info_t *info) \ +{ \ + PIXMAN_COMPOSITE_ARGS (info); \ + dst_type *dst_line, *dst; \ + src_type *src_line, *src; \ + int32_t dst_stride, src_stride; \ + int bpp = PIXMAN_FORMAT_BPP (dest_image->bits.format) / 8; \ + \ + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type, \ + src_stride, src_line, src_cnt); \ + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \ + dst_stride, dst_line, dst_cnt); \ + \ + while (height--) \ + { \ + dst = dst_line; \ + dst_line += dst_stride; \ + src = src_line; \ + src_line += src_stride; \ + \ + if (flags == DO_FAST_MEMCPY) \ + pixman_mips_fast_memcpy (dst, src, width * bpp); \ + else \ + pixman_composite_##name##_asm_mips (dst, src, width); \ + } \ +} + +/*******************************************************************/ + +#define PIXMAN_MIPS_BIND_FAST_PATH_N_MASK_DST(flags, name, \ + mask_type, mask_cnt, \ + dst_type, dst_cnt) \ +void \ +pixman_composite_##name##_asm_mips (dst_type *dst, \ + uint32_t src, \ + mask_type *mask, \ + int32_t w); \ + \ +static void \ +mips_composite_##name (pixman_implementation_t *imp, \ + pixman_composite_info_t *info) \ +{ \ + PIXMAN_COMPOSITE_ARGS (info); \ + dst_type *dst_line, *dst; \ + mask_type *mask_line, *mask; \ + int32_t dst_stride, mask_stride; \ + uint32_t src; \ + \ + src = _pixman_image_get_solid ( \ + imp, src_image, dest_image->bits.format); \ + \ + if ((flags & SKIP_ZERO_SRC) && src == 0) \ + return; \ + \ + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type, \ + dst_stride, dst_line, dst_cnt); \ + PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type, \ + mask_stride, mask_line, mask_cnt); \ + \ + while (height--) \ + { \ + dst = dst_line; \ + dst_line += dst_stride; \ + mask = mask_line; \ + mask_line += mask_stride; \ + pixman_composite_##name##_asm_mips (dst, src, mask, width); \ + } \ +} + +/****************************************************************************/ + +#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_DST(flags, name, op, \ + src_type, dst_type) \ +void \ +pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips( \ + dst_type * dst, \ + const src_type * src_top, \ + const src_type * src_bottom, \ + int32_t w, \ + int wt, \ + int wb, \ + pixman_fixed_t vx, \ + pixman_fixed_t unit_x); \ +static force_inline void \ +scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \ + const uint32_t * mask, \ + const src_type * src_top, \ + const src_type * src_bottom, \ + int32_t w, \ + int wt, \ + int wb, \ + pixman_fixed_t vx, \ + pixman_fixed_t unit_x, \ + pixman_fixed_t max_vx, \ + pixman_bool_t zero_src) \ +{ \ + if ((flags & SKIP_ZERO_SRC) && zero_src) \ + return; \ + pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips (dst, src_top, \ + src_bottom, w, \ + wt, wb, \ + vx, unit_x); \ +} \ + \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, COVER, FLAG_NONE) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, NONE, FLAG_NONE) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, PAD, FLAG_NONE) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint32_t, dst_type, NORMAL, \ + FLAG_NONE) + +/*****************************************************************************/ + +#define PIXMAN_MIPS_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, name, op, \ + src_type, dst_type) \ +void \ +pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \ + dst_type * dst, \ + const uint8_t * mask, \ + const src_type * top, \ + const src_type * bottom, \ + int wt, \ + int wb, \ + pixman_fixed_t x, \ + pixman_fixed_t ux, \ + int width); \ + \ +static force_inline void \ +scaled_bilinear_scanline_mips_##name##_##op (dst_type * dst, \ + const uint8_t * mask, \ + const src_type * src_top, \ + const src_type * src_bottom, \ + int32_t w, \ + int wt, \ + int wb, \ + pixman_fixed_t vx, \ + pixman_fixed_t unit_x, \ + pixman_fixed_t max_vx, \ + pixman_bool_t zero_src) \ +{ \ + if ((flags & SKIP_ZERO_SRC) && zero_src) \ + return; \ + pixman_scaled_bilinear_scanline_##name##_##op##_asm_mips ( \ + dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \ +} \ + \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_cover_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, COVER, \ + FLAG_HAVE_NON_SOLID_MASK) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_none_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, NONE, \ + FLAG_HAVE_NON_SOLID_MASK) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_pad_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, PAD, \ + FLAG_HAVE_NON_SOLID_MASK) \ +FAST_BILINEAR_MAINLOOP_COMMON (mips_##name##_normal_##op, \ + scaled_bilinear_scanline_mips_##name##_##op, \ + src_type, uint8_t, dst_type, NORMAL, \ + FLAG_HAVE_NON_SOLID_MASK) + +#endif //PIXMAN_MIPS_DSPR2_H diff --git a/gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S b/gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S new file mode 100644 index 00000000000..9ad6da53786 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips-memcpy-asm.S @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "pixman-mips-dspr2-asm.h" + +/* + * This routine could be optimized for MIPS64. The current code only + * uses MIPS32 instructions. + */ + +#ifdef EB +# define LWHI lwl /* high part is left in big-endian */ +# define SWHI swl /* high part is left in big-endian */ +# define LWLO lwr /* low part is right in big-endian */ +# define SWLO swr /* low part is right in big-endian */ +#else +# define LWHI lwr /* high part is right in little-endian */ +# define SWHI swr /* high part is right in little-endian */ +# define LWLO lwl /* low part is left in big-endian */ +# define SWLO swl /* low part is left in big-endian */ +#endif + +LEAF_MIPS32R2(pixman_mips_fast_memcpy) + + slti AT, a2, 8 + bne AT, zero, $last8 + move v0, a0 /* memcpy returns the dst pointer */ + +/* Test if the src and dst are word-aligned, or can be made word-aligned */ + xor t8, a1, a0 + andi t8, t8, 0x3 /* t8 is a0/a1 word-displacement */ + + bne t8, zero, $unaligned + negu a3, a0 + + andi a3, a3, 0x3 /* we need to copy a3 bytes to make a0/a1 aligned */ + beq a3, zero, $chk16w /* when a3=0 then the dst (a0) is word-aligned */ + subu a2, a2, a3 /* now a2 is the remining bytes count */ + + LWHI t8, 0(a1) + addu a1, a1, a3 + SWHI t8, 0(a0) + addu a0, a0, a3 + +/* Now the dst/src are mutually word-aligned with word-aligned addresses */ +$chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */ + /* t8 is the byte count after 64-byte chunks */ + + beq a2, t8, $chk8w /* if a2==t8, no 64-byte chunks */ + /* There will be at most 1 32-byte chunk after it */ + subu a3, a2, t8 /* subtract from a2 the reminder */ + /* Here a3 counts bytes in 16w chunks */ + addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */ + + addu t0, a0, a2 /* t0 is the "past the end" address */ + +/* + * When in the loop we exercise "pref 30, x(a0)", the a0+x should not be past + * the "t0-32" address + * This means: for x=128 the last "safe" a0 address is "t0-160" + * Alternatively, for x=64 the last "safe" a0 address is "t0-96" + * In the current version we use "pref 30, 128(a0)", so "t0-160" is the limit + */ + subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */ + + pref 0, 0(a1) /* bring the first line of src, addr 0 */ + pref 0, 32(a1) /* bring the second line of src, addr 32 */ + pref 0, 64(a1) /* bring the third line of src, addr 64 */ + pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */ +/* In case the a0 > t9 don't use "pref 30" at all */ + sgtu v1, a0, t9 + bgtz v1, $loop16w /* skip "pref 30, 64(a0)" for too short arrays */ + nop +/* otherwise, start with using pref30 */ + pref 30, 64(a0) +$loop16w: + pref 0, 96(a1) + lw t0, 0(a1) + bgtz v1, $skip_pref30_96 /* skip "pref 30, 96(a0)" */ + lw t1, 4(a1) + pref 30, 96(a0) /* continue setting up the dest, addr 96 */ +$skip_pref30_96: + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + pref 0, 128(a1) /* bring the next lines of src, addr 128 */ + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + + lw t0, 32(a1) + bgtz v1, $skip_pref30_128 /* skip "pref 30, 128(a0)" */ + lw t1, 36(a1) + pref 30, 128(a0) /* continue setting up the dest, addr 128 */ +$skip_pref30_128: + lw t2, 40(a1) + lw t3, 44(a1) + lw t4, 48(a1) + lw t5, 52(a1) + lw t6, 56(a1) + lw t7, 60(a1) + pref 0, 160(a1) /* bring the next lines of src, addr 160 */ + + sw t0, 32(a0) + sw t1, 36(a0) + sw t2, 40(a0) + sw t3, 44(a0) + sw t4, 48(a0) + sw t5, 52(a0) + sw t6, 56(a0) + sw t7, 60(a0) + + addiu a0, a0, 64 /* adding 64 to dest */ + sgtu v1, a0, t9 + bne a0, a3, $loop16w + addiu a1, a1, 64 /* adding 64 to src */ + move a2, t8 + +/* Here we have src and dest word-aligned but less than 64-bytes to go */ + +$chk8w: + pref 0, 0x0(a1) + andi t8, a2, 0x1f /* is there a 32-byte chunk? */ + /* the t8 is the reminder count past 32-bytes */ + beq a2, t8, $chk1w /* when a2=t8, no 32-byte chunk */ + nop + + lw t0, 0(a1) + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a1, a1, 32 + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + addiu a0, a0, 32 + +$chk1w: + andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */ + beq a2, t8, $last8 + subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */ + addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */ + +/* copying in words (4-byte chunks) */ +$wordCopy_loop: + lw t3, 0(a1) /* the first t3 may be equal t0 ... optimize? */ + addiu a1, a1, 4 + addiu a0, a0, 4 + bne a0, a3, $wordCopy_loop + sw t3, -4(a0) + +/* For the last (<8) bytes */ +$last8: + blez a2, leave + addu a3, a0, a2 /* a3 is the last dst address */ +$last8loop: + lb v1, 0(a1) + addiu a1, a1, 1 + addiu a0, a0, 1 + bne a0, a3, $last8loop + sb v1, -1(a0) + +leave: j ra + nop + +/* + * UNALIGNED case + */ + +$unaligned: + /* got here with a3="negu a0" */ + andi a3, a3, 0x3 /* test if the a0 is word aligned */ + beqz a3, $ua_chk16w + subu a2, a2, a3 /* bytes left after initial a3 bytes */ + + LWHI v1, 0(a1) + LWLO v1, 3(a1) + addu a1, a1, a3 /* a3 may be here 1, 2 or 3 */ + SWHI v1, 0(a0) + addu a0, a0, a3 /* below the dst will be word aligned (NOTE1) */ + +$ua_chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */ + /* t8 is the byte count after 64-byte chunks */ + beq a2, t8, $ua_chk8w /* if a2==t8, no 64-byte chunks */ + /* There will be at most 1 32-byte chunk after it */ + subu a3, a2, t8 /* subtract from a2 the reminder */ + /* Here a3 counts bytes in 16w chunks */ + addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */ + + addu t0, a0, a2 /* t0 is the "past the end" address */ + + subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */ + + pref 0, 0(a1) /* bring the first line of src, addr 0 */ + pref 0, 32(a1) /* bring the second line of src, addr 32 */ + pref 0, 64(a1) /* bring the third line of src, addr 64 */ + pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */ +/* In case the a0 > t9 don't use "pref 30" at all */ + sgtu v1, a0, t9 + bgtz v1, $ua_loop16w /* skip "pref 30, 64(a0)" for too short arrays */ + nop +/* otherwise, start with using pref30 */ + pref 30, 64(a0) +$ua_loop16w: + pref 0, 96(a1) + LWHI t0, 0(a1) + LWLO t0, 3(a1) + LWHI t1, 4(a1) + bgtz v1, $ua_skip_pref30_96 + LWLO t1, 7(a1) + pref 30, 96(a0) /* continue setting up the dest, addr 96 */ +$ua_skip_pref30_96: + LWHI t2, 8(a1) + LWLO t2, 11(a1) + LWHI t3, 12(a1) + LWLO t3, 15(a1) + LWHI t4, 16(a1) + LWLO t4, 19(a1) + LWHI t5, 20(a1) + LWLO t5, 23(a1) + LWHI t6, 24(a1) + LWLO t6, 27(a1) + LWHI t7, 28(a1) + LWLO t7, 31(a1) + pref 0, 128(a1) /* bring the next lines of src, addr 128 */ + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + + LWHI t0, 32(a1) + LWLO t0, 35(a1) + LWHI t1, 36(a1) + bgtz v1, $ua_skip_pref30_128 + LWLO t1, 39(a1) + pref 30, 128(a0) /* continue setting up the dest, addr 128 */ +$ua_skip_pref30_128: + LWHI t2, 40(a1) + LWLO t2, 43(a1) + LWHI t3, 44(a1) + LWLO t3, 47(a1) + LWHI t4, 48(a1) + LWLO t4, 51(a1) + LWHI t5, 52(a1) + LWLO t5, 55(a1) + LWHI t6, 56(a1) + LWLO t6, 59(a1) + LWHI t7, 60(a1) + LWLO t7, 63(a1) + pref 0, 160(a1) /* bring the next lines of src, addr 160 */ + + sw t0, 32(a0) + sw t1, 36(a0) + sw t2, 40(a0) + sw t3, 44(a0) + sw t4, 48(a0) + sw t5, 52(a0) + sw t6, 56(a0) + sw t7, 60(a0) + + addiu a0, a0, 64 /* adding 64 to dest */ + sgtu v1, a0, t9 + bne a0, a3, $ua_loop16w + addiu a1, a1, 64 /* adding 64 to src */ + move a2, t8 + +/* Here we have src and dest word-aligned but less than 64-bytes to go */ + +$ua_chk8w: + pref 0, 0x0(a1) + andi t8, a2, 0x1f /* is there a 32-byte chunk? */ + /* the t8 is the reminder count */ + beq a2, t8, $ua_chk1w /* when a2=t8, no 32-byte chunk */ + + LWHI t0, 0(a1) + LWLO t0, 3(a1) + LWHI t1, 4(a1) + LWLO t1, 7(a1) + LWHI t2, 8(a1) + LWLO t2, 11(a1) + LWHI t3, 12(a1) + LWLO t3, 15(a1) + LWHI t4, 16(a1) + LWLO t4, 19(a1) + LWHI t5, 20(a1) + LWLO t5, 23(a1) + LWHI t6, 24(a1) + LWLO t6, 27(a1) + LWHI t7, 28(a1) + LWLO t7, 31(a1) + addiu a1, a1, 32 + + sw t0, 0(a0) + sw t1, 4(a0) + sw t2, 8(a0) + sw t3, 12(a0) + sw t4, 16(a0) + sw t5, 20(a0) + sw t6, 24(a0) + sw t7, 28(a0) + addiu a0, a0, 32 + +$ua_chk1w: + andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */ + beq a2, t8, $ua_smallCopy + subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */ + addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */ + +/* copying in words (4-byte chunks) */ +$ua_wordCopy_loop: + LWHI v1, 0(a1) + LWLO v1, 3(a1) + addiu a1, a1, 4 + addiu a0, a0, 4 /* note: dst=a0 is word aligned here, see NOTE1 */ + bne a0, a3, $ua_wordCopy_loop + sw v1, -4(a0) + +/* Now less than 4 bytes (value in a2) left to copy */ +$ua_smallCopy: + beqz a2, leave + addu a3, a0, a2 /* a3 is the last dst address */ +$ua_smallCopy_loop: + lb v1, 0(a1) + addiu a1, a1, 1 + addiu a0, a0, 1 + bne a0, a3, $ua_smallCopy_loop + sb v1, -1(a0) + + j ra + nop + +END(pixman_mips_fast_memcpy) diff --git a/gfx/cairo/libpixman/src/pixman-mips.c b/gfx/cairo/libpixman/src/pixman-mips.c new file mode 100644 index 00000000000..2b280c6f164 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-mips.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +#if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI) + +#include +#include + +static pixman_bool_t +have_feature (const char *search_string) +{ +#if defined (__linux__) /* linux ELF */ + /* Simple detection of MIPS features at runtime for Linux. + * It is based on /proc/cpuinfo, which reveals hardware configuration + * to user-space applications. According to MIPS (early 2010), no similar + * facility is universally available on the MIPS architectures, so it's up + * to individual OSes to provide such. + */ + const char *file_name = "/proc/cpuinfo"; + char cpuinfo_line[256]; + FILE *f = NULL; + + if ((f = fopen (file_name, "r")) == NULL) + return FALSE; + + while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL) + { + if (strstr (cpuinfo_line, search_string) != NULL) + { + fclose (f); + return TRUE; + } + } + + fclose (f); +#endif + + /* Did not find string in the proc file, or not Linux ELF. */ + return FALSE; +} + +#endif + +pixman_implementation_t * +_pixman_mips_get_implementations (pixman_implementation_t *imp) +{ +#ifdef USE_LOONGSON_MMI + /* I really don't know if some Loongson CPUs don't have MMI. */ + if (!_pixman_disabled ("loongson-mmi") && have_feature ("Loongson")) + imp = _pixman_implementation_create_mmx (imp); +#endif + +#ifdef USE_MIPS_DSPR2 + /* Only currently available MIPS core that supports DSPr2 is 74K. */ + if (!_pixman_disabled ("mips-dspr2") && have_feature ("MIPS 74K")) + imp = _pixman_implementation_create_mips_dspr2 (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-mmx.c b/gfx/cairo/libpixman/src/pixman-mmx.c index 9fd1a76f920..74a5e87a8f4 100644 --- a/gfx/cairo/libpixman/src/pixman-mmx.c +++ b/gfx/cairo/libpixman/src/pixman-mmx.c @@ -33,11 +33,16 @@ #include #endif -#if defined USE_X86_MMX || defined USE_ARM_IWMMXT +#if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI +#ifdef USE_LOONGSON_MMI +#include +#else #include +#endif #include "pixman-private.h" #include "pixman-combine32.h" +#include "pixman-inlines.h" #define no_vERBOSE @@ -63,6 +68,19 @@ _mm_empty (void) /* We have to compile with -msse to use xmmintrin.h, but that causes SSE * instructions to be generated that we don't want. Just duplicate the * functions we want to use. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movemask_pi8 (__m64 __A) +{ + int ret; + + asm ("pmovmskb %1, %0\n\t" + : "=r" (ret) + : "y" (__A) + ); + + return ret; +} + extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_mulhi_pu16 (__m64 __A, __m64 __B) { @@ -87,8 +105,17 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) return ret; } # else -# define _mm_shuffle_pi16(A, N) \ - ((__m64) __builtin_ia32_pshufw ((__v4hi)(__m64)(A), (int)(N))) +# define _mm_shuffle_pi16(A, N) \ + ({ \ + __m64 ret; \ + \ + asm ("pshufw %2, %1, %0\n\t" \ + : "=y" (ret) \ + : "y" (A), "K" ((const int8_t)N) \ + ); \ + \ + ret; \ + }) # endif # endif #endif @@ -125,11 +152,14 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) * uint64_t and __m64 values, then define USE_CVT_INTRINSICS. * If __m64 and uint64_t values can just be cast to each other directly, * then define USE_M64_CASTS. + * If __m64 is a double datatype, then define USE_M64_DOUBLE. */ #ifdef _MSC_VER # define M64_MEMBER m64_u64 #elif defined(__ICC) # define USE_CVT_INTRINSICS +#elif defined(USE_LOONGSON_MMI) +# define USE_M64_DOUBLE #elif defined(__GNUC__) # define USE_M64_CASTS #elif defined(__SUNPRO_C) @@ -147,7 +177,7 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) # endif #endif -#if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) +#if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) || defined(USE_M64_DOUBLE) typedef uint64_t mmxdatafield; #else typedef __m64 mmxdatafield; @@ -159,15 +189,24 @@ typedef struct mmxdatafield mmx_4x0080; mmxdatafield mmx_565_rgb; mmxdatafield mmx_565_unpack_multiplier; + mmxdatafield mmx_565_pack_multiplier; mmxdatafield mmx_565_r; mmxdatafield mmx_565_g; mmxdatafield mmx_565_b; + mmxdatafield mmx_packed_565_rb; + mmxdatafield mmx_packed_565_g; + mmxdatafield mmx_expand_565_g; + mmxdatafield mmx_expand_565_b; + mmxdatafield mmx_expand_565_r; +#ifndef USE_LOONGSON_MMI mmxdatafield mmx_mask_0; mmxdatafield mmx_mask_1; mmxdatafield mmx_mask_2; mmxdatafield mmx_mask_3; +#endif mmxdatafield mmx_full_alpha; mmxdatafield mmx_4x0101; + mmxdatafield mmx_ff000000; } mmx_data_t; #if defined(_MSC_VER) @@ -184,21 +223,32 @@ static const mmx_data_t c = MMXDATA_INIT (.mmx_4x0080, 0x0080008000800080), MMXDATA_INIT (.mmx_565_rgb, 0x000001f0003f001f), MMXDATA_INIT (.mmx_565_unpack_multiplier, 0x0000008404100840), + MMXDATA_INIT (.mmx_565_pack_multiplier, 0x2000000420000004), MMXDATA_INIT (.mmx_565_r, 0x000000f800000000), MMXDATA_INIT (.mmx_565_g, 0x0000000000fc0000), MMXDATA_INIT (.mmx_565_b, 0x00000000000000f8), + MMXDATA_INIT (.mmx_packed_565_rb, 0x00f800f800f800f8), + MMXDATA_INIT (.mmx_packed_565_g, 0x0000fc000000fc00), + MMXDATA_INIT (.mmx_expand_565_g, 0x07e007e007e007e0), + MMXDATA_INIT (.mmx_expand_565_b, 0x001f001f001f001f), + MMXDATA_INIT (.mmx_expand_565_r, 0xf800f800f800f800), +#ifndef USE_LOONGSON_MMI MMXDATA_INIT (.mmx_mask_0, 0xffffffffffff0000), MMXDATA_INIT (.mmx_mask_1, 0xffffffff0000ffff), MMXDATA_INIT (.mmx_mask_2, 0xffff0000ffffffff), MMXDATA_INIT (.mmx_mask_3, 0x0000ffffffffffff), +#endif MMXDATA_INIT (.mmx_full_alpha, 0x00ff000000000000), MMXDATA_INIT (.mmx_4x0101, 0x0101010101010101), + MMXDATA_INIT (.mmx_ff000000, 0xff000000ff000000), }; #ifdef USE_CVT_INTRINSICS # define MC(x) to_m64 (c.mmx_ ## x) #elif defined(USE_M64_CASTS) # define MC(x) ((__m64)c.mmx_ ## x) +#elif defined(USE_M64_DOUBLE) +# define MC(x) (*(__m64 *)&c.mmx_ ## x) #else # define MC(x) c.mmx_ ## x #endif @@ -213,6 +263,8 @@ to_m64 (uint64_t x) res.M64_MEMBER = x; return res; +#elif defined USE_M64_DOUBLE + return *(__m64 *)&x; #else /* USE_M64_CASTS */ return (__m64)x; #endif @@ -226,6 +278,8 @@ to_uint64 (__m64 x) #elif defined M64_MEMBER /* __m64 is a struct, not an integral type */ uint64_t res = x.M64_MEMBER; return res; +#elif defined USE_M64_DOUBLE + return *(uint64_t *)&x; #else /* USE_M64_CASTS */ return (uint64_t)x; #endif @@ -324,7 +378,7 @@ in_over (__m64 src, __m64 srca, __m64 mask, __m64 dest) /* Elemental unaligned loads */ -static force_inline __m64 ldq_u(uint64_t *p) +static force_inline __m64 ldq_u(__m64 *p) { #ifdef USE_X86_MMX /* x86's alignment restrictions are very relaxed. */ @@ -337,7 +391,7 @@ static force_inline __m64 ldq_u(uint64_t *p) aligned_p = (__m64 *)((uintptr_t)p & ~7); return (__m64) _mm_align_si64 (aligned_p[0], aligned_p[1], align); #else - struct __una_u64 { uint64_t x __attribute__((packed)); }; + struct __una_u64 { __m64 x __attribute__((packed)); }; const struct __una_u64 *ptr = (const struct __una_u64 *) p; return (__m64) ptr->x; #endif @@ -355,17 +409,36 @@ static force_inline uint32_t ldl_u(const uint32_t *p) #endif } +static force_inline __m64 +load (const uint32_t *v) +{ +#ifdef USE_LOONGSON_MMI + __m64 ret; + asm ("lwc1 %0, %1\n\t" + : "=f" (ret) + : "m" (*v) + ); + return ret; +#else + return _mm_cvtsi32_si64 (*v); +#endif +} + static force_inline __m64 load8888 (const uint32_t *v) { - return _mm_unpacklo_pi8 (_mm_cvtsi32_si64 (*v), _mm_setzero_si64 ()); +#ifdef USE_LOONGSON_MMI + return _mm_unpacklo_pi8_f (*(__m32 *)v, _mm_setzero_si64 ()); +#else + return _mm_unpacklo_pi8 (load (v), _mm_setzero_si64 ()); +#endif } static force_inline __m64 load8888u (const uint32_t *v) { - uint32_t l = ldl_u(v); - return load8888(&l); + uint32_t l = ldl_u (v); + return load8888 (&l); } static force_inline __m64 @@ -374,11 +447,53 @@ pack8888 (__m64 lo, __m64 hi) return _mm_packs_pu16 (lo, hi); } +static force_inline void +store (uint32_t *dest, __m64 v) +{ +#ifdef USE_LOONGSON_MMI + asm ("swc1 %1, %0\n\t" + : "=m" (*dest) + : "f" (v) + : "memory" + ); +#else + *dest = _mm_cvtsi64_si32 (v); +#endif +} + static force_inline void store8888 (uint32_t *dest, __m64 v) { - v = pack8888 (v, _mm_setzero_si64()); - *dest = _mm_cvtsi64_si32 (v); + v = pack8888 (v, _mm_setzero_si64 ()); + store (dest, v); +} + +static force_inline pixman_bool_t +is_equal (__m64 a, __m64 b) +{ +#ifdef USE_LOONGSON_MMI + /* __m64 is double, we can compare directly. */ + return a == b; +#else + return _mm_movemask_pi8 (_mm_cmpeq_pi8 (a, b)) == 0xff; +#endif +} + +static force_inline pixman_bool_t +is_opaque (__m64 v) +{ +#ifdef USE_LOONGSON_MMI + return is_equal (_mm_and_si64 (v, MC (full_alpha)), MC (full_alpha)); +#else + __m64 ffs = _mm_cmpeq_pi8 (v, v); + return (_mm_movemask_pi8 (_mm_cmpeq_pi8 (v, ffs)) & 0x40); +#endif +} + +static force_inline pixman_bool_t +is_zero (__m64 v) +{ + return is_equal (v, _mm_setzero_si64 ()); } /* Expand 16 bits positioned at @pos (0-3) of a mmx register into @@ -402,7 +517,11 @@ expand565 (__m64 pixel, int pos) __m64 t1, t2; /* move pixel to low 16 bit and zero the rest */ +#ifdef USE_LOONGSON_MMI + p = loongson_extract_pi16 (p, pos); +#else p = shift (shift (p, (3 - pos) * 16), -48); +#endif t1 = shift (p, 36 - 11); t2 = shift (p, 16 - 5); @@ -415,6 +534,36 @@ expand565 (__m64 pixel, int pos) return _mm_srli_pi16 (pixel, 8); } +/* Expand 4 16 bit pixels in an mmx register into two mmx registers of + * + * AARRGGBBRRGGBB + */ +static force_inline void +expand_4xpacked565 (__m64 vin, __m64 *vout0, __m64 *vout1, int full_alpha) +{ + __m64 t0, t1, alpha = _mm_setzero_si64 ();; + __m64 r = _mm_and_si64 (vin, MC (expand_565_r)); + __m64 g = _mm_and_si64 (vin, MC (expand_565_g)); + __m64 b = _mm_and_si64 (vin, MC (expand_565_b)); + if (full_alpha) + alpha = _mm_cmpeq_pi32 (alpha, alpha); + + /* Replicate high bits into empty low bits. */ + r = _mm_or_si64 (_mm_srli_pi16 (r, 8), _mm_srli_pi16 (r, 13)); + g = _mm_or_si64 (_mm_srli_pi16 (g, 3), _mm_srli_pi16 (g, 9)); + b = _mm_or_si64 (_mm_slli_pi16 (b, 3), _mm_srli_pi16 (b, 2)); + + r = _mm_packs_pu16 (r, _mm_setzero_si64 ()); /* 00 00 00 00 R3 R2 R1 R0 */ + g = _mm_packs_pu16 (g, _mm_setzero_si64 ()); /* 00 00 00 00 G3 G2 G1 G0 */ + b = _mm_packs_pu16 (b, _mm_setzero_si64 ()); /* 00 00 00 00 B3 B2 B1 B0 */ + + t1 = _mm_unpacklo_pi8 (r, alpha); /* A3 R3 A2 R2 A1 R1 A0 R0 */ + t0 = _mm_unpacklo_pi8 (b, g); /* G3 B3 G2 B2 G1 B1 G0 B0 */ + + *vout0 = _mm_unpacklo_pi16 (t0, t1); /* A1 R1 G1 B1 A0 R0 G0 B0 */ + *vout1 = _mm_unpackhi_pi16 (t0, t1); /* A3 R3 G3 B3 A2 R2 G2 B2 */ +} + static force_inline __m64 expand8888 (__m64 in, int pos) { @@ -430,6 +579,17 @@ expandx888 (__m64 in, int pos) return _mm_or_si64 (expand8888 (in, pos), MC (full_alpha)); } +static force_inline void +expand_4x565 (__m64 vin, __m64 *vout0, __m64 *vout1, __m64 *vout2, __m64 *vout3, int full_alpha) +{ + __m64 v0, v1; + expand_4xpacked565 (vin, &v0, &v1, full_alpha); + *vout0 = expand8888 (v0, 0); + *vout1 = expand8888 (v0, 1); + *vout2 = expand8888 (v1, 0); + *vout3 = expand8888 (v1, 1); +} + static force_inline __m64 pack_565 (__m64 pixel, __m64 target, int pos) { @@ -441,6 +601,15 @@ pack_565 (__m64 pixel, __m64 target, int pos) g = _mm_and_si64 (p, MC (565_g)); b = _mm_and_si64 (p, MC (565_b)); +#ifdef USE_LOONGSON_MMI + r = shift (r, -(32 - 8)); + g = shift (g, -(16 - 3)); + b = shift (b, -(0 + 3)); + + p = _mm_or_si64 (r, g); + p = _mm_or_si64 (p, b); + return loongson_insert_pi16 (t, p, pos); +#else r = shift (r, -(32 - 8) + pos * 16); g = shift (g, -(16 - 3) + pos * 16); b = shift (b, -(0 + 3) + pos * 16); @@ -458,10 +627,42 @@ pack_565 (__m64 pixel, __m64 target, int pos) p = _mm_or_si64 (g, p); return _mm_or_si64 (b, p); +#endif +} + +static force_inline __m64 +pack_4xpacked565 (__m64 a, __m64 b) +{ + __m64 rb0 = _mm_and_si64 (a, MC (packed_565_rb)); + __m64 rb1 = _mm_and_si64 (b, MC (packed_565_rb)); + + __m64 t0 = _mm_madd_pi16 (rb0, MC (565_pack_multiplier)); + __m64 t1 = _mm_madd_pi16 (rb1, MC (565_pack_multiplier)); + + __m64 g0 = _mm_and_si64 (a, MC (packed_565_g)); + __m64 g1 = _mm_and_si64 (b, MC (packed_565_g)); + + t0 = _mm_or_si64 (t0, g0); + t1 = _mm_or_si64 (t1, g1); + + t0 = shift(t0, -5); +#ifdef USE_ARM_IWMMXT + t1 = shift(t1, -5); + return _mm_packs_pu32 (t0, t1); +#else + t1 = shift(t1, -5 + 16); + return _mm_shuffle_pi16 (_mm_or_si64 (t0, t1), _MM_SHUFFLE (3, 1, 2, 0)); +#endif } #ifndef _MSC_VER +static force_inline __m64 +pack_4x565 (__m64 v0, __m64 v1, __m64 v2, __m64 v3) +{ + return pack_4xpacked565 (pack8888 (v0, v1), pack8888 (v2, v3)); +} + static force_inline __m64 pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b) { @@ -473,6 +674,11 @@ pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b) #else +/* MSVC only handles a "pass by register" of up to three SSE intrinsics */ + +#define pack_4x565(v0, v1, v2, v3) \ + pack_4xpacked565 (pack8888 (v0, v1), pack8888 (v2, v3)) + #define pix_add_mul(x, a, y, b) \ ( x = pix_multiply (x, a), \ y = pix_multiply (y, b), \ @@ -482,23 +688,38 @@ pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b) /* --------------- MMX code patch for fbcompose.c --------------------- */ -static force_inline uint32_t +static force_inline __m64 combine (const uint32_t *src, const uint32_t *mask) { - uint32_t ssrc = *src; + __m64 vsrc = load8888 (src); if (mask) { __m64 m = load8888 (mask); - __m64 s = load8888 (&ssrc); m = expand_alpha (m); - s = pix_multiply (s, m); - - store8888 (&ssrc, s); + vsrc = pix_multiply (vsrc, m); } - return ssrc; + return vsrc; +} + +static force_inline __m64 +core_combine_over_u_pixel_mmx (__m64 vsrc, __m64 vdst) +{ + vsrc = _mm_unpacklo_pi8 (vsrc, _mm_setzero_si64 ()); + + if (is_opaque (vsrc)) + { + return vsrc; + } + else if (!is_zero (vsrc)) + { + return over (vsrc, expand_alpha (vsrc), + _mm_unpacklo_pi8 (vdst, _mm_setzero_si64 ())); + } + + return _mm_unpacklo_pi8 (vdst, _mm_setzero_si64 ()); } static void @@ -513,19 +734,16 @@ mmx_combine_over_u (pixman_implementation_t *imp, while (dest < end) { - uint32_t ssrc = combine (src, mask); - uint32_t a = ssrc >> 24; + __m64 vsrc = combine (src, mask); - if (a == 0xff) + if (is_opaque (vsrc)) { - *dest = ssrc; + store8888 (dest, vsrc); } - else if (ssrc) + else if (!is_zero (vsrc)) { - __m64 s, sa; - s = load8888 (&ssrc); - sa = expand_alpha (s); - store8888 (dest, over (s, sa, load8888 (dest))); + __m64 sa = expand_alpha (vsrc); + store8888 (dest, over (vsrc, sa, load8888 (dest))); } ++dest; @@ -549,11 +767,11 @@ mmx_combine_over_reverse_u (pixman_implementation_t *imp, while (dest < end) { __m64 d, da; - uint32_t s = combine (src, mask); + __m64 s = combine (src, mask); d = load8888 (dest); da = expand_alpha (d); - store8888 (dest, over (d, da, load8888 (&s))); + store8888 (dest, over (d, da, s)); ++dest; ++src; @@ -575,10 +793,9 @@ mmx_combine_in_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a; + __m64 x = combine (src, mask); - x = load8888 (&ssrc); a = load8888 (dest); a = expand_alpha (a); x = pix_multiply (x, a); @@ -605,11 +822,10 @@ mmx_combine_in_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a = combine (src, mask); + __m64 x; x = load8888 (dest); - a = load8888 (&ssrc); a = expand_alpha (a); x = pix_multiply (x, a); store8888 (dest, x); @@ -634,10 +850,9 @@ mmx_combine_out_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a; + __m64 x = combine (src, mask); - x = load8888 (&ssrc); a = load8888 (dest); a = expand_alpha (a); a = negate (a); @@ -664,11 +879,10 @@ mmx_combine_out_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a = combine (src, mask); + __m64 x; x = load8888 (dest); - a = load8888 (&ssrc); a = expand_alpha (a); a = negate (a); x = pix_multiply (x, a); @@ -695,10 +909,9 @@ mmx_combine_atop_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, da, d, sia; - uint32_t ssrc = combine (src, mask); + __m64 da, d, sia; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sia = expand_alpha (s); sia = negate (sia); @@ -728,10 +941,9 @@ mmx_combine_atop_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, dia, d, sa; - uint32_t ssrc = combine (src, mask); + __m64 dia, d, sa; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sa = expand_alpha (s); dia = expand_alpha (d); @@ -759,10 +971,9 @@ mmx_combine_xor_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, dia, d, sia; - uint32_t ssrc = combine (src, mask); + __m64 dia, d, sia; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sia = expand_alpha (s); dia = expand_alpha (d); @@ -791,10 +1002,9 @@ mmx_combine_add_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, d; - uint32_t ssrc = combine (src, mask); + __m64 d; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); s = pix_add (s, d); store8888 (dest, s); @@ -819,12 +1029,14 @@ mmx_combine_saturate_u (pixman_implementation_t *imp, while (dest < end) { - uint32_t s = combine (src, mask); + uint32_t s, sa, da; uint32_t d = *dest; - __m64 ms = load8888 (&s); - __m64 md = load8888 (&d); - uint32_t sa = s >> 24; - uint32_t da = ~d >> 24; + __m64 ms = combine (src, mask); + __m64 md = load8888 (dest); + + store8888(&s, ms); + da = ~d >> 24; + sa = s >> 24; if (sa > da) { @@ -1270,16 +1482,17 @@ mmx_composite_over_n_0565 (pixman_implementation_t *imp, while (w >= 4) { - __m64 vdest; + __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vdest = *(__m64 *)dst; + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 3)), vdest, 3); + v0 = over (vsrc, vsrca, v0); + v1 = over (vsrc, vsrca, v1); + v2 = over (vsrc, vsrca, v2); + v3 = over (vsrc, vsrca, v3); - *(__m64 *)dst = vdest; + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); dst += 4; w -= 4; @@ -1414,9 +1627,7 @@ mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp, PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format); - mask &= 0xff000000; - mask = mask | mask >> 8 | mask >> 16 | mask >> 24; - vmask = load8888 (&mask); + vmask = expand_alpha (load8888 (&mask)); while (height--) { @@ -1440,7 +1651,7 @@ mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp, while (w >= 2) { - __m64 vs = ldq_u((uint64_t *)src); + __m64 vs = ldq_u ((__m64 *)src); __m64 vd = *(__m64 *)dst; __m64 vsrc0 = expand8888 (vs, 0); __m64 vsrc1 = expand8888 (vs, 1); @@ -1485,9 +1696,7 @@ mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp, PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format); - mask &= 0xff000000; - mask = mask | mask >> 8 | mask >> 16 | mask >> 24; - vmask = load8888 (&mask); + vmask = expand_alpha (load8888 (&mask)); srca = MC (4x00ff); while (height--) @@ -1522,14 +1731,14 @@ mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp, __m64 vd6 = *(__m64 *)(dst + 12); __m64 vd7 = *(__m64 *)(dst + 14); - __m64 vs0 = ldq_u((uint64_t *)(src + 0)); - __m64 vs1 = ldq_u((uint64_t *)(src + 2)); - __m64 vs2 = ldq_u((uint64_t *)(src + 4)); - __m64 vs3 = ldq_u((uint64_t *)(src + 6)); - __m64 vs4 = ldq_u((uint64_t *)(src + 8)); - __m64 vs5 = ldq_u((uint64_t *)(src + 10)); - __m64 vs6 = ldq_u((uint64_t *)(src + 12)); - __m64 vs7 = ldq_u((uint64_t *)(src + 14)); + __m64 vs0 = ldq_u ((__m64 *)(src + 0)); + __m64 vs1 = ldq_u ((__m64 *)(src + 2)); + __m64 vs2 = ldq_u ((__m64 *)(src + 4)); + __m64 vs3 = ldq_u ((__m64 *)(src + 6)); + __m64 vs4 = ldq_u ((__m64 *)(src + 8)); + __m64 vs5 = ldq_u ((__m64 *)(src + 10)); + __m64 vs6 = ldq_u ((__m64 *)(src + 12)); + __m64 vs7 = ldq_u ((__m64 *)(src + 14)); vd0 = pack8888 ( in_over (expandx888 (vs0, 0), srca, vmask, expand8888 (vd0, 0)), @@ -1692,22 +1901,22 @@ mmx_composite_over_8888_0565 (pixman_implementation_t *imp, while (w >= 4) { - __m64 vsrc0, vsrc1, vsrc2, vsrc3; - __m64 vdest; + __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vsrc0 = load8888 ((src + 0)); - vsrc1 = load8888 ((src + 1)); - vsrc2 = load8888 ((src + 2)); - vsrc3 = load8888 ((src + 3)); + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - vdest = *(__m64 *)dst; + __m64 vsrc0 = load8888 ((src + 0)); + __m64 vsrc1 = load8888 ((src + 1)); + __m64 vsrc2 = load8888 ((src + 2)); + __m64 vsrc3 = load8888 ((src + 3)); - vdest = pack_565 (over (vsrc0, expand_alpha (vsrc0), expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (over (vsrc1, expand_alpha (vsrc1), expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (over (vsrc2, expand_alpha (vsrc2), expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (over (vsrc3, expand_alpha (vsrc3), expand565 (vdest, 3)), vdest, 3); + v0 = over (vsrc0, expand_alpha (vsrc0), v0); + v1 = over (vsrc1, expand_alpha (vsrc1), v1); + v2 = over (vsrc2, expand_alpha (vsrc2), v2); + v3 = over (vsrc3, expand_alpha (vsrc3), v3); - *(__m64 *)dst = vdest; + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); w -= 4; dst += 4; @@ -1995,6 +2204,62 @@ pixman_fill_mmx (uint32_t *bits, return TRUE; } +static void +mmx_composite_src_x888_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t *src_line, *src, s; + int dst_stride, src_stride; + int32_t w; + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w && (unsigned long)dst & 7) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + + while (w >= 4) + { + __m64 vdest; + __m64 vsrc0 = ldq_u ((__m64 *)(src + 0)); + __m64 vsrc1 = ldq_u ((__m64 *)(src + 2)); + + vdest = pack_4xpacked565 (vsrc0, vsrc1); + + *(__m64 *)dst = vdest; + + w -= 4; + src += 4; + dst += 4; + } + + while (w) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + } + + _mm_empty (); +} + static void mmx_composite_src_n_8_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) @@ -2123,7 +2388,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, int dst_stride, mask_stride; int32_t w; __m64 vsrc, vsrca, tmp; - uint64_t srcsrcsrcsrc, src16; + __m64 srcsrcsrcsrc; CHECKPOINT (); @@ -2140,11 +2405,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, vsrca = expand_alpha (vsrc); tmp = pack_565 (vsrc, _mm_setzero_si64 (), 0); - src16 = to_uint64 (tmp); - - srcsrcsrcsrc = - (uint64_t)src16 << 48 | (uint64_t)src16 << 32 | - (uint64_t)src16 << 16 | (uint64_t)src16; + srcsrcsrcsrc = expand_alpha_rev (tmp); while (height--) { @@ -2188,29 +2449,28 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff) { - *(uint64_t *)dst = srcsrcsrcsrc; + *(__m64 *)dst = srcsrcsrcsrc; } else if (m0 | m1 | m2 | m3) { - __m64 vdest; - __m64 vm0, vm1, vm2, vm3; + __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vdest = *(__m64 *)dst; + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - vm0 = to_m64 (m0); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm0), - expand565 (vdest, 0)), vdest, 0); - vm1 = to_m64 (m1); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm1), - expand565 (vdest, 1)), vdest, 1); - vm2 = to_m64 (m2); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm2), - expand565 (vdest, 2)), vdest, 2); - vm3 = to_m64 (m3); - vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm3), - expand565 (vdest, 3)), vdest, 3); + __m64 vm0 = to_m64 (m0); + v0 = in_over (vsrc, vsrca, expand_alpha_rev (vm0), v0); - *(__m64 *)dst = vdest; + __m64 vm1 = to_m64 (m1); + v1 = in_over (vsrc, vsrca, expand_alpha_rev (vm1), v1); + + __m64 vm2 = to_m64 (m2); + v2 = in_over (vsrc, vsrca, expand_alpha_rev (vm2), v2); + + __m64 vm3 = to_m64 (m3); + v3 = in_over (vsrc, vsrca, expand_alpha_rev (vm3), v3); + + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3);; } w -= 4; @@ -2307,24 +2567,31 @@ mmx_composite_over_pixbuf_0565 (pixman_implementation_t *imp, if ((a0 & a1 & a2 & a3) == 0xFF) { - __m64 vdest; - vdest = pack_565 (invert_colors (load8888 (&s0)), _mm_setzero_si64 (), 0); - vdest = pack_565 (invert_colors (load8888 (&s1)), vdest, 1); - vdest = pack_565 (invert_colors (load8888 (&s2)), vdest, 2); - vdest = pack_565 (invert_colors (load8888 (&s3)), vdest, 3); + __m64 v0 = invert_colors (load8888 (&s0)); + __m64 v1 = invert_colors (load8888 (&s1)); + __m64 v2 = invert_colors (load8888 (&s2)); + __m64 v3 = invert_colors (load8888 (&s3)); - *(__m64 *)dst = vdest; + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); } else if (s0 | s1 | s2 | s3) { __m64 vdest = *(__m64 *)dst; + __m64 v0, v1, v2, v3; - vdest = pack_565 (over_rev_non_pre (load8888 (&s0), expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (over_rev_non_pre (load8888 (&s1), expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (over_rev_non_pre (load8888 (&s2), expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (over_rev_non_pre (load8888 (&s3), expand565 (vdest, 3)), vdest, 3); + __m64 vsrc0 = load8888 (&s0); + __m64 vsrc1 = load8888 (&s1); + __m64 vsrc2 = load8888 (&s2); + __m64 vsrc3 = load8888 (&s3); - *(__m64 *)dst = vdest; + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); + + v0 = over_rev_non_pre (vsrc0, v0); + v1 = over_rev_non_pre (vsrc1, v1); + v2 = over_rev_non_pre (vsrc2, v2); + v3 = over_rev_non_pre (vsrc3, v3); + + *(__m64 *)dst = pack_4x565 (v0, v1, v2, v3); } w -= 4; @@ -2498,13 +2765,16 @@ mmx_composite_over_n_8888_0565_ca (pixman_implementation_t *imp, if ((m0 | m1 | m2 | m3)) { __m64 vdest = *(__m64 *)q; + __m64 v0, v1, v2, v3; - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m0), expand565 (vdest, 0)), vdest, 0); - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m1), expand565 (vdest, 1)), vdest, 1); - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m2), expand565 (vdest, 2)), vdest, 2); - vdest = pack_565 (in_over (vsrc, vsrca, load8888 (&m3), expand565 (vdest, 3)), vdest, 3); + expand_4x565 (vdest, &v0, &v1, &v2, &v3, 0); - *(__m64 *)q = vdest; + v0 = in_over (vsrc, vsrca, load8888 (&m0), v0); + v1 = in_over (vsrc, vsrca, load8888 (&m1), v1); + v2 = in_over (vsrc, vsrca, load8888 (&m2), v2); + v3 = in_over (vsrc, vsrca, load8888 (&m3), v3); + + *(__m64 *)q = pack_4x565 (v0, v1, v2, v3); } twidth -= 4; p += 4; @@ -2809,7 +3079,7 @@ mmx_composite_add_8_8 (pixman_implementation_t *imp, while (w >= 8) { - *(__m64*)dst = _mm_adds_pu8 (ldq_u((uint64_t *)src), *(__m64*)dst); + *(__m64*)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst); dst += 8; src += 8; w -= 8; @@ -2832,12 +3102,95 @@ mmx_composite_add_8_8 (pixman_implementation_t *imp, _mm_empty (); } +static void +mmx_composite_add_0565_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t d; + uint16_t *src_line, *src; + uint32_t s; + int dst_stride, src_stride; + int32_t w; + + CHECKPOINT (); + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint16_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w && (unsigned long)dst & 7) + { + s = *src++; + if (s) + { + d = *dst; + s = CONVERT_0565_TO_8888 (s); + if (d) + { + d = CONVERT_0565_TO_8888 (d); + UN8x4_ADD_UN8x4 (s, d); + } + *dst = CONVERT_8888_TO_0565 (s); + } + dst++; + w--; + } + + while (w >= 4) + { + __m64 vdest = *(__m64 *)dst; + __m64 vsrc = ldq_u ((__m64 *)src); + __m64 vd0, vd1; + __m64 vs0, vs1; + + expand_4xpacked565 (vdest, &vd0, &vd1, 0); + expand_4xpacked565 (vsrc, &vs0, &vs1, 0); + + vd0 = _mm_adds_pu8 (vd0, vs0); + vd1 = _mm_adds_pu8 (vd1, vs1); + + *(__m64 *)dst = pack_4xpacked565 (vd0, vd1); + + dst += 4; + src += 4; + w -= 4; + } + + while (w--) + { + s = *src++; + if (s) + { + d = *dst; + s = CONVERT_0565_TO_8888 (s); + if (d) + { + d = CONVERT_0565_TO_8888 (d); + UN8x4_ADD_UN8x4 (s, d); + } + *dst = CONVERT_8888_TO_0565 (s); + } + dst++; + } + } + + _mm_empty (); +} + static void mmx_composite_add_8888_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) { PIXMAN_COMPOSITE_ARGS (info); - __m64 dst64; uint32_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; @@ -2858,8 +3211,8 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, while (w && (unsigned long)dst & 7) { - *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src), - _mm_cvtsi32_si64 (*dst))); + store (dst, _mm_adds_pu8 (load ((const uint32_t *)src), + load ((const uint32_t *)dst))); dst++; src++; w--; @@ -2867,8 +3220,7 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, while (w >= 2) { - dst64 = _mm_adds_pu8 (ldq_u((uint64_t *)src), *(__m64*)dst); - *(uint64_t*)dst = to_uint64 (dst64); + *(__m64 *)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst); dst += 2; src += 2; w -= 2; @@ -2876,8 +3228,8 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, if (w) { - *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src), - _mm_cvtsi32_si64 (*dst))); + store (dst, _mm_adds_pu8 (load ((const uint32_t *)src), + load ((const uint32_t *)dst))); } } @@ -2958,7 +3310,7 @@ pixman_blt_mmx (uint32_t *src_bits, while (w >= 4 && ((unsigned long)d & 7)) { - *(uint32_t *)d = ldl_u((uint32_t *)s); + *(uint32_t *)d = ldl_u ((uint32_t *)s); w -= 4; s += 4; @@ -2992,14 +3344,14 @@ pixman_blt_mmx (uint32_t *src_bits, "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"); #else - __m64 v0 = ldq_u((uint64_t *)(s + 0)); - __m64 v1 = ldq_u((uint64_t *)(s + 8)); - __m64 v2 = ldq_u((uint64_t *)(s + 16)); - __m64 v3 = ldq_u((uint64_t *)(s + 24)); - __m64 v4 = ldq_u((uint64_t *)(s + 32)); - __m64 v5 = ldq_u((uint64_t *)(s + 40)); - __m64 v6 = ldq_u((uint64_t *)(s + 48)); - __m64 v7 = ldq_u((uint64_t *)(s + 56)); + __m64 v0 = ldq_u ((__m64 *)(s + 0)); + __m64 v1 = ldq_u ((__m64 *)(s + 8)); + __m64 v2 = ldq_u ((__m64 *)(s + 16)); + __m64 v3 = ldq_u ((__m64 *)(s + 24)); + __m64 v4 = ldq_u ((__m64 *)(s + 32)); + __m64 v5 = ldq_u ((__m64 *)(s + 40)); + __m64 v6 = ldq_u ((__m64 *)(s + 48)); + __m64 v7 = ldq_u ((__m64 *)(s + 56)); *(__m64 *)(d + 0) = v0; *(__m64 *)(d + 8) = v1; *(__m64 *)(d + 16) = v2; @@ -3016,7 +3368,7 @@ pixman_blt_mmx (uint32_t *src_bits, } while (w >= 4) { - *(uint32_t *)d = ldl_u((uint32_t *)s); + *(uint32_t *)d = ldl_u ((uint32_t *)s); w -= 4; s += 4; @@ -3109,6 +3461,490 @@ mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp, _mm_empty (); } +static void +mmx_composite_over_reverse_n_8888 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint32_t src; + uint32_t *dst_line, *dst; + int32_t w; + int dst_stride; + __m64 vsrc; + + CHECKPOINT (); + + src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format); + + if (src == 0) + return; + + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1); + + vsrc = load8888 (&src); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + w = width; + + CHECKPOINT (); + + while (w && (unsigned long)dst & 7) + { + __m64 vdest = load8888 (dst); + + store8888 (dst, over (vdest, expand_alpha (vdest), vsrc)); + + w--; + dst++; + } + + while (w >= 2) + { + __m64 vdest = *(__m64 *)dst; + __m64 dest0 = expand8888 (vdest, 0); + __m64 dest1 = expand8888 (vdest, 1); + + + dest0 = over (dest0, expand_alpha (dest0), vsrc); + dest1 = over (dest1, expand_alpha (dest1), vsrc); + + *(__m64 *)dst = pack8888 (dest0, dest1); + + dst += 2; + w -= 2; + } + + CHECKPOINT (); + + if (w) + { + __m64 vdest = load8888 (dst); + + store8888 (dst, over (vdest, expand_alpha (vdest), vsrc)); + } + } + + _mm_empty (); +} + +#define BSHIFT ((1 << BILINEAR_INTERPOLATION_BITS)) +#define BMSK (BSHIFT - 1) + +#define BILINEAR_DECLARE_VARIABLES \ + const __m64 mm_wt = _mm_set_pi16 (wt, wt, wt, wt); \ + const __m64 mm_wb = _mm_set_pi16 (wb, wb, wb, wb); \ + const __m64 mm_BSHIFT = _mm_set_pi16 (BSHIFT, BSHIFT, BSHIFT, BSHIFT); \ + const __m64 mm_addc7 = _mm_set_pi16 (0, 1, 0, 1); \ + const __m64 mm_xorc7 = _mm_set_pi16 (0, BMSK, 0, BMSK); \ + const __m64 mm_ux = _mm_set_pi16 (unit_x, unit_x, unit_x, unit_x); \ + const __m64 mm_zero = _mm_setzero_si64 (); \ + __m64 mm_x = _mm_set_pi16 (vx, vx, vx, vx) + +#define BILINEAR_INTERPOLATE_ONE_PIXEL(pix) \ +do { \ + /* fetch 2x2 pixel block into 2 mmx registers */ \ + __m64 t = ldq_u ((__m64 *)&src_top [pixman_fixed_to_int (vx)]); \ + __m64 b = ldq_u ((__m64 *)&src_bottom [pixman_fixed_to_int (vx)]); \ + vx += unit_x; \ + /* vertical interpolation */ \ + __m64 t_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (t, mm_zero), mm_wt); \ + __m64 t_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (t, mm_zero), mm_wt); \ + __m64 b_hi = _mm_mullo_pi16 (_mm_unpackhi_pi8 (b, mm_zero), mm_wb); \ + __m64 b_lo = _mm_mullo_pi16 (_mm_unpacklo_pi8 (b, mm_zero), mm_wb); \ + __m64 hi = _mm_add_pi16 (t_hi, b_hi); \ + __m64 lo = _mm_add_pi16 (t_lo, b_lo); \ + if (BILINEAR_INTERPOLATION_BITS < 8) \ + { \ + /* calculate horizontal weights */ \ + __m64 mm_wh = _mm_add_pi16 (mm_addc7, _mm_xor_si64 (mm_xorc7, \ + _mm_srli_pi16 (mm_x, \ + 16 - BILINEAR_INTERPOLATION_BITS))); \ + mm_x = _mm_add_pi16 (mm_x, mm_ux); \ + /* horizontal interpolation */ \ + __m64 p = _mm_unpacklo_pi16 (lo, hi); \ + __m64 q = _mm_unpackhi_pi16 (lo, hi); \ + lo = _mm_madd_pi16 (p, mm_wh); \ + hi = _mm_madd_pi16 (q, mm_wh); \ + } \ + else \ + { \ + /* calculate horizontal weights */ \ + __m64 mm_wh_lo = _mm_sub_pi16 (mm_BSHIFT, _mm_srli_pi16 (mm_x, \ + 16 - BILINEAR_INTERPOLATION_BITS)); \ + __m64 mm_wh_hi = _mm_srli_pi16 (mm_x, \ + 16 - BILINEAR_INTERPOLATION_BITS); \ + mm_x = _mm_add_pi16 (mm_x, mm_ux); \ + /* horizontal interpolation */ \ + __m64 mm_lo_lo = _mm_mullo_pi16 (lo, mm_wh_lo); \ + __m64 mm_lo_hi = _mm_mullo_pi16 (hi, mm_wh_hi); \ + __m64 mm_hi_lo = _mm_mulhi_pu16 (lo, mm_wh_lo); \ + __m64 mm_hi_hi = _mm_mulhi_pu16 (hi, mm_wh_hi); \ + lo = _mm_add_pi32 (_mm_unpacklo_pi16 (mm_lo_lo, mm_hi_lo), \ + _mm_unpacklo_pi16 (mm_lo_hi, mm_hi_hi)); \ + hi = _mm_add_pi32 (_mm_unpackhi_pi16 (mm_lo_lo, mm_hi_lo), \ + _mm_unpackhi_pi16 (mm_lo_hi, mm_hi_hi)); \ + } \ + /* shift and pack the result */ \ + hi = _mm_srli_pi32 (hi, BILINEAR_INTERPOLATION_BITS * 2); \ + lo = _mm_srli_pi32 (lo, BILINEAR_INTERPOLATION_BITS * 2); \ + lo = _mm_packs_pi32 (lo, hi); \ + lo = _mm_packs_pu16 (lo, lo); \ + pix = lo; \ +} while (0) + +#define BILINEAR_SKIP_ONE_PIXEL() \ +do { \ + vx += unit_x; \ + mm_x = _mm_add_pi16 (mm_x, mm_ux); \ +} while(0) + +static force_inline void +scaled_bilinear_scanline_mmx_8888_8888_SRC (uint32_t * dst, + const uint32_t * mask, + const uint32_t * src_top, + const uint32_t * src_bottom, + int32_t w, + int wt, + int wb, + pixman_fixed_t vx, + pixman_fixed_t unit_x, + pixman_fixed_t max_vx, + pixman_bool_t zero_src) +{ + BILINEAR_DECLARE_VARIABLES; + __m64 pix; + + while (w--) + { + BILINEAR_INTERPOLATE_ONE_PIXEL (pix); + store (dst, pix); + dst++; + } + + _mm_empty (); +} + +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_cover_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + COVER, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_pad_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + PAD, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_none_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + NONE, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_normal_SRC, + scaled_bilinear_scanline_mmx_8888_8888_SRC, + uint32_t, uint32_t, uint32_t, + NORMAL, FLAG_NONE) + +static force_inline void +scaled_bilinear_scanline_mmx_8888_8888_OVER (uint32_t * dst, + const uint32_t * mask, + const uint32_t * src_top, + const uint32_t * src_bottom, + int32_t w, + int wt, + int wb, + pixman_fixed_t vx, + pixman_fixed_t unit_x, + pixman_fixed_t max_vx, + pixman_bool_t zero_src) +{ + BILINEAR_DECLARE_VARIABLES; + __m64 pix1, pix2; + + while (w) + { + BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); + + if (!is_zero (pix1)) + { + pix2 = load (dst); + store8888 (dst, core_combine_over_u_pixel_mmx (pix1, pix2)); + } + + w--; + dst++; + } + + _mm_empty (); +} + +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_cover_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + COVER, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_pad_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + PAD, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_none_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + NONE, FLAG_NONE) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8888_normal_OVER, + scaled_bilinear_scanline_mmx_8888_8888_OVER, + uint32_t, uint32_t, uint32_t, + NORMAL, FLAG_NONE) + +static force_inline void +scaled_bilinear_scanline_mmx_8888_8_8888_OVER (uint32_t * dst, + const uint8_t * mask, + const uint32_t * src_top, + const uint32_t * src_bottom, + int32_t w, + int wt, + int wb, + pixman_fixed_t vx, + pixman_fixed_t unit_x, + pixman_fixed_t max_vx, + pixman_bool_t zero_src) +{ + BILINEAR_DECLARE_VARIABLES; + __m64 pix1, pix2; + uint32_t m; + + while (w) + { + m = (uint32_t) *mask++; + + if (m) + { + BILINEAR_INTERPOLATE_ONE_PIXEL (pix1); + + if (m == 0xff && is_opaque (pix1)) + { + store (dst, pix1); + } + else + { + __m64 ms, md, ma, msa; + + pix2 = load (dst); + ma = expand_alpha_rev (to_m64 (m)); + ms = _mm_unpacklo_pi8 (pix1, _mm_setzero_si64 ()); + md = _mm_unpacklo_pi8 (pix2, _mm_setzero_si64 ()); + + msa = expand_alpha (ms); + + store8888 (dst, (in_over (ms, msa, ma, md))); + } + } + else + { + BILINEAR_SKIP_ONE_PIXEL (); + } + + w--; + dst++; + } + + _mm_empty (); +} + +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_cover_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + COVER, FLAG_HAVE_NON_SOLID_MASK) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_pad_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + PAD, FLAG_HAVE_NON_SOLID_MASK) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_none_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + NONE, FLAG_HAVE_NON_SOLID_MASK) +FAST_BILINEAR_MAINLOOP_COMMON (mmx_8888_8_8888_normal_OVER, + scaled_bilinear_scanline_mmx_8888_8_8888_OVER, + uint32_t, uint8_t, uint32_t, + NORMAL, FLAG_HAVE_NON_SOLID_MASK) + +static uint32_t * +mmx_fetch_x8r8g8b8 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint32_t *src = (uint32_t *)iter->bits; + + iter->bits += iter->stride; + + while (w && ((unsigned long)dst) & 7) + { + *dst++ = (*src++) | 0xff000000; + w--; + } + + while (w >= 8) + { + __m64 vsrc1 = ldq_u ((__m64 *)(src + 0)); + __m64 vsrc2 = ldq_u ((__m64 *)(src + 2)); + __m64 vsrc3 = ldq_u ((__m64 *)(src + 4)); + __m64 vsrc4 = ldq_u ((__m64 *)(src + 6)); + + *(__m64 *)(dst + 0) = _mm_or_si64 (vsrc1, MC (ff000000)); + *(__m64 *)(dst + 2) = _mm_or_si64 (vsrc2, MC (ff000000)); + *(__m64 *)(dst + 4) = _mm_or_si64 (vsrc3, MC (ff000000)); + *(__m64 *)(dst + 6) = _mm_or_si64 (vsrc4, MC (ff000000)); + + dst += 8; + src += 8; + w -= 8; + } + + while (w) + { + *dst++ = (*src++) | 0xff000000; + w--; + } + + _mm_empty (); + return iter->buffer; +} + +static uint32_t * +mmx_fetch_r5g6b5 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint16_t *src = (uint16_t *)iter->bits; + + iter->bits += iter->stride; + + while (w && ((unsigned long)dst) & 0x0f) + { + uint16_t s = *src++; + + *dst++ = CONVERT_0565_TO_8888 (s); + w--; + } + + while (w >= 4) + { + __m64 vsrc = ldq_u ((__m64 *)src); + __m64 mm0, mm1; + + expand_4xpacked565 (vsrc, &mm0, &mm1, 1); + + *(__m64 *)(dst + 0) = mm0; + *(__m64 *)(dst + 2) = mm1; + + dst += 4; + src += 4; + w -= 4; + } + + while (w) + { + uint16_t s = *src++; + + *dst++ = CONVERT_0565_TO_8888 (s); + w--; + } + + _mm_empty (); + return iter->buffer; +} + +static uint32_t * +mmx_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint8_t *src = iter->bits; + + iter->bits += iter->stride; + + while (w && (((unsigned long)dst) & 15)) + { + *dst++ = *(src++) << 24; + w--; + } + + while (w >= 8) + { + __m64 mm0 = ldq_u ((__m64 *)src); + + __m64 mm1 = _mm_unpacklo_pi8 (_mm_setzero_si64(), mm0); + __m64 mm2 = _mm_unpackhi_pi8 (_mm_setzero_si64(), mm0); + __m64 mm3 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm1); + __m64 mm4 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm1); + __m64 mm5 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm2); + __m64 mm6 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm2); + + *(__m64 *)(dst + 0) = mm3; + *(__m64 *)(dst + 2) = mm4; + *(__m64 *)(dst + 4) = mm5; + *(__m64 *)(dst + 6) = mm6; + + dst += 8; + src += 8; + w -= 8; + } + + while (w) + { + *dst++ = *(src++) << 24; + w--; + } + + _mm_empty (); + return iter->buffer; +} + +typedef struct +{ + pixman_format_code_t format; + pixman_iter_get_scanline_t get_scanline; +} fetcher_info_t; + +static const fetcher_info_t fetchers[] = +{ + { PIXMAN_x8r8g8b8, mmx_fetch_x8r8g8b8 }, + { PIXMAN_r5g6b5, mmx_fetch_r5g6b5 }, + { PIXMAN_a8, mmx_fetch_a8 }, + { PIXMAN_null } +}; + +static void +mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) +{ + pixman_image_t *image = iter->image; + +#define FLAGS \ + (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | \ + FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST) + + if ((iter->iter_flags & ITER_NARROW) && + (iter->image_flags & FLAGS) == FLAGS) + { + const fetcher_info_t *f; + + for (f = &fetchers[0]; f->format != PIXMAN_null; f++) + { + if (image->common.extended_format_code == f->format) + { + uint8_t *b = (uint8_t *)image->bits.bits; + int s = image->bits.rowstride * 4; + + iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8; + iter->stride = s; + + iter->get_scanline = f->get_scanline; + return; + } + } + } + + imp->delegate->src_iter_init (imp->delegate, iter); +} + static const pixman_fast_path_t mmx_fast_paths[] = { PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mmx_composite_over_n_8_0565 ), @@ -3155,11 +3991,20 @@ static const pixman_fast_path_t mmx_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, x8b8g8r8, mmx_composite_over_8888_8888 ), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, b5g6r5, mmx_composite_over_8888_0565 ), + PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8r8g8b8, mmx_composite_over_reverse_n_8888), + PIXMAN_STD_FAST_PATH (OVER_REVERSE, solid, null, a8b8g8r8, mmx_composite_over_reverse_n_8888), + + PIXMAN_STD_FAST_PATH (ADD, r5g6b5, null, r5g6b5, mmx_composite_add_0565_0565 ), + PIXMAN_STD_FAST_PATH (ADD, b5g6r5, null, b5g6r5, mmx_composite_add_0565_0565 ), PIXMAN_STD_FAST_PATH (ADD, a8r8g8b8, null, a8r8g8b8, mmx_composite_add_8888_8888 ), PIXMAN_STD_FAST_PATH (ADD, a8b8g8r8, null, a8b8g8r8, mmx_composite_add_8888_8888 ), PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, mmx_composite_add_8_8 ), PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, mmx_composite_add_n_8_8 ), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, mmx_composite_src_x888_0565 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, mmx_composite_src_n_8_8888 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, mmx_composite_src_n_8_8888 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, mmx_composite_src_n_8_8888 ), @@ -3176,6 +4021,23 @@ static const pixman_fast_path_t mmx_fast_paths[] = PIXMAN_STD_FAST_PATH (IN, a8, null, a8, mmx_composite_in_8_8 ), PIXMAN_STD_FAST_PATH (IN, solid, a8, a8, mmx_composite_in_n_8_8 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, mmx_8888_8888 ), + + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8888 ), + SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8888 ), + + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, mmx_8888_8_8888 ), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, mmx_8888_8_8888 ), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8r8g8b8, a8r8g8b8, mmx_8888_8_8888 ), + SIMPLE_BILINEAR_A8_MASK_FAST_PATH (OVER, a8b8g8r8, a8b8g8r8, mmx_8888_8_8888 ), + { PIXMAN_OP_NONE }, }; @@ -3260,7 +4122,9 @@ _pixman_implementation_create_mmx (pixman_implementation_t *fallback) imp->blt = mmx_blt; imp->fill = mmx_fill; + imp->src_iter_init = mmx_src_iter_init; + return imp; } -#endif /* USE_X86_MMX || USE_ARM_IWMMXT */ +#endif /* USE_X86_MMX || USE_ARM_IWMMXT || USE_LOONGSON_MMI */ diff --git a/gfx/cairo/libpixman/src/pixman-noop.c b/gfx/cairo/libpixman/src/pixman-noop.c index d835de64f3a..7b017e8ecc8 100644 --- a/gfx/cairo/libpixman/src/pixman-noop.c +++ b/gfx/cairo/libpixman/src/pixman-noop.c @@ -71,18 +71,18 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { iter->get_scanline = get_scanline_null; } - else if ((iter->flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == + else if ((iter->iter_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) == (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) { iter->get_scanline = _pixman_iter_get_scanline_noop; } else if (image->common.extended_format_code == PIXMAN_solid && - ((image->common.flags & (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)) == + ((iter->image_flags & (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP)) == (FAST_PATH_BITS_IMAGE | FAST_PATH_NO_ALPHA_MAP))) { bits_image_t *bits = &image->bits; - if (iter->flags & ITER_NARROW) + if (iter->iter_flags & ITER_NARROW) { uint32_t color = bits->fetch_pixel_32 (bits, 0, 0); uint32_t *buffer = iter->buffer; @@ -104,8 +104,8 @@ noop_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) iter->get_scanline = _pixman_iter_get_scanline_noop; } else if (image->common.extended_format_code == PIXMAN_a8r8g8b8 && - (iter->flags & ITER_NARROW) && - (image->common.flags & FLAGS) == FLAGS && + (iter->iter_flags & ITER_NARROW) && + (iter->image_flags & FLAGS) == FLAGS && iter->x >= 0 && iter->y >= 0 && iter->x + iter->width <= image->bits.width && iter->y + iter->height <= image->bits.height) @@ -125,8 +125,8 @@ static void noop_dest_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { pixman_image_t *image = iter->image; - uint32_t image_flags = image->common.flags; - uint32_t iter_flags = iter->flags; + uint32_t image_flags = iter->image_flags; + uint32_t iter_flags = iter->iter_flags; if ((image_flags & FAST_PATH_STD_DEST_FLAGS) == FAST_PATH_STD_DEST_FLAGS && (iter_flags & ITER_NARROW) == ITER_NARROW && diff --git a/gfx/cairo/libpixman/src/pixman-ppc.c b/gfx/cairo/libpixman/src/pixman-ppc.c new file mode 100644 index 00000000000..f1bea1eacf0 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-ppc.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +#ifdef USE_VMX + +/* The CPU detection code needs to be in a file not compiled with + * "-maltivec -mabi=altivec", as gcc would try to save vector register + * across function calls causing SIGILL on cpus without Altivec/vmx. + */ +#ifdef __APPLE__ +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ + size_t length = sizeof(have_vmx); + int error, have_mmx; + + sysctlbyname ("hw.optional.altivec", &have_vmx, &length, NULL, 0); + + if (error) + return FALSE; + + return have_vmx; +} + +#elif defined (__OpenBSD__) +#include +#include +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ + int mib[2] = { CTL_MACHDEP, CPU_ALTIVEC }; + size_t length = sizeof(have_vmx); + int error, have_vmx; + + error = sysctl (mib, 2, &have_vmx, &length, NULL, 0); + + if (error != 0) + return FALSE; + + return have_vmx; +} + +#elif defined (__linux__) + +#include +#include +#include +#include +#include +#include +#include + +static pixman_bool_t +pixman_have_vmx (void) +{ + int have_vmx = FALSE; + int fd; + struct + { + unsigned long type; + unsigned long value; + } aux; + + fd = open ("/proc/self/auxv", O_RDONLY); + if (fd >= 0) + { + while (read (fd, &aux, sizeof (aux)) == sizeof (aux)) + { + if (aux.type == AT_HWCAP && (aux.value & PPC_FEATURE_HAS_ALTIVEC)) + { + have_vmx = TRUE; + break; + } + } + + close (fd); + } + + return have_vmx; +} + +#else /* !__APPLE__ && !__OpenBSD__ && !__linux__ */ +#include +#include + +static jmp_buf jump_env; + +static void +vmx_test (int sig, + siginfo_t *si, + void * unused) +{ + longjmp (jump_env, 1); +} + +static pixman_bool_t +pixman_have_vmx (void) +{ + struct sigaction sa, osa; + int jmp_result; + + sa.sa_flags = SA_SIGINFO; + sigemptyset (&sa.sa_mask); + sa.sa_sigaction = vmx_test; + sigaction (SIGILL, &sa, &osa); + jmp_result = setjmp (jump_env); + if (jmp_result == 0) + { + asm volatile ( "vor 0, 0, 0" ); + } + sigaction (SIGILL, &osa, NULL); + return (jmp_result == 0); +} + +#endif /* __APPLE__ */ +#endif /* USE_VMX */ + +pixman_implementation_t * +_pixman_ppc_get_implementations (pixman_implementation_t *imp) +{ +#ifdef USE_VMX + if (!_pixman_disabled ("vmx") && pixman_have_vmx ()) + imp = _pixman_implementation_create_vmx (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman-private.h b/gfx/cairo/libpixman/src/pixman-private.h index 4a273c9aca3..4de6261bb40 100644 --- a/gfx/cairo/libpixman/src/pixman-private.h +++ b/gfx/cairo/libpixman/src/pixman-private.h @@ -1,10 +1,33 @@ +#ifndef PIXMAN_PRIVATE_H +#define PIXMAN_PRIVATE_H + +/* + * The defines which are shared between C and assembly code + */ + +/* bilinear interpolation precision (must be <= 8) */ +#ifndef MOZILLA_VERSION +#error "Need mozilla headers" +#endif +#ifdef MOZ_GFX_OPTIMIZE_MOBILE +#define LOW_QUALITY_INTERPOLATION +#define LOWER_QUALITY_INTERPOLATION +#define BILINEAR_INTERPOLATION_BITS 4 +#else +#define BILINEAR_INTERPOLATION_BITS 8 +#endif +#define BILINEAR_INTERPOLATION_RANGE (1 << BILINEAR_INTERPOLATION_BITS) + +/* + * C specific part + */ + +#ifndef __ASSEMBLER__ + #ifndef PACKAGE # error config.h must be included before pixman-private.h #endif -#ifndef PIXMAN_PRIVATE_H -#define PIXMAN_PRIVATE_H - #define PIXMAN_DISABLE_DEPRECATED #define PIXMAN_USE_INTERNAL_API @@ -13,6 +36,7 @@ #include #include #include +#include #include "pixman-compiler.h" @@ -154,9 +178,6 @@ struct bits_image uint32_t * free_me; int rowstride; /* in number of uint32_t's */ - fetch_scanline_t get_scanline_32; - fetch_scanline_t get_scanline_64; - fetch_scanline_t fetch_scanline_16; fetch_scanline_t fetch_scanline_32; @@ -229,13 +250,15 @@ struct pixman_iter_t int x, y; int width; int height; - iter_flags_t flags; + iter_flags_t iter_flags; + uint32_t image_flags; /* These function pointers are initialized by the implementation */ pixman_iter_get_scanline_t get_scanline; pixman_iter_write_back_t write_back; /* These fields are scratch data that implementations can use */ + void * data; uint8_t * bits; int stride; }; @@ -530,7 +553,8 @@ _pixman_implementation_src_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags); + iter_flags_t flags, + uint32_t image_flags); void _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, @@ -541,7 +565,8 @@ _pixman_implementation_dest_iter_init (pixman_implementation_t *imp, int width, int height, uint8_t *buffer, - iter_flags_t flags); + iter_flags_t flags, + uint32_t image_flags); /* Specific implementations */ pixman_implementation_t * @@ -553,7 +578,7 @@ _pixman_implementation_create_fast_path (pixman_implementation_t *fallback); pixman_implementation_t * _pixman_implementation_create_noop (pixman_implementation_t *fallback); -#if defined USE_X86_MMX || defined USE_ARM_IWMMXT +#if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI pixman_implementation_t * _pixman_implementation_create_mmx (pixman_implementation_t *fallback); #endif @@ -583,14 +608,44 @@ pixman_implementation_t * _pixman_implementation_create_vmx (pixman_implementation_t *fallback); #endif +pixman_bool_t +_pixman_implementation_disabled (const char *name); + +pixman_implementation_t * +_pixman_x86_get_implementations (pixman_implementation_t *imp); + +pixman_implementation_t * +_pixman_arm_get_implementations (pixman_implementation_t *imp); + +pixman_implementation_t * +_pixman_ppc_get_implementations (pixman_implementation_t *imp); + +pixman_implementation_t * +_pixman_mips_get_implementations (pixman_implementation_t *imp); + pixman_implementation_t * _pixman_choose_implementation (void); +pixman_bool_t +_pixman_disabled (const char *name); /* * Utilities */ +pixman_bool_t +_pixman_compute_composite_region32 (pixman_region32_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dest_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height); uint32_t * _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); @@ -699,6 +754,18 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); dest, FAST_PATH_STD_DEST_FLAGS, \ func) } +extern pixman_implementation_t *global_implementation; + +static force_inline pixman_implementation_t * +get_implementation (void) +{ +#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR + if (!global_implementation) + global_implementation = _pixman_choose_implementation (); +#endif + return global_implementation; +} + /* Memory allocation helpers */ void * pixman_malloc_ab (unsigned int n, unsigned int b); @@ -748,6 +815,50 @@ pixman_bool_t pixman_region16_copy_from_region32 (pixman_region16_t *dst, pixman_region32_t *src); +/* Doubly linked lists */ +typedef struct pixman_link_t pixman_link_t; +struct pixman_link_t +{ + pixman_link_t *next; + pixman_link_t *prev; +}; + +typedef struct pixman_list_t pixman_list_t; +struct pixman_list_t +{ + pixman_link_t *head; + pixman_link_t *tail; +}; + +static force_inline void +pixman_list_init (pixman_list_t *list) +{ + list->head = (pixman_link_t *)list; + list->tail = (pixman_link_t *)list; +} + +static force_inline void +pixman_list_prepend (pixman_list_t *list, pixman_link_t *link) +{ + link->next = list->head; + link->prev = (pixman_link_t *)list; + list->head->prev = link; + list->head = link; +} + +static force_inline void +pixman_list_unlink (pixman_link_t *link) +{ + link->prev->next = link->next; + link->next->prev = link->prev; +} + +static force_inline void +pixman_list_move_to_front (pixman_list_t *list, pixman_link_t *link) +{ + pixman_list_unlink (link); + pixman_list_prepend (list, link); +} /* Misc macros */ @@ -800,7 +911,8 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst, (PIXMAN_FORMAT_A (f) > 8 || \ PIXMAN_FORMAT_R (f) > 8 || \ PIXMAN_FORMAT_G (f) > 8 || \ - PIXMAN_FORMAT_B (f) > 8) + PIXMAN_FORMAT_B (f) > 8 || \ + PIXMAN_FORMAT_TYPE (f) == PIXMAN_TYPE_ARGB_SRGB) #ifdef WORDS_BIGENDIAN # define SCREEN_SHIFT_LEFT(x,n) ((x) << (n)) @@ -996,4 +1108,18 @@ void pixman_timer_register (pixman_timer_t *timer); #endif /* PIXMAN_TIMERS */ +/* sRGB<->linear conversion tables. Linear color space is the same + * as sRGB but the components are in linear light (gamma 1.0). + * + * linear_to_srgb maps linear value from 0 to 4095 ([0.0, 1.0]) + * and returns 8-bit sRGB value. + * + * srgb_to_linear maps 8-bit sRGB value to 16-bit linear value + * with range 0 to 65535 ([0.0, 1.0]). + */ +extern const uint8_t linear_to_srgb[4096]; +extern const uint16_t srgb_to_linear[256]; + +#endif /* __ASSEMBLER__ */ + #endif /* PIXMAN_PRIVATE_H */ diff --git a/gfx/cairo/libpixman/src/pixman-radial-gradient.c b/gfx/cairo/libpixman/src/pixman-radial-gradient.c index d31aa14d29f..9f43a53e805 100644 --- a/gfx/cairo/libpixman/src/pixman-radial-gradient.c +++ b/gfx/cairo/libpixman/src/pixman-radial-gradient.c @@ -671,9 +671,9 @@ radial_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask) void _pixman_radial_gradient_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_16) + if (iter->iter_flags & ITER_16) iter->get_scanline = radial_get_scanline_16; - else if (iter->flags & ITER_NARROW) + else if (iter->iter_flags & ITER_NARROW) iter->get_scanline = radial_get_scanline_narrow; else iter->get_scanline = radial_get_scanline_wide; diff --git a/gfx/cairo/libpixman/src/pixman-region.c b/gfx/cairo/libpixman/src/pixman-region.c index 70c282d4091..4626f9cc68e 100644 --- a/gfx/cairo/libpixman/src/pixman-region.c +++ b/gfx/cairo/libpixman/src/pixman-region.c @@ -2041,10 +2041,10 @@ PREFIX (_subtract) (region_type_t *reg_d, * *----------------------------------------------------------------------- */ -pixman_bool_t -PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region */ - region_type_t *reg1, /* Region to invert */ - box_type_t * inv_rect) /* Bounding box for inversion */ +PIXMAN_EXPORT pixman_bool_t +PREFIX (_inverse) (region_type_t *new_reg, /* Destination region */ + region_type_t *reg1, /* Region to invert */ + box_type_t * inv_rect) /* Bounding box for inversion */ { region_type_t inv_reg; /* Quick and dirty region made from the * bounding box */ @@ -2137,9 +2137,9 @@ find_box_for_y (box_type_t *begin, box_type_t *end, int y) * partially in the region) or is outside the region (we reached a band * that doesn't overlap the box at all and part_in is false) */ -pixman_region_overlap_t -PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region, - box_type_t * prect) +PIXMAN_EXPORT pixman_region_overlap_t +PREFIX (_contains_rectangle) (region_type_t * region, + box_type_t * prect) { box_type_t * pbox; box_type_t * pbox_end; diff --git a/gfx/cairo/libpixman/src/pixman-solid-fill.c b/gfx/cairo/libpixman/src/pixman-solid-fill.c index 852e13568b5..8b25d5d08bc 100644 --- a/gfx/cairo/libpixman/src/pixman-solid-fill.c +++ b/gfx/cairo/libpixman/src/pixman-solid-fill.c @@ -29,7 +29,7 @@ void _pixman_solid_fill_iter_init (pixman_image_t *image, pixman_iter_t *iter) { - if (iter->flags & ITER_NARROW) + if (iter->iter_flags & ITER_NARROW) { uint32_t *b = (uint32_t *)iter->buffer; uint32_t *e = b + iter->width; diff --git a/gfx/cairo/libpixman/src/pixman-srgb.c b/gfx/cairo/libpixman/src/pixman-srgb.c new file mode 100644 index 00000000000..abe5cdb9793 --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-srgb.c @@ -0,0 +1,455 @@ +/* WARNING: This file is generated by make-srgb.pl. + * Please edit that file instead of this one. + */ + +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +const uint8_t linear_to_srgb[4096] = +{ + 0, 1, 2, 2, 3, 4, 5, 6, 6, 7, + 8, 9, 10, 10, 11, 12, 13, 13, 14, 15, + 15, 16, 16, 17, 18, 18, 19, 19, 20, 20, + 21, 21, 22, 22, 23, 23, 23, 24, 24, 25, + 25, 25, 26, 26, 27, 27, 27, 28, 28, 29, + 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, + 32, 33, 33, 33, 34, 34, 34, 34, 35, 35, + 35, 36, 36, 36, 37, 37, 37, 37, 38, 38, + 38, 38, 39, 39, 39, 40, 40, 40, 40, 41, + 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, + 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 47, 47, 47, 47, 48, + 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, + 50, 50, 50, 50, 51, 51, 51, 51, 51, 52, + 52, 52, 52, 52, 53, 53, 53, 53, 53, 54, + 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, + 57, 58, 58, 58, 58, 58, 58, 59, 59, 59, + 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, + 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, + 62, 63, 63, 63, 63, 63, 63, 64, 64, 64, + 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, + 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, + 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, + 68, 69, 69, 69, 69, 69, 69, 69, 70, 70, + 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, + 71, 71, 72, 72, 72, 72, 72, 72, 72, 72, + 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, + 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, + 75, 75, 75, 76, 76, 76, 76, 76, 76, 76, + 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, + 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, + 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + 113, 113, 113, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 115, 115, 115, 115, + 115, 115, 115, 115, 115, 115, 115, 115, 115, 116, + 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 120, 120, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, + 125, 125, 125, 125, 125, 125, 125, 125, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 131, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 131, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 140, 140, 140, 140, + 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, + 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 142, 142, 142, 142, 142, 142, 142, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 146, 146, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, 150, 150, 150, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 153, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 153, 153, 153, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, + 155, 155, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, + 156, 156, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 165, 165, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 171, 171, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, + 175, 175, 175, 175, 175, 175, 175, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, + 183, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, + 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, + 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, + 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 189, 189, 189, 189, 189, 189, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 191, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 201, + 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, + 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, + 202, 202, 202, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, + 205, 205, 205, 205, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, + 208, 208, 208, 208, 208, 208, 208, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, + 209, 209, 209, 209, 209, 209, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, + 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, + 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 223, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 223, 223, + 223, 223, 223, 223, 223, 223, 223, 223, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, + 225, 225, 225, 225, 225, 225, 225, 225, 225, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, + 227, 227, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, + 228, 228, 228, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, + 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 245, 245, 245, + 245, 245, 245, 245, 245, 245, 245, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, + 248, 248, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 249, 249, 249, + 249, 249, 249, 249, 249, 249, 249, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, + 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 251, 251, 251, 251, 251, 251, 251, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, + 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, +}; + +const uint16_t srgb_to_linear[256] = +{ + 0, 20, 40, 64, 80, 99, 119, 144, 160, 179, + 199, 224, 241, 264, 288, 313, 340, 368, 396, 427, + 458, 491, 526, 562, 599, 637, 677, 718, 761, 805, + 851, 898, 947, 997, 1048, 1101, 1156, 1212, 1270, 1330, + 1391, 1453, 1517, 1583, 1651, 1720, 1790, 1863, 1937, 2013, + 2090, 2170, 2250, 2333, 2418, 2504, 2592, 2681, 2773, 2866, + 2961, 3058, 3157, 3258, 3360, 3464, 3570, 3678, 3788, 3900, + 4014, 4129, 4247, 4366, 4488, 4611, 4736, 4864, 4993, 5124, + 5257, 5392, 5530, 5669, 5810, 5953, 6099, 6246, 6395, 6547, + 6700, 6856, 7014, 7174, 7335, 7500, 7666, 7834, 8004, 8177, + 8352, 8528, 8708, 8889, 9072, 9258, 9445, 9635, 9828, 10022, + 10219, 10417, 10619, 10822, 11028, 11235, 11446, 11658, 11873, 12090, + 12309, 12530, 12754, 12980, 13209, 13440, 13673, 13909, 14146, 14387, + 14629, 14874, 15122, 15371, 15623, 15878, 16135, 16394, 16656, 16920, + 17187, 17456, 17727, 18001, 18277, 18556, 18837, 19121, 19407, 19696, + 19987, 20281, 20577, 20876, 21177, 21481, 21787, 22096, 22407, 22721, + 23038, 23357, 23678, 24002, 24329, 24658, 24990, 25325, 25662, 26001, + 26344, 26688, 27036, 27386, 27739, 28094, 28452, 28813, 29176, 29542, + 29911, 30282, 30656, 31033, 31412, 31794, 32179, 32567, 32957, 33350, + 33745, 34143, 34544, 34948, 35355, 35764, 36176, 36591, 37008, 37429, + 37852, 38278, 38706, 39138, 39572, 40009, 40449, 40891, 41337, 41785, + 42236, 42690, 43147, 43606, 44069, 44534, 45002, 45473, 45947, 46423, + 46903, 47385, 47871, 48359, 48850, 49344, 49841, 50341, 50844, 51349, + 51858, 52369, 52884, 53401, 53921, 54445, 54971, 55500, 56032, 56567, + 57105, 57646, 58190, 58737, 59287, 59840, 60396, 60955, 61517, 62082, + 62650, 63221, 63795, 64372, 64952, 65535, +}; diff --git a/gfx/cairo/libpixman/src/pixman-sse2.c b/gfx/cairo/libpixman/src/pixman-sse2.c index cafa5897889..636a74e431f 100644 --- a/gfx/cairo/libpixman/src/pixman-sse2.c +++ b/gfx/cairo/libpixman/src/pixman-sse2.c @@ -53,6 +53,9 @@ static __m128i mask_blue; static __m128i mask_565_fix_rb; static __m128i mask_565_fix_g; +static __m128i mask_565_rb; +static __m128i mask_565_pack_multiplier; + static force_inline __m128i unpack_32_1x128 (uint32_t data) { @@ -121,6 +124,29 @@ pack_2x128_128 (__m128i lo, __m128i hi) } static force_inline __m128i +pack_565_2packedx128_128 (__m128i lo, __m128i hi) +{ + __m128i rb0 = _mm_and_si128 (lo, mask_565_rb); + __m128i rb1 = _mm_and_si128 (hi, mask_565_rb); + + __m128i t0 = _mm_madd_epi16 (rb0, mask_565_pack_multiplier); + __m128i t1 = _mm_madd_epi16 (rb1, mask_565_pack_multiplier); + + __m128i g0 = _mm_and_si128 (lo, mask_green); + __m128i g1 = _mm_and_si128 (hi, mask_green); + + t0 = _mm_or_si128 (t0, g0); + t1 = _mm_or_si128 (t1, g1); + + /* Simulates _mm_packus_epi32 */ + t0 = _mm_slli_epi32 (t0, 16 - 5); + t1 = _mm_slli_epi32 (t1, 16 - 5); + t0 = _mm_srai_epi32 (t0, 16); + t1 = _mm_srai_epi32 (t1, 16); + return _mm_packs_epi32 (t0, t1); +} + +__m128i pack_565_2x128_128 (__m128i lo, __m128i hi) { __m128i data; @@ -2831,6 +2857,57 @@ sse2_composite_over_8888_n_8888 (pixman_implementation_t *imp, } +static void +sse2_composite_src_x888_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t *src_line, *src, s; + int dst_stride, src_stride; + int32_t w; + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w && (unsigned long)dst & 15) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + + while (w >= 8) + { + __m128i xmm_src0 = load_128_unaligned ((__m128i *)src + 0); + __m128i xmm_src1 = load_128_unaligned ((__m128i *)src + 1); + + save_128_aligned ((__m128i*)dst, pack_565_2packedx128_128 (xmm_src0, xmm_src1)); + + w -= 8; + src += 8; + dst += 8; + } + + while (w) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + } +} + static void sse2_composite_src_x888_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) @@ -5317,11 +5394,15 @@ FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_normal_OVER, scaled_nearest_scanline_sse2_8888_n_8888_OVER, uint32_t, uint32_t, uint32_t, NORMAL, TRUE, TRUE) +#define BMSK ((1 << BILINEAR_INTERPOLATION_BITS) - 1) + #define BILINEAR_DECLARE_VARIABLES \ const __m128i xmm_wt = _mm_set_epi16 (wt, wt, wt, wt, wt, wt, wt, wt); \ const __m128i xmm_wb = _mm_set_epi16 (wb, wb, wb, wb, wb, wb, wb, wb); \ - const __m128i xmm_xorc = _mm_set_epi16 (0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff);\ - const __m128i xmm_addc = _mm_set_epi16 (0, 0, 0, 0, 1, 1, 1, 1); \ + const __m128i xmm_xorc8 = _mm_set_epi16 (0, 0, 0, 0, BMSK, BMSK, BMSK, BMSK);\ + const __m128i xmm_addc8 = _mm_set_epi16 (0, 0, 0, 0, 1, 1, 1, 1); \ + const __m128i xmm_xorc7 = _mm_set_epi16 (0, BMSK, 0, BMSK, 0, BMSK, 0, BMSK);\ + const __m128i xmm_addc7 = _mm_set_epi16 (0, 1, 0, 1, 0, 1, 0, 1); \ const __m128i xmm_ux = _mm_set_epi16 (unit_x, unit_x, unit_x, unit_x, \ unit_x, unit_x, unit_x, unit_x); \ const __m128i xmm_zero = _mm_setzero_si128 (); \ @@ -5330,30 +5411,41 @@ FAST_NEAREST_MAINLOOP_COMMON (sse2_8888_n_8888_normal_OVER, #define BILINEAR_INTERPOLATE_ONE_PIXEL(pix) \ do { \ __m128i xmm_wh, xmm_lo, xmm_hi, a; \ - /* fetch 2x2 pixel block into sse2 register */ \ - uint32_t tl = src_top [pixman_fixed_to_int (vx)]; \ - uint32_t tr = src_top [pixman_fixed_to_int (vx) + 1]; \ - uint32_t bl = src_bottom [pixman_fixed_to_int (vx)]; \ - uint32_t br = src_bottom [pixman_fixed_to_int (vx) + 1]; \ - a = _mm_set_epi32 (tr, tl, br, bl); \ + /* fetch 2x2 pixel block into sse2 registers */ \ + __m128i tltr = _mm_loadl_epi64 ( \ + (__m128i *)&src_top[pixman_fixed_to_int (vx)]); \ + __m128i blbr = _mm_loadl_epi64 ( \ + (__m128i *)&src_bottom[pixman_fixed_to_int (vx)]); \ vx += unit_x; \ /* vertical interpolation */ \ - a = _mm_add_epi16 (_mm_mullo_epi16 (_mm_unpackhi_epi8 (a, xmm_zero), \ + a = _mm_add_epi16 (_mm_mullo_epi16 (_mm_unpacklo_epi8 (tltr, xmm_zero), \ xmm_wt), \ - _mm_mullo_epi16 (_mm_unpacklo_epi8 (a, xmm_zero), \ + _mm_mullo_epi16 (_mm_unpacklo_epi8 (blbr, xmm_zero), \ xmm_wb)); \ - /* calculate horizontal weights */ \ - xmm_wh = _mm_add_epi16 (xmm_addc, \ - _mm_xor_si128 (xmm_xorc, \ - _mm_srli_epi16 (xmm_x, 8))); \ - xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ - /* horizontal interpolation */ \ - xmm_lo = _mm_mullo_epi16 (a, xmm_wh); \ - xmm_hi = _mm_mulhi_epu16 (a, xmm_wh); \ - a = _mm_add_epi32 (_mm_unpacklo_epi16 (xmm_lo, xmm_hi), \ - _mm_unpackhi_epi16 (xmm_lo, xmm_hi)); \ + if (BILINEAR_INTERPOLATION_BITS < 8) \ + { \ + /* calculate horizontal weights */ \ + xmm_wh = _mm_add_epi16 (xmm_addc7, _mm_xor_si128 (xmm_xorc7, \ + _mm_srli_epi16 (xmm_x, 16 - BILINEAR_INTERPOLATION_BITS))); \ + xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ + /* horizontal interpolation */ \ + a = _mm_madd_epi16 (_mm_unpackhi_epi16 (_mm_shuffle_epi32 ( \ + a, _MM_SHUFFLE (1, 0, 3, 2)), a), xmm_wh); \ + } \ + else \ + { \ + /* calculate horizontal weights */ \ + xmm_wh = _mm_add_epi16 (xmm_addc8, _mm_xor_si128 (xmm_xorc8, \ + _mm_srli_epi16 (xmm_x, 16 - BILINEAR_INTERPOLATION_BITS))); \ + xmm_x = _mm_add_epi16 (xmm_x, xmm_ux); \ + /* horizontal interpolation */ \ + xmm_lo = _mm_mullo_epi16 (a, xmm_wh); \ + xmm_hi = _mm_mulhi_epu16 (a, xmm_wh); \ + a = _mm_add_epi32 (_mm_unpacklo_epi16 (xmm_lo, xmm_hi), \ + _mm_unpackhi_epi16 (xmm_lo, xmm_hi)); \ + } \ /* shift and pack the result */ \ - a = _mm_srli_epi32 (a, 16); \ + a = _mm_srli_epi32 (a, BILINEAR_INTERPOLATION_BITS * 2); \ a = _mm_packs_epi32 (a, a); \ a = _mm_packus_epi16 (a, a); \ pix = _mm_cvtsi128_si32 (a); \ @@ -5735,6 +5827,7 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (OVER, solid, null, a8r8g8b8, sse2_composite_over_n_8888), PIXMAN_STD_FAST_PATH (OVER, solid, null, x8r8g8b8, sse2_composite_over_n_8888), PIXMAN_STD_FAST_PATH (OVER, solid, null, r5g6b5, sse2_composite_over_n_0565), + PIXMAN_STD_FAST_PATH (OVER, solid, null, b5g6r5, sse2_composite_over_n_0565), PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, a8r8g8b8, sse2_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8r8g8b8, null, x8r8g8b8, sse2_composite_over_8888_8888), PIXMAN_STD_FAST_PATH (OVER, a8b8g8r8, null, a8b8g8r8, sse2_composite_over_8888_8888), @@ -5794,6 +5887,10 @@ static const pixman_fast_path_t sse2_fast_paths[] = PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, sse2_composite_src_n_8_8888), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, sse2_composite_src_n_8_8888), PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8b8g8r8, sse2_composite_src_n_8_8888), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, sse2_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, sse2_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, sse2_composite_src_x888_0565), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, sse2_composite_src_x888_0565), PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, a8r8g8b8, sse2_composite_src_x888_8888), PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, a8b8g8r8, sse2_composite_src_x888_8888), PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, a8r8g8b8, sse2_composite_copy_area), @@ -5839,6 +5936,9 @@ static const pixman_fast_path_t sse2_fast_paths[] = SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, a8r8g8b8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (SRC, a8r8g8b8, x8r8g8b8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (SRC, x8r8g8b8, x8r8g8b8, sse2_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, a8b8g8r8, sse2_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, a8b8g8r8, x8b8g8r8, sse2_8888_8888), + SIMPLE_BILINEAR_FAST_PATH (SRC, x8b8g8r8, x8b8g8r8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (OVER, a8r8g8b8, x8r8g8b8, sse2_8888_8888), SIMPLE_BILINEAR_FAST_PATH (OVER, a8b8g8r8, x8b8g8r8, sse2_8888_8888), @@ -6056,19 +6156,13 @@ static void sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) { pixman_image_t *image = iter->image; - int x = iter->x; - int y = iter->y; - int width = iter->width; - int height = iter->height; #define FLAGS \ - (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | FAST_PATH_BITS_IMAGE) + (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | \ + FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST) - if ((iter->flags & ITER_NARROW) && - (image->common.flags & FLAGS) == FLAGS && - x >= 0 && y >= 0 && - x + width <= image->bits.width && - y + height <= image->bits.height) + if ((iter->iter_flags & ITER_NARROW) && + (iter->image_flags & FLAGS) == FLAGS) { const fetcher_info_t *f; @@ -6079,7 +6173,7 @@ sse2_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) uint8_t *b = (uint8_t *)image->bits.bits; int s = image->bits.rowstride * 4; - iter->bits = b + s * iter->y + x * PIXMAN_FORMAT_BPP (f->format) / 8; + iter->bits = b + s * iter->y + iter->x * PIXMAN_FORMAT_BPP (f->format) / 8; iter->stride = s; iter->get_scanline = f->get_scanline; @@ -6115,6 +6209,8 @@ _pixman_implementation_create_sse2 (pixman_implementation_t *fallback) mask_ffff = create_mask_16_128 (0xffff); mask_ff000000 = create_mask_2x32_128 (0xff000000, 0xff000000); mask_alpha = create_mask_2x32_128 (0x00ff0000, 0x00000000); + mask_565_rb = create_mask_2x32_128 (0x00f800f8, 0x00f800f8); + mask_565_pack_multiplier = create_mask_2x32_128 (0x20000004, 0x20000004); /* Set up function pointers */ imp->combine_32[PIXMAN_OP_OVER] = sse2_combine_over_u; diff --git a/gfx/cairo/libpixman/src/pixman-utils.c b/gfx/cairo/libpixman/src/pixman-utils.c index de05c0e5203..83c011dfa6b 100644 --- a/gfx/cairo/libpixman/src/pixman-utils.c +++ b/gfx/cairo/libpixman/src/pixman-utils.c @@ -184,6 +184,22 @@ pixman_malloc_abc (unsigned int a, return malloc (a * b * c); } +static void +unorm_to_unorm_params (int in_width, int out_width, uint32_t *factor, int *shift) +{ + int w = 0; + + *factor = 0; + while (in_width != 0 && w < out_width) + { + *factor |= 1 << w; + w += in_width; + } + + /* Did we generate too many bits? */ + *shift = w - out_width; +} + /* * This function expands images from ARGB8 format to ARGB16. To preserve * precision, it needs to know the original source format. For example, if the @@ -213,8 +229,15 @@ pixman_expand (uint64_t * dst, r_mask = ~(~0 << r_size), g_mask = ~(~0 << g_size), b_mask = ~(~0 << b_size); + uint32_t au_factor, ru_factor, gu_factor, bu_factor; + int au_shift, ru_shift, gu_shift, bu_shift; int i; + unorm_to_unorm_params (a_size, 16, &au_factor, &au_shift); + unorm_to_unorm_params (r_size, 16, &ru_factor, &ru_shift); + unorm_to_unorm_params (g_size, 16, &gu_factor, &gu_shift); + unorm_to_unorm_params (b_size, 16, &bu_factor, &bu_shift); + /* Start at the end so that we can do the expansion in place * when src == dst */ @@ -227,7 +250,7 @@ pixman_expand (uint64_t * dst, if (a_size) { a = (pixel >> a_shift) & a_mask; - a16 = unorm_to_unorm (a, a_size, 16); + a16 = a * au_factor >> au_shift; } else { @@ -239,9 +262,9 @@ pixman_expand (uint64_t * dst, r = (pixel >> r_shift) & r_mask; g = (pixel >> g_shift) & g_mask; b = (pixel >> b_shift) & b_mask; - r16 = unorm_to_unorm (r, r_size, 16); - g16 = unorm_to_unorm (g, g_size, 16); - b16 = unorm_to_unorm (b, b_size, 16); + r16 = r * ru_factor >> ru_shift; + g16 = g * gu_factor >> gu_shift; + b16 = b * bu_factor >> bu_shift; } else { diff --git a/gfx/cairo/libpixman/src/pixman-version.h b/gfx/cairo/libpixman/src/pixman-version.h index c0f45a849aa..fac4225b076 100644 --- a/gfx/cairo/libpixman/src/pixman-version.h +++ b/gfx/cairo/libpixman/src/pixman-version.h @@ -32,10 +32,10 @@ #endif #define PIXMAN_VERSION_MAJOR 0 -#define PIXMAN_VERSION_MINOR 21 -#define PIXMAN_VERSION_MICRO 7 +#define PIXMAN_VERSION_MINOR 27 +#define PIXMAN_VERSION_MICRO 1 -#define PIXMAN_VERSION_STRING "0.21.7" +#define PIXMAN_VERSION_STRING "0.27.1" #define PIXMAN_VERSION_ENCODE(major, minor, micro) ( \ ((major) * 10000) \ diff --git a/gfx/cairo/libpixman/src/pixman-vmx.c b/gfx/cairo/libpixman/src/pixman-vmx.c index 32dff3f390e..6868704a875 100644 --- a/gfx/cairo/libpixman/src/pixman-vmx.c +++ b/gfx/cairo/libpixman/src/pixman-vmx.c @@ -25,10 +25,7 @@ * Based on fbmmx.c by Owen Taylor, Søren Sandmann and Nicholas Miell */ -#ifdef HAVE_CONFIG_H #include -#endif - #include "pixman-private.h" #include "pixman-combine32.h" #include diff --git a/gfx/cairo/libpixman/src/pixman-x86.c b/gfx/cairo/libpixman/src/pixman-x86.c new file mode 100644 index 00000000000..57e4d1f351b --- /dev/null +++ b/gfx/cairo/libpixman/src/pixman-x86.c @@ -0,0 +1,237 @@ +/* + * Copyright © 2000 SuSE, Inc. + * Copyright © 2007 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "pixman-private.h" + +#if defined(USE_X86_MMX) || defined (USE_SSE2) + +/* The CPU detection code needs to be in a file not compiled with + * "-mmmx -msse", as gcc would generate CMOV instructions otherwise + * that would lead to SIGILL instructions on old CPUs that don't have + * it. + */ + +typedef enum +{ + X86_MMX = (1 << 0), + X86_MMX_EXTENSIONS = (1 << 1), + X86_SSE = (1 << 2) | X86_MMX_EXTENSIONS, + X86_SSE2 = (1 << 3), + X86_CMOV = (1 << 4) +} cpu_features_t; + +#ifdef HAVE_GETISAX + +#include + +static cpu_features_t +detect_cpu_features (void) +{ + cpu_features_t features = 0; + unsigned int result = 0; + + if (getisax (&result, 1)) + { + if (result & AV_386_CMOV) + features |= X86_CMOV; + if (result & AV_386_MMX) + features |= X86_MMX; + if (result & AV_386_AMD_MMX) + features |= X86_MMX_EXTENSIONS; + if (result & AV_386_SSE) + features |= X86_SSE; + if (result & AV_386_SSE2) + features |= X86_SSE2; + } + + return features; +} + +#else + +#define _PIXMAN_X86_64 \ + (defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64)) + +static pixman_bool_t +have_cpuid (void) +{ +#if _PIXMAN_X86_64 || defined (_MSC_VER) + + return TRUE; + +#elif defined (__GNUC__) + uint32_t result; + + __asm__ volatile ( + "pushf" "\n\t" + "pop %%eax" "\n\t" + "mov %%eax, %%ecx" "\n\t" + "xor $0x00200000, %%eax" "\n\t" + "push %%eax" "\n\t" + "popf" "\n\t" + "pushf" "\n\t" + "pop %%eax" "\n\t" + "xor %%ecx, %%eax" "\n\t" + "mov %%eax, %0" "\n\t" + : "=r" (result) + : + : "%eax", "%ecx"); + + return !!result; + +#else +#error "Unknown compiler" +#endif +} + +static void +pixman_cpuid (uint32_t feature, + uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) +{ +#if defined (__GNUC__) + +#if _PIXMAN_X86_64 + __asm__ volatile ( + "cpuid" "\n\t" + : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) + : "a" (feature)); +#else + /* On x86-32 we need to be careful about the handling of %ebx + * and %esp. We can't declare either one as clobbered + * since they are special registers (%ebx is the "PIC + * register" holding an offset to global data, %esp the + * stack pointer), so we need to make sure that %ebx is + * preserved, and that %esp has its original value when + * accessing the output operands. + */ + __asm__ volatile ( + "xchg %%ebx, %1" "\n\t" + "cpuid" "\n\t" + "xchg %%ebx, %1" "\n\t" + : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) + : "a" (feature)); +#endif + +#elif defined (_MSC_VER) + int info[4]; + + __cpuid (info, feature); + + *a = info[0]; + *b = info[1]; + *c = info[2]; + *d = info[3]; +#else +#error Unknown compiler +#endif +} + +static cpu_features_t +detect_cpu_features (void) +{ + uint32_t a, b, c, d; + cpu_features_t features = 0; + + if (!have_cpuid()) + return features; + + /* Get feature bits */ + pixman_cpuid (0x01, &a, &b, &c, &d); + if (d & (1 << 15)) + features |= X86_CMOV; + if (d & (1 << 23)) + features |= X86_MMX; + if (d & (1 << 25)) + features |= X86_SSE; + if (d & (1 << 26)) + features |= X86_SSE2; + + /* Check for AMD specific features */ + if ((features & X86_MMX) && !(features & X86_SSE)) + { + char vendor[13]; + + /* Get vendor string */ + memset (vendor, 0, sizeof vendor); + + pixman_cpuid (0x00, &a, &b, &c, &d); + memcpy (vendor + 0, &b, 4); + memcpy (vendor + 4, &d, 4); + memcpy (vendor + 8, &c, 4); + + if (strcmp (vendor, "AuthenticAMD") == 0 || + strcmp (vendor, "Geode by NSC") == 0) + { + pixman_cpuid (0x80000000, &a, &b, &c, &d); + if (a >= 0x80000001) + { + pixman_cpuid (0x80000001, &a, &b, &c, &d); + + if (d & (1 << 22)) + features |= X86_MMX_EXTENSIONS; + } + } + } + + return features; +} + +#endif + +static pixman_bool_t +have_feature (cpu_features_t feature) +{ + static pixman_bool_t initialized; + static cpu_features_t features; + + if (!initialized) + { + features = detect_cpu_features(); + initialized = TRUE; + } + + return (features & feature) == feature; +} + +#endif + +pixman_implementation_t * +_pixman_x86_get_implementations (pixman_implementation_t *imp) +{ +#define MMX_BITS (X86_MMX | X86_MMX_EXTENSIONS) +#define SSE2_BITS (X86_MMX | X86_MMX_EXTENSIONS | X86_SSE | X86_SSE2) + +#ifdef USE_X86_MMX + if (!_pixman_disabled ("mmx") && have_feature (MMX_BITS)) + imp = _pixman_implementation_create_mmx (imp); +#endif + +#ifdef USE_SSE2 + if (!_pixman_disabled ("sse2") && have_feature (SSE2_BITS)) + imp = _pixman_implementation_create_sse2 (imp); +#endif + + return imp; +} diff --git a/gfx/cairo/libpixman/src/pixman.c b/gfx/cairo/libpixman/src/pixman.c index 8fb53568fbe..994ef388c7c 100644 --- a/gfx/cairo/libpixman/src/pixman.c +++ b/gfx/cairo/libpixman/src/pixman.c @@ -30,7 +30,7 @@ #include -static pixman_implementation_t *global_implementation; +pixman_implementation_t *global_implementation; #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR static void __attribute__((constructor)) @@ -40,16 +40,6 @@ pixman_constructor (void) } #endif -static force_inline pixman_implementation_t * -get_implementation (void) -{ -#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR - if (!global_implementation) - global_implementation = _pixman_choose_implementation (); -#endif - return global_implementation; -} - typedef struct operator_info_t operator_info_t; struct operator_info_t @@ -234,19 +224,19 @@ clip_source_image (pixman_region32_t * region, * returns FALSE if the final region is empty. Indistinguishable from * an allocation failure, but rendering ignores those anyways. */ -static pixman_bool_t -pixman_compute_composite_region32 (pixman_region32_t * region, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dest_image, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +pixman_bool_t +_pixman_compute_composite_region32 (pixman_region32_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dest_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { region->extents.x1 = dest_x; region->extents.x2 = dest_x + width; @@ -625,7 +615,7 @@ pixman_image_composite32 (pixman_op_t op, pixman_region32_init (®ion); - if (!pixman_compute_composite_region32 ( + if (!_pixman_compute_composite_region32 ( ®ion, src, mask, dest, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) { @@ -1027,6 +1017,7 @@ pixman_format_supported_source (pixman_format_code_t format) case PIXMAN_a2r10g10b10: case PIXMAN_x2r10g10b10: case PIXMAN_a8r8g8b8: + case PIXMAN_a8r8g8b8_sRGB: case PIXMAN_x8r8g8b8: case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: @@ -1124,7 +1115,7 @@ pixman_compute_composite_region (pixman_region16_t * region, pixman_region32_init (&r32); - retval = pixman_compute_composite_region32 ( + retval = _pixman_compute_composite_region32 ( &r32, src_image, mask_image, dest_image, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height); diff --git a/gfx/cairo/libpixman/src/pixman.h b/gfx/cairo/libpixman/src/pixman.h index 0c6ce62383e..bfb056d31e8 100644 --- a/gfx/cairo/libpixman/src/pixman.h +++ b/gfx/cairo/libpixman/src/pixman.h @@ -655,6 +655,7 @@ struct pixman_indexed #define PIXMAN_TYPE_YV12 7 #define PIXMAN_TYPE_BGRA 8 #define PIXMAN_TYPE_RGBA 9 +#define PIXMAN_TYPE_ARGB_SRGB 10 #define PIXMAN_FORMAT_COLOR(f) \ (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \ @@ -678,6 +679,9 @@ typedef enum { PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10), PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10), +/* sRGB formats */ + PIXMAN_a8r8g8b8_sRGB = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB_SRGB,8,8,8,8), + /* 24bpp formats */ PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8), @@ -869,6 +873,65 @@ void pixman_image_composite32 (pixman_op_t op, */ void pixman_disable_out_of_bounds_workaround (void); +/* + * Glyphs + */ +typedef struct pixman_glyph_cache_t pixman_glyph_cache_t; +typedef struct +{ + int x, y; + const void *glyph; +} pixman_glyph_t; + +pixman_glyph_cache_t *pixman_glyph_cache_create (void); +void pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache); +void pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache); +void pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache); +const void * pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key); +const void * pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key, + int origin_x, + int origin_y, + pixman_image_t *glyph_image); +void pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key); +void pixman_glyph_get_extents (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs, + pixman_box32_t *extents); +pixman_format_code_t pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t * glyphs); +void pixman_composite_glyphs (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + pixman_format_code_t mask_format, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs); +void pixman_composite_glyphs_no_mask (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t dest_x, + int32_t dest_y, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs); + /* * Trapezoids */ From 96940593d7bb559d40bfee9e64cb518593366e2e Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:30:12 -0800 Subject: [PATCH 25/70] Bug 822289 trivial followup: remove completely-unused 'nsresult rv' in InMemoryDataSource::GetAllResources. --- rdf/base/src/nsInMemoryDataSource.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/rdf/base/src/nsInMemoryDataSource.cpp b/rdf/base/src/nsInMemoryDataSource.cpp index b711778626a..42189a38a3e 100644 --- a/rdf/base/src/nsInMemoryDataSource.cpp +++ b/rdf/base/src/nsInMemoryDataSource.cpp @@ -1758,8 +1758,6 @@ InMemoryDataSource::ResourceEnumerator(PLDHashTable* aTable, NS_IMETHODIMP InMemoryDataSource::GetAllResources(nsISimpleEnumerator** aResult) { - nsresult rv; - nsCOMArray nodes; if (!nodes.SetCapacity(mForwardArcs.entryCount)) { return NS_ERROR_OUT_OF_MEMORY; From e6de6b4afd6f07432242e06d20493e4f535ebd6a Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:30:13 -0800 Subject: [PATCH 26/70] Bug 835715: #undef LOG at the top of nsJARChannel.cpp to fix build warning about it being (re)defined later on. r=jduell --- modules/libjar/nsJARChannel.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index 348ebbc7a38..c6eb053e71c 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -36,6 +36,12 @@ static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); //----------------------------------------------------------------------------- +// Ignore any LOG macro that we inherit from arbitrary headers. (We define our +// own LOG macro below.) +#ifdef LOG +#undef LOG +#endif + #if defined(PR_LOGGING) // // set NSPR_LOG_MODULES=nsJarProtocol:5 @@ -43,6 +49,7 @@ static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID); static PRLogModuleInfo *gJarProtocolLog = nullptr; #endif +// If you ever want to define PR_FORCE_LOGGING in this file, see bug 545995 #define LOG(args) PR_LOG(gJarProtocolLog, PR_LOG_DEBUG, args) #define LOG_ENABLED() PR_LOG_TEST(gJarProtocolLog, 4) From b0a333bc267170e4e05711f07afb23aecf645f02 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:30:13 -0800 Subject: [PATCH 27/70] Bug 835912: Mark modules/libjar as FAIL_ON_WARNINGS. r=jduell --- modules/libjar/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/libjar/Makefile.in b/modules/libjar/Makefile.in index c4dd63b2172..c375524018c 100644 --- a/modules/libjar/Makefile.in +++ b/modules/libjar/Makefile.in @@ -29,6 +29,7 @@ IS_COMPONENT = 1 MODULE_NAME = nsJarModule GRE_MODULE = 1 LIBXUL_LIBRARY = 1 +FAIL_ON_WARNINGS = 1 CPPSRCS = $(MODULES_LIBJAR_LCPPSRCS) From f4414b6e56e505311879a942250d2060efea4e40 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:30:13 -0800 Subject: [PATCH 28/70] Bug 835915: Iterate across nsTArray using a size_t loop counter instead of an int. r=ehsan --- tools/profiler/JSCustomObjectBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/profiler/JSCustomObjectBuilder.cpp b/tools/profiler/JSCustomObjectBuilder.cpp index 741ebf75515..66d501e1b24 100644 --- a/tools/profiler/JSCustomObjectBuilder.cpp +++ b/tools/profiler/JSCustomObjectBuilder.cpp @@ -208,7 +208,7 @@ operator<<(std::ostream& stream, JSCustomArray* entry) { bool needsComma = false; stream << "["; - for (int i = 0; i < entry->mValues.Length(); i++) { + for (size_t i = 0; i < entry->mValues.Length(); i++) { if (needsComma) { stream << ","; } From 2394710e260d4e6d35d78ded2e716f83d5aada80 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:30:13 -0800 Subject: [PATCH 29/70] Bug 835543 part 1: Remove unused class nsNavHistoryFullVisitResultNode. r=mak --- .../components/places/nsNavHistoryResult.cpp | 18 ---------- .../components/places/nsNavHistoryResult.h | 33 ------------------- 2 files changed, 51 deletions(-) diff --git a/toolkit/components/places/nsNavHistoryResult.cpp b/toolkit/components/places/nsNavHistoryResult.cpp index d519c603117..10530862780 100644 --- a/toolkit/components/places/nsNavHistoryResult.cpp +++ b/toolkit/components/places/nsNavHistoryResult.cpp @@ -302,24 +302,6 @@ nsNavHistoryVisitResultNode::nsNavHistoryVisitResultNode( { } - -NS_IMPL_ISUPPORTS_INHERITED1(nsNavHistoryFullVisitResultNode, - nsNavHistoryVisitResultNode, - nsINavHistoryFullVisitResultNode) - -nsNavHistoryFullVisitResultNode::nsNavHistoryFullVisitResultNode( - const nsACString& aURI, const nsACString& aTitle, uint32_t aAccessCount, - PRTime aTime, const nsACString& aIconURI, int64_t aSession, - int64_t aVisitId, int64_t aReferringVisitId, int32_t aTransitionType) : - nsNavHistoryVisitResultNode(aURI, aTitle, aAccessCount, aTime, aIconURI, - aSession), - mVisitId(aVisitId), - mReferringVisitId(aReferringVisitId), - mTransitionType(aTransitionType) -{ -} - - NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsNavHistoryContainerResultNode, nsNavHistoryResultNode) NS_IMPL_CYCLE_COLLECTION_UNLINK(mResult) NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildren) diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h index b2f216681c0..2283effda60 100644 --- a/toolkit/components/places/nsNavHistoryResult.h +++ b/toolkit/components/places/nsNavHistoryResult.h @@ -416,39 +416,6 @@ public: }; -// nsNavHistoryFullVisitResultNode - -#define NS_IMPLEMENT_FULLVISITRESULT \ - NS_IMPLEMENT_VISITRESULT \ - NS_IMETHOD GetVisitId(int64_t *aVisitId) \ - { *aVisitId = mVisitId; return NS_OK; } \ - NS_IMETHOD GetReferringVisitId(int64_t *aReferringVisitId) \ - { *aReferringVisitId = mReferringVisitId; return NS_OK; } \ - NS_IMETHOD GetTransitionType(int32_t *aTransitionType) \ - { *aTransitionType = mTransitionType; return NS_OK; } - -class nsNavHistoryFullVisitResultNode : public nsNavHistoryVisitResultNode, - public nsINavHistoryFullVisitResultNode -{ -public: - nsNavHistoryFullVisitResultNode( - const nsACString& aURI, const nsACString& aTitle, uint32_t aAccessCount, - PRTime aTime, const nsACString& aIconURI, int64_t aSession, - int64_t aVisitId, int64_t aReferringVisitId, int32_t aTransitionType); - - NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_COMMON_RESULTNODE_TO_BASE - NS_IMETHOD GetType(uint32_t* type) - { *type = nsNavHistoryResultNode::RESULT_TYPE_FULL_VISIT; return NS_OK; } - NS_IMPLEMENT_FULLVISITRESULT - -public: - int64_t mVisitId; - int64_t mReferringVisitId; - int32_t mTransitionType; -}; - - // nsNavHistoryContainerResultNode // // This is the base class for all nodes that can have children. It is From e5d02104607baabe3e66f5c37352566b024f75a0 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:30:13 -0800 Subject: [PATCH 30/70] Bug 835543 part 2: Remove deprecated interface nsINavHistoryFullVisitResultNode. r=mak --- .../components/places/content/controller.js | 1 - toolkit/components/places/PlacesUtils.jsm | 8 +--- .../places/nsINavHistoryService.idl | 38 ++++--------------- .../components/places/nsNavHistoryResult.h | 6 +-- 4 files changed, 12 insertions(+), 41 deletions(-) diff --git a/browser/components/places/content/controller.js b/browser/components/places/content/controller.js index 34f0bfa9b41..18a08360173 100644 --- a/browser/components/places/content/controller.js +++ b/browser/components/places/content/controller.js @@ -460,7 +460,6 @@ PlacesController.prototype = { break; case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI: case Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT: - case Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT: nodeData["link"] = true; uri = NetUtil.newURI(node.uri); if (PlacesUtils.nodeIsBookmark(node)) { diff --git a/toolkit/components/places/PlacesUtils.jsm b/toolkit/components/places/PlacesUtils.jsm index f08178087a1..4528d47f699 100644 --- a/toolkit/components/places/PlacesUtils.jsm +++ b/toolkit/components/places/PlacesUtils.jsm @@ -66,7 +66,6 @@ function QI_node(aNode, aIID) { return result; } function asVisit(aNode) QI_node(aNode, Ci.nsINavHistoryVisitResultNode); -function asFullVisit(aNode) QI_node(aNode, Ci.nsINavHistoryFullVisitResultNode); function asContainer(aNode) QI_node(aNode, Ci.nsINavHistoryContainerResultNode); function asQuery(aNode) QI_node(aNode, Ci.nsINavHistoryQueryResultNode); @@ -104,7 +103,6 @@ this.PlacesUtils = { TOPIC_BOOKMARKS_RESTORE_FAILED: "bookmarks-restore-failed", asVisit: function(aNode) asVisit(aNode), - asFullVisit: function(aNode) asFullVisit(aNode), asContainer: function(aNode) asContainer(aNode), asQuery: function(aNode) asQuery(aNode), @@ -182,8 +180,7 @@ this.PlacesUtils = { */ nodeIsVisit: function PU_nodeIsVisit(aNode) { var type = aNode.type; - return type == Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT || - type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT; + return type == Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT; }, /** @@ -193,8 +190,7 @@ this.PlacesUtils = { * @returns true if the node is a URL item, false otherwise */ uriTypes: [Ci.nsINavHistoryResultNode.RESULT_TYPE_URI, - Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT, - Ci.nsINavHistoryResultNode.RESULT_TYPE_FULL_VISIT], + Ci.nsINavHistoryResultNode.RESULT_TYPE_VISIT], nodeIsURI: function PU_nodeIsURI(aNode) { return this.uriTypes.indexOf(aNode.type) != -1; }, diff --git a/toolkit/components/places/nsINavHistoryService.idl b/toolkit/components/places/nsINavHistoryService.idl index 977f2400fed..8409986a5c1 100644 --- a/toolkit/components/places/nsINavHistoryService.idl +++ b/toolkit/components/places/nsINavHistoryService.idl @@ -51,10 +51,15 @@ interface nsINavHistoryResultNode : nsISupports */ const unsigned long RESULT_TYPE_URI = 0; // nsINavHistoryResultNode const unsigned long RESULT_TYPE_VISIT = 1; // nsINavHistoryVisitResultNode - const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode + + // Full visit nodes are deprecated and unsupported. + // This line exists just to avoid reusing the value: + // const unsigned long RESULT_TYPE_FULL_VISIT = 2; // nsINavHistoryFullVisitResultNode + // Dynamic containers are deprecated and unsupported. - // This const exists just to avoid reusing the value. - const unsigned long RESULT_TYPE_DYNAMIC_CONTAINER = 4; // nsINavHistoryContainerResultNode + // This const exists just to avoid reusing the value: + // const unsigned long RESULT_TYPE_DYNAMIC_CONTAINER = 4; // nsINavHistoryContainerResultNode + const unsigned long RESULT_TYPE_QUERY = 5; // nsINavHistoryQueryResultNode const unsigned long RESULT_TYPE_FOLDER = 6; // nsINavHistoryQueryResultNode const unsigned long RESULT_TYPE_SEPARATOR = 7; // nsINavHistoryResultNode @@ -165,33 +170,6 @@ interface nsINavHistoryVisitResultNode : nsINavHistoryResultNode }; -/** - * This structure will be returned when you request RESULT_TYPE_FULL_VISIT in - * the query options. This includes uncommonly used information about each - * visit. - */ -[scriptable, uuid(c49fd9d5-56e2-43eb-932c-f933f28cba85)] -interface nsINavHistoryFullVisitResultNode : nsINavHistoryVisitResultNode -{ - /** - * This indicates the visit ID of the visit. - */ - readonly attribute long long visitId; - - /** - * This indicates the referring visit ID of the visit. The referrer should - * have the same sessionId. - */ - readonly attribute long long referringVisitId; - - /** - * Indicates the transition type of the visit. - * One of nsINavHistoryService.TRANSITION_* - */ - readonly attribute long transitionType; -}; - - /** * Base class for container results. This includes all types of groupings. * Bookmark folders and places queries will be QueryResultNodes which extends diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h index 2283effda60..1883c7f37b9 100644 --- a/toolkit/components/places/nsNavHistoryResult.h +++ b/toolkit/components/places/nsNavHistoryResult.h @@ -303,8 +303,7 @@ public: } static bool IsTypeURI(uint32_t type) { return (type == nsINavHistoryResultNode::RESULT_TYPE_URI || - type == nsINavHistoryResultNode::RESULT_TYPE_VISIT || - type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT); + type == nsINavHistoryResultNode::RESULT_TYPE_VISIT); } bool IsURI() { uint32_t type; @@ -312,8 +311,7 @@ public: return IsTypeURI(type); } static bool IsTypeVisit(uint32_t type) { - return (type == nsINavHistoryResultNode::RESULT_TYPE_VISIT || - type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT); + return type == nsINavHistoryResultNode::RESULT_TYPE_VISIT; } bool IsVisit() { uint32_t type; From 2b6dbe05307cd78d516ac395a14c6973d1723cda Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:35:54 -0800 Subject: [PATCH 31/70] backout 2620d0977696 because it landed w/ wrong bug number --- rdf/base/src/nsInMemoryDataSource.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rdf/base/src/nsInMemoryDataSource.cpp b/rdf/base/src/nsInMemoryDataSource.cpp index 42189a38a3e..b711778626a 100644 --- a/rdf/base/src/nsInMemoryDataSource.cpp +++ b/rdf/base/src/nsInMemoryDataSource.cpp @@ -1758,6 +1758,8 @@ InMemoryDataSource::ResourceEnumerator(PLDHashTable* aTable, NS_IMETHODIMP InMemoryDataSource::GetAllResources(nsISimpleEnumerator** aResult) { + nsresult rv; + nsCOMArray nodes; if (!nodes.SetCapacity(mForwardArcs.entryCount)) { return NS_ERROR_OUT_OF_MEMORY; From f2bb846f2b83fa6f617feab9410d87f202aa9702 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 14:30:12 -0800 Subject: [PATCH 32/70] Bug 819936 trivial followup: remove completely-unused 'nsresult rv' in InMemoryDataSource::GetAllResources. (DONTBUILD because just re-landing w/ fixed bug number) --- rdf/base/src/nsInMemoryDataSource.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/rdf/base/src/nsInMemoryDataSource.cpp b/rdf/base/src/nsInMemoryDataSource.cpp index b711778626a..42189a38a3e 100644 --- a/rdf/base/src/nsInMemoryDataSource.cpp +++ b/rdf/base/src/nsInMemoryDataSource.cpp @@ -1758,8 +1758,6 @@ InMemoryDataSource::ResourceEnumerator(PLDHashTable* aTable, NS_IMETHODIMP InMemoryDataSource::GetAllResources(nsISimpleEnumerator** aResult) { - nsresult rv; - nsCOMArray nodes; if (!nodes.SetCapacity(mForwardArcs.entryCount)) { return NS_ERROR_OUT_OF_MEMORY; From ad9a101b7d68e34a473c89e10a55e5f8f6e21ba9 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 29 Jan 2013 23:49:35 +0100 Subject: [PATCH 33/70] Bug 725587 - Firefox jumps randomly from IPv6 to IPv4 and vice versa in dual-stack environment, r=mcmanus --- netwerk/base/public/nsISocketTransport.idl | 6 +++ netwerk/base/src/nsSocketTransport2.cpp | 19 ++++--- netwerk/dns/nsDNSService2.cpp | 3 ++ netwerk/dns/nsIDNSService.idl | 5 ++ netwerk/protocol/http/nsHttpChannel.cpp | 4 +- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 52 +++++++++++++++++-- netwerk/protocol/http/nsHttpConnectionMgr.h | 17 ++++++ 7 files changed, 95 insertions(+), 11 deletions(-) diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index cf43807f5b8..0c8c585aadd 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -163,6 +163,12 @@ interface nsISocketTransport : nsITransport */ const unsigned long NO_PERMANENT_STORAGE = (1 << 3); + /** + * If set, we will skip all IPv4 addresses the host may have and only + * connect to IPv6 ones. + */ + const unsigned long DISABLE_IPV4 = (1 << 4); + /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 0396e75b99d..7dd872ad19c 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -926,6 +926,12 @@ nsSocketTransport::ResolveHost() dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; if (mConnectionFlags & nsSocketTransport::DISABLE_IPV6) dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6; + if (mConnectionFlags & nsSocketTransport::DISABLE_IPV4) + dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4; + + NS_ASSERTION(!(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV6) || + !(dnsFlags & nsIDNSService::RESOLVE_DISABLE_IPV4), + "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4"); SendStatus(NS_NET_STATUS_RESOLVING_HOST); rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nullptr, @@ -1267,12 +1273,12 @@ nsSocketTransport::RecoverFromError() bool tryAgain = false; - if (mConnectionFlags & DISABLE_IPV6 && + if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4) && mCondition == NS_ERROR_UNKNOWN_HOST && mState == STATE_RESOLVING && !mProxyTransparentResolvesHost) { SOCKET_LOG((" trying lookup again with both ipv4/ipv6 enabled\n")); - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } @@ -1285,14 +1291,15 @@ nsSocketTransport::RecoverFromError() SOCKET_LOG((" trying again with next ip address\n")); tryAgain = true; } - else if (mConnectionFlags & DISABLE_IPV6) { + else if (mConnectionFlags & (DISABLE_IPV6 | DISABLE_IPV4)) { // Drop state to closed. This will trigger new round of DNS // resolving bellow. - // XXX Here should idealy be set now non-existing flag DISABLE_IPV4 - SOCKET_LOG((" failed to connect all ipv4 hosts," + // XXX Could be optimized to only switch the flags to save duplicate + // connection attempts. + SOCKET_LOG((" failed to connect all ipv4-only or ipv6-only hosts," " trying lookup/connect again with both ipv4/ipv6\n")); mState = STATE_CLOSED; - mConnectionFlags &= ~DISABLE_IPV6; + mConnectionFlags &= ~(DISABLE_IPV6 | DISABLE_IPV4); tryAgain = true; } } diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp index f1fe85b2460..05be514c72f 100644 --- a/netwerk/dns/nsDNSService2.cpp +++ b/netwerk/dns/nsDNSService2.cpp @@ -850,6 +850,9 @@ nsDNSService::GetAFForLookup(const nsACString &host, uint32_t flags) } while (*end); } + if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4)) + af = PR_AF_INET6; + return af; } diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl index 6b06a194f83..183ca004422 100644 --- a/netwerk/dns/nsIDNSService.idl +++ b/netwerk/dns/nsIDNSService.idl @@ -134,4 +134,9 @@ interface nsIDNSService : nsISupports * asyncResolve. */ const unsigned long RESOLVE_OFFLINE = (1 << 6); + + /** + * If set, only IPv6 addresses will be returned from resolve/asyncResolve. + */ + const unsigned long RESOLVE_DISABLE_IPV4 = (1 << 7); }; diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 4eca5e109cd..d15af44d21e 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -4484,8 +4484,10 @@ nsHttpChannel::BeginConnect() // Force-Reload should reset the persistent connection pool for this host if (mLoadFlags & LOAD_FRESH_CONNECTION) { // just the initial document resets the whole pool - if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) + if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) { gHttpHandler->ConnMgr()->ClosePersistentConnections(); + gHttpHandler->ConnMgr()->ResetIPFamillyPreference(mConnectionInfo); + } // each sub resource gets a fresh connection mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING); } diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index e079b15e6bd..d46a1fa6362 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -2521,8 +2521,13 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, // IPv6 on the backup connection gives them a much better user experience // with dual-stack hosts, though they still pay the 250ms delay for each new // connection. This strategy is also known as "happy eyeballs". - if (isBackup && gHttpHandler->FastFallbackToIPv4()) + if (mEnt->mPreferIPv6) { + tmpFlags |= nsISocketTransport::DISABLE_IPV4; + } + else if (mEnt->mPreferIPv4 || + (isBackup && gHttpHandler->FastFallbackToIPv4())) { tmpFlags |= nsISocketTransport::DISABLE_IPV6; + } socketTransport->SetConnectionFlags(tmpFlags); @@ -2714,6 +2719,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) LOG(("nsHalfOpenSocket::OnOutputStreamReady " "Created new nshttpconnection %p\n", conn.get())); + NetAddr peeraddr; nsCOMPtr callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks)); if (out == mStreamOut) { @@ -2724,6 +2730,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mStreamOut = nullptr; mStreamIn = nullptr; @@ -2737,6 +2746,9 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) callbacks, PR_MillisecondsToInterval(rtt.ToMilliseconds())); + if (NS_SUCCEEDED(mBackupTransport->GetPeerAddr(&peeraddr))) + mEnt->RecordIPFamilyPreference(peeraddr.raw.family); + // The nsHttpConnection object now owns these streams and sockets mBackupStreamOut = nullptr; mBackupStreamIn = nullptr; @@ -2949,6 +2961,8 @@ nsConnectionEntry::nsConnectionEntry(nsHttpConnectionInfo *ci) , mUsingSpdy(false) , mTestedSpdy(false) , mSpdyPreferred(false) + , mPreferIPv4(false) + , mPreferIPv6(false) { NS_ADDREF(mConnInfo); if (gHttpHandler->GetPipelineAggressive()) { @@ -3104,7 +3118,8 @@ nsConnectionEntry::SetYellowConnection(nsHttpConnection *conn) } void -nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() +nsHttpConnectionMgr:: +nsConnectionEntry::OnYellowComplete() { if (mPipelineState == PS_YELLOW) { if (mYellowGoodEvents && !mYellowBadEvents) { @@ -3127,7 +3142,8 @@ nsHttpConnectionMgr::nsConnectionEntry::OnYellowComplete() } void -nsHttpConnectionMgr::nsConnectionEntry::CreditPenalty() +nsHttpConnectionMgr:: +nsConnectionEntry::CreditPenalty() { if (mLastCreditTime.IsNull()) return; @@ -3223,8 +3239,17 @@ nsHttpConnectionMgr::GetConnectionData(nsTArray *aA return true; } +void +nsHttpConnectionMgr::ResetIPFamillyPreference(nsHttpConnectionInfo *ci) +{ + nsConnectionEntry *ent = LookupConnectionEntry(ci, nullptr, nullptr); + if (ent) + ent->ResetIPFamilyPreference(); +} + uint32_t -nsHttpConnectionMgr::nsConnectionEntry::UnconnectedHalfOpens() +nsHttpConnectionMgr:: +nsConnectionEntry::UnconnectedHalfOpens() { uint32_t unconnectedHalfOpens = 0; for (uint32_t i = 0; i < mHalfOpens.Length(); ++i) { @@ -3250,3 +3275,22 @@ nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen) // altering the pending q vector from an arbitrary stack gHttpHandler->ConnMgr()->ProcessPendingQ(mConnInfo); } + +void +nsHttpConnectionMgr:: +nsConnectionEntry::RecordIPFamilyPreference(uint16_t family) +{ + if (family == PR_AF_INET && !mPreferIPv6) + mPreferIPv4 = true; + + if (family == PR_AF_INET6 && !mPreferIPv4) + mPreferIPv6 = true; +} + +void +nsHttpConnectionMgr:: +nsConnectionEntry::ResetIPFamilyPreference() +{ + mPreferIPv4 = false; + mPreferIPv6 = false; +} diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.h b/netwerk/protocol/http/nsHttpConnectionMgr.h index a27b9598959..30d917bc6ea 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.h +++ b/netwerk/protocol/http/nsHttpConnectionMgr.h @@ -225,6 +225,9 @@ public: bool SupportsPipelining(nsHttpConnectionInfo *); bool GetConnectionData(nsTArray *); + + void ResetIPFamillyPreference(nsHttpConnectionInfo *); + private: virtual ~nsHttpConnectionMgr(); @@ -343,6 +346,20 @@ private: bool mTestedSpdy; bool mSpdyPreferred; + + // Flags to remember our happy-eyeballs decision. + // Reset only by Ctrl-F5 reload. + // True when we've first connected an IPv4 server for this host, + // initially false. + bool mPreferIPv4 : 1; + // True when we've first connected an IPv6 server for this host, + // initially false. + bool mPreferIPv6 : 1; + + // Set the IP family preference flags according the connected family + void RecordIPFamilyPreference(uint16_t family); + // Resets all flags to their default values + void ResetIPFamilyPreference(); }; // nsConnectionHandle From a2dcee3f253dad3948f376db96a3c41ab7f434ee Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 29 Jan 2013 17:53:52 -0500 Subject: [PATCH 34/70] Bug 835417 part 1. Mark Node.namespaceURI as not throwing, since [Constant] things aren't allowed to throw (though we were not enforcing that). r=peterv --- content/base/public/nsINode.h | 9 ++++----- content/base/public/nsINodeInfo.h | 2 +- content/base/src/nsNodeInfo.cpp | 15 ++++++++------- content/base/src/nsNodeInfo.h | 2 +- .../xul/document/src/nsXULPrototypeDocument.cpp | 5 +---- dom/webidl/Node.webidl | 2 +- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index 9c221d222b9..a65505092f9 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -1550,9 +1550,9 @@ public: already_AddRefed CloneNode(bool aDeep, mozilla::ErrorResult& aError); bool IsEqualNode(nsINode* aNode); bool IsSupported(const nsAString& aFeature, const nsAString& aVersion); - void GetNamespaceURI(nsAString& aNamespaceURI, mozilla::ErrorResult& aError) const + void GetNamespaceURI(nsAString& aNamespaceURI) const { - aError = mNodeInfo->GetNamespaceURI(aNamespaceURI); + mNodeInfo->GetNamespaceURI(aNamespaceURI); } #ifdef MOZILLA_INTERNAL_API void GetPrefix(nsAString& aPrefix) @@ -2000,9 +2000,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID) } \ NS_IMETHOD GetNamespaceURI(nsAString& aNamespaceURI) __VA_ARGS__ \ { \ - mozilla::ErrorResult rv; \ - nsINode::GetNamespaceURI(aNamespaceURI, rv); \ - return rv.ErrorCode(); \ + nsINode::GetNamespaceURI(aNamespaceURI); \ + return NS_OK; \ } \ NS_IMETHOD GetPrefix(nsAString& aPrefix) __VA_ARGS__ \ { \ diff --git a/content/base/public/nsINodeInfo.h b/content/base/public/nsINodeInfo.h index dc7fbc05361..d7dc1d6db6d 100644 --- a/content/base/public/nsINodeInfo.h +++ b/content/base/public/nsINodeInfo.h @@ -132,7 +132,7 @@ public: /* * Get the namespace URI for a node, if the node has a namespace URI. */ - virtual nsresult GetNamespaceURI(nsAString& aNameSpaceURI) const = 0; + virtual void GetNamespaceURI(nsAString& aNameSpaceURI) const = 0; /* * Get the namespace ID for a node if the node has a namespace, if not this diff --git a/content/base/src/nsNodeInfo.cpp b/content/base/src/nsNodeInfo.cpp index 78f6c8dd380..4ff1ed65cc5 100644 --- a/content/base/src/nsNodeInfo.cpp +++ b/content/base/src/nsNodeInfo.cpp @@ -208,19 +208,20 @@ NS_INTERFACE_MAP_END // nsINodeInfo -nsresult +void nsNodeInfo::GetNamespaceURI(nsAString& aNameSpaceURI) const { - nsresult rv = NS_OK; - if (mInner.mNamespaceID > 0) { - rv = nsContentUtils::NameSpaceManager()->GetNameSpaceURI(mInner.mNamespaceID, - aNameSpaceURI); + nsresult rv = + nsContentUtils::NameSpaceManager()->GetNameSpaceURI(mInner.mNamespaceID, + aNameSpaceURI); + // How can we possibly end up with a bogus namespace ID here? + if (NS_FAILED(rv)) { + MOZ_CRASH(); + } } else { SetDOMStringToNull(aNameSpaceURI); } - - return rv; } diff --git a/content/base/src/nsNodeInfo.h b/content/base/src/nsNodeInfo.h index 0384e6896b1..4a9905d587a 100644 --- a/content/base/src/nsNodeInfo.h +++ b/content/base/src/nsNodeInfo.h @@ -29,7 +29,7 @@ public: NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(nsNodeInfo) // nsINodeInfo - virtual nsresult GetNamespaceURI(nsAString& aNameSpaceURI) const; + virtual void GetNamespaceURI(nsAString& aNameSpaceURI) const; virtual bool NamespaceEquals(const nsAString& aNamespaceURI) const; // nsNodeInfo diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index e480f997c3f..cb55bc251e9 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -478,10 +478,7 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream) NS_ENSURE_TRUE(nodeInfo, NS_ERROR_FAILURE); nsAutoString namespaceURI; - tmp = nodeInfo->GetNamespaceURI(namespaceURI); - if (NS_FAILED(tmp)) { - rv = tmp; - } + nodeInfo->GetNamespaceURI(namespaceURI); tmp = aStream->WriteWStringZ(namespaceURI.get()); if (NS_FAILED(tmp)) { rv = tmp; diff --git a/dom/webidl/Node.webidl b/dom/webidl/Node.webidl index f86c04930ef..a5300c5defe 100644 --- a/dom/webidl/Node.webidl +++ b/dom/webidl/Node.webidl @@ -82,7 +82,7 @@ interface Node : EventTarget { readonly attribute NamedNodeMap? attributes; // If we move namespaceURI, prefix and localName to Element they should return // a non-nullable type. - [Throws, Constant] + [Constant] readonly attribute DOMString? namespaceURI; [Constant] readonly attribute DOMString? prefix; From 89d5ad423c1d16a18a4a678c4d06195713726509 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 29 Jan 2013 17:53:53 -0500 Subject: [PATCH 35/70] Bug 835417 part 2. Implement WebIDL parser and codegen support for marking things pure. r=peterv --- dom/bindings/Codegen.py | 34 ++++++++++++++++++++++------------ dom/bindings/parser/WebIDL.py | 15 +++++++++++++-- dom/webidl/Document.webidl | 2 +- js/src/jsfriendapi.h | 3 +++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 4eb8cca1e47..edbfaf738a5 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -4547,11 +4547,13 @@ class CGMemberJITInfo(CGThing): return "" def defineJitInfo(self, infoName, opName, opType, infallible, constant, - returnTypes): + pure, returnTypes): + assert(not constant or pure) # constants are always pure protoID = "prototypes::id::%s" % self.descriptor.name depth = "PrototypeTraits<%s>::Depth" % protoID failstr = toStringBool(infallible) conststr = toStringBool(constant) + purestr = toStringBool(pure) returnType = reduce(CGMemberJITInfo.getSingleReturnType, returnTypes, "") return ("\n" @@ -4562,26 +4564,30 @@ class CGMemberJITInfo(CGThing): " JSJitInfo::%s,\n" " %s, /* isInfallible. False in setters. */\n" " %s, /* isConstant. Only relevant for getters. */\n" + " %s, /* isPure. Only relevant for getters. */\n" " %s /* returnType. Only relevant for getters/methods. */\n" "};\n" % (infoName, opName, protoID, depth, opType, failstr, - conststr, returnType)) + conststr, purestr, returnType)) def define(self): if self.member.isAttr(): getterinfo = ("%s_getterinfo" % self.member.identifier.name) getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name) getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True) - getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor) getterconst = self.member.getExtendedAttribute("Constant") + getterpure = getterconst or self.member.getExtendedAttribute("Pure") + assert (getterinfal or (not getterconst and not getterpure)) + + getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor) result = self.defineJitInfo(getterinfo, getter, "Getter", - getterinfal, getterconst, + getterinfal, getterconst, getterpure, [self.member.type]) if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None: setterinfo = ("%s_setterinfo" % self.member.identifier.name) setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name) # Setters are always fallible, since they have to do a typed unwrap. result += self.defineJitInfo(setterinfo, setter, "Setter", - False, False, + False, False, False, [BuiltinTypes[IDLBuiltinType.Types.void]]) return result if self.member.isMethod(): @@ -4593,18 +4599,22 @@ class CGMemberJITInfo(CGThing): # Methods are infallible if they are infallible, have no arguments # to unwrap, and have a return type that's infallible to wrap up for # return. - methodInfal = False sigs = self.member.signatures() - if len(sigs) == 1: - # Don't handle overloading. If there's more than one signature, + if len(sigs) != 1: + # Don't handle overloading. If there's more than one signature, # one of them must take arguments. + methodInfal = False + else: sig = sigs[0] - if len(sig[1]) == 0 and infallibleForMember(self.member, sig[0], self.descriptor): - # No arguments and infallible return boxing - methodInfal = True + if (len(sig[1]) != 0 or + not infallibleForMember(self.member, sig[0], self.descriptor)): + # We have arguments or our return-value boxing can fail + methodInfal = False + else: + methodInfal = "infallible" in self.descriptor.getExtendedAttributes(self.member) result = self.defineJitInfo(methodinfo, method, "Method", - methodInfal, False, + methodInfal, False, False, [s[0] for s in sigs]) return result raise TypeError("Illegal member type to CGPropertyJITInfo") diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 825eb83e4dc..90c3da15560 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -2194,6 +2194,14 @@ class IDLAttribute(IDLInterfaceMember): raise WebIDLError("Readonly attributes must not be flagged as " "[SetterThrows]", [self.location]) + elif (((identifier == "Throws" or identifier == "GetterThrows") and + (self.getExtendedAttribute("Pure") or + self.getExtendedAttribute("Constant"))) or + ((identifier == "Pure" or identifier == "Constant") and + (self.getExtendedAttribute("Throws") or + self.getExtendedAttribute("GetterThrows")))): + raise WebIDLError("Throwing things can't be [Pure] or [Constant]", + [attr.location]) elif identifier == "LenientThis": if not attr.noArguments(): raise WebIDLError("[LenientThis] must take no arguments", @@ -2736,8 +2744,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope): "[Unforgeable]", [attr.location, self.location]) elif identifier == "Constant": - raise WebIDLError("Methods must not be flagged as " - "[Constant]", + raise WebIDLError("Methods must not be flagged as [Constant]", + [attr.location, self.location]); + elif identifier == "Pure": + raise WebIDLError("Methods must not be flagged as [Pure] and if " + "that changes, don't forget to check for [Throws]", [attr.location, self.location]); elif identifier == "PutForwards": raise WebIDLError("Only attributes support [PutForwards]", diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index d3b17a3f8fc..9412209d1af 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -31,7 +31,7 @@ enum VisibilityState { "hidden", "visible" }; /* http://dom.spec.whatwg.org/#interface-document */ [Constructor] interface Document : Node { - [Throws, Constant] + [Throws] readonly attribute DOMImplementation implementation; readonly attribute DOMString URL; readonly attribute DOMString documentURI; diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index 9a7e7eebc7b..6f23f369dc9 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1263,6 +1263,9 @@ struct JSJitInfo { OpType type; bool isInfallible; /* Is op fallible? False in setters. */ bool isConstant; /* Getting a construction-time constant? */ + bool isPure; /* As long as no non-pure DOM things happen, will + keep returning the same value for the given + "this" object" */ JSValueType returnType; /* The return type tag. Might be JSVAL_TYPE_UNKNOWN */ }; From ad93d158ffedf36cb374c3be9b321f90079fd1fc Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 29 Jan 2013 17:53:53 -0500 Subject: [PATCH 36/70] Bug 835417 part 3. Add the notion of aliasing DOM stuff to MIR and flag MGetDOMProperty with the right alias set if it's pure. r=jandem --- js/src/ion/MIR.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 4d95f21e7bd..0aa55b40bda 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -196,10 +196,11 @@ class AliasSet { DynamicSlot = 1 << 2, // A member of obj->slots. FixedSlot = 1 << 3, // A member of obj->fixedSlots(). TypedArrayElement = 1 << 4, // A typed array element. - Last = TypedArrayElement, + DOMProperty = 1 << 5, // A DOM property + Last = DOMProperty, Any = Last | (Last - 1), - NumCategories = 5, + NumCategories = 6, // Indicates load or store. Store_ = 1 << 31 @@ -5394,7 +5395,7 @@ class MGetDOMProperty setOperand(1, guard); // We are movable iff the jitinfo says we can be. - if (jitinfo->isConstant) + if (jitinfo->isPure) setMovable(); setResultType(MIRType_Value); @@ -5422,6 +5423,9 @@ class MGetDOMProperty bool isDomConstant() const { return info_->isConstant; } + bool isDomPure() const { + return info_->isPure; + } MDefinition *object() { return getOperand(0); } @@ -5431,7 +5435,7 @@ class MGetDOMProperty } bool congruentTo(MDefinition *const &ins) const { - if (!isDomConstant()) + if (!isDomPure()) return false; if (!ins->isGetDOMProperty()) @@ -5449,6 +5453,10 @@ class MGetDOMProperty // conflict with anything if (isDomConstant()) return AliasSet::None(); + // Pure DOM attributes can only alias things that alias the world or + // explicitly alias DOM properties. + if (isDomPure()) + return AliasSet::Load(AliasSet::DOMProperty); return AliasSet::Store(AliasSet::Any); } From 451df52664b43b4c6972493463075d1d2d9add1a Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 29 Jan 2013 17:53:53 -0500 Subject: [PATCH 37/70] Bug 835417 part 4. Flag a bunch of DOM getters as [Pure]. r=peterv --- dom/webidl/Element.webidl | 8 ++++++++ dom/webidl/HTMLElement.webidl | 22 +++++++++++++--------- dom/webidl/Node.webidl | 13 +++++++++++-- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/dom/webidl/Element.webidl b/dom/webidl/Element.webidl index 9469c40a6af..43c267a76a9 100644 --- a/dom/webidl/Element.webidl +++ b/dom/webidl/Element.webidl @@ -26,8 +26,10 @@ interface Element : Node { readonly attribute DOMString localName; */ // Not [Constant] because it depends on which document we're in + [Pure] readonly attribute DOMString tagName; + [Pure] attribute DOMString id; /* FIXME Bug 810677 Move className from HTMLElement to Element @@ -57,10 +59,15 @@ interface Element : Node { [Constant] readonly attribute HTMLCollection children; + [Pure] readonly attribute Element? firstElementChild; + [Pure] readonly attribute Element? lastElementChild; + [Pure] readonly attribute Element? previousElementSibling; + [Pure] readonly attribute Element? nextElementSibling; + [Pure] readonly attribute unsigned long childElementCount; // NEW @@ -148,6 +155,7 @@ partial interface Element { // scrolling void scrollIntoView(optional boolean top = true); + // None of the CSSOM attributes are [Pure], because they flush attribute long scrollTop; // scroll on setting attribute long scrollLeft; // scroll on setting readonly attribute long scrollWidth; diff --git a/dom/webidl/HTMLElement.webidl b/dom/webidl/HTMLElement.webidl index 6b298b94597..d03d897187c 100644 --- a/dom/webidl/HTMLElement.webidl +++ b/dom/webidl/HTMLElement.webidl @@ -21,16 +21,16 @@ interface HTMLElement : Element { attribute DOMString title; attribute DOMString lang; // attribute boolean translate; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString dir; [Constant] readonly attribute DOMStringMap dataset; // microdata - [SetterThrows] + [SetterThrows, Pure] attribute boolean itemScope; [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemType; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString itemId; [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemRef; [PutForwards=value,Constant] readonly attribute DOMSettableTokenList itemProp; @@ -40,28 +40,31 @@ interface HTMLElement : Element { attribute any itemValue; // user interaction - [SetterThrows] + [SetterThrows, Pure] attribute boolean hidden; void click(); - [SetterThrows] + [SetterThrows, Pure] attribute long tabIndex; [Throws] void focus(); [Throws] void blur(); - [SetterThrows] + [SetterThrows, Pure] attribute DOMString accessKey; + [Pure] readonly attribute DOMString accessKeyLabel; - [SetterThrows] + [SetterThrows, Pure] attribute boolean draggable; //[PutForwards=value] readonly attribute DOMSettableTokenList dropzone; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString contentEditable; + [Pure] readonly attribute boolean isContentEditable; + [Pure] readonly attribute HTMLMenuElement? contextMenu; //[SetterThrows] // attribute HTMLMenuElement? contextMenu; - [SetterThrows] + [SetterThrows, Pure] attribute boolean spellcheck; // command API @@ -103,6 +106,7 @@ interface HTMLElement : Element { // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-htmlelement-interface partial interface HTMLElement { + // CSSOM things are not [Pure] because they can flush readonly attribute Element? offsetParent; readonly attribute long offsetTop; readonly attribute long offsetLeft; diff --git a/dom/webidl/Node.webidl b/dom/webidl/Node.webidl index a5300c5defe..89613b165ee 100644 --- a/dom/webidl/Node.webidl +++ b/dom/webidl/Node.webidl @@ -30,24 +30,33 @@ interface Node : EventTarget { const unsigned short NOTATION_NODE = 12; // historical [Constant] readonly attribute unsigned short nodeType; + [Pure] readonly attribute DOMString nodeName; + [Pure] readonly attribute DOMString? baseURI; + [Pure] readonly attribute Document? ownerDocument; + [Pure] readonly attribute Node? parentNode; + [Pure] readonly attribute Element? parentElement; boolean hasChildNodes(); [Constant] readonly attribute NodeList childNodes; + [Pure] readonly attribute Node? firstChild; + [Pure] readonly attribute Node? lastChild; + [Pure] readonly attribute Node? previousSibling; + [Pure] readonly attribute Node? nextSibling; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString? nodeValue; - [SetterThrows] + [SetterThrows, Pure] attribute DOMString? textContent; [Throws] Node insertBefore(Node node, Node? child); From dbcf164ddf9fe0b38a261a41cf4a44aeccce1cdf Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Tue, 29 Jan 2013 18:07:29 -0500 Subject: [PATCH 38/70] bug 804875: backout due to regressions of various uses of .src/mozSrcObject (bugs 836011/835705) rs=kinetik --- .../html/content/public/nsHTMLMediaElement.h | 7 -- .../html/content/src/nsHTMLAudioElement.cpp | 2 +- .../html/content/src/nsHTMLMediaElement.cpp | 26 ------ content/media/AbstractMediaDecoder.h | 10 +-- content/media/MediaDecoder.cpp | 7 +- content/media/MediaDecoder.h | 3 +- content/media/MediaDecoderOwner.h | 1 - content/media/MediaDecoderStateMachine.cpp | 8 +- content/media/MediaDecoderStateMachine.h | 2 +- content/media/MediaMetadataManager.h | 3 - content/media/VideoFrameContainer.cpp | 11 +-- content/media/VideoFrameContainer.h | 4 +- content/media/ogg/OggReader.cpp | 1 - content/media/test/Makefile.in | 1 - content/media/test/test_reset_src.html | 81 ------------------- gfx/layers/ImageContainer.h | 9 --- 16 files changed, 13 insertions(+), 163 deletions(-) delete mode 100644 content/media/test/test_reset_src.html diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index b001fa08420..92da4527aa9 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -120,7 +120,6 @@ public: virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, const MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE; // Called by the video decoder object, on the main thread, @@ -476,12 +475,6 @@ protected: */ void QueueSelectResourceTask(); - /** - * When loading a new source on an existing media element, make sure to reset - * everything that is accessible using the media element API. - */ - void ResetState(); - /** * The resource-fetch algorithm step of the load algorithm. */ diff --git a/content/html/content/src/nsHTMLAudioElement.cpp b/content/html/content/src/nsHTMLAudioElement.cpp index a4ec0cbc171..4b4aff120e0 100644 --- a/content/html/content/src/nsHTMLAudioElement.cpp +++ b/content/html/content/src/nsHTMLAudioElement.cpp @@ -123,7 +123,7 @@ nsHTMLAudioElement::MozSetup(uint32_t aChannels, uint32_t aRate) return rv; } - MetadataLoaded(aChannels, aRate, true, false, nullptr); + MetadataLoaded(aChannels, aRate, true, nullptr); mAudioStream->SetVolume(mVolume); return NS_OK; diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 0acf162cb08..224abd7c498 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -733,20 +733,10 @@ NS_IMETHODIMP nsHTMLMediaElement::Load() AbortExistingLoads(); SetPlaybackRate(mDefaultPlaybackRate); QueueSelectResourceTask(); - ResetState(); mIsRunningLoadMethod = false; return NS_OK; } -void nsHTMLMediaElement::ResetState() -{ - mMediaSize = nsIntSize(-1, -1); - VideoFrameContainer* container = GetVideoFrameContainer(); - if (container) { - container->Reset(); - } -} - static bool HasSourceChildren(nsIContent *aElement) { for (nsIContent* child = aElement->GetFirstChild(); @@ -2607,7 +2597,6 @@ void nsHTMLMediaElement::ProcessMediaFragmentURI() void nsHTMLMediaElement::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, const MetadataTags* aTags) { mChannels = aChannels; @@ -2621,13 +2610,6 @@ void nsHTMLMediaElement::MetadataLoaded(int aChannels, ProcessMediaFragmentURI(); mDecoder->SetFragmentEndTime(mFragmentEnd); } - - // If this element had a video track, but consists only of an audio track now, - // delete the VideoFrameContainer. This happens when the src is changed to an - // audio only file. - if (!aHasVideo) { - mVideoFrameContainer = nullptr; - } } void nsHTMLMediaElement::FirstFrameLoaded(bool aResourceFullyLoaded) @@ -2971,14 +2953,6 @@ void nsHTMLMediaElement::NotifyAutoplayDataReady() VideoFrameContainer* nsHTMLMediaElement::GetVideoFrameContainer() { - // If we have loaded the metadata, and the size of the video is still - // (-1, -1), the media has no video. Don't go a create a video frame - // container. - if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA && - mMediaSize == nsIntSize(-1, -1)) { - return nullptr; - } - if (mVideoFrameContainer) return mVideoFrameContainer; diff --git a/content/media/AbstractMediaDecoder.h b/content/media/AbstractMediaDecoder.h index f08d1a8856d..a06c0bdcd02 100644 --- a/content/media/AbstractMediaDecoder.h +++ b/content/media/AbstractMediaDecoder.h @@ -81,8 +81,8 @@ public: // Return true if the transport layer supports seeking. virtual bool IsMediaSeekable() = 0; - virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) = 0; - virtual void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) = 0; + virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) = 0; + virtual void QueueMetadata(int64_t aTime, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) = 0; // Set the media end time in microseconds virtual void SetMediaEndTime(int64_t aTime) = 0; @@ -119,25 +119,23 @@ class AudioMetadataEventRunner : public nsRunnable private: nsRefPtr mDecoder; public: - AudioMetadataEventRunner(AbstractMediaDecoder* aDecoder, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) + AudioMetadataEventRunner(AbstractMediaDecoder* aDecoder, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) : mDecoder(aDecoder), mChannels(aChannels), mRate(aRate), mHasAudio(aHasAudio), - mHasVideo(aHasVideo), mTags(aTags) {} NS_IMETHOD Run() { - mDecoder->MetadataLoaded(mChannels, mRate, mHasAudio, mHasVideo, mTags); + mDecoder->MetadataLoaded(mChannels, mRate, mHasAudio, mTags); return NS_OK; } int mChannels; int mRate; bool mHasAudio; - bool mHasVideo; MetadataTags* mTags; }; diff --git a/content/media/MediaDecoder.cpp b/content/media/MediaDecoder.cpp index 2b8ed741a2d..172c561a575 100644 --- a/content/media/MediaDecoder.cpp +++ b/content/media/MediaDecoder.cpp @@ -641,13 +641,12 @@ void MediaDecoder::QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, MetadataTags* aTags) { NS_ASSERTION(mDecoderStateMachine->OnDecodeThread(), "Should be on decode thread."); GetReentrantMonitor().AssertCurrentThreadIn(); - mDecoderStateMachine->QueueMetadata(aPublishTime, aChannels, aRate, aHasAudio, aHasVideo, aTags); + mDecoderStateMachine->QueueMetadata(aPublishTime, aChannels, aRate, aHasAudio, aTags); } bool @@ -660,7 +659,7 @@ MediaDecoder::IsDataCachedToEndOfResource() mResource->IsDataCachedToEndOfResource(mDecoderPosition)); } -void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags) +void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) { MOZ_ASSERT(NS_IsMainThread()); if (mShuttingDown) { @@ -682,7 +681,7 @@ void MediaDecoder::MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool // Make sure the element and the frame (if any) are told about // our new size. Invalidate(); - mOwner->MetadataLoaded(aChannels, aRate, aHasAudio, aHasVideo, aTags); + mOwner->MetadataLoaded(aChannels, aRate, aHasAudio, aTags); } if (!mCalledResourceLoaded) { diff --git a/content/media/MediaDecoder.h b/content/media/MediaDecoder.h index d727be273d3..f3ddc2e799b 100644 --- a/content/media/MediaDecoder.h +++ b/content/media/MediaDecoder.h @@ -658,7 +658,6 @@ public: int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, MetadataTags* aTags); /****** @@ -677,7 +676,7 @@ public: // Called when the metadata from the media file has been loaded by the // state machine. Call on the main thread only. - void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags); + void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags); // Called when the first frame has been loaded. // Call on the main thread only. diff --git a/content/media/MediaDecoderOwner.h b/content/media/MediaDecoderOwner.h index 03f148ac681..ed68963cea5 100644 --- a/content/media/MediaDecoderOwner.h +++ b/content/media/MediaDecoderOwner.h @@ -56,7 +56,6 @@ public: virtual void MetadataLoaded(int aChannels, int aRate, bool aHasAudio, - bool aHasVideo, const MetadataTags* aTags) = 0; // Called by the video decoder object, on the main thread, diff --git a/content/media/MediaDecoderStateMachine.cpp b/content/media/MediaDecoderStateMachine.cpp index 9ca480adc6d..7e7f38e8c20 100644 --- a/content/media/MediaDecoderStateMachine.cpp +++ b/content/media/MediaDecoderStateMachine.cpp @@ -1861,7 +1861,6 @@ nsresult MediaDecoderStateMachine::DecodeMetadata() mInfo.mAudioChannels, mInfo.mAudioRate, HasAudio(), - HasVideo(), tags); NS_DispatchToMainThread(metadataLoadedEvent, NS_DISPATCH_NORMAL); @@ -2787,12 +2786,7 @@ bool MediaDecoderStateMachine::IsShutdown() return GetState() == DECODER_STATE_SHUTDOWN; } -void MediaDecoderStateMachine::QueueMetadata(int64_t aPublishTime, - int aChannels, - int aRate, - bool aHasAudio, - bool aHasVideo, - MetadataTags* aTags) +void MediaDecoderStateMachine::QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags) { NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); diff --git a/content/media/MediaDecoderStateMachine.h b/content/media/MediaDecoderStateMachine.h index 86c1dd40d51..a6505ebf526 100644 --- a/content/media/MediaDecoderStateMachine.h +++ b/content/media/MediaDecoderStateMachine.h @@ -319,7 +319,7 @@ public: // shutting down. The decoder monitor must be held while calling this. bool IsShutdown(); - void QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags); + void QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, MetadataTags* aTags); protected: virtual uint32_t GetAmpleVideoFrames() { return mAmpleVideoFrames; } diff --git a/content/media/MediaMetadataManager.h b/content/media/MediaMetadataManager.h index e718f22d38a..5a37ffdb63f 100644 --- a/content/media/MediaMetadataManager.h +++ b/content/media/MediaMetadataManager.h @@ -28,8 +28,6 @@ namespace mozilla { int mChannels; // True if this media has an audio track. bool mHasAudio; - // True if this media has a video track. - bool mHasVideo; }; // This class encapsulate the logic to give the metadata from the reader to @@ -55,7 +53,6 @@ namespace mozilla { metadata->mChannels, metadata->mRate, metadata->mHasAudio, - metadata->mHasVideo, metadata->mTags.forget()); NS_DispatchToMainThread(metadataUpdatedEvent, NS_DISPATCH_NORMAL); mMetadataQueue.popFirst(); diff --git a/content/media/VideoFrameContainer.cpp b/content/media/VideoFrameContainer.cpp index b89e99efbbc..5789cb4d733 100644 --- a/content/media/VideoFrameContainer.cpp +++ b/content/media/VideoFrameContainer.cpp @@ -67,15 +67,7 @@ void VideoFrameContainer::SetCurrentFrame(const gfxIntSize& aIntrinsicSize, mPaintTarget = aTargetTime; } -void VideoFrameContainer::Reset() -{ - ClearCurrentFrame(true); - Invalidate(); - mPaintDelay = TimeDuration(); - mImageContainer->ResetPaintCount(); -} - -void VideoFrameContainer::ClearCurrentFrame(bool aResetSize) +void VideoFrameContainer::ClearCurrentFrame() { MutexAutoLock lock(mMutex); @@ -84,7 +76,6 @@ void VideoFrameContainer::ClearCurrentFrame(bool aResetSize) nsRefPtr kungFuDeathGrip; kungFuDeathGrip = mImageContainer->LockCurrentImage(); mImageContainer->UnlockCurrentImage(); - mImageSizeChanged = aResetSize; mImageContainer->SetCurrentImage(nullptr); diff --git a/content/media/VideoFrameContainer.h b/content/media/VideoFrameContainer.h index fc2f719b165..14f3bc06f3b 100644 --- a/content/media/VideoFrameContainer.h +++ b/content/media/VideoFrameContainer.h @@ -46,9 +46,7 @@ public: // Call on any thread void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage, TimeStamp aTargetTime); - void ClearCurrentFrame(bool aResetSize = false); - // Reset the VideoFrameContainer - void Reset(); + void ClearCurrentFrame(); // Time in seconds by which the last painted video frame was late by. // E.g. if the last painted frame should have been painted at time t, // but was actually painted at t+n, this returns n in seconds. Threadsafe. diff --git a/content/media/ogg/OggReader.cpp b/content/media/ogg/OggReader.cpp index 3ab829ee5ef..7e3854a43e6 100644 --- a/content/media/ogg/OggReader.cpp +++ b/content/media/ogg/OggReader.cpp @@ -732,7 +732,6 @@ bool OggReader::ReadOggChain() channels, rate, HasAudio(), - HasVideo(), tags); } return true; diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index d0919c76750..d309c14d261 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -133,7 +133,6 @@ MOCHITEST_FILES = \ test_media_sniffer.html \ contentType.sjs \ test_streams_srcObject.html \ - test_reset_src.html \ $(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \ $(NULL) diff --git a/content/media/test/test_reset_src.html b/content/media/test/test_reset_src.html deleted file mode 100644 index afc1e010c2d..00000000000 --- a/content/media/test/test_reset_src.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - Test for bug 804875 - - - - - -Mozilla Bug 804875 - - - - -
-
-
- - diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index 40575a8553a..d7b92a8f5b6 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -443,15 +443,6 @@ public: return mPaintCount; } - /** - * Resets the paint count to zero. - * Can be called from any thread. - */ - void ResetPaintCount() { - ReentrantMonitorAutoEnter mon(mReentrantMonitor); - mPaintCount = 0; - } - /** * Increments mPaintCount if this is the first time aPainted has been * painted, and sets mPaintTime if the painted image is the current image. From 33f74ff1b37a995c6abdc76190315c09b45bd4eb Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Tue, 29 Jan 2013 16:20:03 -0700 Subject: [PATCH 39/70] Bug 833898 - Allow converting mixed arrays of ints and doubles to uniform doubles, r=jandem. --- js/src/ion/CodeGenerator.cpp | 20 +++++++ js/src/ion/CodeGenerator.h | 1 + js/src/ion/IonAnalysis.cpp | 5 ++ js/src/ion/IonBuilder.cpp | 39 +++++++++++++- js/src/ion/IonBuilder.h | 1 + js/src/ion/IonMacroAssembler.cpp | 2 + js/src/ion/LIR-Common.h | 15 ++++++ js/src/ion/LOpcodes.h | 1 + js/src/ion/Lowering.cpp | 7 +++ js/src/ion/Lowering.h | 1 + js/src/ion/MCallOptimize.cpp | 28 +++++++++- js/src/ion/MIR.h | 51 ++++++++++++++++-- js/src/ion/MOpcodes.h | 1 + js/src/ion/TypeOracle.cpp | 30 ++++++++++- js/src/ion/TypeOracle.h | 12 +++++ js/src/ion/VMFunctions.h | 1 + js/src/ion/arm/CodeGenerator-arm.cpp | 12 ++++- js/src/ion/x64/Assembler-x64.h | 10 ++++ js/src/ion/x64/CodeGenerator-x64.cpp | 11 +++- js/src/ion/x86/Assembler-x86.h | 10 ++++ js/src/ion/x86/CodeGenerator-x86.cpp | 15 ++++-- js/src/jit-test/tests/ion/doubleArrays.js | 51 ++++++++++++++++++ js/src/jsinfer.cpp | 64 +++++++++++++++++++++++ js/src/jsinfer.h | 20 +++++++ js/src/jsobj.cpp | 2 +- js/src/jsobj.h | 3 ++ js/src/jsobjinlines.h | 31 +++++++++-- js/src/jstypedarrayinlines.h | 2 +- js/src/methodjit/BaseAssembler.h | 2 + js/src/methodjit/Compiler.cpp | 9 +++- js/src/methodjit/Compiler.h | 5 +- js/src/methodjit/FastBuiltins.cpp | 23 +++++++- js/src/methodjit/FastOps.cpp | 26 +++++++-- js/src/vm/ObjectImpl.cpp | 24 +++++++++ js/src/vm/ObjectImpl.h | 11 ++-- 35 files changed, 512 insertions(+), 34 deletions(-) create mode 100644 js/src/jit-test/tests/ion/doubleArrays.js diff --git a/js/src/ion/CodeGenerator.cpp b/js/src/ion/CodeGenerator.cpp index d77f26d0baf..31d6d44027c 100644 --- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -735,6 +735,26 @@ CodeGenerator::visitElements(LElements *lir) return true; } +typedef bool (*ConvertElementsToDoublesFn)(JSContext *, uintptr_t); +static const VMFunction ConvertElementsToDoublesInfo = + FunctionInfo(ObjectElements::ConvertElementsToDoubles); + +bool +CodeGenerator::visitConvertElementsToDoubles(LConvertElementsToDoubles *lir) +{ + Register elements = ToRegister(lir->elements()); + + OutOfLineCode *ool = oolCallVM(ConvertElementsToDoublesInfo, lir, + (ArgList(), elements), StoreNothing()); + if (!ool) + return false; + + Address convertedAddress(elements, ObjectElements::offsetOfConvertDoubleElements()); + masm.branch32(Assembler::Equal, convertedAddress, Imm32(0), ool->entry()); + masm.bind(ool->rejoin()); + return true; +} + bool CodeGenerator::visitFunctionEnvironment(LFunctionEnvironment *lir) { diff --git a/js/src/ion/CodeGenerator.h b/js/src/ion/CodeGenerator.h index 8b4fb60c4c8..42bc16e86a6 100644 --- a/js/src/ion/CodeGenerator.h +++ b/js/src/ion/CodeGenerator.h @@ -76,6 +76,7 @@ class CodeGenerator : public CodeGeneratorSpecific bool visitSlots(LSlots *lir); bool visitStoreSlotV(LStoreSlotV *store); bool visitElements(LElements *lir); + bool visitConvertElementsToDoubles(LConvertElementsToDoubles *lir); bool visitTypeBarrier(LTypeBarrier *lir); bool visitMonitorTypes(LMonitorTypes *lir); bool visitCallNative(LCallNative *call); diff --git a/js/src/ion/IonAnalysis.cpp b/js/src/ion/IonAnalysis.cpp index f894b964c02..2b7917606af 100644 --- a/js/src/ion/IonAnalysis.cpp +++ b/js/src/ion/IonAnalysis.cpp @@ -1361,6 +1361,11 @@ ion::EliminateRedundantChecks(MIRGraph &graph) } else if (iter->isTypeBarrier()) { if (!TryEliminateTypeBarrier(iter->toTypeBarrier(), &eliminated)) return false; + } else if (iter->isConvertElementsToDoubles()) { + // Now that code motion passes have finished, replace any + // ConvertElementsToDoubles with the actual elements. + MConvertElementsToDoubles *ins = iter->toConvertElementsToDoubles(); + ins->replaceAllUsesWith(ins->elements()); } if (eliminated) diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index c528201c439..0c402607328 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -4376,6 +4376,9 @@ IonBuilder::jsop_newarray(uint32_t count) if (!templateObject) return false; + if (oracle->arrayResultShouldHaveDoubleConversion(script(), pc)) + templateObject->setShouldConvertDoubleElements(); + MNewArray *ins = new MNewArray(count, templateObject, MNewArray::NewArray_Allocating); current->add(ins); @@ -4434,6 +4437,12 @@ IonBuilder::jsop_initelem_array() MElements *elements = MElements::New(obj); current->add(elements); + if (obj->toNewArray()->templateObject()->shouldConvertDoubleElements()) { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + // Store the value. MStoreElement *store = MStoreElement::New(elements, id, value, /* needsHoleCheck = */ false); current->add(store); @@ -5416,9 +5425,20 @@ IonBuilder::jsop_getelem_dense() id = idInt32; // Get the elements vector. - MElements *elements = MElements::New(obj); + MInstruction *elements = MElements::New(obj); current->add(elements); + // If we can load the element as a definite double, make sure to check that + // the array has been converted to homogenous doubles first. + bool loadDouble = !barrier && + loopDepth_ && + !readOutOfBounds && + oracle->elementReadShouldAlwaysLoadDoubles(script(), pc); + if (loadDouble) { + JS_ASSERT(!needsHoleCheck && knownType == JSVAL_TYPE_DOUBLE); + elements = addConvertElementsToDoubles(elements); + } + MInitializedLength *initLength = MInitializedLength::New(elements); current->add(initLength); @@ -5431,7 +5451,7 @@ IonBuilder::jsop_getelem_dense() // hoisting. id = addBoundsCheck(id, initLength); - load = MLoadElement::New(elements, id, needsHoleCheck); + load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble); current->add(load); } else { // This load may return undefined, so assume that we *can* read holes, @@ -5641,6 +5661,13 @@ IonBuilder::jsop_setelem_dense() current->add(idInt32); id = idInt32; + // Ensure the value is a double, if double conversion might be needed. + if (oracle->elementWriteNeedsDoubleConversion(script(), pc)) { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + // Get the elements vector. MElements *elements = MElements::New(obj); current->add(elements); @@ -7000,6 +7027,14 @@ IonBuilder::jsop_instanceof() return resumeAfter(ins); } +MInstruction * +IonBuilder::addConvertElementsToDoubles(MDefinition *elements) +{ + MInstruction *convert = MConvertElementsToDoubles::New(elements); + current->add(convert); + return convert; +} + MInstruction * IonBuilder::addBoundsCheck(MDefinition *index, MDefinition *length) { diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h index 429187937a6..402c7fab280 100644 --- a/js/src/ion/IonBuilder.h +++ b/js/src/ion/IonBuilder.h @@ -284,6 +284,7 @@ class IonBuilder : public MIRGenerator MDefinition *walkScopeChain(unsigned hops); + MInstruction *addConvertElementsToDoubles(MDefinition *elements); MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length); MInstruction *addShapeGuard(MDefinition *obj, const UnrootedShape shape, BailoutKind bailoutKind); diff --git a/js/src/ion/IonMacroAssembler.cpp b/js/src/ion/IonMacroAssembler.cpp index d1bca696c29..e3445cd185f 100644 --- a/js/src/ion/IonMacroAssembler.cpp +++ b/js/src/ion/IonMacroAssembler.cpp @@ -356,6 +356,8 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject) Address(obj, elementsOffset + ObjectElements::offsetOfInitializedLength())); store32(Imm32(templateObject->getArrayLength()), Address(obj, elementsOffset + ObjectElements::offsetOfLength())); + store32(Imm32(templateObject->shouldConvertDoubleElements() ? 1 : 0), + Address(obj, elementsOffset + ObjectElements::offsetOfConvertDoubleElements())); } else { storePtr(ImmWord(emptyObjectElements), Address(obj, JSObject::offsetOfElements())); diff --git a/js/src/ion/LIR-Common.h b/js/src/ion/LIR-Common.h index 2b7f869f785..cfeb0aadc5b 100644 --- a/js/src/ion/LIR-Common.h +++ b/js/src/ion/LIR-Common.h @@ -2123,6 +2123,21 @@ class LElements : public LInstructionHelper<1, 1, 0> } }; +// If necessary, convert any int32 elements in a vector into doubles. +class LConvertElementsToDoubles : public LInstructionHelper<0, 1, 0> +{ + public: + LIR_HEADER(ConvertElementsToDoubles) + + LConvertElementsToDoubles(const LAllocation &elements) { + setOperand(0, elements); + } + + const LAllocation *elements() { + return getOperand(0); + } +}; + // Load a dense array's initialized length from an elements vector. class LInitializedLength : public LInstructionHelper<1, 1, 0> { diff --git a/js/src/ion/LOpcodes.h b/js/src/ion/LOpcodes.h index 90415095d47..f9b7ef20fa8 100644 --- a/js/src/ion/LOpcodes.h +++ b/js/src/ion/LOpcodes.h @@ -111,6 +111,7 @@ _(ImplicitThis) \ _(Slots) \ _(Elements) \ + _(ConvertElementsToDoubles) \ _(LoadSlotV) \ _(LoadSlotT) \ _(StoreSlotV) \ diff --git a/js/src/ion/Lowering.cpp b/js/src/ion/Lowering.cpp index db721cfc81a..e074848bcb1 100644 --- a/js/src/ion/Lowering.cpp +++ b/js/src/ion/Lowering.cpp @@ -1396,6 +1396,13 @@ LIRGenerator::visitConstantElements(MConstantElements *ins) return define(new LPointer(ins->value(), LPointer::NON_GC_THING), ins); } +bool +LIRGenerator::visitConvertElementsToDoubles(MConvertElementsToDoubles *ins) +{ + LInstruction *check = new LConvertElementsToDoubles(useRegister(ins->elements())); + return add(check, ins) && assignSafepoint(check, ins); +} + bool LIRGenerator::visitLoadSlot(MLoadSlot *ins) { diff --git a/js/src/ion/Lowering.h b/js/src/ion/Lowering.h index 1c3ab7b0a2d..7a1f8c8c1d8 100644 --- a/js/src/ion/Lowering.h +++ b/js/src/ion/Lowering.h @@ -140,6 +140,7 @@ class LIRGenerator : public LIRGeneratorSpecific bool visitSlots(MSlots *ins); bool visitElements(MElements *ins); bool visitConstantElements(MConstantElements *ins); + bool visitConvertElementsToDoubles(MConvertElementsToDoubles *ins); bool visitLoadSlot(MLoadSlot *ins); bool visitFunctionEnvironment(MFunctionEnvironment *ins); bool visitStoreSlot(MStoreSlot *ins); diff --git a/js/src/ion/MCallOptimize.cpp b/js/src/ion/MCallOptimize.cpp index 7509e8ee1bf..1eea0ad8423 100644 --- a/js/src/ion/MCallOptimize.cpp +++ b/js/src/ion/MCallOptimize.cpp @@ -205,6 +205,10 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing) if (!templateObject) return InliningStatus_Error; + bool convertDoubles = oracle->arrayResultShouldHaveDoubleConversion(script(), pc); + if (convertDoubles) + templateObject->setShouldConvertDoubleElements(); + MNewArray *ins = new MNewArray(initLength, templateObject, allocating); current->add(ins); current->push(ins); @@ -222,7 +226,14 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing) id = MConstant::New(Int32Value(i)); current->add(id); - MStoreElement *store = MStoreElement::New(elements, id, argv[i + 1], + MDefinition *value = argv[i + 1]; + if (convertDoubles) { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + + MStoreElement *store = MStoreElement::New(elements, id, value, /* needsHoleCheck = */ false); current->add(store); } @@ -313,11 +324,24 @@ IonBuilder::inlineArrayPush(uint32_t argc, bool constructing) if (types::ArrayPrototypeHasIndexedProperty(cx, script)) return InliningStatus_NotInlined; + types::StackTypeSet::DoubleConversion conversion = thisTypes->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AmbiguousDoubleConversion) + return InliningStatus_NotInlined; + MDefinitionVector argv; if (!discardCall(argc, argv, current)) return InliningStatus_Error; - MArrayPush *ins = MArrayPush::New(argv[0], argv[1]); + MDefinition *value = argv[1]; + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles || + conversion == types::StackTypeSet::MaybeConvertToDoubles) + { + MInstruction *valueDouble = MToDouble::New(value); + current->add(valueDouble); + value = valueDouble; + } + + MArrayPush *ins = MArrayPush::New(argv[0], value); current->add(ins); current->push(ins); diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 0aa55b40bda..9d32999d2fe 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -3501,6 +3501,43 @@ class MConstantElements : public MNullaryInstruction } }; +// Passes through an object's elements, after ensuring it is entirely doubles. +class MConvertElementsToDoubles + : public MUnaryInstruction +{ + MConvertElementsToDoubles(MDefinition *elements) + : MUnaryInstruction(elements) + { + setGuard(); + setMovable(); + setResultType(MIRType_Elements); + } + + public: + INSTRUCTION_HEADER(ConvertElementsToDoubles) + + static MConvertElementsToDoubles *New(MDefinition *elements) { + return new MConvertElementsToDoubles(elements); + } + + MDefinition *elements() const { + return getOperand(0); + } + bool congruentTo(MDefinition *const &ins) const { + return congruentIfOperandsEqual(ins); + } + AliasSet getAliasSet() const { + // This instruction can read and write to the elements' contents. + // However, it is alright to hoist this from loops which explicitly + // read or write to the elements: such reads and writes will use double + // values and can be reordered freely wrt this conversion, except that + // definite double loads must follow the conversion. The latter + // property is ensured by chaining this instruction with the elements + // themselves, in the same manner as MBoundsCheck. + return AliasSet::None(); + } +}; + // Load a dense array's initialized length from an elements vector. class MInitializedLength : public MUnaryInstruction @@ -3793,10 +3830,12 @@ class MLoadElement public SingleObjectPolicy { bool needsHoleCheck_; + bool loadDoubles_; - MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck) + MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles) : MBinaryInstruction(elements, index), - needsHoleCheck_(needsHoleCheck) + needsHoleCheck_(needsHoleCheck), + loadDoubles_(loadDoubles) { setResultType(MIRType_Value); setMovable(); @@ -3807,8 +3846,9 @@ class MLoadElement public: INSTRUCTION_HEADER(LoadElement) - static MLoadElement *New(MDefinition *elements, MDefinition *index, bool needsHoleCheck) { - return new MLoadElement(elements, index, needsHoleCheck); + static MLoadElement *New(MDefinition *elements, MDefinition *index, + bool needsHoleCheck, bool loadDoubles) { + return new MLoadElement(elements, index, needsHoleCheck, loadDoubles); } TypePolicy *typePolicy() { @@ -3823,6 +3863,9 @@ class MLoadElement bool needsHoleCheck() const { return needsHoleCheck_; } + bool loadDoubles() const { + return loadDoubles_; + } bool fallible() const { return needsHoleCheck(); } diff --git a/js/src/ion/MOpcodes.h b/js/src/ion/MOpcodes.h index 0a476e780ac..aed4e50e966 100644 --- a/js/src/ion/MOpcodes.h +++ b/js/src/ion/MOpcodes.h @@ -88,6 +88,7 @@ namespace ion { _(Slots) \ _(Elements) \ _(ConstantElements) \ + _(ConvertElementsToDoubles) \ _(LoadSlot) \ _(StoreSlot) \ _(FunctionEnvironment) \ diff --git a/js/src/ion/TypeOracle.cpp b/js/src/ion/TypeOracle.cpp index 16309d5c083..811ac450714 100644 --- a/js/src/ion/TypeOracle.cpp +++ b/js/src/ion/TypeOracle.cpp @@ -359,6 +359,14 @@ TypeInferenceOracle::elementReadIsString(UnrootedScript script, jsbytecode *pc) return true; } +bool +TypeInferenceOracle::elementReadShouldAlwaysLoadDoubles(UnrootedScript script, jsbytecode *pc) +{ + StackTypeSet *types = script->analysis()->poppedTypes(pc, 1); + types::StackTypeSet::DoubleConversion conversion = types->convertDoubleElements(cx); + return conversion == StackTypeSet::AlwaysConvertToDoubles; +} + bool TypeInferenceOracle::elementReadHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc) { @@ -405,7 +413,10 @@ TypeInferenceOracle::elementWriteIsDenseNative(HandleScript script, jsbytecode * return false; Class *clasp = obj->getKnownClass(); - return clasp && clasp->isNative(); + if (!clasp || !clasp->isNative()) + return false; + + return obj->convertDoubleElements(cx) != StackTypeSet::AmbiguousDoubleConversion; } bool @@ -426,6 +437,15 @@ TypeInferenceOracle::elementWriteIsTypedArray(RawScript script, jsbytecode *pc, return true; } +bool +TypeInferenceOracle::elementWriteNeedsDoubleConversion(UnrootedScript script, jsbytecode *pc) +{ + StackTypeSet *types = script->analysis()->poppedTypes(pc, 2); + types::StackTypeSet::DoubleConversion conversion = types->convertDoubleElements(cx); + return conversion == StackTypeSet::AlwaysConvertToDoubles || + conversion == StackTypeSet::MaybeConvertToDoubles; +} + bool TypeInferenceOracle::elementWriteHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc) { @@ -483,6 +503,14 @@ TypeInferenceOracle::elementWrite(UnrootedScript script, jsbytecode *pc) return elementType; } +bool +TypeInferenceOracle::arrayResultShouldHaveDoubleConversion(UnrootedScript script, jsbytecode *pc) +{ + types::StackTypeSet::DoubleConversion conversion = + script->analysis()->pushedTypes(pc, 0)->convertDoubleElements(cx); + return conversion == types::StackTypeSet::AlwaysConvertToDoubles; +} + bool TypeInferenceOracle::canInlineCalls() { diff --git a/js/src/ion/TypeOracle.h b/js/src/ion/TypeOracle.h index 4e157aea712..4ca647b3025 100644 --- a/js/src/ion/TypeOracle.h +++ b/js/src/ion/TypeOracle.h @@ -90,6 +90,9 @@ class TypeOracle virtual bool elementReadIsString(UnrootedScript script, jsbytecode *pc) { return false; } + virtual bool elementReadShouldAlwaysLoadDoubles(UnrootedScript script, jsbytecode *pc) { + return false; + } virtual bool elementReadHasExtraIndexedProperty(UnrootedScript, jsbytecode *pc) { return false; } @@ -109,12 +112,18 @@ class TypeOracle virtual bool elementWriteIsTypedArray(RawScript script, jsbytecode *pc, int *arrayType) { return false; } + virtual bool elementWriteNeedsDoubleConversion(UnrootedScript script, jsbytecode *pc) { + return false; + } virtual bool elementWriteHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc) { return false; } virtual bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc) { return false; } + virtual bool arrayResultShouldHaveDoubleConversion(UnrootedScript script, jsbytecode *pc) { + return false; + } virtual bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc) { return true; } @@ -237,13 +246,16 @@ class TypeInferenceOracle : public TypeOracle bool elementReadIsDenseNative(RawScript script, jsbytecode *pc); bool elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *atype); bool elementReadIsString(UnrootedScript script, jsbytecode *pc); + bool elementReadShouldAlwaysLoadDoubles(UnrootedScript script, jsbytecode *pc); bool elementReadHasExtraIndexedProperty(UnrootedScript, jsbytecode *pc); bool elementReadIsPacked(UnrootedScript script, jsbytecode *pc); void elementReadGeneric(UnrootedScript script, jsbytecode *pc, bool *cacheable, bool *monitorResult); bool elementWriteIsDenseNative(HandleScript script, jsbytecode *pc); bool elementWriteIsTypedArray(RawScript script, jsbytecode *pc, int *arrayType); + bool elementWriteNeedsDoubleConversion(UnrootedScript script, jsbytecode *pc); bool elementWriteHasExtraIndexedProperty(UnrootedScript script, jsbytecode *pc); bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc); + bool arrayResultShouldHaveDoubleConversion(UnrootedScript script, jsbytecode *pc); bool setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc); bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc); bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, RawId id); diff --git a/js/src/ion/VMFunctions.h b/js/src/ion/VMFunctions.h index d86b6803c7f..4d25cff9551 100644 --- a/js/src/ion/VMFunctions.h +++ b/js/src/ion/VMFunctions.h @@ -465,6 +465,7 @@ bool OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, JSBool *out); bool GetIntrinsicValue(JSContext *cx, HandlePropertyName name, MutableHandleValue rval); bool CreateThis(JSContext *cx, HandleObject callee, MutableHandleValue rval); + } // namespace ion } // namespace js diff --git a/js/src/ion/arm/CodeGenerator-arm.cpp b/js/src/ion/arm/CodeGenerator-arm.cpp index a10f2d8c904..012ac1fd35c 100644 --- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -1456,11 +1456,19 @@ CodeGeneratorARM::visitLoadElementT(LLoadElementT *load) { Register base = ToRegister(load->elements()); if (load->mir()->type() == MIRType_Double) { + FloatRegister fpreg = ToFloatRegister(load->output()); if (load->index()->isConstant()) { Address source(base, ToInt32(load->index()) * sizeof(Value)); - masm.loadInt32OrDouble(source, ToFloatRegister(load->output())); + if (load->mir()->loadDoubles()) + masm.loadDouble(source, fpreg); + else + masm.loadInt32OrDouble(source, fpreg); } else { - masm.loadInt32OrDouble(base, ToRegister(load->index()), ToFloatRegister(load->output())); + Register index = ToRegister(load->index()); + if (load->mir()->loadDoubles()) + masm.loadDouble(BaseIndex(base, index, TimesEight), fpreg); + else + masm.loadInt32OrDouble(base, index, fpreg); } } else { if (load->index()->isConstant()) { diff --git a/js/src/ion/x64/Assembler-x64.h b/js/src/ion/x64/Assembler-x64.h index e0ba264d6e2..e45c7e68c30 100644 --- a/js/src/ion/x64/Assembler-x64.h +++ b/js/src/ion/x64/Assembler-x64.h @@ -189,6 +189,16 @@ class Operand disp_(disp) { } + Address toAddress() { + JS_ASSERT(kind() == REG_DISP); + return Address(Register::FromCode(base()), disp()); + } + + BaseIndex toBaseIndex() { + JS_ASSERT(kind() == SCALE); + return BaseIndex(Register::FromCode(base()), Register::FromCode(index()), scale(), disp()); + } + Kind kind() const { return kind_; } diff --git a/js/src/ion/x64/CodeGenerator-x64.cpp b/js/src/ion/x64/CodeGenerator-x64.cpp index 0c054cfc29c..8c2e3424b77 100644 --- a/js/src/ion/x64/CodeGenerator-x64.cpp +++ b/js/src/ion/x64/CodeGenerator-x64.cpp @@ -251,7 +251,16 @@ bool CodeGeneratorX64::visitLoadElementT(LLoadElementT *load) { Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index()); - loadUnboxedValue(source, load->mir()->type(), load->output()); + + if (load->mir()->loadDoubles()) { + FloatRegister fpreg = ToFloatRegister(load->output()); + if (source.kind() == Operand::REG_DISP) + masm.loadDouble(source.toAddress(), fpreg); + else + masm.loadDouble(source.toBaseIndex(), fpreg); + } else { + loadUnboxedValue(source, load->mir()->type(), load->output()); + } JS_ASSERT(!load->mir()->needsHoleCheck()); return true; diff --git a/js/src/ion/x86/Assembler-x86.h b/js/src/ion/x86/Assembler-x86.h index 0456c5e6e73..d348bad77bf 100644 --- a/js/src/ion/x86/Assembler-x86.h +++ b/js/src/ion/x86/Assembler-x86.h @@ -144,6 +144,16 @@ class Operand base_(reinterpret_cast(address)) { } + Address toAddress() { + JS_ASSERT(kind() == REG_DISP); + return Address(Register::FromCode(base()), disp()); + } + + BaseIndex toBaseIndex() { + JS_ASSERT(kind() == SCALE); + return BaseIndex(Register::FromCode(base()), Register::FromCode(index()), scale(), disp()); + } + Kind kind() const { return kind_; } diff --git a/js/src/ion/x86/CodeGenerator-x86.cpp b/js/src/ion/x86/CodeGenerator-x86.cpp index 52f53c7c3f1..02db3c3b0fc 100644 --- a/js/src/ion/x86/CodeGenerator-x86.cpp +++ b/js/src/ion/x86/CodeGenerator-x86.cpp @@ -240,10 +240,19 @@ CodeGeneratorX86::visitLoadElementT(LLoadElementT *load) return false; } - if (load->mir()->type() == MIRType_Double) - masm.loadInt32OrDouble(source, ToFloatRegister(load->output())); - else + if (load->mir()->type() == MIRType_Double) { + FloatRegister fpreg = ToFloatRegister(load->output()); + if (load->mir()->loadDoubles()) { + if (source.kind() == Operand::REG_DISP) + masm.loadDouble(source.toAddress(), fpreg); + else + masm.loadDouble(source.toBaseIndex(), fpreg); + } else { + masm.loadInt32OrDouble(source, fpreg); + } + } else { masm.movl(masm.ToPayload(source), ToRegister(load->output())); + } return true; } diff --git a/js/src/jit-test/tests/ion/doubleArrays.js b/js/src/jit-test/tests/ion/doubleArrays.js new file mode 100644 index 00000000000..4622c3f29ea --- /dev/null +++ b/js/src/jit-test/tests/ion/doubleArrays.js @@ -0,0 +1,51 @@ + +function testPushConvert() { + var x = []; + for (var i = 0; i < 10; i++) + x.push(i + .5); + for (var i = 0; i < 5; i++) + x.push(i); + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 60); +} +testPushConvert(); + +function testArrayInitializer() { + var x = [.5,1.5,2.5,3]; + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 7.5); +} +for (var i = 0; i < 5; i++) + testArrayInitializer(); + +function testArrayConstructor() { + var x = Array(.5,1.5,2.5,3); + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 7.5); +} +for (var i = 0; i < 5; i++) + testArrayConstructor(); + +function addInt(a) { + // inhibit ion + try { + a[0] = 10; + } catch (e) {} +} + +function testBaseline() { + var x = Array(.5,1.5,2.5,3); + addInt(x); + var res = 0; + for (var i = 0; i < x.length; i++) + res += x[i]; + assertEq(res, 17); +} +for (var i = 0; i < 5; i++) + testBaseline(); diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 24b2eaa6311..eb16baccaa6 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -1996,6 +1996,70 @@ StackTypeSet::filtersType(const StackTypeSet *other, Type filteredType) const return true; } +StackTypeSet::DoubleConversion +StackTypeSet::convertDoubleElements(JSContext *cx) +{ + if (unknownObject() || !getObjectCount()) + return AmbiguousDoubleConversion; + + bool alwaysConvert = true; + bool maybeConvert = false; + bool dontConvert = false; + + for (unsigned i = 0; i < getObjectCount(); i++) { + TypeObject *type = getTypeObject(i); + if (!type) { + if (JSObject *obj = getSingleObject(i)) { + type = obj->getType(cx); + if (!type) + return AmbiguousDoubleConversion; + } else { + continue; + } + } + + if (type->unknownProperties()) { + alwaysConvert = false; + continue; + } + + HeapTypeSet *types = type->getProperty(cx, JSID_VOID, false); + if (!types) + return AmbiguousDoubleConversion; + + // We can't convert to double elements for objects which do not have + // double in their element types (as the conversion may render the type + // information incorrect), nor for non-array objects (as their elements + // may point to emptyObjectElements, which cannot be converted). + if (!types->hasType(Type::DoubleType()) || type->clasp != &ArrayClass) { + dontConvert = true; + alwaysConvert = false; + continue; + } + + // Only bother with converting known packed arrays whose possible + // element types are int or double. Other arrays require type tests + // when elements are accessed regardless of the conversion. + if (types->getKnownTypeTag(cx) == JSVAL_TYPE_DOUBLE && + !HeapTypeSet::HasObjectFlags(cx, type, OBJECT_FLAG_NON_PACKED)) + { + maybeConvert = true; + } else { + alwaysConvert = false; + } + } + + JS_ASSERT_IF(alwaysConvert, maybeConvert); + + if (maybeConvert && dontConvert) + return AmbiguousDoubleConversion; + if (alwaysConvert) + return AlwaysConvertToDoubles; + if (maybeConvert) + return MaybeConvertToDoubles; + return DontConvertToDoubles; +} + bool HeapTypeSet::knownSubset(JSContext *cx, TypeSet *other) { diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 7afb207f582..d43ba287139 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -637,6 +637,26 @@ class StackTypeSet : public TypeSet return true; } + + enum DoubleConversion { + /* All types in the set should use eager double conversion. */ + AlwaysConvertToDoubles, + + /* Some types in the set should use eager double conversion. */ + MaybeConvertToDoubles, + + /* No types should use eager double conversion. */ + DontConvertToDoubles, + + /* Some types should use eager double conversion, others cannot. */ + AmbiguousDoubleConversion + }; + + /* + * Whether known double optimizations are possible for element accesses on + * objects in this type set. + */ + DoubleConversion convertDoubleElements(JSContext *cx); }; /* diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 7c8cb2be4f9..9fe265ff355 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3185,7 +3185,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal if (result == JSObject::ED_FAILED) return false; if (result == JSObject::ED_OK) { - obj->setDenseElement(index, value); + obj->setDenseElementMaybeConvertDouble(index, value); if (!CallAddPropertyHookDense(cx, clasp, obj, index, value)) { JSObject::setDenseElementHole(cx, obj, index); return false; diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 2d3e717c9a1..4b23970a87a 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -589,6 +589,7 @@ class JSObject : public js::ObjectImpl inline void ensureDenseInitializedLength(JSContext *cx, unsigned index, unsigned extra); inline void setDenseElement(unsigned idx, const js::Value &val); inline void initDenseElement(unsigned idx, const js::Value &val); + inline void setDenseElementMaybeConvertDouble(unsigned idx, const js::Value &val); static inline void setDenseElementWithType(JSContext *cx, js::HandleObject obj, unsigned idx, const js::Value &val); static inline void initDenseElementWithType(JSContext *cx, js::HandleObject obj, @@ -600,6 +601,8 @@ class JSObject : public js::ObjectImpl inline void initDenseElements(unsigned dstStart, const js::Value *src, unsigned count); inline void moveDenseElements(unsigned dstStart, unsigned srcStart, unsigned count); inline void moveDenseElementsUnbarriered(unsigned dstStart, unsigned srcStart, unsigned count); + inline bool shouldConvertDoubleElements(); + inline void setShouldConvertDoubleElements(); /* Packed information for this object's elements. */ inline void markDenseElementsNotPacked(JSContext *cx); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index c3da9ea2148..efa77baf8d8 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -388,10 +388,7 @@ JSObject::setArrayLength(JSContext *cx, js::HandleObject obj, uint32_t length) JS_ASSERT(obj->isArray()); if (length > INT32_MAX) { - /* - * Mark the type of this object as possibly not a dense array, per the - * requirements of OBJECT_FLAG_NON_DENSE_ARRAY. - */ + /* Track objects with overflowing lengths in type information. */ js::types::MarkTypeObjectFlags(cx, obj, js::types::OBJECT_FLAG_LENGTH_OVERFLOW); jsid lengthId = js::NameToId(cx->names().length); @@ -427,6 +424,20 @@ JSObject::getDenseCapacity() return getElementsHeader()->capacity; } +inline bool +JSObject::shouldConvertDoubleElements() +{ + JS_ASSERT(isNative()); + return getElementsHeader()->convertDoubleElements; +} + +inline void +JSObject::setShouldConvertDoubleElements() +{ + JS_ASSERT(isArray() && !hasEmptyElements()); + getElementsHeader()->convertDoubleElements = 1; +} + inline bool JSObject::ensureElements(JSContext *cx, uint32_t capacity) { @@ -450,6 +461,15 @@ JSObject::setDenseElement(unsigned idx, const js::Value &val) elements[idx].set(this, js::HeapSlot::Element, idx, val); } +inline void +JSObject::setDenseElementMaybeConvertDouble(unsigned idx, const js::Value &val) +{ + if (val.isInt32() && shouldConvertDoubleElements()) + setDenseElement(idx, js::DoubleValue(val.toInt32())); + else + setDenseElement(idx, val); +} + inline void JSObject::initDenseElement(unsigned idx, const js::Value &val) { @@ -462,13 +482,14 @@ JSObject::setDenseElementWithType(JSContext *cx, js::HandleObject obj, unsigned const js::Value &val) { js::types::AddTypePropertyId(cx, obj, JSID_VOID, val); - obj->setDenseElement(idx, val); + obj->setDenseElementMaybeConvertDouble(idx, val); } /* static */ inline void JSObject::initDenseElementWithType(JSContext *cx, js::HandleObject obj, unsigned idx, const js::Value &val) { + JS_ASSERT(!obj->shouldConvertDoubleElements()); js::types::AddTypePropertyId(cx, obj, JSID_VOID, val); obj->initDenseElement(idx, val); } diff --git a/js/src/jstypedarrayinlines.h b/js/src/jstypedarrayinlines.h index 2e498b0a3ba..a8d3fff0b7e 100644 --- a/js/src/jstypedarrayinlines.h +++ b/js/src/jstypedarrayinlines.h @@ -28,7 +28,7 @@ js::ArrayBufferObject::setElementsHeader(js::ObjectElements *header, uint32_t by header->capacity = bytes / sizeof(js::Value); header->initializedLength = bytes; header->length = 0; - header->unused = 0; + header->convertDoubleElements = 0; } inline uint32_t diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index d26f14cc54b..4ace5cdb0e7 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -1412,6 +1412,8 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste Address(result, elementsOffset + ObjectElements::offsetOfInitializedLength())); store32(Imm32(templateObject->getArrayLength()), Address(result, elementsOffset + ObjectElements::offsetOfLength())); + store32(Imm32(templateObject->shouldConvertDoubleElements() ? 1 : 0), + Address(result, elementsOffset + ObjectElements::offsetOfConvertDoubleElements())); } else { /* * Fixed slots of non-array objects are required to be initialized; diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 5d309770218..fa7174ab466 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -6980,10 +6980,15 @@ mjit::Compiler::jsop_newinit() } JSObject *templateObject; - if (isArray) + if (isArray) { templateObject = NewDenseUnallocatedArray(cx, count); - else + types::StackTypeSet::DoubleConversion conversion = + script->analysis()->pushedTypes(PC, 0)->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles) + templateObject->setShouldConvertDoubleElements(); + } else { templateObject = CopyInitializerObject(cx, baseobj); + } if (!templateObject) return false; templateObject->setType(type); diff --git a/js/src/methodjit/Compiler.h b/js/src/methodjit/Compiler.h index 962220a0d15..bcf1d0e1ccb 100644 --- a/js/src/methodjit/Compiler.h +++ b/js/src/methodjit/Compiler.h @@ -716,7 +716,7 @@ private: void jsop_initmethod(); void jsop_initprop(); void jsop_initelem_array(); - void jsop_setelem_dense(); + void jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion); #ifdef JS_METHODJIT_TYPED_ARRAY void jsop_setelem_typed(int atype); void convertForTypedArray(int atype, ValueRemat *vr, bool *allocated); @@ -780,7 +780,8 @@ private: CompileStatus compileMathMinMaxInt(FrameEntry *arg1, FrameEntry *arg2, Assembler::Condition cond); CompileStatus compileMathPowSimple(FrameEntry *arg1, FrameEntry *arg2); - CompileStatus compileArrayPush(FrameEntry *thisv, FrameEntry *arg); + CompileStatus compileArrayPush(FrameEntry *thisv, FrameEntry *arg, + types::StackTypeSet::DoubleConversion conversion); CompileStatus compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *argTypes, FrameEntry *thisValue, FrameEntry *argValue); CompileStatus compileArrayPopShift(FrameEntry *thisv, bool isPacked, bool isArrayPop); diff --git a/js/src/methodjit/FastBuiltins.cpp b/js/src/methodjit/FastBuiltins.cpp index ad55c0ef164..5415930e9ab 100644 --- a/js/src/methodjit/FastBuiltins.cpp +++ b/js/src/methodjit/FastBuiltins.cpp @@ -414,7 +414,8 @@ mjit::Compiler::compileStringFromCode(FrameEntry *arg) } CompileStatus -mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg) +mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg, + types::StackTypeSet::DoubleConversion conversion) { /* This behaves like an assignment this[this.length] = arg; */ @@ -422,6 +423,12 @@ mjit::Compiler::compileArrayPush(FrameEntry *thisValue, FrameEntry *arg) if (frame.haveSameBacking(thisValue, arg) || thisValue->isConstant()) return Compile_InlineAbort; + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles || + conversion == types::StackTypeSet::MaybeConvertToDoubles) + { + frame.ensureDouble(arg); + } + /* Allocate registers. */ ValueRemat vr; frame.pinEntry(arg, vr, /* breakDouble = */ false); @@ -765,6 +772,16 @@ mjit::Compiler::compileArrayWithArgs(uint32_t argc) JS_ASSERT(templateObject->getDenseCapacity() >= argc); + types::StackTypeSet::DoubleConversion conversion = + script->analysis()->pushedTypes(PC, 0)->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles) { + templateObject->setShouldConvertDoubleElements(); + for (unsigned i = 0; i < argc; i++) { + FrameEntry *arg = frame.peek(-(int32_t)argc + i); + frame.ensureDouble(arg); + } + } + RegisterID result = frame.allocReg(); Jump emptyFreeList = getNewObject(cx, result, templateObject); stubcc.linkExit(emptyFreeList, Uses(0)); @@ -1004,7 +1021,9 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew) !thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES | types::OBJECT_FLAG_LENGTH_OVERFLOW) && !types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) { - return compileArrayPush(thisValue, arg); + types::StackTypeSet::DoubleConversion conversion = thisTypes->convertDoubleElements(cx); + if (conversion != types::StackTypeSet::AmbiguousDoubleConversion) + return compileArrayPush(thisValue, arg, conversion); } } if (native == js::array_concat && argType == JSVAL_TYPE_OBJECT && diff --git a/js/src/methodjit/FastOps.cpp b/js/src/methodjit/FastOps.cpp index 2a4849fb16f..b104730dcb1 100644 --- a/js/src/methodjit/FastOps.cpp +++ b/js/src/methodjit/FastOps.cpp @@ -858,7 +858,7 @@ IsCacheableSetElem(FrameEntry *obj, FrameEntry *id, FrameEntry *value) } void -mjit::Compiler::jsop_setelem_dense() +mjit::Compiler::jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion) { FrameEntry *obj = frame.peek(-3); FrameEntry *id = frame.peek(-2); @@ -866,6 +866,14 @@ mjit::Compiler::jsop_setelem_dense() frame.forgetMismatchedObject(obj); + // If the array being written to might need integer elements converted to + // doubles, make the conversion before writing. + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles || + conversion == types::StackTypeSet::MaybeConvertToDoubles) + { + frame.ensureDouble(value); + } + // We might not know whether this is an object, but if it is an object we // know it is a dense array. if (!obj->isTypeKnown()) { @@ -1340,13 +1348,18 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed) if (cx->typeInferenceEnabled()) { types::StackTypeSet *types = analysis->poppedTypes(PC, 2); + types::StackTypeSet::DoubleConversion conversion = types->convertDoubleElements(cx); if (types->getKnownClass() == &ArrayClass && !types->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES | types::OBJECT_FLAG_LENGTH_OVERFLOW) && - !types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) + !types::ArrayPrototypeHasIndexedProperty(cx, outerScript) && + conversion != types::StackTypeSet::AmbiguousDoubleConversion && + (conversion == types::StackTypeSet::DontConvertToDoubles || + value->isType(JSVAL_TYPE_DOUBLE) || + popGuaranteed)) { // Inline dense array path. - jsop_setelem_dense(); + jsop_setelem_dense(conversion); return true; } @@ -2515,6 +2528,13 @@ mjit::Compiler::jsop_initelem_array() FrameEntry *obj = frame.peek(-2); FrameEntry *fe = frame.peek(-1); + if (cx->typeInferenceEnabled()) { + types::StackTypeSet::DoubleConversion conversion = + script_->analysis()->poppedTypes(PC, 1)->convertDoubleElements(cx); + if (conversion == types::StackTypeSet::AlwaysConvertToDoubles) + frame.ensureDouble(fe); + } + uint32_t index = GET_UINT24(PC); RegisterID objReg = frame.copyDataIntoReg(obj); diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 470b439524e..b4a57f6743c 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -150,6 +150,30 @@ static ObjectElements emptyElementsHeader(0, 0); HeapSlot *js::emptyObjectElements = reinterpret_cast(uintptr_t(&emptyElementsHeader) + sizeof(ObjectElements)); +/* static */ bool +ObjectElements::ConvertElementsToDoubles(JSContext *cx, uintptr_t elementsPtr) +{ + /* + * This function is infallible, but has a fallible interface so that it can + * be called directly from Ion code. Only arrays can have their dense + * elements converted to doubles, and arrays never have empty elements. + */ + HeapSlot *elementsHeapPtr = (HeapSlot *) elementsPtr; + JS_ASSERT(elementsHeapPtr != emptyObjectElements); + + ObjectElements *header = ObjectElements::fromElements(elementsHeapPtr); + JS_ASSERT(!header->convertDoubleElements); + + Value *vp = (Value *) elementsPtr; + for (size_t i = 0; i < header->initializedLength; i++) { + if (vp[i].isInt32()) + vp[i].setDouble(vp[i].toInt32()); + } + + header->convertDoubleElements = 1; + return true; +} + #ifdef DEBUG void js::ObjectImpl::checkShapeConsistency() diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 04665b78832..1c0b25d7c81 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -935,8 +935,8 @@ class ObjectElements /* 'length' property of array objects, unused for other objects. */ uint32_t length; - /* :XXX: bug 586842 store state about sparse slots. */ - uint32_t unused; + /* If non-zero, integer elements should be converted to doubles. */ + uint32_t convertDoubleElements; void staticAsserts() { MOZ_STATIC_ASSERT(sizeof(ObjectElements) == VALUES_PER_HEADER * sizeof(Value), @@ -946,7 +946,7 @@ class ObjectElements public: ObjectElements(uint32_t capacity, uint32_t length) - : capacity(capacity), initializedLength(0), length(length) + : capacity(capacity), initializedLength(0), length(length), convertDoubleElements(0) {} HeapSlot *elements() { return (HeapSlot *)(uintptr_t(this) + sizeof(ObjectElements)); } @@ -963,6 +963,11 @@ class ObjectElements static int offsetOfLength() { return (int)offsetof(ObjectElements, length) - (int)sizeof(ObjectElements); } + static int offsetOfConvertDoubleElements() { + return (int)offsetof(ObjectElements, convertDoubleElements) - (int)sizeof(ObjectElements); + } + + static bool ConvertElementsToDoubles(JSContext *cx, uintptr_t elements); static const size_t VALUES_PER_HEADER = 2; }; From 634051e6b18275fe5c700e313e3d65730f473d84 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 15:25:01 -0800 Subject: [PATCH 40/70] Bug 835446: Convert nsNavHistoryResultNode::mTransitionType to be uint32_t rather than int32_t, to fix build warning when passing it to nsTArray::Contains(). r=mak --- toolkit/components/places/nsNavHistoryResult.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h index 1883c7f37b9..d71fb8f7758 100644 --- a/toolkit/components/places/nsNavHistoryResult.h +++ b/toolkit/components/places/nsNavHistoryResult.h @@ -382,7 +382,7 @@ public: bool mHidden; // Transition type used when this node represents a single visit. - int32_t mTransitionType; + uint32_t mTransitionType; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode, NS_NAVHISTORYRESULTNODE_IID) From 18cfd86d7e94c478278a628c6ec2180bd5348b23 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 29 Jan 2013 19:01:45 -0500 Subject: [PATCH 41/70] Backed out changeset 3eb633a97c1f (bug 835648) for suspected Windows orange on a CLOSED TREE. --- content/events/src/nsEventStateManager.h | 2 - content/media/webaudio/AudioEventTimeline.h | 4 +- content/media/webaudio/BiquadFilterNode.h | 2 +- content/media/webaudio/PannerNode.h | 2 +- .../svg/content/src/SVGPreserveAspectRatio.h | 2 - editor/libeditor/base/nsEditor.h | 3 +- layout/generic/nsIFrame.h | 2 +- mfbt/Attributes.h | 174 ++++++++++++++ mfbt/TypedEnum.h | 212 ------------------ mfbt/exported_headers.mk | 3 +- 10 files changed, 180 insertions(+), 226 deletions(-) delete mode 100644 mfbt/TypedEnum.h diff --git a/content/events/src/nsEventStateManager.h b/content/events/src/nsEventStateManager.h index 4659e024482..642d8e99d7a 100644 --- a/content/events/src/nsEventStateManager.h +++ b/content/events/src/nsEventStateManager.h @@ -6,8 +6,6 @@ #ifndef nsEventStateManager_h__ #define nsEventStateManager_h__ -#include "mozilla/TypedEnum.h" - #include "nsEvent.h" #include "nsGUIEvent.h" #include "nsIContent.h" diff --git a/content/media/webaudio/AudioEventTimeline.h b/content/media/webaudio/AudioEventTimeline.h index 4b49ebf9bec..d931975087e 100644 --- a/content/media/webaudio/AudioEventTimeline.h +++ b/content/media/webaudio/AudioEventTimeline.h @@ -7,10 +7,8 @@ #ifndef AudioEventTimeline_h_ #define AudioEventTimeline_h_ -#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" #include "mozilla/FloatingPoint.h" -#include "mozilla/TypedEnum.h" - #include "nsTArray.h" #include "math.h" diff --git a/content/media/webaudio/BiquadFilterNode.h b/content/media/webaudio/BiquadFilterNode.h index fa4ef74e941..da77897be1f 100644 --- a/content/media/webaudio/BiquadFilterNode.h +++ b/content/media/webaudio/BiquadFilterNode.h @@ -9,8 +9,8 @@ #include "AudioNode.h" #include "AudioParam.h" +#include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" -#include "mozilla/TypedEnum.h" namespace mozilla { namespace dom { diff --git a/content/media/webaudio/PannerNode.h b/content/media/webaudio/PannerNode.h index 8dc27eb7fc7..7be68b192c0 100644 --- a/content/media/webaudio/PannerNode.h +++ b/content/media/webaudio/PannerNode.h @@ -9,8 +9,8 @@ #include "AudioNode.h" #include "AudioParam.h" +#include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" -#include "mozilla/TypedEnum.h" #include "ThreeDPoint.h" namespace mozilla { diff --git a/content/svg/content/src/SVGPreserveAspectRatio.h b/content/svg/content/src/SVGPreserveAspectRatio.h index e1d4e64d2ef..ebe724eceea 100644 --- a/content/svg/content/src/SVGPreserveAspectRatio.h +++ b/content/svg/content/src/SVGPreserveAspectRatio.h @@ -5,8 +5,6 @@ #pragma once -#include "mozilla/TypedEnum.h" - #include "nsWrapperCache.h" #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h index 3eb2866deb4..a47bbbb8d2a 100644 --- a/editor/libeditor/base/nsEditor.h +++ b/editor/libeditor/base/nsEditor.h @@ -6,8 +6,7 @@ #ifndef __editor_h__ #define __editor_h__ -#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc. -#include "mozilla/TypedEnum.h" // for MOZ_BEGIN_ENUM_CLASS, etc. +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "nsAutoPtr.h" // for nsRefPtr #include "nsCOMArray.h" // for nsCOMArray #include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index f7742bf7da4..3cb52232f03 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -31,7 +31,7 @@ #include "nsAlgorithm.h" #include "mozilla/layout/FrameChildList.h" #include "FramePropertyTable.h" -#include "mozilla/TypedEnum.h" +#include "mozilla/Attributes.h" #include #ifdef ACCESSIBILITY diff --git a/mfbt/Attributes.h b/mfbt/Attributes.h index ca18d6e9e5f..d227b906e5d 100644 --- a/mfbt/Attributes.h +++ b/mfbt/Attributes.h @@ -73,6 +73,10 @@ # define MOZ_HAVE_CXX11_OVERRIDE # define MOZ_HAVE_CXX11_FINAL final # endif +# if __has_extension(cxx_strong_enums) +# define MOZ_HAVE_CXX11_ENUM_TYPE +# define MOZ_HAVE_CXX11_STRONG_ENUMS +# endif # if __has_attribute(noinline) # define MOZ_HAVE_NEVER_INLINE __attribute__((noinline)) # endif @@ -94,6 +98,10 @@ # define MOZ_HAVE_CXX11_CONSTEXPR # endif # define MOZ_HAVE_CXX11_DELETE +# if __GNUC_MINOR__ >= 5 +# define MOZ_HAVE_CXX11_ENUM_TYPE +# define MOZ_HAVE_CXX11_STRONG_ENUMS +# endif # endif # else /* __final is a non-C++11 GCC synonym for 'final', per GCC r176655. */ @@ -110,11 +118,13 @@ #elif defined(_MSC_VER) # if _MSC_VER >= 1700 # define MOZ_HAVE_CXX11_FINAL final +# define MOZ_HAVE_CXX11_STRONG_ENUMS # else /* MSVC <= 10 used to spell "final" as "sealed". */ # define MOZ_HAVE_CXX11_FINAL sealed # endif # define MOZ_HAVE_CXX11_OVERRIDE +# define MOZ_HAVE_CXX11_ENUM_TYPE # define MOZ_HAVE_NEVER_INLINE __declspec(noinline) # define MOZ_HAVE_NORETURN __declspec(noreturn) #endif @@ -315,6 +325,170 @@ # define MOZ_FINAL /* no support */ #endif +/** + * MOZ_ENUM_TYPE specifies the underlying numeric type for an enum. It's + * specified by placing MOZ_ENUM_TYPE(type) immediately after the enum name in + * its declaration, and before the opening curly brace, like + * + * enum MyEnum MOZ_ENUM_TYPE(uint16_t) + * { + * A, + * B = 7, + * C + * }; + * + * In supporting compilers, the macro will expand to ": uint16_t". The + * compiler will allocate exactly two bytes for MyEnum, and will require all + * enumerators to have values between 0 and 65535. (Thus specifying "B = + * 100000" instead of "B = 7" would fail to compile.) In old compilers, the + * macro expands to the empty string, and the underlying type is generally + * undefined. + */ +#ifdef MOZ_HAVE_CXX11_ENUM_TYPE +# define MOZ_ENUM_TYPE(type) : type +#else +# define MOZ_ENUM_TYPE(type) /* no support */ +#endif + +/** + * MOZ_BEGIN_ENUM_CLASS and MOZ_END_ENUM_CLASS provide access to the + * strongly-typed enumeration feature of C++11 ("enum class"). If supported + * by the compiler, an enum defined using these macros will not be implicitly + * converted to any other type, and its enumerators will be scoped using the + * enumeration name. Place MOZ_BEGIN_ENUM_CLASS(EnumName, type) in place of + * "enum EnumName {", and MOZ_END_ENUM_CLASS(EnumName) in place of the closing + * "};". For example, + * + * MOZ_BEGIN_ENUM_CLASS(Enum, int32_t) + * A, B = 6 + * MOZ_END_ENUM_CLASS(Enum) + * + * This will make "Enum::A" and "Enum::B" appear in the global scope, but "A" + * and "B" will not. In compilers that support C++11 strongly-typed + * enumerations, implicit conversions of Enum values to numeric types will + * fail. In other compilers, Enum itself will actually be defined as a class, + * and some implicit conversions will fail while others will succeed. + * + * The type argument specifies the underlying type for the enum where + * supported, as with MOZ_ENUM_TYPE(). For simplicity, it is currently + * mandatory. As with MOZ_ENUM_TYPE(), it will do nothing on compilers that do + * not support it. + * + * Note that the workaround implemented here is not compatible with enums + * nested inside a class. + */ +#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) + /* All compilers that support strong enums also support an explicit + * underlying type, so no extra check is needed */ +# define MOZ_BEGIN_ENUM_CLASS(Name, type) enum class Name : type { +# define MOZ_END_ENUM_CLASS(Name) }; +#else + /** + * We need Name to both name a type, and scope the provided enumerator + * names. Namespaces and classes both provide scoping, but namespaces + * aren't types, so we need to use a class that wraps the enum values. We + * have an implicit conversion from the inner enum type to the class, so + * statements like + * + * Enum x = Enum::A; + * + * will still work. We need to define an implicit conversion from the class + * to the inner enum as well, so that (for instance) switch statements will + * work. This means that the class can be implicitly converted to a numeric + * value as well via the enum type, since C++ allows an implicit + * user-defined conversion followed by a standard conversion to still be + * implicit. + * + * We have an explicit constructor from int defined, so that casts like + * (Enum)7 will still work. We also have a zero-argument constructor with + * no arguments, so declaration without initialization (like "Enum foo;") + * will work. + * + * Additionally, we'll delete as many operators as possible for the inner + * enum type, so statements like this will still fail: + * + * f(5 + Enum::B); // deleted operator+ + * + * But we can't prevent things like this, because C++ doesn't allow + * overriding conversions or assignment operators for enums: + * + * int x = Enum::A; + * int f() + * { + * return Enum::A; + * } + */ +# define MOZ_BEGIN_ENUM_CLASS(Name, type) \ + class Name \ + { \ + public: \ + enum Enum MOZ_ENUM_TYPE(type) \ + { +# define MOZ_END_ENUM_CLASS(Name) \ + }; \ + Name() {} \ + Name(Enum aEnum) : mEnum(aEnum) {} \ + explicit Name(int num) : mEnum((Enum)num) {} \ + operator Enum() const { return mEnum; } \ + private: \ + Enum mEnum; \ + }; \ + inline int operator+(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator+(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator-(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator-(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator*(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator*(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator/(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator/(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator%(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator%(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator+(const Name::Enum&) MOZ_DELETE; \ + inline int operator-(const Name::Enum&) MOZ_DELETE; \ + inline int& operator++(Name::Enum&) MOZ_DELETE; \ + inline int operator++(Name::Enum&, int) MOZ_DELETE; \ + inline int& operator--(Name::Enum&) MOZ_DELETE; \ + inline int operator--(Name::Enum&, int) MOZ_DELETE; \ + inline bool operator==(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator==(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator!=(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator!=(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator>(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator>(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator<(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator<(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator>=(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator>=(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator<=(const int&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator<=(const Name::Enum&, const int&) MOZ_DELETE; \ + inline bool operator!(const Name::Enum&) MOZ_DELETE; \ + inline bool operator&&(const bool&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator&&(const Name::Enum&, const bool&) MOZ_DELETE; \ + inline bool operator||(const bool&, const Name::Enum&) MOZ_DELETE; \ + inline bool operator||(const Name::Enum&, const bool&) MOZ_DELETE; \ + inline int operator~(const Name::Enum&) MOZ_DELETE; \ + inline int operator&(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator&(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator|(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator|(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator^(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator^(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator<<(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator<<(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int operator>>(const int&, const Name::Enum&) MOZ_DELETE; \ + inline int operator>>(const Name::Enum&, const int&) MOZ_DELETE; \ + inline int& operator+=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator-=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator*=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator/=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator%=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator&=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator|=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator^=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator<<=(int&, const Name::Enum&) MOZ_DELETE; \ + inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE; +#endif + /** * MOZ_WARN_UNUSED_RESULT tells the compiler to emit a warning if a function's * return value is not used by the caller. diff --git a/mfbt/TypedEnum.h b/mfbt/TypedEnum.h deleted file mode 100644 index b94f1279662..00000000000 --- a/mfbt/TypedEnum.h +++ /dev/null @@ -1,212 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* Macros to emulate C++11 typed enums and enum classes. */ - -#ifndef mozilla_TypedEnum_h_ -#define mozilla_TypedEnum_h_ - -#if defined(__clang__) - /* - * Per Clang documentation, "Note that marketing version numbers should not - * be used to check for language features, as different vendors use different - * numbering schemes. Instead, use the feature checking macros." - */ -# ifndef __has_extension -# define __has_extension __has_feature /* compatibility, for older versions of clang */ -# endif -# if __has_extension(cxx_strong_enums) -# define MOZ_HAVE_CXX11_ENUM_TYPE -# define MOZ_HAVE_CXX11_STRONG_ENUMS -# endif -#elif defined(__GNUC__) -# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L -# if __GNUC__ > 4 -# define MOZ_HAVE_CXX11_ENUM_TYPE -# define MOZ_HAVE_CXX11_STRONG_ENUMS -# elif __GNUC__ == 4 -# if __GNUC_MINOR__ >= 5 -# define MOZ_HAVE_CXX11_ENUM_TYPE -# define MOZ_HAVE_CXX11_STRONG_ENUMS -# endif -# endif -# endif -#elif defined(_MSC_VER) -# if _MSC_VER >= 1400 -# define MOZ_HAVE_CXX11_ENUM_TYPE -# endif -# if _MSC_VER >= 1700 -# define MOZ_HAVE_CXX11_STRONG_ENUMS -# endif -#endif - -/** - * MOZ_ENUM_TYPE specifies the underlying numeric type for an enum. It's - * specified by placing MOZ_ENUM_TYPE(type) immediately after the enum name in - * its declaration, and before the opening curly brace, like - * - * enum MyEnum MOZ_ENUM_TYPE(uint16_t) - * { - * A, - * B = 7, - * C - * }; - * - * In supporting compilers, the macro will expand to ": uint16_t". The - * compiler will allocate exactly two bytes for MyEnum and will require all - * enumerators to have values between 0 and 65535. (Thus specifying "B = - * 100000" instead of "B = 7" would fail to compile.) In old compilers the - * macro expands to the empty string, and the underlying type is generally - * undefined. - */ -#ifdef MOZ_HAVE_CXX11_ENUM_TYPE -# define MOZ_ENUM_TYPE(type) : type -#else -# define MOZ_ENUM_TYPE(type) /* no support */ -#endif - -/** - * MOZ_BEGIN_ENUM_CLASS and MOZ_END_ENUM_CLASS provide access to the - * strongly-typed enumeration feature of C++11 ("enum class"). If supported - * by the compiler, an enum defined using these macros will not be implicitly - * converted to any other type, and its enumerators will be scoped using the - * enumeration name. Place MOZ_BEGIN_ENUM_CLASS(EnumName, type) in place of - * "enum EnumName {", and MOZ_END_ENUM_CLASS(EnumName) in place of the closing - * "};". For example, - * - * MOZ_BEGIN_ENUM_CLASS(Enum, int32_t) - * A, - * B = 6 - * MOZ_END_ENUM_CLASS(Enum) - * - * This will make "Enum::A" and "Enum::B" appear in the global scope, but "A" - * and "B" will not. In compilers that support C++11 strongly-typed - * enumerations, implicit conversions of Enum values to numeric types will - * fail. In other compilers, Enum itself will actually be defined as a class, - * and some implicit conversions will fail while others will succeed. - * - * The type argument specifies the underlying type for the enum where - * supported, as with MOZ_ENUM_TYPE(). For simplicity, it is currently - * mandatory. As with MOZ_ENUM_TYPE(), it will do nothing on compilers that do - * not support it. - * - * Note that the workaround implemented here is not compatible with enums - * nested inside a class. - */ -#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) - /* - * All compilers that support strong enums also support an explicit - * underlying type, so no extra check is needed. - */ -# define MOZ_BEGIN_ENUM_CLASS(Name, type) enum class Name : type { -# define MOZ_END_ENUM_CLASS(Name) }; -#else - /** - * We need Name to both name a type, and scope the provided enumerator - * names. Namespaces and classes both provide scoping, but namespaces - * aren't types, so we need to use a class that wraps the enum values. We - * have an implicit conversion from the inner enum type to the class, so - * statements like - * - * Enum x = Enum::A; - * - * will still work. We need to define an implicit conversion from the class - * to the inner enum as well, so that (for instance) switch statements will - * work. This means that the class can be implicitly converted to a numeric - * value as well via the enum type, since C++ allows an implicit - * user-defined conversion followed by a standard conversion to still be - * implicit. - * - * We have an explicit constructor from int defined, so that casts like - * (Enum)7 will still work. We also have a zero-argument constructor with - * no arguments, so declaration without initialization (like "Enum foo;") - * will work. - * - * Additionally, we'll delete as many operators as possible for the inner - * enum type, so statements like this will still fail: - * - * f(5 + Enum::B); // deleted operator+ - * - * But we can't prevent things like this, because C++ doesn't allow - * overriding conversions or assignment operators for enums: - * - * int x = Enum::A; - * int f() - * { - * return Enum::A; - * } - */ -# define MOZ_BEGIN_ENUM_CLASS(Name, type) \ - class Name \ - { \ - public: \ - enum Enum MOZ_ENUM_TYPE(type) \ - { -# define MOZ_END_ENUM_CLASS(Name) \ - }; \ - Name() {} \ - Name(Enum aEnum) : mEnum(aEnum) {} \ - explicit Name(int num) : mEnum((Enum)num) {} \ - operator Enum() const { return mEnum; } \ - private: \ - Enum mEnum; \ - }; \ - inline int operator+(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator+(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator-(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator-(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator*(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator*(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator/(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator/(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator%(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator%(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator+(const Name::Enum&) MOZ_DELETE; \ - inline int operator-(const Name::Enum&) MOZ_DELETE; \ - inline int& operator++(Name::Enum&) MOZ_DELETE; \ - inline int operator++(Name::Enum&, int) MOZ_DELETE; \ - inline int& operator--(Name::Enum&) MOZ_DELETE; \ - inline int operator--(Name::Enum&, int) MOZ_DELETE; \ - inline bool operator==(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator==(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator!=(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator!=(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator>(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator>(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator<(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator<(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator>=(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator>=(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator<=(const int&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator<=(const Name::Enum&, const int&) MOZ_DELETE; \ - inline bool operator!(const Name::Enum&) MOZ_DELETE; \ - inline bool operator&&(const bool&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator&&(const Name::Enum&, const bool&) MOZ_DELETE; \ - inline bool operator||(const bool&, const Name::Enum&) MOZ_DELETE; \ - inline bool operator||(const Name::Enum&, const bool&) MOZ_DELETE; \ - inline int operator~(const Name::Enum&) MOZ_DELETE; \ - inline int operator&(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator&(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator|(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator|(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator^(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator^(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator<<(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator<<(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int operator>>(const int&, const Name::Enum&) MOZ_DELETE; \ - inline int operator>>(const Name::Enum&, const int&) MOZ_DELETE; \ - inline int& operator+=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator-=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator*=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator/=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator%=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator&=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator|=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator^=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator<<=(int&, const Name::Enum&) MOZ_DELETE; \ - inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE; -#endif - -#endif /* mozilla_TypedEnum_h_ */ diff --git a/mfbt/exported_headers.mk b/mfbt/exported_headers.mk index d1d3ecf2753..ad0324b8b3b 100644 --- a/mfbt/exported_headers.mk +++ b/mfbt/exported_headers.mk @@ -33,9 +33,8 @@ EXPORTS_mozilla += \ SplayTree.h \ StandardInteger.h \ ThreadLocal.h \ - TypedEnum.h \ - Types.h \ TypeTraits.h \ + Types.h \ Util.h \ WeakPtr.h \ $(NULL) From 0ad7a5b1292aba0cc032ad88f5a9265e3fd2a1cc Mon Sep 17 00:00:00 2001 From: Nicholas Cameron Date: Tue, 29 Jan 2013 14:38:46 +1300 Subject: [PATCH 42/70] Bug 836058; remove UseTiledThebes; r=BenWa --- gfx/layers/Layers.cpp | 7 ------- gfx/layers/Layers.h | 2 -- gfx/layers/TiledLayerBuffer.h | 5 +++++ gfx/layers/basic/BasicLayerManager.cpp | 5 +++-- gfx/layers/opengl/LayerManagerOGL.cpp | 6 ++++-- gfx/layers/opengl/ThebesLayerOGL.cpp | 5 +++-- mobile/android/app/mobile.js | 3 --- 7 files changed, 15 insertions(+), 18 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 1c0d2f520e6..b4a464fb9ac 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -260,13 +260,6 @@ LayerManager::GetScrollableLayers(nsTArray& aArray) } } -bool ThebesLayer::UseTiledThebes() -{ - static bool useTiledThebesLayer = - Preferences::GetBool("gfx.use_tiled_thebes", false); - return useTiledThebesLayer; -} - already_AddRefed LayerManager::CreateOptimalSurface(const gfxIntSize &aSize, gfxASurface::gfxImageFormat aFormat) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 2644f9b0c90..a346b4f6a05 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1286,8 +1286,6 @@ public: */ gfxPoint GetResidualTranslation() const { return mResidualTranslation; } - static bool UseTiledThebes(); - protected: ThebesLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData) diff --git a/gfx/layers/TiledLayerBuffer.h b/gfx/layers/TiledLayerBuffer.h index 0c9001a91a1..70f9f3c559e 100644 --- a/gfx/layers/TiledLayerBuffer.h +++ b/gfx/layers/TiledLayerBuffer.h @@ -8,6 +8,11 @@ #define TILEDLAYERBUFFER_TILE_SIZE 256 // Debug defines +#ifdef MOZ_ANDROID_OMTC + // This needs to go away as we enabled tiled + // layers everywhere. + #define FORCE_BASICTILEDTHEBESLAYER +#endif //#define GFX_TILEDLAYER_DEBUG_OVERLAY //#define GFX_TILEDLAYER_PREF_WARNINGS diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index 6ec2d76c51e..a984708371c 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -1341,8 +1341,8 @@ already_AddRefed BasicShadowLayerManager::CreateThebesLayer() { NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); - if (HasShadowManager() && GetParentBackendType() == LAYERS_OPENGL && - ThebesLayer::UseTiledThebes()) { +#ifdef FORCE_BASICTILEDTHEBESLAYER + if (HasShadowManager() && GetParentBackendType() == LAYERS_OPENGL) { // BasicTiledThebesLayer doesn't support main // thread compositing so only return this layer // type if we have a shadow manager. @@ -1351,6 +1351,7 @@ BasicShadowLayerManager::CreateThebesLayer() MAYBE_CREATE_SHADOW(Thebes); return layer.forget(); } else +#endif { nsRefPtr layer = new BasicShadowableThebesLayer(this); diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 920babe9a42..2e96692f674 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -1554,9 +1554,11 @@ LayerManagerOGL::CreateShadowThebesLayer() NS_WARNING("Call on destroyed layer manager"); return nullptr; } - if (ThebesLayer::UseTiledThebes()) - return nsRefPtr(new TiledThebesLayerOGL(this)).forget(); +#ifdef FORCE_BASICTILEDTHEBESLAYER + return nsRefPtr(new TiledThebesLayerOGL(this)).forget(); +#else return nsRefPtr(new ShadowThebesLayerOGL(this)).forget(); +#endif } already_AddRefed diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp index ee339f9084a..432ada089aa 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -1027,8 +1027,9 @@ ShadowThebesLayerOGL::ShadowThebesLayerOGL(LayerManagerOGL *aManager) : ShadowThebesLayer(aManager, nullptr) , LayerOGL(aManager) { - if (ThebesLayer::UseTiledThebes()) - NS_ABORT(); +#ifdef FORCE_BASICTILEDTHEBESLAYER + NS_ABORT(); +#endif mImplData = static_cast(this); } diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index e0319a243f1..61a9d7b086b 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -674,6 +674,3 @@ pref("app.orientation.default", ""); // On memory pressure, release dirty but unused pages held by jemalloc // back to the system. pref("memory.free_dirty_pages", true); - -// Enable tiled layers rendering by default on android -pref("gfx.use_tiled_thebes", true); From bcd8c7f50862aa1e28cfc4a7c4b2a46662e0feda Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Tue, 29 Jan 2013 17:50:12 -0800 Subject: [PATCH 43/70] Update Jetpack tests in run against Firefox to pick up bug 832590. r=kwierso --- testing/jetpack/jetpack-location.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/jetpack/jetpack-location.txt b/testing/jetpack/jetpack-location.txt index 59321cff4b1..00e2024b1b0 100644 --- a/testing/jetpack/jetpack-location.txt +++ b/testing/jetpack/jetpack-location.txt @@ -1 +1 @@ -http://hg.mozilla.org/projects/addon-sdk/archive/03fc0406c5e2.tar.bz2 +http://hg.mozilla.org/projects/addon-sdk/archive/f68c6b75d728.tar.bz2 From 74281ba12ff827bd3932772204d7ddf743e3cf39 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 17:59:12 -0800 Subject: [PATCH 44/70] Bug 836088: move variable 'platformData' closer to where it's used, in TableTicker.cpp, to fix unused variable warning on Mac OS X. r=BenWa --- tools/profiler/TableTicker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index 6acf8a1ec1c..faead5f4995 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -820,11 +820,6 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample) // Start with the current function. StackWalkCallback(aSample->pc, aSample->sp, &array); - void *platformData = nullptr; -#ifdef XP_WIN - platformData = aSample->context; -#endif - uint32_t maxFrames = array.size - array.count; #ifdef XP_MACOSX pthread_t pt = GetProfiledThread(platform_data()); @@ -837,6 +832,11 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample) maxFrames, &array, reinterpret_cast(aSample->fp), stackEnd); #else + void *platformData = nullptr; +#ifdef XP_WIN + platformData = aSample->context; +#endif // XP_WIN + nsresult rv = NS_StackWalk(StackWalkCallback, /* skipFrames */ 0, maxFrames, &array, thread, platformData); #endif From 7accb646e1cf449474544dc55887583d373c97c0 Mon Sep 17 00:00:00 2001 From: ithinc Date: Wed, 9 Jan 2013 21:01:18 +0800 Subject: [PATCH 45/70] Bug 821859 - Use stylesheet for tab delay resizing instead of setting each tab.style. r=fryn --- browser/base/content/browser.css | 8 ++++ browser/base/content/tabbrowser.xml | 67 +++++++++++++++-------------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index f14829d8f06..3e6278c191b 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -52,6 +52,14 @@ tabbrowser { opacity 50ms ease-out 180ms /* hide the tab for the last 20ms of the max-width transition */; } +.tabbrowser-tabs[dontresize] > .tabbrowser-tab[fadein]:not([pinned]) { + /* controlled in tabbrowser.xml */ +} + +.tabbrowser-tabs[dontanimate] > .tabbrowser-tab { + transition: none !important; +} + .tab-throbber:not([fadein]):not([pinned]), .tab-label:not([fadein]):not([pinned]), .tab-icon-image:not([fadein]):not([pinned]), diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 59bbaedee45..9d8cd32792e 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1584,7 +1584,6 @@ aTab._animStartTime = Date.now(); this._blurTab(aTab); - aTab.style.maxWidth = ""; // ensure that fade-out transition happens aTab.removeAttribute("fadein"); setTimeout(function (tab, tabbrowser) { @@ -3075,9 +3074,18 @@ document.getAnonymousElementByAttribute(this, "anonid", "closing-tabs-spacer"); - NaN false - false + + .tabbrowser-tab[fadein]:not([pinned])"; + + // XXX: document.styleSheets is not iterable (see bug 738196) + for (let sheet of Array.slice(document.styleSheets)) + if (sheet.href == href) + for (let rule of Array.slice(sheet.cssRules)) + if (rule.selectorText == selector) { rule; break; } + ]]> @@ -3090,9 +3098,6 @@ var isEndTab = (aTab._tPos > tabs[tabs.length-1]._tPos); var tabWidth = aTab.getBoundingClientRect().width; - if (!this._tabDefaultMaxWidth) - this._tabDefaultMaxWidth = - parseFloat(window.getComputedStyle(aTab).maxWidth); this._lastTabClosedByMouse = true; if (this.getAttribute("overflow") == "true") { @@ -3110,30 +3115,31 @@ this._expandSpacerBy(tabWidth); } else { // non-overflow mode // Locking is neither in effect nor needed, so let tabs expand normally. - if (isEndTab && !this._hasTabTempMaxWidth) + if (isEndTab && !this.hasAttribute("dontresize")) return; - let numPinned = this.tabbrowser._numPinnedTabs; - // Force tabs to stay the same width, unless we're closing the last tab, - // which case we need to let them expand just enough so that the overall - // tabbar width is the same. + // Let spacer grow to the maximum and lock it, then let tabs expand normally if (isEndTab) { - let numNormalTabs = tabs.length - numPinned; - tabWidth = tabWidth * (numNormalTabs + 1) / numNormalTabs; - if (tabWidth > this._tabDefaultMaxWidth) - tabWidth = this._tabDefaultMaxWidth; + let spacer = this._closingTabsSpacer; + spacer.style.MozBoxFlex = 1; + spacer.style.minWidth = getComputedStyle(spacer).width; + spacer.style.MozBoxFlex = ""; + + this.setAttribute("dontanimate", "true"); + this.removeAttribute("dontresize"); + this.clientTop; + this.removeAttribute("dontanimate"); + return; } - tabWidth += "px"; - for (let i = numPinned; i < tabs.length; i++) { - let tab = tabs[i]; - tab.style.setProperty("max-width", tabWidth, "important"); - if (!isEndTab) { // keep tabs the same width - tab.style.transition = "none"; - tab.clientTop; // flush styles to skip animation; see bug 649247 - tab.style.transition = ""; - } - } - this._hasTabTempMaxWidth = true; + + if (this.hasAttribute("dontresize")) + return; + + this._delayResizingRule.style.setProperty("max-width", tabWidth + "px", "important"); + this.setAttribute("dontanimate", "true"); + this.setAttribute("dontresize", "true"); + this.clientTop; // flush styles to skip animation; see bug 649247 + this.removeAttribute("dontanimate"); this.tabbrowser.addEventListener("mousemove", this, false); window.addEventListener("mouseout", this, false); } @@ -3156,17 +3162,12 @@ this.tabbrowser.removeEventListener("mousemove", this, false); window.removeEventListener("mouseout", this, false); - if (this._hasTabTempMaxWidth) { - this._hasTabTempMaxWidth = false; - let tabs = this.tabbrowser.visibleTabs; - for (let i = 0; i < tabs.length; i++) - tabs[i].style.maxWidth = ""; - } - if (this.hasAttribute("using-closing-tabs-spacer")) { this.removeAttribute("using-closing-tabs-spacer"); this._closingTabsSpacer.style.width = 0; } + this._closingTabsSpacer.style.minWidth = ""; + this.removeAttribute("dontresize"); ]]> From 9c7dfa41cde212b8560c1ca12ff697e2f3571e4d Mon Sep 17 00:00:00 2001 From: ithinc Date: Tue, 29 Jan 2013 18:14:45 -0800 Subject: [PATCH 46/70] Bug 649654 - When tab bar underflow occurs and tab strip was scrolled to the beginning, resize tabs such that they can be closed in succession. r=fryn --- browser/base/content/tabbrowser.css | 3 +- browser/base/content/tabbrowser.xml | 105 ++++++++++++---------------- 2 files changed, 48 insertions(+), 60 deletions(-) diff --git a/browser/base/content/tabbrowser.css b/browser/base/content/tabbrowser.css index 2dd6a05297c..9f1b8a91f44 100644 --- a/browser/base/content/tabbrowser.css +++ b/browser/base/content/tabbrowser.css @@ -47,11 +47,12 @@ tabpanels { } .closing-tabs-spacer { + min-width: 0; pointer-events: none; } .tabbrowser-tabs:not(:hover) > .tabbrowser-arrowscrollbox > .closing-tabs-spacer { - transition: width .15s ease-out; + transition: min-width 150ms ease-out; } /** diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 9d8cd32792e..62e887dae38 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1780,10 +1780,6 @@ // update tab close buttons state this.tabContainer.adjustTabstrip(); - - setTimeout(function(tabs) { - tabs._lastTabClosedByMouse = false; - }, 0, this.tabContainer); } // update first-tab/last-tab/beforeselected/afterselected attributes @@ -2828,10 +2824,13 @@ return; // Ignore vertical events var tabs = document.getBindingParent(this); - tabs.removeAttribute("overflow"); - if (tabs._lastTabClosedByMouse) - tabs._expandSpacerBy(this._scrollButtonDown.clientWidth); + if (tabs.hasAttribute("dontresize") || tabs.hasAttribute("using-closing-tabs-spacer")) { + tabs.mTabstrip._scrollButtonUp.style.visibility = "hidden"; + tabs.mTabstrip._scrollButtonDown.style.visibility = "hidden"; + } else { + tabs.removeAttribute("overflow"); + } tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab, tabs.tabbrowser); @@ -2876,8 +2875,7 @@ command="cmd_newNavigatorTab" onclick="checkForMiddleClick(this, event);" tooltiptext="&newTabButton.tooltip;"/> - + @@ -3074,8 +3072,6 @@ document.getAnonymousElementByAttribute(this, "anonid", "closing-tabs-spacer"); - false - .tabbrowser-tab[fadein]:not([pinned])"; @@ -3098,60 +3094,48 @@ var isEndTab = (aTab._tPos > tabs[tabs.length-1]._tPos); var tabWidth = aTab.getBoundingClientRect().width; - this._lastTabClosedByMouse = true; + // Locking is neither in effect nor needed, so let tabs expand normally. + if (isEndTab && !this.hasAttribute("dontresize")) + return; - if (this.getAttribute("overflow") == "true") { - // Don't need to do anything if we're in overflow mode and aren't scrolled - // all the way to the right, or if we're closing the last tab. - if (isEndTab || !this.mTabstrip._scrollButtonDown.disabled) - return; + // Let spacer grow to the maximum and lock it, then let tabs expand normally + if (isEndTab) { + let spacer = this._closingTabsSpacer; + spacer.style.MozBoxFlex = 1; + spacer.style.minWidth = getComputedStyle(spacer).width; + spacer.style.MozBoxFlex = ""; - // If the tab has an owner that will become the active tab, the owner will - // be to the left of it, so we actually want the left tab to slide over. - // This can't be done as easily in non-overflow mode, so we don't bother. - if (aTab.owner) - return; - - this._expandSpacerBy(tabWidth); - } else { // non-overflow mode - // Locking is neither in effect nor needed, so let tabs expand normally. - if (isEndTab && !this.hasAttribute("dontresize")) - return; - - // Let spacer grow to the maximum and lock it, then let tabs expand normally - if (isEndTab) { - let spacer = this._closingTabsSpacer; - spacer.style.MozBoxFlex = 1; - spacer.style.minWidth = getComputedStyle(spacer).width; - spacer.style.MozBoxFlex = ""; - - this.setAttribute("dontanimate", "true"); - this.removeAttribute("dontresize"); - this.clientTop; - this.removeAttribute("dontanimate"); - return; - } - - if (this.hasAttribute("dontresize")) - return; + this.setAttribute("dontanimate", "true"); + this.removeAttribute("dontresize"); + this.clientTop; + this.removeAttribute("dontanimate"); + return; + } + if (!this.hasAttribute("dontresize")) { this._delayResizingRule.style.setProperty("max-width", tabWidth + "px", "important"); this.setAttribute("dontanimate", "true"); this.setAttribute("dontresize", "true"); this.clientTop; // flush styles to skip animation; see bug 649247 this.removeAttribute("dontanimate"); - this.tabbrowser.addEventListener("mousemove", this, false); - window.addEventListener("mouseout", this, false); } - ]]> - - - - = 0) { + spacer.style.minWidth = width + "px"; + this.setAttribute("using-closing-tabs-spacer", "true"); + } + } + this.tabbrowser.addEventListener("mousemove", this, false); window.addEventListener("mouseout", this, false); ]]> @@ -3162,12 +3146,15 @@ this.tabbrowser.removeEventListener("mousemove", this, false); window.removeEventListener("mouseout", this, false); - if (this.hasAttribute("using-closing-tabs-spacer")) { - this.removeAttribute("using-closing-tabs-spacer"); - this._closingTabsSpacer.style.width = 0; - } this._closingTabsSpacer.style.minWidth = ""; + this.removeAttribute("using-closing-tabs-spacer"); this.removeAttribute("dontresize"); + + if (this.hasAttribute("overflow") && this.mTabstrip._scrollbox.scrollWidth <= this.mTabstrip._scrollbox.clientWidth) { + this.mTabstrip._scrollButtonUp.style.visibility = ""; + this.mTabstrip._scrollButtonDown.style.visibility = ""; + this.removeAttribute("overflow"); + } ]]> From 34f7f843298b3650d056330f7f0130195801754d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Tue, 29 Jan 2013 18:24:43 -0800 Subject: [PATCH 47/70] Bug 836045 - Update Webapps code to use the new deviceStorage stat() support r=djf --- dom/apps/src/FreeSpaceWatcher.jsm | 4 ++-- dom/apps/src/Webapps.jsm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dom/apps/src/FreeSpaceWatcher.jsm b/dom/apps/src/FreeSpaceWatcher.jsm index b9b3f98895c..cfe95b58b6b 100644 --- a/dom/apps/src/FreeSpaceWatcher.jsm +++ b/dom/apps/src/FreeSpaceWatcher.jsm @@ -44,13 +44,13 @@ this.FreeSpaceWatcher = { try { let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser") .navigator.getDeviceStorage("apps"); - let req = deviceStorage.stat(); + let req = deviceStorage.freeSpace(); req.onsuccess = req.onerror = function statResult(e) { if (!e.target.result) { return; } - let freeBytes = e.target.result.freeBytes; + let freeBytes = e.target.result; debug("Free bytes: " + freeBytes); let newStatus = freeBytes > aThreshold; if (newStatus != callback.currentStatus) { diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index e72a0ac4c14..9fe0245f31f 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -2265,7 +2265,7 @@ this.DOMApplicationRegistry = { let deviceStorage = Services.wm.getMostRecentWindow("navigator:browser") .navigator.getDeviceStorage("apps"); - let req = deviceStorage.stat(); + let req = deviceStorage.freeSpace(); req.onsuccess = req.onerror = function statResult(e) { // Even if we could not retrieve the device storage free space, we try // to download the package. @@ -2274,7 +2274,7 @@ this.DOMApplicationRegistry = { return; } - let freeBytes = e.target.result.freeBytes; + let freeBytes = e.target.result; if (freeBytes) { debug("Free storage: " + freeBytes + ". Download size: " + aApp.downloadSize); From 61d51edd4c561aabfb3758c1b862da2b4ec6c0d3 Mon Sep 17 00:00:00 2001 From: Chuck Lee Date: Tue, 29 Jan 2013 10:32:31 +0800 Subject: [PATCH 48/70] Bug 831627 - 0001. Add event object. r=yoshi. sr=sicking --- dom/icc/interfaces/SimToolKit.idl | 23 ++++++++++++++++++++--- dom/icc/interfaces/nsIDOMIccManager.idl | 2 ++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dom/icc/interfaces/SimToolKit.idl b/dom/icc/interfaces/SimToolKit.idl index fc3de08df49..f80071a7fec 100644 --- a/dom/icc/interfaces/SimToolKit.idl +++ b/dom/icc/interfaces/SimToolKit.idl @@ -592,14 +592,31 @@ dictionary MozStkLocalInfo DOMString language; }; +dictionary MozStkLanguageSelectionEvent +{ + /** + * The type of this event. + * It shall be nsIDOMMozIccManager.STK_EVENT_TYPE_LANGUAGE_SELECTION. + */ + unsigned short eventType; + + /** + * Language Information + * + * @see ISO 639-1, Alpha-2 code + * "de" for German, "en" for English, "zh" for Chinese, etc. + */ + DOMString language; +}; + dictionary MozStkGeneralEvent { /** * The type of this event, MozStkGeneralEvent can be used for all Stk Event * requires no more parameter than event type, including - * nsIDOMMozIccManager.STK_EVENT_TYPE_USER_ACTIVITY - * nsIDOMMozIccManager.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE - * HCI Connectivity Event(Not defined in interface yet) + * nsIDOMMozIccManager.STK_EVENT_TYPE_USER_ACTIVITY. + * nsIDOMMozIccManager.STK_EVENT_TYPE_IDLE_SCREEN_AVAILABLE. + * HCI Connectivity Event(Not defined in interface yet). */ unsigned short eventType; }; diff --git a/dom/icc/interfaces/nsIDOMIccManager.idl b/dom/icc/interfaces/nsIDOMIccManager.idl index 2c040acedfb..51bbb2724ea 100644 --- a/dom/icc/interfaces/nsIDOMIccManager.idl +++ b/dom/icc/interfaces/nsIDOMIccManager.idl @@ -256,6 +256,8 @@ interface nsIDOMMozIccManager : nsIDOMEventTarget * one of events below: * - MozStkLocationEvent * - MozStkCallEvent + * - MozStkLanguageSelectionEvent + * - MozStkGeneralEvent */ void sendStkEventDownload(in jsval event); From d5e659c5e00743d31c759a8b5744f0c41cbdd679 Mon Sep 17 00:00:00 2001 From: Chuck Lee Date: Mon, 28 Jan 2013 10:44:12 +0800 Subject: [PATCH 49/70] Bug 831627 - 0002. Handle event. r=yoshi --- dom/system/gonk/ril_worker.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index ca304107fae..534f3b347e6 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -2608,6 +2608,13 @@ let RIL = { destinationId: STK_DEVICE_ID_SIM }; break; + case STK_EVENT_TYPE_LANGUAGE_SELECTION: + command.deviceId = { + sourceId: STK_DEVICE_ID_ME, + destinationId: STK_DEVICE_ID_SIM + }; + command.language = command.event.language; + break; } this.sendICCEnvelopeCommand(command); }, @@ -2729,6 +2736,11 @@ let RIL = { ComprehensionTlvHelper.writeTimerValueTlv(options.timerValue, true); } + // Language + if (options.language) { + ComprehensionTlvHelper.writeLanguageTlv(options.language); + } + // Calculate and write BER length to 2nd mark Buf.stopCalOutgoingSize(); From c247be6759bb360a21e76d595ecccd2a4c72c4e9 Mon Sep 17 00:00:00 2001 From: Chuck Lee Date: Mon, 28 Jan 2013 10:44:13 +0800 Subject: [PATCH 50/70] Bug 831627 - 0003. Mark event as supported. r=yoshi --- dom/system/gonk/ril_consts.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dom/system/gonk/ril_consts.js b/dom/system/gonk/ril_consts.js index 155c39cc80a..c26b4457cf7 100644 --- a/dom/system/gonk/ril_consts.js +++ b/dom/system/gonk/ril_consts.js @@ -907,6 +907,11 @@ this.STK_TERMINAL_SUPPORT_EVENT_USER_ACTIVITY = 0; this.STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE = 1; this.STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS = 0; +this.STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION = 1; +this.STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION = 0; +this.STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE = 0; +this.STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS = 0; + this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP = 1; this.STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT = 1; this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_DATE = 1; @@ -925,6 +930,11 @@ this.STK_TERMINAL_SUPPORT_PROACTIVE_LANGUAGE_NOTIFICATION = 0; this.STK_TERMINAL_SUPPORT_PROACTIVE_LAUNCH_BROWSER = 1; this.STK_TERMINAL_SUPPORT_PROACTIVE_LOCAL_INFO_ACCESS_TECH = 0; +/** + * SAT profile + * + * @see ETSI TS 101.267, section 5.2. + */ this.STK_TERMINAL_PROFILE_DOWNLOAD = (STK_TERMINAL_SUPPORT_PROFILE_DOWNLOAD << 0) | (STK_TERMINAL_SUPPORT_SMS_PP_DOWNLOAD << 1) | @@ -975,6 +985,12 @@ this.STK_TERMINAL_PROFILE_EVENT = (STK_TERMINAL_SUPPORT_EVENT_IDLE_SCREEN_AVAILABLE << 6) | (STK_TERMINAL_SUPPORT_EVENT_CARD_READER_STATUS << 7); +this.STK_TERMINAL_PROFILE_EVENT_EXT = + (STK_TERMINAL_SUPPORT_EVENT_LANGUAGE_SELECTION << 0) | + (STK_TERMINAL_SUPPORT_EVENT_BROWSER_TERMINATION << 1) | + (STK_TERMINAL_SUPPORT_EVENT_DATA_AVAILABLE << 2) | + (STK_TERMINAL_SUPPORT_EVENT_CHANNEL_STATUS << 3); + this.STK_TERMINAL_PROFILE_PROACTIVE_3 = (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_START_STOP << 0) | (STK_TERMINAL_SUPPORT_PROACTIVE_TIMER_GET_CURRENT << 1) | @@ -1001,7 +1017,7 @@ this.STK_SUPPORTED_TERMINAL_PROFILE = [ STK_TERMINAL_PROFILE_PROACTIVE_1, STK_TERMINAL_PROFILE_PROACTIVE_2, STK_TERMINAL_PROFILE_EVENT, - 0x00, // Event extension + STK_TERMINAL_PROFILE_EVENT_EXT, // Event extension 0x00, // Multiple card proactive commands STK_TERMINAL_PROFILE_PROACTIVE_3, STK_TERMINAL_PROFILE_PROACTIVE_4, From 2b34101ca4b21d81e46d9a41c3c6f218a076e6cd Mon Sep 17 00:00:00 2001 From: Chuck Lee Date: Mon, 28 Jan 2013 14:06:06 +0800 Subject: [PATCH 51/70] Bug 831627 - 0004. Test case for Event Download Command : Language Selection. r=yoshi --- dom/system/gonk/tests/test_ril_worker_icc.js | 58 ++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/dom/system/gonk/tests/test_ril_worker_icc.js b/dom/system/gonk/tests/test_ril_worker_icc.js index b8ceafcb33a..d7fc994ea49 100644 --- a/dom/system/gonk/tests/test_ril_worker_icc.js +++ b/dom/system/gonk/tests/test_ril_worker_icc.js @@ -1514,6 +1514,64 @@ add_test(function test_stk_terminal_response() { worker.RIL.sendStkTerminalResponse(response); }); +/** + * Verify Event Download Command : Language Selection + */ +add_test(function test_stk_event_download_language_selection() { + let worker = newUint8SupportOutgoingIndexWorker(); + let buf = worker.Buf; + let pduHelper = worker.GsmPDUHelper; + + buf.sendParcel = function () { + // Type + do_check_eq(this.readUint32(), REQUEST_STK_SEND_ENVELOPE_COMMAND) + + // Token : we don't care + this.readUint32(); + + // Data Size, 26 = 2 * (2 + TLV_DEVICE_ID_SIZE(4) + + // TLV_EVENT_LIST_SIZE(3) + + // TLV_LANGUAGE(4)) + do_check_eq(this.readUint32(), 26); + + // BER tag + do_check_eq(pduHelper.readHexOctet(), BER_EVENT_DOWNLOAD_TAG); + + // BER length, 19 = TLV_DEVICE_ID_SIZE(4) + + // TLV_EVENT_LIST_SIZE(3) + + // TLV_LANGUAGE(4) + do_check_eq(pduHelper.readHexOctet(), 11); + + // Device Identifies, Type-Length-Value(Source ID-Destination ID) + do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_DEVICE_ID | + COMPREHENSIONTLV_FLAG_CR); + do_check_eq(pduHelper.readHexOctet(), 2); + do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_ME); + do_check_eq(pduHelper.readHexOctet(), STK_DEVICE_ID_SIM); + + // Event List, Type-Length-Value + do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_EVENT_LIST | + COMPREHENSIONTLV_FLAG_CR); + do_check_eq(pduHelper.readHexOctet(), 1); + do_check_eq(pduHelper.readHexOctet(), STK_EVENT_TYPE_LANGUAGE_SELECTION); + + // Language, Type-Length-Value + do_check_eq(pduHelper.readHexOctet(), COMPREHENSIONTLV_TAG_LANGUAGE); + do_check_eq(pduHelper.readHexOctet(), 2); + do_check_eq(pduHelper.read8BitUnpackedToString(2), "zh"); + + run_next_test(); + }; + + let event = { + eventType: STK_EVENT_TYPE_LANGUAGE_SELECTION, + language: "zh" + }; + worker.RIL.sendStkEventDownload({ + event: event + }); +}); + /** * Verify Event Download Command : Idle Screen Available */ From 2d849cea23b9bca3b6c8897f49a97984983ee047 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Tue, 29 Jan 2013 19:50:41 -0700 Subject: [PATCH 52/70] Bug 835102 - Convert sufficiently sparse objects back to using dense elements, r=billm. --- js/src/jsarray.h | 10 +- js/src/jsinterpinlines.h | 2 +- js/src/jsobj.cpp | 288 ++++++++++++++++++++++++++------------- js/src/jsobj.h | 18 ++- js/src/vm/Shape-inl.h | 2 - js/src/vm/Shape.cpp | 18 +++ js/src/vm/Shape.h | 5 +- 7 files changed, 236 insertions(+), 107 deletions(-) diff --git a/js/src/jsarray.h b/js/src/jsarray.h index f20ea1c42a8..68dc2e689bf 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -15,9 +15,6 @@ #include "jsatom.h" #include "jsobj.h" -/* Small arrays are dense, no matter what. */ -const unsigned MIN_SPARSE_INDEX = 512; - namespace js { /* 2^32-2, inclusive */ const uint32_t MAX_ARRAY_INDEX = 4294967294u; @@ -28,14 +25,13 @@ js_IdIsIndex(jsid id, uint32_t *indexp) { if (JSID_IS_INT(id)) { int32_t i = JSID_TO_INT(id); - if (i < 0) - return JS_FALSE; + JS_ASSERT(i >= 0); *indexp = (uint32_t)i; - return JS_TRUE; + return true; } if (JS_UNLIKELY(!JSID_IS_STRING(id))) - return JS_FALSE; + return false; return js::StringIsArrayIndex(JSID_TO_ATOM(id), indexp); } diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 238b04019bc..67f431ae2de 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -359,7 +359,7 @@ SetPropertyOperation(JSContext *cx, jsbytecode *pc, HandleValue lval, HandleValu } else { RootedValue rref(cx, rval); bool strict = cx->stack.currentScript()->strict; - if (!js_NativeSet(cx, obj, obj, shape, false, strict, &rref)) + if (!js_NativeSet(cx, obj, obj, shape, strict, &rref)) return false; } return true; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 9fe265ff355..d02914772e4 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2524,10 +2524,10 @@ JSObject::willBeSparseElements(unsigned requiredCapacity, unsigned newElementsHi unsigned cap = getDenseCapacity(); JS_ASSERT(requiredCapacity >= cap); - if (requiredCapacity >= JSObject::NELEMENTS_LIMIT) + if (requiredCapacity >= NELEMENTS_LIMIT) return true; - unsigned minimalDenseCount = requiredCapacity / 4; + unsigned minimalDenseCount = requiredCapacity / SPARSE_DENSITY_RATIO; if (newElementsHint >= minimalDenseCount) return false; minimalDenseCount -= newElementsHint; @@ -2544,6 +2544,119 @@ JSObject::willBeSparseElements(unsigned requiredCapacity, unsigned newElementsHi return true; } +/* static */ JSObject::EnsureDenseResult +JSObject::maybeDensifySparseElements(JSContext *cx, HandleObject obj) +{ + /* This should only be called after adding a sparse index to an object. */ + JS_ASSERT(JSID_IS_INT(obj->lastProperty()->propid())); + + /* + * Wait until after the object goes into dictionary mode, which must happen + * when sparsely packing any array with more than MIN_SPARSE_INDEX elements + * (see PropertyTree::MAX_HEIGHT). + */ + if (!obj->inDictionaryMode()) + return ED_SPARSE; + + /* + * Only measure the number of indexed properties every log(n) times when + * populating the object. + */ + uint32_t slotSpan = obj->slotSpan(); + if (slotSpan != RoundUpPow2(slotSpan)) + return ED_SPARSE; + + /* Watch for conditions under which an object's elements cannot be dense. */ + if (!obj->isExtensible() || obj->watched()) + return ED_SPARSE; + + /* + * The indexes in the object need to be sufficiently dense before they can + * be converted to dense mode. + */ + uint32_t numDenseElements = 0; + uint32_t newInitializedLength = 0; + + RootedShape shape(cx, obj->lastProperty()); + while (!shape->isEmptyShape()) { + uint32_t index; + if (js_IdIsIndex(shape->propid(), &index)) { + if (shape->attributes() == JSPROP_ENUMERATE && + shape->hasDefaultGetter() && + shape->hasDefaultSetter()) + { + numDenseElements++; + newInitializedLength = Max(newInitializedLength, index + 1); + } else { + /* + * For simplicity, only densify the object if all indexed + * properties can be converted to dense elements. + */ + return ED_SPARSE; + } + } + shape = shape->previous(); + } + + if (numDenseElements * SPARSE_DENSITY_RATIO < newInitializedLength) + return ED_SPARSE; + + if (newInitializedLength >= NELEMENTS_LIMIT) + return ED_SPARSE; + + /* + * This object meets all necessary restrictions, convert all indexed + * properties into dense elements. + */ + + if (!obj->growElements(cx, newInitializedLength)) + return ED_FAILED; + + obj->ensureDenseInitializedLength(cx, newInitializedLength, 0); + + RootedValue value(cx); + + shape = obj->lastProperty(); + while (!shape->isEmptyShape()) { + jsid id = shape->propid(); + uint32_t index; + if (js_IdIsIndex(id, &index)) { + value = obj->getSlot(shape->slot()); + + /* + * When removing a property from a dictionary, the specified + * property will be removed from the dictionary list and the + * last property will then be changed due to reshaping the object. + * Compute the next shape in the traverse, watching for such + * removals from the list. + */ + if (shape != obj->lastProperty()) { + shape = shape->previous(); + if (!obj->removeProperty(cx, id)) + return ED_FAILED; + } else { + if (!obj->removeProperty(cx, id)) + return ED_FAILED; + shape = obj->lastProperty(); + } + + obj->setDenseElement(index, value); + } else { + shape = shape->previous(); + } + } + + /* + * All indexed properties on the object are now dense, clear the indexed + * flag so that we will not start using sparse indexes again if we need + * to grow the object. + */ + if (!obj->clearFlag(cx, BaseShape::INDEXED)) + return ED_FAILED; + + return ED_OK; +} + bool JSObject::growElements(JSContext *cx, unsigned newcap) { @@ -3055,8 +3168,10 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape s RootedValue value(cx, nominal); Rooted id(cx, shape->propid()); - if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) + if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) { + obj->removeProperty(cx, shape->propid()); return false; + } if (value.get() != nominal) { if (shape->hasSlot()) JSObject::nativeSetSlotWithType(cx, obj, shape, value); @@ -3082,14 +3197,75 @@ CallAddPropertyHookDense(JSContext *cx, Class *clasp, HandleObject obj, uint32_t RootedValue value(cx, nominal); Rooted id(cx, INT_TO_JSID(index)); - if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) + if (!CallJSPropertyOp(cx, clasp->addProperty, obj, id, &value)) { + JSObject::setDenseElementHole(cx, obj, index); return false; + } if (value.get() != nominal) JSObject::setDenseElementWithType(cx, obj, index, value); } return true; } +static inline bool +DefinePropertyOrElement(JSContext *cx, HandleObject obj, HandleId id, + PropertyOp getter, StrictPropertyOp setter, + unsigned attrs, unsigned flags, int shortid, + HandleValue value, bool callSetterAfterwards, bool setterIsStrict) +{ + /* Use dense storage for new indexed properties where possible. */ + if (JSID_IS_INT(id) && + getter == JS_PropertyStub && + setter == JS_StrictPropertyStub && + attrs == JSPROP_ENUMERATE && + (!obj->isIndexed() || !obj->nativeContains(cx, id))) + { + uint32_t index = JSID_TO_INT(id); + JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, index, 1); + if (result == JSObject::ED_FAILED) + return false; + if (result == JSObject::ED_OK) { + obj->setDenseElementMaybeConvertDouble(index, value); + return CallAddPropertyHookDense(cx, obj->getClass(), obj, index, value); + } + } + + AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); + + RootedShape shape(cx, JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT, + attrs, flags, shortid)); + if (!shape) + return false; + + if (shape->hasSlot()) + obj->nativeSetSlot(shape->slot(), value); + + /* + * Clear any existing dense index after adding a sparse indexed property, + * and investigate converting the object to dense indexes. + */ + if (JSID_IS_INT(id)) { + uint32_t index = JSID_TO_INT(id); + JSObject::removeDenseElementForSparseIndex(cx, obj, index); + JSObject::EnsureDenseResult result = JSObject::maybeDensifySparseElements(cx, obj); + if (result == JSObject::ED_FAILED) + return false; + if (result == JSObject::ED_OK) { + JS_ASSERT(setter == JS_StrictPropertyStub); + return CallAddPropertyHookDense(cx, obj->getClass(), obj, index, value); + } + } + + if (!CallAddPropertyHook(cx, obj->getClass(), obj, shape, value)) + return false; + + if (callSetterAfterwards && setter != JS_StrictPropertyStub) { + RootedValue nvalue(cx, value); + return js_NativeSet(cx, obj, obj, shape, setterIsStrict, &nvalue); + } + return true; +} + bool js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs, @@ -3148,7 +3324,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal /* * Purge the property cache of any properties named by id that are about * to be shadowed in obj's scope chain unless it is known a priori that it - * is not possible. We do this before locking obj to avoid nesting locks. + * is not possible. */ if (!(defineHow & DNP_DONT_PURGE)) { if (!js_PurgeScopeChain(cx, obj, id)) @@ -3173,47 +3349,14 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal } if (!shape) { - /* Use dense storage for new indexed properties where possible. */ - if (JSID_IS_INT(id) && - getter == JS_PropertyStub && - setter == JS_StrictPropertyStub && - attrs == JSPROP_ENUMERATE && - (!obj->isIndexed() || !obj->nativeContains(cx, id))) - { - uint32_t index = JSID_TO_INT(id); - JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, index, 1); - if (result == JSObject::ED_FAILED) - return false; - if (result == JSObject::ED_OK) { - obj->setDenseElementMaybeConvertDouble(index, value); - if (!CallAddPropertyHookDense(cx, clasp, obj, index, value)) { - JSObject::setDenseElementHole(cx, obj, index); - return false; - } - return true; - } - } - - shape = JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT, - attrs, flags, shortid); - if (!shape) - return false; - - /* Clear any existing dense index after adding a sparse indexed property. */ - if (JSID_IS_INT(id)) - JSObject::removeDenseElementForSparseIndex(cx, obj, JSID_TO_INT(id)); + return DefinePropertyOrElement(cx, obj, id, getter, setter, + attrs, flags, shortid, value, false, false); } - /* Store valueCopy before calling addProperty, in case the latter GC's. */ if (shape->hasSlot()) obj->nativeSetSlot(shape->slot(), value); - if (!CallAddPropertyHook(cx, clasp, obj, shape, value)) { - obj->removeProperty(cx, id); - return false; - } - - return shape; + return CallAddPropertyHook(cx, clasp, obj, shape, value); } /* @@ -3554,7 +3697,7 @@ js_NativeGet(JSContext *cx, Handle obj, Handle pobj, Handl JSBool js_NativeSet(JSContext *cx, Handle obj, Handle receiver, - HandleShape shape, bool added, bool strict, MutableHandleValue vp) + HandleShape shape, bool strict, MutableHandleValue vp) { JS_ASSERT(obj->isNative()); @@ -3898,7 +4041,6 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive Class *clasp; PropertyOp getter; StrictPropertyOp setter; - bool added; JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0); @@ -4038,7 +4180,6 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive return true; } - added = false; if (!shape) { if (!obj->isExtensible()) { /* Error in strict mode code, warn with strict option, otherwise do nothing. */ @@ -4046,65 +4187,24 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive return obj->reportNotExtensible(cx); if (cx->hasStrictOption()) return obj->reportNotExtensible(cx, JSREPORT_STRICT | JSREPORT_WARNING); - return JS_TRUE; + return true; } - /* Use dense storage for new indexed properties where possible. */ - if (JSID_IS_INT(id) && - getter == JS_PropertyStub && - setter == JS_StrictPropertyStub && - attrs == JSPROP_ENUMERATE) - { - uint32_t index = JSID_TO_INT(id); - JSObject::EnsureDenseResult result = obj->ensureDenseElements(cx, index, 1); - if (result == JSObject::ED_FAILED) - return false; - if (result == JSObject::ED_OK) { - obj->setDenseElement(index, UndefinedValue()); - if (!CallAddPropertyHookDense(cx, clasp, obj, index, vp)) { - JSObject::setDenseElementHole(cx, obj, index); - return false; - } - JSObject::setDenseElementWithType(cx, obj, index, vp); - return true; - } - } - - /* - * Purge the property cache of now-shadowed id in obj's scope chain. - * Do this early, before locking obj to avoid nesting locks. - */ + /* Purge the property cache of now-shadowed id in obj's scope chain. */ if (!js_PurgeScopeChain(cx, obj, id)) - return JS_FALSE; + return false; - shape = JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT, - attrs, flags, shortid); - if (!shape) - return JS_FALSE; + if (getter == JS_PropertyStub) + AddTypePropertyId(cx, obj, id, vp); - /* Clear any existing dense index after adding a sparse indexed property. */ - if (JSID_IS_INT(id)) - JSObject::removeDenseElementForSparseIndex(cx, obj, JSID_TO_INT(id)); - - /* - * Initialize the new property value (passed to setter) to undefined. - * Note that we store before calling addProperty, to match the order - * in DefineNativeProperty. - */ - if (shape->hasSlot()) - obj->nativeSetSlot(shape->slot(), UndefinedValue()); - - if (!CallAddPropertyHook(cx, clasp, obj, shape, vp)) { - obj->removeProperty(cx, id); - return JS_FALSE; - } - added = true; + return DefinePropertyOrElement(cx, obj, id, getter, setter, + attrs, flags, shortid, vp, true, strict); } - if ((defineHow & DNP_CACHE_RESULT) && !added) + if (defineHow & DNP_CACHE_RESULT) cx->propertyCache().fill(cx, obj, obj, shape); - return js_NativeSet(cx, obj, receiver, shape, added, strict, vp); + return js_NativeSet(cx, obj, receiver, shape, strict, vp); } JSBool diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 4b23970a87a..41001253da8 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -367,6 +367,7 @@ class JSObject : public js::ObjectImpl bool setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag, GenerateShape generateShape = GENERATE_NONE); + bool clearFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag); public: inline bool nativeEmpty() const; @@ -627,12 +628,27 @@ class JSObject : public js::ObjectImpl /* Convert all dense elements to sparse properties. */ static bool sparsifyDenseElements(JSContext *cx, js::HandleObject obj); + /* Small objects are dense, no matter what. */ + static const unsigned MIN_SPARSE_INDEX = 1000; + + /* + * Element storage for an object will be sparse if fewer than 1/8 indexes + * are filled in. + */ + static const unsigned SPARSE_DENSITY_RATIO = 8; + /* * Check if after growing the object's elements will be too sparse. * newElementsHint is an estimated number of elements to be added. */ bool willBeSparseElements(unsigned requiredCapacity, unsigned newElementsHint); + /* + * After adding a sparse index to obj, see if it should be converted to use + * dense elements. + */ + static EnsureDenseResult maybeDensifySparseElements(JSContext *cx, js::HandleObject obj); + /* Array specific accessors. */ inline uint32_t getArrayLength() const; static inline void setArrayLength(JSContext *cx, js::HandleObject obj, uint32_t length); @@ -1331,7 +1347,7 @@ js_NativeGet(JSContext *cx, js::Handle obj, js::Handle pob extern JSBool js_NativeSet(JSContext *cx, js::Handle obj, js::Handle receiver, - js::Handle shape, bool added, bool strict, js::MutableHandleValue vp); + js::Handle shape, bool strict, js::MutableHandleValue vp); namespace js { diff --git a/js/src/vm/Shape-inl.h b/js/src/vm/Shape-inl.h index 10a916a836a..01af9c7025d 100644 --- a/js/src/vm/Shape-inl.h +++ b/js/src/vm/Shape-inl.h @@ -158,8 +158,6 @@ BaseShape::adoptUnowned(UnrootedUnownedBaseShape other) * unowned base shape of a new last property. */ JS_ASSERT(isOwned()); - mozilla::DebugOnly flags = getObjectFlags(); - JS_ASSERT((flags & other->getObjectFlags()) == flags); uint32_t span = slotSpan(); ShapeTable *table = &this->table(); diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index 3d3309642dd..f91ba856b90 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1092,6 +1092,24 @@ JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateSha return true; } +bool +JSObject::clearFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag) +{ + JS_ASSERT(inDictionaryMode()); + JS_ASSERT(lastProperty()->getObjectFlags() & flag); + + RootedObject self(cx, this); + + StackBaseShape base(self->lastProperty()); + base.flags &= ~flag; + UnrootedUnownedBaseShape nbase = BaseShape::getUnowned(cx, base); + if (!nbase) + return false; + + self->lastProperty()->base()->adoptUnowned(nbase); + return true; +} + /* static */ UnrootedShape Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last) { diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h index 88df2485b30..8cfc602ffd4 100644 --- a/js/src/vm/Shape.h +++ b/js/src/vm/Shape.h @@ -245,8 +245,9 @@ class BaseShape : public js::gc::Cell /* * Flags set which describe the referring object. Once set these cannot - * be unset, and are transferred from shape to shape as the object's - * last property changes. + * be unset (except during object densification of sparse indexes), and + * are transferred from shape to shape as the object's last property + * changes. */ DELEGATE = 0x8, From 39ec29c7b7dcecffb93476ce43cbae464f67d3b4 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 18:51:43 -0800 Subject: [PATCH 53/70] Bug 836149: declare pseudoStackPos as uint32_t instead of int in TableTicker.cpp, to fix signed/unsigned comparison build warning. r=BenWa --- tools/profiler/TableTicker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index faead5f4995..c39e04f6c48 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -844,7 +844,7 @@ void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample) aProfile.addTag(ProfileEntry('s', "(root)")); ProfileStack* stack = aProfile.GetStack(); - int pseudoStackPos = 0; + uint32_t pseudoStackPos = 0; /* We have two stacks, the native C stack we extracted from unwinding, * and the pseudostack we managed during execution. We want to consolidate From e99111ca7e76d6ebbbc17199770db403aebd3b3c Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 20:03:42 -0800 Subject: [PATCH 54/70] Bug 834768: Fix signed/unsigned comparison build warnings in signaling_unittests.cpp. r=jesup --- media/webrtc/signaling/test/signaling_unittests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/media/webrtc/signaling/test/signaling_unittests.cpp b/media/webrtc/signaling/test/signaling_unittests.cpp index 957dc26415d..945dbd78343 100644 --- a/media/webrtc/signaling/test/signaling_unittests.cpp +++ b/media/webrtc/signaling/test/signaling_unittests.cpp @@ -467,7 +467,7 @@ class ParsedSDP { //generate our final sdp in string format std::string sdp; - for(int i=0; i < sdp_lines.size(); i++) + for (size_t i = 0; i < sdp_lines.size(); i++) { sdp += sdp_lines[i]; } @@ -760,7 +760,7 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer, void CloseReceiveStreams() { std::vector streams = pObserver->GetStreams(); - for(int i=0; i < streams.size(); i++) { + for (size_t i = 0; i < streams.size(); i++) { streams[i]->GetStream()->AsSourceStream()->StopStream(); } } From 20d50f0b1f8f04a15fb390a5d1ef122dcd47dd8a Mon Sep 17 00:00:00 2001 From: Gene Lian Date: Wed, 30 Jan 2013 11:54:05 +0800 Subject: [PATCH 55/70] Bug 830258 - [Webapps] .uninstall() should return "Webapps:Uninstall:Return:KO" when uninstalling a non-removable app (part 1, fix .uninstall()). r=fabrice --- dom/apps/src/Webapps.jsm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dom/apps/src/Webapps.jsm b/dom/apps/src/Webapps.jsm index 9fe0245f31f..e71bd2b9562 100644 --- a/dom/apps/src/Webapps.jsm +++ b/dom/apps/src/Webapps.jsm @@ -2298,8 +2298,10 @@ this.DOMApplicationRegistry = { dump("-- webapps.js uninstall " + app.manifestURL + "\n"); - if (!app.removable) - return; + if (!app.removable) { + debug("Error: cannot unintall a non-removable app."); + break; + } // Check if we are downloading something for this app, and cancel the // download if needed. @@ -2343,6 +2345,9 @@ this.DOMApplicationRegistry = { return; } + // Fall-through, fails to uninstall the desired app because: + // - we cannot find the app to be uninstalled. + // - the app to be uninstalled is not removable. aMm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData); }, From fed214b1e734b1eb1d62fa6c4b826e54d11eb9b4 Mon Sep 17 00:00:00 2001 From: Gene Lian Date: Wed, 30 Jan 2013 12:00:55 +0800 Subject: [PATCH 56/70] Bug 830258 - [Webapps] .uninstall() should return "Webapps:Uninstall:Return:KO" when uninstalling a non-removable app (part 2, provide test case). r=fabrice --- dom/tests/mochitest/webapps/Makefile.in | 1 + .../webapps/test_uninstall_errors.xul | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 dom/tests/mochitest/webapps/test_uninstall_errors.xul diff --git a/dom/tests/mochitest/webapps/Makefile.in b/dom/tests/mochitest/webapps/Makefile.in index 5cd517b9ec6..8ca51182ac6 100644 --- a/dom/tests/mochitest/webapps/Makefile.in +++ b/dom/tests/mochitest/webapps/Makefile.in @@ -28,6 +28,7 @@ MOCHITEST_CHROME_FILES = \ test_install_receipts.xul \ test_getNotInstalled.xul \ test_launch_paths.xul \ + test_uninstall_errors.xul \ $(NULL) MOCHITEST_FILES = \ diff --git a/dom/tests/mochitest/webapps/test_uninstall_errors.xul b/dom/tests/mochitest/webapps/test_uninstall_errors.xul new file mode 100644 index 00000000000..c537b7394a8 --- /dev/null +++ b/dom/tests/mochitest/webapps/test_uninstall_errors.xul @@ -0,0 +1,82 @@ + + + + + + + + + + From 43cf1c22e673afb9d8718b43e39bda64936b56e9 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 30 Jan 2013 17:19:03 +1300 Subject: [PATCH 57/70] Bug 806754. Make MediaDecoders detect when a MediaStream has been destroyed because its DOM wrapper has been collected, and remove the no-longer-relevant MediaStream from the output list. r=cpearce --HG-- extra : rebase_source : a7316907f453330c0c23eb7a11afb3c2cd5a1e9c --- content/media/MediaDecoder.cpp | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/content/media/MediaDecoder.cpp b/content/media/MediaDecoder.cpp index 172c561a575..8c0b6aa623b 100644 --- a/content/media/MediaDecoder.cpp +++ b/content/media/MediaDecoder.cpp @@ -188,14 +188,18 @@ void MediaDecoder::DestroyDecodedStream() // All streams are having their SourceMediaStream disconnected, so they // need to be explicitly blocked again. - for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) { + for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) { OutputStreamData& os = mOutputStreams[i]; // During cycle collection, nsDOMMediaStream can be destroyed and send // its Destroy message before this decoder is destroyed. So we have to // be careful not to send any messages after the Destroy(). - if (!os.mStream->IsDestroyed()) { - os.mStream->ChangeExplicitBlockerCount(1); + if (os.mStream->IsDestroyed()) { + // Probably the DOM MediaStream was GCed. Clean up. + os.mPort->Destroy(); + mOutputStreams.RemoveElementAt(i); + continue; } + os.mStream->ChangeExplicitBlockerCount(1); // Explicitly remove all existing ports. This is not strictly necessary but it's // good form. os.mPort->Destroy(); @@ -220,8 +224,15 @@ void MediaDecoder::RecreateDecodedStream(int64_t aStartTimeUSecs) // Note that the delay between removing ports in DestroyDecodedStream // and adding new ones won't cause a glitch since all graph operations // between main-thread stable states take effect atomically. - for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) { - ConnectDecodedStreamToOutputStream(&mOutputStreams[i]); + for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) { + OutputStreamData& os = mOutputStreams[i]; + if (os.mStream->IsDestroyed()) { + // Probably the DOM MediaStream was GCed. Clean up. + // No need to destroy the port; all ports have been destroyed here. + mOutputStreams.RemoveElementAt(i); + continue; + } + ConnectDecodedStreamToOutputStream(&os); } mDecodedStream->mHaveBlockedForPlayState = mPlayState != PLAY_STATE_PLAYING; @@ -244,7 +255,7 @@ void MediaDecoder::NotifyDecodedStreamMainThreadStateChanged() } void MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream, - bool aFinishWhenEnded) + bool aFinishWhenEnded) { MOZ_ASSERT(NS_IsMainThread()); LOG(PR_LOG_DEBUG, ("MediaDecoder::AddOutputStream this=%p aStream=%p!", @@ -810,12 +821,17 @@ void MediaDecoder::PlaybackEnded() for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) { OutputStreamData& os = mOutputStreams[i]; + if (os.mStream->IsDestroyed()) { + // Probably the DOM MediaStream was GCed. Clean up. + os.mPort->Destroy(); + mOutputStreams.RemoveElementAt(i); + continue; + } if (os.mFinishWhenEnded) { // Shouldn't really be needed since mDecodedStream should already have // finished, but doesn't hurt. os.mStream->Finish(); os.mPort->Destroy(); - os.mPort = nullptr; // Not really needed but it keeps the invariant that a stream not // connected to mDecodedStream is explicity blocked. os.mStream->ChangeExplicitBlockerCount(1); From 9f2a4c9275a26c3d0859fd0eaed3aec3dfe61800 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 30 Jan 2013 17:20:03 +1300 Subject: [PATCH 58/70] Bug 806754. Part 2: Fix bogus assertions. r=cpearce SendStreamAudio gets called by SendStreamData which can be called on the state machine thread since bug 794426 was fixed. At the same time PlayFromAudioQueuec can no longer guarantee that mAudioCaptured is false. It could be true and we're waiting for the audio thread to shut down. We can just remove that assertion; the logic in SendStreamData guarantees that we don't try to pass audio to MediaStreams until the audio thread has actually stopped. --HG-- extra : rebase_source : 431b4af63710ef13a57f7560aeec553b8aae6139 --- content/media/MediaDecoderStateMachine.cpp | 6 +-- content/media/test/Makefile.in | 1 + content/media/test/test_streams_gc.html | 45 ++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 content/media/test/test_streams_gc.html diff --git a/content/media/MediaDecoderStateMachine.cpp b/content/media/MediaDecoderStateMachine.cpp index 7e7f38e8c20..457afc2f156 100644 --- a/content/media/MediaDecoderStateMachine.cpp +++ b/content/media/MediaDecoderStateMachine.cpp @@ -506,7 +506,8 @@ void MediaDecoderStateMachine::SendStreamAudio(AudioData* aAudio, DecodedStreamData* aStream, AudioSegment* aOutput) { - NS_ASSERTION(OnDecodeThread(), "Should be on decode thread."); + NS_ASSERTION(OnDecodeThread() || + OnStateMachineThread(), "Should be on decode thread or state machine thread"); mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); if (aAudio->mTime <= aStream->mLastAudioPacketTime) { @@ -1210,7 +1211,7 @@ uint32_t MediaDecoderStateMachine::PlaySilence(uint32_t aFrames, } uint32_t MediaDecoderStateMachine::PlayFromAudioQueue(uint64_t aFrameOffset, - uint32_t aChannels) + uint32_t aChannels) { NS_ASSERTION(OnAudioThread(), "Only call on audio thread."); NS_ASSERTION(!mAudioStream->IsPaused(), "Don't play when paused"); @@ -1218,7 +1219,6 @@ uint32_t MediaDecoderStateMachine::PlayFromAudioQueue(uint64_t aFrameOffset, { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); NS_WARN_IF_FALSE(IsPlaying(), "Should be playing"); - NS_ASSERTION(!mAudioCaptured, "Audio cannot be captured here!"); // Awaken the decode loop if it's waiting for space to free up in the // audio queue. mDecoder->GetReentrantMonitor().NotifyAll(); diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in index d309c14d261..d19837cd6a7 100644 --- a/content/media/test/Makefile.in +++ b/content/media/test/Makefile.in @@ -133,6 +133,7 @@ MOCHITEST_FILES = \ test_media_sniffer.html \ contentType.sjs \ test_streams_srcObject.html \ + test_streams_gc.html \ $(filter disabled-for-intermittent-failures--bug-608634, test_error_in_video_document.html) \ $(NULL) diff --git a/content/media/test/test_streams_gc.html b/content/media/test/test_streams_gc.html new file mode 100644 index 00000000000..545b0c19286 --- /dev/null +++ b/content/media/test/test_streams_gc.html @@ -0,0 +1,45 @@ + + + + Test garbage collection of captured stream (bug 806754) + + + + + + +
+
+
+ + From a0060964a3cdfe11d1f50e3daa2f6fab76dc75e2 Mon Sep 17 00:00:00 2001 From: Gina Yeh Date: Wed, 30 Jan 2013 12:33:23 +0800 Subject: [PATCH 59/70] Bug 835740 - Modified BRSF value in hands-free profile, r=echou --- dom/bluetooth/BluetoothHfpManager.cpp | 2 +- dom/bluetooth/BluetoothUtils.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dom/bluetooth/BluetoothHfpManager.cpp b/dom/bluetooth/BluetoothHfpManager.cpp index c33aa57adb9..c47dd92e022 100644 --- a/dom/bluetooth/BluetoothHfpManager.cpp +++ b/dom/bluetooth/BluetoothHfpManager.cpp @@ -679,7 +679,7 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage) // For more information, please refer to 4.34.1 "Bluetooth Defined AT // Capabilities" in Bluetooth hands-free profile 1.6 if (msg.Find("AT+BRSF=") != -1) { - SendCommand("+BRSF: ", 33); + SendCommand("+BRSF: ", 97); } else if (msg.Find("AT+CIND=?") != -1) { // Asking for CIND range SendCommand("+CIND: ", 0); diff --git a/dom/bluetooth/BluetoothUtils.cpp b/dom/bluetooth/BluetoothUtils.cpp index 9fe6e7a9c35..5c14c3d395d 100644 --- a/dom/bluetooth/BluetoothUtils.cpp +++ b/dom/bluetooth/BluetoothUtils.cpp @@ -48,7 +48,7 @@ SetJsObject(JSContext* aContext, JS_NewStringCopyN(aContext, NS_ConvertUTF16toUTF8(v.get_nsString()).get(), v.get_nsString().Length()); - NS_ENSURE_TRUE(JsData, NS_ERROR_FAILURE); + NS_ENSURE_TRUE(JsData, false); val = STRING_TO_JSVAL(JsData); break; case BluetoothValue::Tuint32_t: @@ -66,7 +66,7 @@ SetJsObject(JSContext* aContext, NS_ConvertUTF16toUTF8(arr[i].name()).get(), &val)) { NS_WARNING("Failed to set property"); - return NS_ERROR_FAILURE; + return false; } } } else { From caf94abdb6f3f10fd4de35968fa6fe93911d5741 Mon Sep 17 00:00:00 2001 From: Eric Chou Date: Wed, 30 Jan 2013 12:58:40 +0800 Subject: [PATCH 60/70] Bug 835474 - Assign length of the message with aMessage->mSize, r=gyeh --- dom/bluetooth/BluetoothHfpManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/bluetooth/BluetoothHfpManager.cpp b/dom/bluetooth/BluetoothHfpManager.cpp index c47dd92e022..1b4d1804a9f 100644 --- a/dom/bluetooth/BluetoothHfpManager.cpp +++ b/dom/bluetooth/BluetoothHfpManager.cpp @@ -671,7 +671,7 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage) { MOZ_ASSERT(NS_IsMainThread()); - nsAutoCString msg((const char*)aMessage->mData.get()); + nsAutoCString msg((const char*)aMessage->mData.get(), aMessage->mSize); msg.StripWhitespace(); nsTArray atCommandValues; From f18c00bb62cd8e58e3a6c473fd72295b5b7087ee Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 30 Jan 2013 18:07:29 +1300 Subject: [PATCH 61/70] Bug 832341 - Use the correct border area (rather than the canvas area) when computing the bounds of an nsDisplayCanvasBackgroundImage. r=roc --- layout/base/nsDisplayList.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 5ab9f069063..449e4039c70 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -2179,10 +2179,6 @@ nsDisplayBackgroundImage::GetBoundsInternal() { } nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize()); - if (mFrame->GetType() == nsGkAtoms::canvasFrame) { - nsCanvasFrame* frame = static_cast(mFrame); - borderBox = frame->CanvasArea() + ToReferenceFrame(); - } const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer]; return nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame, borderBox, *mBackgroundStyle, layer); From 6ff7e265f41dab3ee95f905068056b641b445b95 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 30 Jan 2013 18:07:30 +1300 Subject: [PATCH 62/70] Bug 836179 - Add WriteDebugInfo so that display items can add extra information when printing display lists. r=roc --- layout/base/nsDisplayList.cpp | 11 +++++++++++ layout/base/nsDisplayList.h | 19 +++++++++++++++++++ layout/base/nsLayoutDebugger.cpp | 3 ++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 449e4039c70..d3c7ffbe626 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1567,6 +1567,17 @@ nsDisplayBackgroundImage::~nsDisplayBackgroundImage() #endif } +#ifdef MOZ_DUMP_PAINTING +void +nsDisplayBackgroundImage::WriteDebugInfo(FILE *aOutput) +{ + if (mIsThemed) { + fprintf(aOutput, "(themed, appearance:%d) ", mFrame->GetStyleDisplay()->mAppearance); + } + +} +#endif + /*static*/ nsresult nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 48b6283bb81..6fbff13457f 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1056,6 +1056,8 @@ public: * For debugging and stuff */ virtual const char* Name() = 0; + + virtual void WriteDebugInfo(FILE *aOutput) {} #endif nsDisplayItem* GetAbove() { return mAbove; } @@ -1905,6 +1907,10 @@ public: static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, nsPresContext* aPresContext, uint8_t aClip, const nsRect& aRect, bool* aSnap); + +#ifdef MOZ_DUMP_PAINTING + virtual void WriteDebugInfo(FILE *aOutput); +#endif protected: typedef class mozilla::layers::ImageContainer ImageContainer; typedef class mozilla::layers::ImageLayer ImageLayer; @@ -1961,6 +1967,14 @@ public: } NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR) +#ifdef MOZ_DUMP_PAINTING + virtual void WriteDebugInfo(FILE *aOutput) { + fprintf(aOutput, "(rgba %d,%d,%d,%d)", + NS_GET_R(mColor), NS_GET_G(mColor), + NS_GET_B(mColor), NS_GET_A(mColor)); + + } +#endif protected: const nsStyleBackground* mBackgroundStyle; @@ -2288,6 +2302,11 @@ public: // We don't need to compute an invalidation region since we have LayerTreeInvalidation } NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY) +#ifdef MOZ_DUMP_PAINTING + virtual void WriteDebugInfo(FILE *aOutput) { + fprintf(aOutput, "(opacity %f)", mFrame->GetStyleDisplay()->mOpacity); + } +#endif bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder); }; diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp index 43808129d3f..79c13b330bd 100644 --- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -185,8 +185,9 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList, i->IsUniform(aBuilder, &color) ? " uniform" : ""); nsRegionRectIterator iter(opaque); for (const nsRect* r = iter.Next(); r; r = iter.Next()) { - printf("(opaque %d,%d,%d,%d)", r->x, r->y, r->width, r->height); + fprintf(aOutput, "(opaque %d,%d,%d,%d)", r->x, r->y, r->width, r->height); } + i->WriteDebugInfo(aOutput); if (aDumpHtml && i->Painted()) { fprintf(aOutput, ""); } From 8fb50beb926069353f0d2466fb124fbb0f2cc32c Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 30 Jan 2013 18:07:30 +1300 Subject: [PATCH 63/70] Bug 833033 - Schedule a paint when document state changes. r=roc --- layout/base/nsPresShell.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index b8ffe99c873..f879a496229 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -4005,6 +4005,7 @@ PresShell::DocumentStatesChanged(nsIDocument* aDocument, if (root->HasView()) { root->GetView()->SetForcedRepaint(true); } + root->SchedulePaint(); } } } From 5a8b8d1acd3ff19da70231513f7b5263f0d2ad37 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 29 Jan 2013 21:12:07 -0800 Subject: [PATCH 64/70] Bug 836150: Mark tools/profiler as FAIL_ON_WARNINGS, for non-MSVC compilers. r=BenWa --- tools/profiler/Makefile.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/profiler/Makefile.in b/tools/profiler/Makefile.in index 009ffb69bf8..e5e615e2bff 100644 --- a/tools/profiler/Makefile.in +++ b/tools/profiler/Makefile.in @@ -37,6 +37,9 @@ LIBRARY_NAME = profiler EXPORT_LIBRARY = 1 LIBXUL_LIBRARY = 1 IS_COMPONENT = 1 +ifndef _MSC_VER +FAIL_ON_WARNINGS = 1 +endif # !_MSC_VER CPPSRCS = \ nsProfilerFactory.cpp \ From 85e24bcae820417b02e10163f3f5d58bc1cc0be0 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 30 Jan 2013 18:20:53 +1300 Subject: [PATCH 65/70] Bug 832788. Part 5: Add suffixes for large integer literals. r=bz --HG-- extra : rebase_source : 9555960acea609a3e4a3deaacd468e64435f5ff2 --- dom/bindings/Codegen.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index edbfaf738a5..acf9fb2193c 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -1825,13 +1825,18 @@ builtinNames = { IDLType.Tags.double: 'double' } -numericTags = [ - IDLType.Tags.int8, IDLType.Tags.uint8, - IDLType.Tags.int16, IDLType.Tags.uint16, - IDLType.Tags.int32, IDLType.Tags.uint32, - IDLType.Tags.int64, IDLType.Tags.uint64, - IDLType.Tags.float, IDLType.Tags.double - ] +numericSuffixes = { + IDLType.Tags.int8: '', + IDLType.Tags.uint8: '', + IDLType.Tags.int16: '', + IDLType.Tags.uint16: '', + IDLType.Tags.int32: '', + IDLType.Tags.uint32: 'U', + IDLType.Tags.int64: 'LL', + IDLType.Tags.uint64: 'ULL', + IDLType.Tags.float: 'F', + IDLType.Tags.double: 'D' +} class CastableObjectUnwrapper(): """ @@ -2987,8 +2992,9 @@ for (uint32_t i = 0; i < length; ++i) { # We already handled IDLNullValue, so just deal with the other ones not isinstance(defaultValue, IDLNullValue)): tag = defaultValue.type.tag() - if tag in numericTags: - defaultStr = defaultValue.value + if tag in numericSuffixes: + # Some numeric literals require a suffix to compile without warnings + defaultStr = "%s%s" % (defaultValue.value, numericSuffixes[tag]) else: assert(tag == IDLType.Tags.bool) defaultStr = toStringBool(defaultValue.value) @@ -3093,9 +3099,9 @@ def convertConstIDLValueToJSVal(value): IDLType.Tags.uint16, IDLType.Tags.int32]: return "INT_TO_JSVAL(%s)" % (value.value) if tag == IDLType.Tags.uint32: - return "UINT_TO_JSVAL(%s)" % (value.value) + return "UINT_TO_JSVAL(%sU)" % (value.value) if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]: - return "DOUBLE_TO_JSVAL(%s)" % (value.value) + return "DOUBLE_TO_JSVAL(%s%s)" % (value.value, numericSuffixes[tag]) if tag == IDLType.Tags.bool: return "JSVAL_TRUE" if value.value else "JSVAL_FALSE" if tag in [IDLType.Tags.float, IDLType.Tags.double]: From dd3935d1cb425f01901048ab4a5b0bc3ee2c18f8 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 30 Jan 2013 18:20:53 +1300 Subject: [PATCH 66/70] Bug 832788. Part 6: Enable FAIL_ON_WARNINGS in dom/bindings. r=bz --HG-- extra : rebase_source : 67fb14efbd022dac7ba32fe31584c386872ff9d6 --- dom/bindings/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index 2a7842d1723..e6d52c46cc7 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -12,6 +12,7 @@ LIBRARY_NAME = dombindings_s LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 EXPORT_LIBRARY = 1 +FAIL_ON_WARNINGS := 1 include $(topsrcdir)/config/config.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk From 234f80e7bbefda0771eca519796d0b093836935d Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Wed, 30 Jan 2013 01:31:11 -0500 Subject: [PATCH 67/70] Bug 836176: Add nsIDocument::AsHTMLDocument r=bz --- content/base/public/nsIDocument.h | 3 +++ content/base/src/nsDocument.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 5b8f6ba3745..8cee0f3d5b9 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -34,6 +34,7 @@ class nsDOMNavigationTiming; class nsEventStates; class nsFrameLoader; class nsHTMLCSSStyleSheet; +class nsHTMLDocument; class nsHTMLStyleSheet; class nsIAtom; class nsIBFCacheEntry; @@ -1974,6 +1975,8 @@ public: already_AddRefed CreateTouchList(const mozilla::dom::Sequence >& aTouches); + nsHTMLDocument* AsHTMLDocument(); + private: uint64_t mWarnedAbout; diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 0a1ef143f1c..e8469423188 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1850,6 +1850,12 @@ nsDocument::Init() return NS_OK; } +nsHTMLDocument* +nsIDocument::AsHTMLDocument() +{ + return IsHTML() ? static_cast(this) : nullptr; +} + void nsIDocument::DeleteAllProperties() { From 1a5a7794525b4cb875e496f1bd083aaf6e8d82b1 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Wed, 30 Jan 2013 01:31:11 -0500 Subject: [PATCH 68/70] Various cleanups for SVGAngle, no bug --- content/svg/content/src/SVGAnimatedAngle.cpp | 8 ++------ content/svg/content/src/SVGAnimatedAngle.h | 6 ------ content/svg/content/src/nsSVGAngle.cpp | 14 ++++++-------- content/svg/content/src/nsSVGAngle.h | 4 ++-- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/content/svg/content/src/SVGAnimatedAngle.cpp b/content/svg/content/src/SVGAnimatedAngle.cpp index 726acc3a544..ce5bd10fd54 100644 --- a/content/svg/content/src/SVGAnimatedAngle.cpp +++ b/content/svg/content/src/SVGAnimatedAngle.cpp @@ -30,16 +30,12 @@ SVGAnimatedAngle::WrapObject(JSContext* aCx, JSObject* aScope, bool* aTriedToWra already_AddRefed SVGAnimatedAngle::BaseVal() { - nsRefPtr angle; - mVal->ToDOMBaseVal(getter_AddRefs(angle), mSVGElement); - return angle.forget(); + return mVal->ToDOMBaseVal(mSVGElement); } already_AddRefed SVGAnimatedAngle::AnimVal() { - nsRefPtr angle; - mVal->ToDOMAnimVal(getter_AddRefs(angle), mSVGElement); - return angle.forget(); + return mVal->ToDOMAnimVal(mSVGElement); } diff --git a/content/svg/content/src/SVGAnimatedAngle.h b/content/svg/content/src/SVGAnimatedAngle.h index 965fbb62a08..63324d07f28 100644 --- a/content/svg/content/src/SVGAnimatedAngle.h +++ b/content/svg/content/src/SVGAnimatedAngle.h @@ -29,12 +29,6 @@ public: } ~SVGAnimatedAngle(); - NS_IMETHOD GetBaseVal(nsISupports **aBaseVal) - { *aBaseVal = BaseVal().get(); return NS_OK; } - - NS_IMETHOD GetAnimVal(nsISupports **aAnimVal) - { *aAnimVal = AnimVal().get(); return NS_OK; } - // WebIDL nsSVGElement* GetParentObject() { return mSVGElement; } virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap); diff --git a/content/svg/content/src/nsSVGAngle.cpp b/content/svg/content/src/nsSVGAngle.cpp index 526c5e2b949..9e6c371c633 100644 --- a/content/svg/content/src/nsSVGAngle.cpp +++ b/content/svg/content/src/nsSVGAngle.cpp @@ -217,8 +217,8 @@ nsSVGAngle::NewValueSpecifiedUnits(uint16_t unitType, return NS_OK; } -nsresult -nsSVGAngle::ToDOMBaseVal(SVGAngle **aResult, nsSVGElement *aSVGElement) +already_AddRefed +nsSVGAngle::ToDOMBaseVal(nsSVGElement *aSVGElement) { nsRefPtr domBaseVal = sBaseSVGAngleTearoffTable.GetTearoff(this); @@ -227,12 +227,11 @@ nsSVGAngle::ToDOMBaseVal(SVGAngle **aResult, nsSVGElement *aSVGElement) sBaseSVGAngleTearoffTable.AddTearoff(this, domBaseVal); } - domBaseVal.forget(aResult); - return NS_OK; + return domBaseVal.forget(); } -nsresult -nsSVGAngle::ToDOMAnimVal(SVGAngle **aResult, nsSVGElement *aSVGElement) +already_AddRefed +nsSVGAngle::ToDOMAnimVal(nsSVGElement *aSVGElement) { nsRefPtr domAnimVal = sAnimSVGAngleTearoffTable.GetTearoff(this); @@ -241,8 +240,7 @@ nsSVGAngle::ToDOMAnimVal(SVGAngle **aResult, nsSVGElement *aSVGElement) sAnimSVGAngleTearoffTable.AddTearoff(this, domAnimVal); } - domAnimVal.forget(aResult); - return NS_OK; + return domAnimVal.forget(); } SVGAngle::~SVGAngle() diff --git a/content/svg/content/src/nsSVGAngle.h b/content/svg/content/src/nsSVGAngle.h index 5d26c2ac083..9a9dc3fc9ac 100644 --- a/content/svg/content/src/nsSVGAngle.h +++ b/content/svg/content/src/nsSVGAngle.h @@ -88,8 +88,8 @@ private: nsresult NewValueSpecifiedUnits(uint16_t aUnitType, float aValue, nsSVGElement *aSVGElement); nsresult ConvertToSpecifiedUnits(uint16_t aUnitType, nsSVGElement *aSVGElement); - nsresult ToDOMBaseVal(mozilla::dom::SVGAngle **aResult, nsSVGElement* aSVGElement); - nsresult ToDOMAnimVal(mozilla::dom::SVGAngle **aResult, nsSVGElement* aSVGElement); + already_AddRefed ToDOMBaseVal(nsSVGElement* aSVGElement); + already_AddRefed ToDOMAnimVal(nsSVGElement* aSVGElement); public: // We do not currently implemente a SMILAngle struct because in SVG 1.1 the From df4b373948e73ca62f54225bee5d293909a04785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Tue, 29 Jan 2013 23:29:08 -0800 Subject: [PATCH 69/70] Bug 836103 - Enable/disable ADB when changing the "remote debugging" setting in the Settings App r=dhylands --- b2g/chrome/content/settings.js | 45 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/b2g/chrome/content/settings.js b/b2g/chrome/content/settings.js index a3684f95f65..6e5f25e5655 100644 --- a/b2g/chrome/content/settings.js +++ b/b2g/chrome/content/settings.js @@ -14,6 +14,13 @@ const Cr = Components.results; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); +#ifdef MOZ_WIDGET_GONK +XPCOMUtils.defineLazyGetter(this, "libcutils", function () { + Cu.import("resource://gre/modules/systemlibs.js"); + return libcutils; +}); +#endif + // Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget // is resolved this helper could be removed. var SettingsListener = { @@ -174,27 +181,10 @@ Components.utils.import('resource://gre/modules/ctypes.jsm'); // Get the hardware info and firmware revision from device properties. let hardware_info = null; let firmware_revision = null; - try { - let cutils = ctypes.open('libcutils.so'); - let cbuf = ctypes.char.array(128)(); - let c_property_get = cutils.declare('property_get', ctypes.default_abi, - ctypes.int, // return value: length - ctypes.char.ptr, // key - ctypes.char.ptr, // value - ctypes.char.ptr); // default - let property_get = function (key, defaultValue) { - if (defaultValue === undefined) { - defaultValue = null; - } - c_property_get(key, cbuf, defaultValue); - return cbuf.readString(); - } - hardware_info = property_get('ro.hardware'); - firmware_revision = property_get('ro.firmware_revision'); - cutils.close(); - } catch(e) { - // Error. - } +#ifdef MOZ_WIDGET_GONK + hardware_info = libcutils.property_get('ro.hardware'); + firmware_revision = libcutils.property_get('ro.firmware_revision'); +#endif lock.set('deviceinfo.hardware', hardware_info, null, null); lock.set('deviceinfo.firmware_revision', firmware_revision, null, null); })(); @@ -205,6 +195,19 @@ SettingsListener.observe('devtools.debugger.remote-enabled', false, function(val // This preference is consulted during startup Services.prefs.savePrefFile(null); value ? RemoteDebugger.start() : RemoteDebugger.stop(); + +#ifdef MOZ_WIDGET_GONK + // Configure adb. + try { + let current = libcutils.property_get("persist.sys.usb.config"); + let prefix = current.replace(/,adb/, ""); + libcutils.property_set("persist.sys.usb.config", + prefix + (value ? ",adb" : "")); + current = libcutils.property_get("persist.sys.usb.config"); + } catch(e) { + dump("Error configuring adb: " + e); + } +#endif }); SettingsListener.observe('debug.log-animations.enabled', false, function(value) { From 97782b36c6f253e99d090578f455f1c1eab3f8b0 Mon Sep 17 00:00:00 2001 From: Hsin-Yi Tsai Date: Wed, 30 Jan 2013 11:16:31 +0800 Subject: [PATCH 70/70] Bug 836168 - B2G RIL: update audioPhoneState when rejecting an incoming call. r=allstars.chh --- dom/system/gonk/RadioInterfaceLayer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index b6d118ef0b0..6c680d7bd9b 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -1237,8 +1237,12 @@ RadioInterfaceLayer.prototype = { call.isActive = false; if (this._activeCall && this._activeCall.callIndex == call.callIndex) { - // Previously active call is not active now. Disable audio. + // Previously active call is not active now. this._activeCall = null; + } + + if (!this._activeCall) { + // No active call. Disable the audio. gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL; debug("No active call, put audio system into PHONE_STATE_NORMAL: " + gAudioManager.phoneState);