зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central, a=merge
MozReview-Commit-ID: 5tBON9YUdAO
This commit is contained in:
Коммит
cf8f3268a1
|
@ -174,14 +174,6 @@ var whitelist = [
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Temporary whitelisted while WebPayments in construction
|
|
||||||
// See Bug 1381141
|
|
||||||
if (AppConstants.NIGHTLY_BUILD && AppConstants.MOZ_BUILD_APP == "browser") {
|
|
||||||
whitelist.push(
|
|
||||||
{file: "chrome://payments/content/paymentRequest.xhtml"}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!AppConstants.MOZ_PHOTON_THEME) {
|
if (!AppConstants.MOZ_PHOTON_THEME) {
|
||||||
whitelist.push(
|
whitelist.push(
|
||||||
// Bug 1343824
|
// Bug 1343824
|
||||||
|
|
|
@ -63,11 +63,6 @@ function getTopWin(skipPopups) {
|
||||||
allowPopups: !skipPopups});
|
allowPopups: !skipPopups});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openTopWin(url) {
|
|
||||||
/* deprecated */
|
|
||||||
openUILinkIn(url, "current");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBoolPref(prefname, def) {
|
function getBoolPref(prefname, def) {
|
||||||
try {
|
try {
|
||||||
return Services.prefs.getBoolPref(prefname);
|
return Services.prefs.getBoolPref(prefname);
|
||||||
|
|
|
@ -400,9 +400,8 @@
|
||||||
@RESPATH@/components/nsSearchService.js
|
@RESPATH@/components/nsSearchService.js
|
||||||
@RESPATH@/components/nsSearchSuggestions.js
|
@RESPATH@/components/nsSearchSuggestions.js
|
||||||
@RESPATH@/components/nsSidebar.js
|
@RESPATH@/components/nsSidebar.js
|
||||||
#if defined(NIGHTLY_BUILD) && defined(MOZ_BUILD_APP_IS_BROWSER)
|
|
||||||
@RESPATH@/components/payments.manifest
|
@RESPATH@/components/payments.manifest
|
||||||
#endif
|
@RESPATH@/components/paymentUIService.js
|
||||||
@RESPATH@/components/passwordmgr.manifest
|
@RESPATH@/components/passwordmgr.manifest
|
||||||
@RESPATH@/components/nsLoginInfo.js
|
@RESPATH@/components/nsLoginInfo.js
|
||||||
@RESPATH@/components/nsLoginManager.js
|
@RESPATH@/components/nsLoginManager.js
|
||||||
|
|
|
@ -4105,20 +4105,26 @@ nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText,
|
||||||
nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
|
nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (spec.IsEmpty() && aURI) {
|
|
||||||
spec = aURI->GetSpecOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptError> errorObject =
|
nsCOMPtr<nsIScriptError> errorObject =
|
||||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = errorObject->InitWithWindowID(aErrorText,
|
if (!spec.IsEmpty()) {
|
||||||
NS_ConvertUTF8toUTF16(spec), // file name
|
rv = errorObject->InitWithWindowID(aErrorText,
|
||||||
aSourceLine,
|
NS_ConvertUTF8toUTF16(spec), // file name
|
||||||
aLineNumber, aColumnNumber,
|
aSourceLine,
|
||||||
aErrorFlags, aCategory,
|
aLineNumber, aColumnNumber,
|
||||||
aInnerWindowID);
|
aErrorFlags, aCategory,
|
||||||
|
aInnerWindowID);
|
||||||
|
} else {
|
||||||
|
rv = errorObject->InitWithSourceURI(aErrorText,
|
||||||
|
aURI,
|
||||||
|
aSourceLine,
|
||||||
|
aLineNumber, aColumnNumber,
|
||||||
|
aErrorFlags, aCategory,
|
||||||
|
aInnerWindowID);
|
||||||
|
}
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return sConsoleService->LogMessage(errorObject);
|
return sConsoleService->LogMessage(errorObject);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
#include "nsIArray.idl"
|
#include "nsIArray.idl"
|
||||||
#include "nsIConsoleMessage.idl"
|
#include "nsIConsoleMessage.idl"
|
||||||
|
interface nsIURI;
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
#include "nsStringGlue.h" // for nsDependentCString
|
#include "nsStringGlue.h" // for nsDependentCString
|
||||||
|
@ -97,8 +98,17 @@ interface nsIScriptError : nsIConsoleMessage
|
||||||
in string category);
|
in string category);
|
||||||
|
|
||||||
/* This should be called instead of nsIScriptError.init to
|
/* This should be called instead of nsIScriptError.init to
|
||||||
initialize with a window id. The window id should be for the
|
* initialize with a window id. The window id should be for the
|
||||||
inner window associated with this error. */
|
* inner window associated with this error.
|
||||||
|
*
|
||||||
|
* This function will check whether sourceName is a uri and sanitize it if
|
||||||
|
* needed. If you know the source name is sanitized already, use
|
||||||
|
* initWithSanitizedSource.
|
||||||
|
* A "sanitized" source name means that passwords are not shown. It will
|
||||||
|
* use the sensitiveInfoHiddenSpec function of nsIURI interface, that is
|
||||||
|
* replacing paswords with ***
|
||||||
|
* (e.g. https://USERNAME:****@example.com/some/path).
|
||||||
|
*/
|
||||||
void initWithWindowID(in AString message,
|
void initWithWindowID(in AString message,
|
||||||
in AString sourceName,
|
in AString sourceName,
|
||||||
in AString sourceLine,
|
in AString sourceLine,
|
||||||
|
@ -107,8 +117,33 @@ interface nsIScriptError : nsIConsoleMessage
|
||||||
in uint32_t flags,
|
in uint32_t flags,
|
||||||
in ACString category,
|
in ACString category,
|
||||||
in unsigned long long innerWindowID);
|
in unsigned long long innerWindowID);
|
||||||
|
|
||||||
|
/* This is the same function as initWithWindowID, but it expects an already
|
||||||
|
* sanitized sourceName.
|
||||||
|
* Please use it only if sourceName string is already sanitized.
|
||||||
|
*/
|
||||||
|
void initWithSanitizedSource(in AString message,
|
||||||
|
in AString sourceName,
|
||||||
|
in AString sourceLine,
|
||||||
|
in uint32_t lineNumber,
|
||||||
|
in uint32_t columnNumber,
|
||||||
|
in uint32_t flags,
|
||||||
|
in ACString category,
|
||||||
|
in unsigned long long innerWindowID);
|
||||||
|
|
||||||
|
/* This is the same function as initWithWindowID with an uri as a source parameter.
|
||||||
|
*/
|
||||||
|
void initWithSourceURI(in AString message,
|
||||||
|
in nsIURI sourceURI,
|
||||||
|
in AString sourceLine,
|
||||||
|
in uint32_t lineNumber,
|
||||||
|
in uint32_t columnNumber,
|
||||||
|
in uint32_t flags,
|
||||||
|
in ACString category,
|
||||||
|
in unsigned long long innerWindowID);
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
// This overload allows passing a literal string for category.
|
// These overloads allow passing a literal string for category.
|
||||||
template<uint32_t N>
|
template<uint32_t N>
|
||||||
nsresult InitWithWindowID(const nsAString& message,
|
nsresult InitWithWindowID(const nsAString& message,
|
||||||
const nsAString& sourceName,
|
const nsAString& sourceName,
|
||||||
|
@ -123,6 +158,38 @@ interface nsIScriptError : nsIConsoleMessage
|
||||||
return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
|
return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
|
||||||
columnNumber, flags, category, aInnerWindowID);
|
columnNumber, flags, category, aInnerWindowID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<uint32_t N>
|
||||||
|
nsresult InitWithSanitizedSource(const nsAString& message,
|
||||||
|
const nsAString& sourceName,
|
||||||
|
const nsAString& sourceLine,
|
||||||
|
uint32_t lineNumber,
|
||||||
|
uint32_t columnNumber,
|
||||||
|
uint32_t flags,
|
||||||
|
const char (&c)[N],
|
||||||
|
uint64_t aInnerWindowID)
|
||||||
|
{
|
||||||
|
nsDependentCString category(c, N - 1);
|
||||||
|
return InitWithSanitizedSource(message, sourceName, sourceLine,
|
||||||
|
lineNumber, columnNumber, flags,
|
||||||
|
category, aInnerWindowID);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<uint32_t N>
|
||||||
|
nsresult InitWithSourceURI(const nsAString& message,
|
||||||
|
nsIURI* sourceURI,
|
||||||
|
const nsAString& sourceLine,
|
||||||
|
uint32_t lineNumber,
|
||||||
|
uint32_t columnNumber,
|
||||||
|
uint32_t flags,
|
||||||
|
const char (&c)[N],
|
||||||
|
uint64_t aInnerWindowID)
|
||||||
|
{
|
||||||
|
nsDependentCString category(c, N - 1);
|
||||||
|
return InitWithSourceURI(message, sourceURI, sourceLine,
|
||||||
|
lineNumber, columnNumber, flags,
|
||||||
|
category, aInnerWindowID);
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -210,14 +210,41 @@ AssignSourceNameHelper(nsString& aSourceNameDest, const nsAString& aSourceNameSr
|
||||||
NS_SUCCEEDED(uri->GetPassword(pass)) &&
|
NS_SUCCEEDED(uri->GetPassword(pass)) &&
|
||||||
!pass.IsEmpty())
|
!pass.IsEmpty())
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(uri);
|
NS_GetSanitizedURIStringFromURI(uri, aSourceNameDest);
|
||||||
|
|
||||||
nsAutoCString loc;
|
|
||||||
if (safeUri && NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc)))
|
|
||||||
aSourceNameDest.Assign(NS_ConvertUTF8toUTF16(loc));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
AssignSourceNameHelper(nsIURI* aSourceURI, nsString& aSourceNameDest)
|
||||||
|
{
|
||||||
|
if (!aSourceURI)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (NS_FAILED(NS_GetSanitizedURIStringFromURI(aSourceURI,
|
||||||
|
aSourceNameDest))) {
|
||||||
|
aSourceNameDest.AssignLiteral("[nsIURI::GetSpec failed]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsScriptErrorBase::InitializationHelper(const nsAString& message,
|
||||||
|
const nsAString& sourceLine,
|
||||||
|
uint32_t lineNumber,
|
||||||
|
uint32_t columnNumber,
|
||||||
|
uint32_t flags,
|
||||||
|
const nsACString& category,
|
||||||
|
uint64_t aInnerWindowID)
|
||||||
|
{
|
||||||
|
mMessage.Assign(message);
|
||||||
|
mLineNumber = lineNumber;
|
||||||
|
mSourceLine.Assign(sourceLine);
|
||||||
|
mColumnNumber = columnNumber;
|
||||||
|
mFlags = flags;
|
||||||
|
mCategory = category;
|
||||||
|
mTimeStamp = JS_Now() / 1000;
|
||||||
|
mInnerWindowID = aInnerWindowID;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
||||||
const nsAString& sourceName,
|
const nsAString& sourceName,
|
||||||
|
@ -228,15 +255,49 @@ nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
||||||
const nsACString& category,
|
const nsACString& category,
|
||||||
uint64_t aInnerWindowID)
|
uint64_t aInnerWindowID)
|
||||||
{
|
{
|
||||||
mMessage.Assign(message);
|
InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
|
||||||
|
category, aInnerWindowID);
|
||||||
AssignSourceNameHelper(mSourceName, sourceName);
|
AssignSourceNameHelper(mSourceName, sourceName);
|
||||||
mLineNumber = lineNumber;
|
|
||||||
mSourceLine.Assign(sourceLine);
|
if (aInnerWindowID && NS_IsMainThread())
|
||||||
mColumnNumber = columnNumber;
|
InitializeOnMainThread();
|
||||||
mFlags = flags;
|
|
||||||
mCategory = category;
|
return NS_OK;
|
||||||
mTimeStamp = JS_Now() / 1000;
|
}
|
||||||
mInnerWindowID = aInnerWindowID;
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsScriptErrorBase::InitWithSanitizedSource(const nsAString& message,
|
||||||
|
const nsAString& sourceName,
|
||||||
|
const nsAString& sourceLine,
|
||||||
|
uint32_t lineNumber,
|
||||||
|
uint32_t columnNumber,
|
||||||
|
uint32_t flags,
|
||||||
|
const nsACString& category,
|
||||||
|
uint64_t aInnerWindowID)
|
||||||
|
{
|
||||||
|
InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
|
||||||
|
category, aInnerWindowID);
|
||||||
|
mSourceName = sourceName;
|
||||||
|
|
||||||
|
if (aInnerWindowID && NS_IsMainThread())
|
||||||
|
InitializeOnMainThread();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsScriptErrorBase::InitWithSourceURI(const nsAString& message,
|
||||||
|
nsIURI *sourceURI,
|
||||||
|
const nsAString& sourceLine,
|
||||||
|
uint32_t lineNumber,
|
||||||
|
uint32_t columnNumber,
|
||||||
|
uint32_t flags,
|
||||||
|
const nsACString& category,
|
||||||
|
uint64_t aInnerWindowID)
|
||||||
|
{
|
||||||
|
InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
|
||||||
|
category, aInnerWindowID);
|
||||||
|
AssignSourceNameHelper(sourceURI, mSourceName);
|
||||||
|
|
||||||
if (aInnerWindowID && NS_IsMainThread())
|
if (aInnerWindowID && NS_IsMainThread())
|
||||||
InitializeOnMainThread();
|
InitializeOnMainThread();
|
||||||
|
|
|
@ -53,6 +53,12 @@ protected:
|
||||||
void
|
void
|
||||||
InitializeOnMainThread();
|
InitializeOnMainThread();
|
||||||
|
|
||||||
|
void InitializationHelper(const nsAString& message,
|
||||||
|
const nsAString& sourceLine, uint32_t lineNumber,
|
||||||
|
uint32_t columnNumber, uint32_t flags,
|
||||||
|
const nsACString& category,
|
||||||
|
uint64_t aInnerWindowID);
|
||||||
|
|
||||||
nsCOMArray<nsIScriptErrorNote> mNotes;
|
nsCOMArray<nsIScriptErrorNote> mNotes;
|
||||||
nsString mMessage;
|
nsString mMessage;
|
||||||
nsString mMessageName;
|
nsString mMessageName;
|
||||||
|
|
|
@ -6,12 +6,18 @@
|
||||||
#include "nsISupports.idl"
|
#include "nsISupports.idl"
|
||||||
#include "nsIPaymentActionResponse.idl"
|
#include "nsIPaymentActionResponse.idl"
|
||||||
|
|
||||||
[scriptable, uuid(ea008d0c-9e9f-411f-a6c5-a62106ba7ab9)]
|
[scriptable, uuid(01f8bd55-9017-438b-85ec-7c15d2b35cdc)]
|
||||||
interface nsIPaymentUIService : nsISupports
|
interface nsIPaymentUIService : nsISupports
|
||||||
{
|
{
|
||||||
nsIPaymentActionResponse canMakePayment(in AString requestId);
|
void showPayment(in AString requestId);
|
||||||
nsIPaymentActionResponse showPayment(in AString requestId);
|
void abortPayment(in AString requestId);
|
||||||
nsIPaymentActionResponse abortPayment(in AString requestId);
|
void completePayment(in AString requestId);
|
||||||
nsIPaymentActionResponse completePayment(in AString requestId);
|
void updatePayment(in AString requestId);
|
||||||
nsIPaymentActionResponse updatePayment(in AString requestId);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
%{C++
|
||||||
|
#define NS_PAYMENT_UI_SERVICE_CID \
|
||||||
|
{ 0x01f8bd55, 0x9017, 0x438b, { 0x85, 0xec, 0x7c, 0x15, 0xd2, 0xb3, 0x5c, 0xdc } }
|
||||||
|
#define NS_PAYMENT_UI_SERVICE_CONTRACT_ID \
|
||||||
|
"@mozilla.org/dom/payments/payment-ui-service;1"
|
||||||
|
%}
|
||||||
|
|
|
@ -1227,7 +1227,7 @@ MediaDecoder::GetCompositor()
|
||||||
RefPtr<LayerManager> layerManager =
|
RefPtr<LayerManager> layerManager =
|
||||||
ownerDoc ? nsContentUtils::LayerManagerForDocument(ownerDoc) : nullptr;
|
ownerDoc ? nsContentUtils::LayerManagerForDocument(ownerDoc) : nullptr;
|
||||||
RefPtr<KnowsCompositor> knows =
|
RefPtr<KnowsCompositor> knows =
|
||||||
layerManager ? layerManager->AsShadowForwarder() : nullptr;
|
layerManager ? layerManager->AsKnowsCompositor() : nullptr;
|
||||||
return knows.forget();
|
return knows.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -643,7 +643,7 @@ private:
|
||||||
RefPtr<MFTDecoder> mTransform;
|
RefPtr<MFTDecoder> mTransform;
|
||||||
RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
|
RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
|
||||||
RefPtr<ID3D11VideoDecoder> mDecoder;
|
RefPtr<ID3D11VideoDecoder> mDecoder;
|
||||||
RefPtr<layers::SyncObject> mSyncObject;
|
RefPtr<layers::SyncObjectClient> mSyncObject;
|
||||||
GUID mDecoderGUID;
|
GUID mDecoderGUID;
|
||||||
uint32_t mWidth = 0;
|
uint32_t mWidth = 0;
|
||||||
uint32_t mHeight = 0;
|
uint32_t mHeight = 0;
|
||||||
|
@ -711,9 +711,10 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
|
||||||
// and because it allows color conversion ocurring directly from this texture
|
// and because it allows color conversion ocurring directly from this texture
|
||||||
// DXVA does not seem to accept IDXGIKeyedMutex textures as input.
|
// DXVA does not seem to accept IDXGIKeyedMutex textures as input.
|
||||||
mSyncObject =
|
mSyncObject =
|
||||||
layers::SyncObject::CreateSyncObject(layers::ImageBridgeChild::GetSingleton()->
|
layers::SyncObjectClient::CreateSyncObjectClient(
|
||||||
GetTextureFactoryIdentifier().mSyncHandle,
|
layers::ImageBridgeChild::GetSingleton()->
|
||||||
mDevice);
|
GetTextureFactoryIdentifier().mSyncHandle,
|
||||||
|
mDevice);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mTextureClientAllocator =
|
mTextureClientAllocator =
|
||||||
|
@ -723,8 +724,9 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
|
||||||
// and because it allows color conversion ocurring directly from this texture
|
// and because it allows color conversion ocurring directly from this texture
|
||||||
// DXVA does not seem to accept IDXGIKeyedMutex textures as input.
|
// DXVA does not seem to accept IDXGIKeyedMutex textures as input.
|
||||||
mSyncObject =
|
mSyncObject =
|
||||||
layers::SyncObject::CreateSyncObject(aKnowsCompositor->GetTextureFactoryIdentifier().mSyncHandle,
|
layers::SyncObjectClient::CreateSyncObjectClient(
|
||||||
mDevice);
|
aKnowsCompositor->GetTextureFactoryIdentifier().mSyncHandle,
|
||||||
|
mDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mTextureClientAllocator->SetMaxPoolSize(5);
|
mTextureClientAllocator->SetMaxPoolSize(5);
|
||||||
|
@ -882,7 +884,8 @@ D3D11DXVA2Manager::CreateOutputSample(RefPtr<IMFSample>& aSample,
|
||||||
__uuidof(ID3D11Texture2D), aTexture, 0, FALSE, getter_AddRefs(buffer));
|
__uuidof(ID3D11Texture2D), aTexture, 0, FALSE, getter_AddRefs(buffer));
|
||||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||||
|
|
||||||
sample->AddBuffer(buffer);
|
hr = sample->AddBuffer(buffer);
|
||||||
|
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||||
|
|
||||||
aSample = sample;
|
aSample = sample;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -952,6 +955,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
|
||||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||||
|
|
||||||
hr = mTransform->Output(&sample);
|
hr = mTransform->Output(&sample);
|
||||||
|
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,7 +963,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
|
||||||
// It appears some race-condition may allow us to arrive here even when mSyncObject
|
// It appears some race-condition may allow us to arrive here even when mSyncObject
|
||||||
// is null. It's better to avoid that crash.
|
// is null. It's better to avoid that crash.
|
||||||
client->SyncWithObject(mSyncObject);
|
client->SyncWithObject(mSyncObject);
|
||||||
mSyncObject->FinalizeFrame();
|
mSyncObject->Synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
image.forget(aOutImage);
|
image.forget(aOutImage);
|
||||||
|
|
|
@ -449,7 +449,10 @@ WMFVideoMFTManager::InitializeDXVA()
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(!mDXVA2Manager);
|
MOZ_ASSERT(!mDXVA2Manager);
|
||||||
LayersBackend backend = GetCompositorBackendType(mKnowsCompositor);
|
LayersBackend backend = GetCompositorBackendType(mKnowsCompositor);
|
||||||
if (backend != LayersBackend::LAYERS_D3D11) {
|
bool useANGLE =
|
||||||
|
mKnowsCompositor ? mKnowsCompositor->GetCompositorUseANGLE() : false;
|
||||||
|
bool wrWithANGLE = (backend == LayersBackend::LAYERS_WR) && useANGLE;
|
||||||
|
if (backend != LayersBackend::LAYERS_D3D11 && !wrWithANGLE) {
|
||||||
mDXVAFailureReason.AssignLiteral("Unsupported layers backend");
|
mDXVAFailureReason.AssignLiteral("Unsupported layers backend");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -934,7 +937,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample,
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocks until decoded sample is produced by the deoder.
|
// Blocks until decoded sample is produced by the decoder.
|
||||||
HRESULT
|
HRESULT
|
||||||
WMFVideoMFTManager::Output(int64_t aStreamOffset,
|
WMFVideoMFTManager::Output(int64_t aStreamOffset,
|
||||||
RefPtr<MediaData>& aOutData)
|
RefPtr<MediaData>& aOutData)
|
||||||
|
|
|
@ -353,9 +353,7 @@ BasicCardService::DecodeBasicCardData(const nsAString& aData,
|
||||||
#undef EncodeBasicCardProperty
|
#undef EncodeBasicCardProperty
|
||||||
#undef EncodeAddressProperty
|
#undef EncodeAddressProperty
|
||||||
#undef DecodeBasicCardProperty
|
#undef DecodeBasicCardProperty
|
||||||
#undef DecodeBasicCardCardNumber
|
|
||||||
#undef DecodeAddressProperty
|
#undef DecodeAddressProperty
|
||||||
#undef DecodeAddressLine
|
|
||||||
#undef AMEX
|
#undef AMEX
|
||||||
#undef CARTEBANCAIRE
|
#undef CARTEBANCAIRE
|
||||||
#undef DINERS
|
#undef DINERS
|
||||||
|
|
|
@ -148,84 +148,41 @@ PaymentRequestService::SetTestingUIService(nsIPaymentUIService* aUIService)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PaymentRequestService::CallTestingUIAction(const nsAString& aRequestId, uint32_t aActionType)
|
PaymentRequestService::LaunchUIAction(const nsAString& aRequestId, uint32_t aActionType)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIPaymentActionResponse> response;
|
nsCOMPtr<nsIPaymentUIService> uiService;
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
if (mTestingUIService) {
|
if (mTestingUIService) {
|
||||||
switch (aActionType) {
|
uiService = mTestingUIService;
|
||||||
case nsIPaymentActionRequest::CANMAKE_ACTION: {
|
} else {
|
||||||
rv = mTestingUIService->CanMakePayment(aRequestId, getter_AddRefs(response));
|
uiService = do_GetService(NS_PAYMENT_UI_SERVICE_CONTRACT_ID, &rv);
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIPaymentActionRequest::SHOW_ACTION: {
|
|
||||||
rv = mTestingUIService->ShowPayment(aRequestId, getter_AddRefs(response));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIPaymentActionRequest::ABORT_ACTION: {
|
|
||||||
rv = mTestingUIService->AbortPayment(aRequestId, getter_AddRefs(response));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIPaymentActionRequest::COMPLETE_ACTION: {
|
|
||||||
rv = mTestingUIService->CompletePayment(aRequestId, getter_AddRefs(response));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIPaymentActionRequest::UPDATE_ACTION: {
|
|
||||||
rv = mTestingUIService->UpdatePayment(aRequestId, getter_AddRefs(response));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default : {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Since there is no UI implementation and no testing UI Service is registered,
|
|
||||||
// set false response for canMakePayment(), ABORT_SUCCEEDED for abort() and
|
|
||||||
// COMPLETE_SUCCEEDED for complete().
|
|
||||||
switch (aActionType) {
|
|
||||||
case nsIPaymentActionRequest::CANMAKE_ACTION: {
|
|
||||||
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
|
|
||||||
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
|
|
||||||
MOZ_ASSERT(canMakeResponse);
|
|
||||||
rv = canMakeResponse->Init(aRequestId, false);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
response = do_QueryInterface(canMakeResponse);
|
|
||||||
MOZ_ASSERT(response);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIPaymentActionRequest::ABORT_ACTION: {
|
|
||||||
nsCOMPtr<nsIPaymentAbortActionResponse> abortResponse =
|
|
||||||
do_CreateInstance(NS_PAYMENT_ABORT_ACTION_RESPONSE_CONTRACT_ID);
|
|
||||||
MOZ_ASSERT(abortResponse);
|
|
||||||
rv = abortResponse->Init(aRequestId, nsIPaymentActionResponse::ABORT_SUCCEEDED);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
response = do_QueryInterface(abortResponse);
|
|
||||||
MOZ_ASSERT(response);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nsIPaymentActionRequest::COMPLETE_ACTION: {
|
|
||||||
nsCOMPtr<nsIPaymentCompleteActionResponse> completeResponse =
|
|
||||||
do_CreateInstance(NS_PAYMENT_COMPLETE_ACTION_RESPONSE_CONTRACT_ID);
|
|
||||||
MOZ_ASSERT(completeResponse);
|
|
||||||
rv = completeResponse->Init(aRequestId, nsIPaymentActionResponse::COMPLETE_SUCCEEDED);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
response = do_QueryInterface(completeResponse);
|
|
||||||
MOZ_ASSERT(response);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default : {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (response) {
|
switch (aActionType) {
|
||||||
rv = RespondPayment(response);
|
case nsIPaymentActionRequest::SHOW_ACTION: {
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
rv = uiService->ShowPayment(aRequestId);
|
||||||
return rv;
|
break;
|
||||||
}
|
}
|
||||||
|
case nsIPaymentActionRequest::ABORT_ACTION: {
|
||||||
|
rv = uiService->AbortPayment(aRequestId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case nsIPaymentActionRequest::COMPLETE_ACTION: {
|
||||||
|
rv = uiService->CompletePayment(aRequestId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case nsIPaymentActionRequest::UPDATE_ACTION: {
|
||||||
|
rv = uiService->UpdatePayment(aRequestId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -305,31 +262,25 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
||||||
* registered third party payment apps.
|
* registered third party payment apps.
|
||||||
*/
|
*/
|
||||||
case nsIPaymentActionRequest::CANMAKE_ACTION: {
|
case nsIPaymentActionRequest::CANMAKE_ACTION: {
|
||||||
|
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
|
||||||
|
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
|
||||||
|
MOZ_ASSERT(canMakeResponse);
|
||||||
if (IsBasicCardPayment(requestId)) {
|
if (IsBasicCardPayment(requestId)) {
|
||||||
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
|
|
||||||
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
|
|
||||||
MOZ_ASSERT(canMakeResponse);
|
|
||||||
rv = canMakeResponse->Init(requestId, true);
|
rv = canMakeResponse->Init(requestId, true);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIPaymentActionResponse> response = do_QueryInterface(canMakeResponse);
|
|
||||||
MOZ_ASSERT(response);
|
|
||||||
rv = RespondPayment(response);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
rv = CallTestingUIAction(requestId, type);
|
rv = canMakeResponse->Init(requestId, false);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
}
|
||||||
return NS_ERROR_FAILURE;
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
}
|
return rv;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIPaymentActionResponse> response = do_QueryInterface(canMakeResponse);
|
||||||
|
MOZ_ASSERT(response);
|
||||||
|
rv = RespondPayment(response);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* TODO: Launch/inform payment UI here once the UI module is implemented.
|
|
||||||
*/
|
|
||||||
case nsIPaymentActionRequest::SHOW_ACTION: {
|
case nsIPaymentActionRequest::SHOW_ACTION: {
|
||||||
if (mShowingRequest) {
|
if (mShowingRequest) {
|
||||||
nsCOMPtr<nsIPaymentResponseData> responseData =
|
nsCOMPtr<nsIPaymentResponseData> responseData =
|
||||||
|
@ -356,7 +307,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
rv = CallTestingUIAction(requestId, type);
|
rv = LaunchUIAction(requestId, type);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -365,7 +316,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
||||||
}
|
}
|
||||||
case nsIPaymentActionRequest::ABORT_ACTION:
|
case nsIPaymentActionRequest::ABORT_ACTION:
|
||||||
case nsIPaymentActionRequest::COMPLETE_ACTION: {
|
case nsIPaymentActionRequest::COMPLETE_ACTION: {
|
||||||
rv = CallTestingUIAction(requestId, type);
|
rv = LaunchUIAction(requestId, type);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +341,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
rv = CallTestingUIAction(requestId, type);
|
rv = LaunchUIAction(requestId, type);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ private:
|
||||||
|
|
||||||
// this method is only used for testing
|
// this method is only used for testing
|
||||||
nsresult
|
nsresult
|
||||||
CallTestingUIAction(const nsAString& aRequestId, uint32_t aActionType);
|
LaunchUIAction(const nsAString& aRequestId, uint32_t aActionType);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsBasicCardPayment(const nsAString& aRequestId);
|
IsBasicCardPayment(const nsAString& aRequestId);
|
||||||
|
|
|
@ -41,20 +41,17 @@ function abortPaymentResponse(requestId) {
|
||||||
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"].
|
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"].
|
||||||
createInstance(Ci.nsIPaymentAbortActionResponse);
|
createInstance(Ci.nsIPaymentAbortActionResponse);
|
||||||
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
|
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
|
||||||
return abortResponse.QueryInterface(Ci.nsIPaymentActionResponse);
|
paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
function completePaymentResponse(requestId) {
|
function completePaymentResponse(requestId) {
|
||||||
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
|
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
|
||||||
createInstance(Ci.nsIPaymentCompleteActionResponse);
|
createInstance(Ci.nsIPaymentCompleteActionResponse);
|
||||||
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
|
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
|
||||||
return completeResponse;
|
paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
const detailedResponseUI = {
|
const detailedResponseUI = {
|
||||||
canMakePayment: function(requestId) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
showPayment: function(requestId) {
|
showPayment: function(requestId) {
|
||||||
try {
|
try {
|
||||||
basiccardResponseData.initData("Bill A. Pacheco", // cardholderName
|
basiccardResponseData.initData("Bill A. Pacheco", // cardholderName
|
||||||
|
@ -73,20 +70,16 @@ const detailedResponseUI = {
|
||||||
"Bill A. Pacheco", // payer name
|
"Bill A. Pacheco", // payer name
|
||||||
"", // payer email
|
"", // payer email
|
||||||
""); // payer phone
|
""); // payer phone
|
||||||
return showResponse;
|
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
},
|
},
|
||||||
abortPayment: abortPaymentResponse,
|
abortPayment: abortPaymentResponse,
|
||||||
completePayment: completePaymentResponse,
|
completePayment: completePaymentResponse,
|
||||||
updatePayment: function(requestId) {
|
updatePayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||||
};
|
};
|
||||||
|
|
||||||
const simpleResponseUI = {
|
const simpleResponseUI = {
|
||||||
canMakePayment: function(requestId) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
showPayment: function(requestId) {
|
showPayment: function(requestId) {
|
||||||
try {
|
try {
|
||||||
basiccardResponseData.initData("", // cardholderName
|
basiccardResponseData.initData("", // cardholderName
|
||||||
|
@ -105,12 +98,11 @@ const simpleResponseUI = {
|
||||||
"Bill A. Pacheco", // payer name
|
"Bill A. Pacheco", // payer name
|
||||||
"", // payer email
|
"", // payer email
|
||||||
""); // payer phone
|
""); // payer phone
|
||||||
return showResponse;
|
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
},
|
},
|
||||||
abortPayment: abortPaymentResponse,
|
abortPayment: abortPaymentResponse,
|
||||||
completePayment: completePaymentResponse,
|
completePayment: completePaymentResponse,
|
||||||
updatePayment: function(requestId) {
|
updatePayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|
||||||
|
|
||||||
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
|
|
||||||
const DummyUIService = {
|
|
||||||
canMakePayment: function(requestId) {
|
|
||||||
let canMakeResponse = Cc["@mozilla.org/dom/payments/payment-canmake-action-response;1"].
|
|
||||||
createInstance(Ci.nsIPaymentCanMakeActionResponse);
|
|
||||||
canMakeResponse.init(requestId, true);
|
|
||||||
return canMakeResponse.QueryInterface(Ci.nsIPaymentActionResponse);
|
|
||||||
},
|
|
||||||
showPayment: function(requestId) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
abortPayment: function(requestId) {
|
|
||||||
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"].
|
|
||||||
createInstance(Ci.nsIPaymentAbortActionResponse);
|
|
||||||
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
|
|
||||||
return abortResponse.QueryInterface(Ci.nsIPaymentActionResponse);
|
|
||||||
},
|
|
||||||
completePayment: function(requestId) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
|
||||||
};
|
|
||||||
|
|
||||||
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
|
||||||
paymentSrv.setTestingUIService(DummyUIService.QueryInterface(Ci.nsIPaymentUIService));
|
|
||||||
|
|
||||||
addMessageListener('teardown', function() {
|
|
||||||
paymentSrv.cleanup();
|
|
||||||
paymentSrv.setTestingUIService(null);
|
|
||||||
sendAsyncMessage('teardown-complete');
|
|
||||||
});
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||||
|
|
||||||
|
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
||||||
|
|
||||||
|
addMessageListener("teardown", function() {
|
||||||
|
paymentSrv.cleanup();
|
||||||
|
paymentSrv.setTestingUIService(null);
|
||||||
|
sendAsyncMessage('teardown-complete');
|
||||||
|
});
|
|
@ -33,21 +33,16 @@ shippingAddress.init("USA", // country
|
||||||
|
|
||||||
const NormalUIService = {
|
const NormalUIService = {
|
||||||
shippingOptionChanged: false,
|
shippingOptionChanged: false,
|
||||||
canMakePayment: function(requestId) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
showPayment: function(requestId) {
|
showPayment: function(requestId) {
|
||||||
paymentSrv.changeShippingAddress(requestId, shippingAddress);
|
paymentSrv.changeShippingAddress(requestId, shippingAddress);
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
abortPayment: function(requestId) {
|
abortPayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
completePayment: function(requestId) {
|
completePayment: function(requestId) {
|
||||||
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
|
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
|
||||||
createInstance(Ci.nsIPaymentCompleteActionResponse);
|
createInstance(Ci.nsIPaymentCompleteActionResponse);
|
||||||
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
|
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
|
||||||
return completeResponse;
|
paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
},
|
},
|
||||||
updatePayment: function(requestId) {
|
updatePayment: function(requestId) {
|
||||||
let showResponse = null;
|
let showResponse = null;
|
||||||
|
@ -87,16 +82,13 @@ const NormalUIService = {
|
||||||
"Bill A. Pacheco", // payer name
|
"Bill A. Pacheco", // payer name
|
||||||
"", // payer email
|
"", // payer email
|
||||||
""); // payer phone
|
""); // payer phone
|
||||||
|
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
}
|
}
|
||||||
return showResponse;
|
|
||||||
},
|
},
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||||
};
|
};
|
||||||
|
|
||||||
const RejectUIService = {
|
const RejectUIService = {
|
||||||
canMakePayment: function(requestId) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
showPayment: function(requestId) {
|
showPayment: function(requestId) {
|
||||||
const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
|
const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
|
||||||
createInstance(Ci.nsIGeneralResponseData);
|
createInstance(Ci.nsIGeneralResponseData);
|
||||||
|
@ -115,34 +107,24 @@ const RejectUIService = {
|
||||||
"", // payer name
|
"", // payer name
|
||||||
"", // payer email
|
"", // payer email
|
||||||
""); // payer phone
|
""); // payer phone
|
||||||
|
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
return showResponse;
|
|
||||||
},
|
},
|
||||||
abortPayment: function(requestId) {
|
abortPayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
completePayment: function(requestId) {
|
completePayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
updatePayment: function(requestId) {
|
updatePayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||||
};
|
};
|
||||||
|
|
||||||
const ErrorUIService = {
|
const ErrorUIService = {
|
||||||
canMakePayment: function(requestId) {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
showPayment: function(requestId) {
|
showPayment: function(requestId) {
|
||||||
paymentSrv.changeShippingOption(requestId, "");
|
paymentSrv.changeShippingOption(requestId, "");
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
abortPayment: function(requestId) {
|
abortPayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
completePayment: function(requestId) {
|
completePayment: function(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
updatePayment: function(requestId) {
|
updatePayment: function(requestId) {
|
||||||
let payRequest = paymentSrv.getPaymentRequestById(requestId);
|
let payRequest = paymentSrv.getPaymentRequestById(requestId);
|
||||||
|
@ -168,8 +150,7 @@ const ErrorUIService = {
|
||||||
"", // payer name
|
"", // payer name
|
||||||
"", // payer email
|
"", // payer email
|
||||||
""); // payer phone
|
""); // payer phone
|
||||||
|
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
return showResponse;
|
|
||||||
},
|
},
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ scheme = https
|
||||||
support-files =
|
support-files =
|
||||||
simple_payment_request.html
|
simple_payment_request.html
|
||||||
BasiccardChromeScript.js
|
BasiccardChromeScript.js
|
||||||
CanMakePaymentChromeScript.js
|
|
||||||
ConstructorChromeScript.js
|
ConstructorChromeScript.js
|
||||||
|
GeneralChromeScript.js
|
||||||
ShowPaymentChromeScript.js
|
ShowPaymentChromeScript.js
|
||||||
|
|
||||||
[test_abortPayment.html]
|
[test_abortPayment.html]
|
||||||
|
|
|
@ -13,6 +13,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345367
|
||||||
"use strict";
|
"use strict";
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
var gUrl = SimpleTest.getTestFileURL('GeneralChromeScript.js');
|
||||||
|
var gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||||
|
|
||||||
const defaultMethods = [{
|
const defaultMethods = [{
|
||||||
supportedMethods: "basic-card",
|
supportedMethods: "basic-card",
|
||||||
}];
|
}];
|
||||||
|
@ -54,10 +57,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345367
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function teardown() {
|
||||||
|
gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
|
||||||
|
gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
|
||||||
|
gScript.destroy();
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
gScript.sendAsyncMessage("teardown");
|
||||||
|
}
|
||||||
|
|
||||||
function runTests() {
|
function runTests() {
|
||||||
testBeforeShow()
|
testBeforeShow()
|
||||||
.then(testAfterShow)
|
.then(testAfterShow)
|
||||||
.then(SimpleTest.finish)
|
.then(teardown)
|
||||||
.catch( e => {
|
.catch( e => {
|
||||||
ok(false, "Unexpected error: " + e.name);
|
ok(false, "Unexpected error: " + e.name);
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
|
|
|
@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
|
||||||
"use strict";
|
"use strict";
|
||||||
SimpleTest.waitForExplicitFinish();
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
var gUrl = SimpleTest.getTestFileURL('CanMakePaymentChromeScript.js');
|
var gUrl = SimpleTest.getTestFileURL('GeneralChromeScript.js');
|
||||||
var gScript = SpecialPowers.loadChromeScript(gUrl);
|
var gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||||
|
|
||||||
const defaultMethods = [{
|
const defaultMethods = [{
|
||||||
|
@ -29,11 +29,28 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const nonsupportedMethods = [{
|
||||||
|
supportedMethods: "testing-payment-method",
|
||||||
|
}];
|
||||||
|
|
||||||
|
function testDefaultAction() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const payRequest = new PaymentRequest(nonsupportedMethods, defaultDetails);
|
||||||
|
payRequest.canMakePayment().then((result) => {
|
||||||
|
ok(!result, "Should be resolved with false, but got " + result + ".");
|
||||||
|
resolve();
|
||||||
|
}).catch((err) => {
|
||||||
|
ok(false, "Expected no error, but got '" + err.name +"'.");
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function testSimple() {
|
function testSimple() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
|
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
|
||||||
payRequest.canMakePayment().then((result) => {
|
payRequest.canMakePayment().then((result) => {
|
||||||
ok(result, "Should be resolved with true, but got false.");
|
ok(result, "Should be resolved with true, but got " + result + ".");
|
||||||
resolve();
|
resolve();
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
ok(false, "Expected no error, but got '" + err.name +"'.");
|
ok(false, "Expected no error, but got '" + err.name +"'.");
|
||||||
|
@ -118,7 +135,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
|
||||||
}
|
}
|
||||||
|
|
||||||
function runTests() {
|
function runTests() {
|
||||||
testSimple()
|
testDefaultAction()
|
||||||
|
.then(testSimple)
|
||||||
.then(testAfterShow)
|
.then(testAfterShow)
|
||||||
.then(testAfterAbort)
|
.then(testAfterAbort)
|
||||||
.then(testNotAllowed)
|
.then(testNotAllowed)
|
||||||
|
|
|
@ -330,10 +330,12 @@ FramingChecker::ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = errorObject->InitWithWindowID(msg, EmptyString(), EmptyString(), 0, 0,
|
// It is ok to use InitWithSanitizedSource, because the source string is
|
||||||
nsIScriptError::errorFlag,
|
// empty.
|
||||||
"X-Frame-Options",
|
rv = errorObject->InitWithSanitizedSource(msg, EmptyString(), EmptyString(),
|
||||||
topInnerWindow->WindowID());
|
0, 0, nsIScriptError::errorFlag,
|
||||||
|
"X-Frame-Options",
|
||||||
|
topInnerWindow->WindowID());
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6221,6 +6221,26 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the hybrid event target stops dispatching runnables
|
||||||
|
// once we reaching the killing state.
|
||||||
|
if (aStatus == Killing) {
|
||||||
|
// To avoid deadlock we always acquire the event target mutex before the
|
||||||
|
// worker private mutex. (We do it in this order because this is what
|
||||||
|
// workers best for event dispatching.) To enforce that order here we
|
||||||
|
// need to unlock the worker private mutex before we lock the event target
|
||||||
|
// mutex in ForgetWorkerPrivate.
|
||||||
|
{
|
||||||
|
MutexAutoUnlock unlock(mMutex);
|
||||||
|
mWorkerHybridEventTarget->ForgetWorkerPrivate(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the status code again in case another NotifyInternal came in
|
||||||
|
// while we were unlocked above.
|
||||||
|
if (mStatus >= aStatus) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
previousStatus = mStatus;
|
previousStatus = mStatus;
|
||||||
mStatus = aStatus;
|
mStatus = aStatus;
|
||||||
|
|
||||||
|
@ -6229,12 +6249,6 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
||||||
if (aStatus == Closing) {
|
if (aStatus == Closing) {
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the hybrid event target stops dispatching runnables
|
|
||||||
// once we reaching the killing state.
|
|
||||||
if (aStatus == Killing) {
|
|
||||||
mWorkerHybridEventTarget->ForgetWorkerPrivate(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCrossThreadDispatcher) {
|
if (mCrossThreadDispatcher) {
|
||||||
|
|
|
@ -339,9 +339,6 @@ XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
|
||||||
|
|
||||||
bool isChrome = false;
|
bool isChrome = false;
|
||||||
if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
|
if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
|
||||||
nsAutoCString spec;
|
|
||||||
if (mDocumentURI)
|
|
||||||
mDocumentURI->GetSpec(spec);
|
|
||||||
|
|
||||||
nsAutoString error;
|
nsAutoString error;
|
||||||
error.AssignLiteral("Cross site loading using document.load is no "
|
error.AssignLiteral("Cross site loading using document.load is no "
|
||||||
|
@ -353,14 +350,15 @@ XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = errorObject->InitWithWindowID(error,
|
rv = errorObject->InitWithSourceURI(error,
|
||||||
NS_ConvertUTF8toUTF16(spec),
|
mDocumentURI,
|
||||||
EmptyString(),
|
EmptyString(),
|
||||||
0, 0, nsIScriptError::warningFlag,
|
0, 0,
|
||||||
"DOM",
|
nsIScriptError::warningFlag,
|
||||||
callingDoc ?
|
"DOM",
|
||||||
callingDoc->InnerWindowID() :
|
callingDoc ?
|
||||||
this->InnerWindowID());
|
callingDoc->InnerWindowID() :
|
||||||
|
this->InnerWindowID());
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
aRv.Throw(rv);
|
aRv.Throw(rv);
|
||||||
|
|
|
@ -57,7 +57,6 @@ static const char* sEGLExtensionNames[] = {
|
||||||
"EGL_KHR_create_context",
|
"EGL_KHR_create_context",
|
||||||
"EGL_KHR_stream",
|
"EGL_KHR_stream",
|
||||||
"EGL_KHR_stream_consumer_gltexture",
|
"EGL_KHR_stream_consumer_gltexture",
|
||||||
"EGL_EXT_device_base",
|
|
||||||
"EGL_EXT_device_query",
|
"EGL_EXT_device_query",
|
||||||
"EGL_NV_stream_consumer_gltexture_yuv",
|
"EGL_NV_stream_consumer_gltexture_yuv",
|
||||||
"EGL_ANGLE_stream_producer_d3d_texture_nv12",
|
"EGL_ANGLE_stream_producer_d3d_texture_nv12",
|
||||||
|
@ -627,19 +626,9 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsExtensionSupported(EXT_device_base)) {
|
|
||||||
const GLLibraryLoader::SymLoadStruct deviceBaseSymbols[] = {
|
|
||||||
SYMBOL(QueryDisplayAttribEXT),
|
|
||||||
END_OF_SYMBOLS
|
|
||||||
};
|
|
||||||
if (!fnLoadSymbols(deviceBaseSymbols)) {
|
|
||||||
NS_ERROR("EGL supports EXT_device_base without exposing its functions!");
|
|
||||||
MarkExtensionUnsupported(EXT_device_base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsExtensionSupported(EXT_device_query)) {
|
if (IsExtensionSupported(EXT_device_query)) {
|
||||||
const GLLibraryLoader::SymLoadStruct queryDisplaySymbols[] = {
|
const GLLibraryLoader::SymLoadStruct queryDisplaySymbols[] = {
|
||||||
|
SYMBOL(QueryDisplayAttribEXT),
|
||||||
SYMBOL(QueryDeviceAttribEXT),
|
SYMBOL(QueryDeviceAttribEXT),
|
||||||
END_OF_SYMBOLS
|
END_OF_SYMBOLS
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,7 +108,6 @@ public:
|
||||||
KHR_create_context,
|
KHR_create_context,
|
||||||
KHR_stream,
|
KHR_stream,
|
||||||
KHR_stream_consumer_gltexture,
|
KHR_stream_consumer_gltexture,
|
||||||
EXT_device_base,
|
|
||||||
EXT_device_query,
|
EXT_device_query,
|
||||||
NV_stream_consumer_gltexture_yuv,
|
NV_stream_consumer_gltexture_yuv,
|
||||||
ANGLE_stream_producer_d3d_texture_nv12,
|
ANGLE_stream_producer_d3d_texture_nv12,
|
||||||
|
@ -292,8 +291,8 @@ public:
|
||||||
EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) const
|
EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) const
|
||||||
WRAP( fCreateStreamKHR(dpy, attrib_list) )
|
WRAP( fCreateStreamKHR(dpy, attrib_list) )
|
||||||
|
|
||||||
EGLStreamKHR fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const
|
EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const
|
||||||
WRAP( fDestroyStreamKHR(dpy, stream) )
|
WRAP( fDestroyStreamKHR(dpy, stream) )
|
||||||
|
|
||||||
EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint* value) const
|
EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint* value) const
|
||||||
WRAP( fQueryStreamKHR(dpy, stream, attribute, value) )
|
WRAP( fQueryStreamKHR(dpy, stream, attribute, value) )
|
||||||
|
@ -305,11 +304,10 @@ public:
|
||||||
EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) const
|
EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) const
|
||||||
WRAP( fStreamConsumerReleaseKHR(dpy, stream) )
|
WRAP( fStreamConsumerReleaseKHR(dpy, stream) )
|
||||||
|
|
||||||
// EXT_device_base
|
// EXT_device_query
|
||||||
EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib* value) const
|
EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib* value) const
|
||||||
WRAP( fQueryDisplayAttribEXT(dpy, attribute, value) )
|
WRAP( fQueryDisplayAttribEXT(dpy, attribute, value) )
|
||||||
|
|
||||||
// EXT_device_query
|
|
||||||
EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib* value) const
|
EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib* value) const
|
||||||
WRAP( fQueryDeviceAttribEXT(device, attribute, value) )
|
WRAP( fQueryDeviceAttribEXT(device, attribute, value) )
|
||||||
|
|
||||||
|
@ -454,7 +452,7 @@ private:
|
||||||
EGLint (GLAPIENTRY * fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
|
EGLint (GLAPIENTRY * fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
|
||||||
//KHR_stream
|
//KHR_stream
|
||||||
EGLStreamKHR (GLAPIENTRY * fCreateStreamKHR)(EGLDisplay dpy, const EGLint* attrib_list);
|
EGLStreamKHR (GLAPIENTRY * fCreateStreamKHR)(EGLDisplay dpy, const EGLint* attrib_list);
|
||||||
EGLStreamKHR (GLAPIENTRY * fDestroyStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream);
|
EGLBoolean (GLAPIENTRY * fDestroyStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream);
|
||||||
EGLBoolean (GLAPIENTRY * fQueryStreamKHR)(EGLDisplay dpy,
|
EGLBoolean (GLAPIENTRY * fQueryStreamKHR)(EGLDisplay dpy,
|
||||||
EGLStreamKHR stream,
|
EGLStreamKHR stream,
|
||||||
EGLenum attribute,
|
EGLenum attribute,
|
||||||
|
@ -464,11 +462,10 @@ private:
|
||||||
EGLStreamKHR stream);
|
EGLStreamKHR stream);
|
||||||
EGLBoolean (GLAPIENTRY * fStreamConsumerReleaseKHR)(EGLDisplay dpy,
|
EGLBoolean (GLAPIENTRY * fStreamConsumerReleaseKHR)(EGLDisplay dpy,
|
||||||
EGLStreamKHR stream);
|
EGLStreamKHR stream);
|
||||||
// EXT_device_base
|
// EXT_device_query
|
||||||
EGLBoolean (GLAPIENTRY * fQueryDisplayAttribEXT)(EGLDisplay dpy,
|
EGLBoolean (GLAPIENTRY * fQueryDisplayAttribEXT)(EGLDisplay dpy,
|
||||||
EGLint attribute,
|
EGLint attribute,
|
||||||
EGLAttrib* value);
|
EGLAttrib* value);
|
||||||
// EXT_device_query
|
|
||||||
EGLBoolean (GLAPIENTRY * fQueryDeviceAttribEXT)(EGLDeviceEXT device,
|
EGLBoolean (GLAPIENTRY * fQueryDeviceAttribEXT)(EGLDeviceEXT device,
|
||||||
EGLint attribute,
|
EGLint attribute,
|
||||||
EGLAttrib* value);
|
EGLAttrib* value);
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "SyncObject.h"
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
#include "mozilla/layers/TextureD3D11.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
already_AddRefed<SyncObjectHost>
|
||||||
|
SyncObjectHost::CreateSyncObjectHost(
|
||||||
|
#ifdef XP_WIN
|
||||||
|
ID3D11Device* aDevice
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#ifdef XP_WIN
|
||||||
|
return MakeAndAddRef<SyncObjectD3D11Host>(aDevice);
|
||||||
|
#else
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<SyncObjectClient>
|
||||||
|
SyncObjectClient::CreateSyncObjectClient(SyncHandle aHandle
|
||||||
|
#ifdef XP_WIN
|
||||||
|
, ID3D11Device* aDevice
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!aHandle) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
return MakeAndAddRef<SyncObjectD3D11Client>(aHandle, aDevice);
|
||||||
|
#else
|
||||||
|
MOZ_ASSERT_UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef MOZILLA_GFX_LAYERS_SYNCOBJECT_H
|
||||||
|
#define MOZILLA_GFX_LAYERS_SYNCOBJECT_H
|
||||||
|
|
||||||
|
#include "mozilla/RefCounted.h"
|
||||||
|
|
||||||
|
struct ID3D11Device;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
typedef void* SyncHandle;
|
||||||
|
#else
|
||||||
|
typedef uintptr_t SyncHandle;
|
||||||
|
#endif // XP_WIN
|
||||||
|
|
||||||
|
class SyncObjectHost : public RefCounted<SyncObjectHost>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectHost)
|
||||||
|
virtual ~SyncObjectHost() { }
|
||||||
|
|
||||||
|
static already_AddRefed<SyncObjectHost> CreateSyncObjectHost(
|
||||||
|
#ifdef XP_WIN
|
||||||
|
ID3D11Device* aDevice = nullptr
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual bool Init() = 0;
|
||||||
|
|
||||||
|
virtual SyncHandle GetSyncHandle() = 0;
|
||||||
|
|
||||||
|
virtual bool Synchronize() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SyncObjectHost() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class SyncObjectClient : public RefCounted<SyncObjectClient>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectClient)
|
||||||
|
virtual ~SyncObjectClient() { }
|
||||||
|
|
||||||
|
static already_AddRefed<SyncObjectClient> CreateSyncObjectClient(SyncHandle aHandle
|
||||||
|
#ifdef XP_WIN
|
||||||
|
, ID3D11Device* aDevice = nullptr
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
enum class SyncType {
|
||||||
|
D3D11,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual SyncType GetSyncType() = 0;
|
||||||
|
|
||||||
|
virtual void Synchronize() = 0;
|
||||||
|
|
||||||
|
virtual bool IsSyncObjectValid() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SyncObjectClient() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif //MOZILLA_GFX_LAYERS_SYNCOBJECT_H
|
|
@ -20,6 +20,7 @@
|
||||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||||
#include "mozilla/layers/LayerTransactionChild.h"
|
#include "mozilla/layers/LayerTransactionChild.h"
|
||||||
#include "mozilla/layers/PersistentBufferProvider.h"
|
#include "mozilla/layers/PersistentBufferProvider.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include "ClientReadbackLayer.h" // for ClientReadbackLayer
|
#include "ClientReadbackLayer.h" // for ClientReadbackLayer
|
||||||
#include "nsAString.h"
|
#include "nsAString.h"
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
|
@ -728,7 +729,7 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
|
||||||
if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
|
if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
|
||||||
if (mForwarder->GetSyncObject() &&
|
if (mForwarder->GetSyncObject() &&
|
||||||
mForwarder->GetSyncObject()->IsSyncObjectValid()) {
|
mForwarder->GetSyncObject()->IsSyncObjectValid()) {
|
||||||
mForwarder->GetSyncObject()->FinalizeFrame();
|
mForwarder->GetSyncObject()->Synchronize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1745,25 +1745,6 @@ UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<SyncObject>
|
|
||||||
SyncObject::CreateSyncObject(SyncHandle aHandle
|
|
||||||
#ifdef XP_WIN
|
|
||||||
, ID3D11Device* aDevice
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!aHandle) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef XP_WIN
|
|
||||||
return MakeAndAddRef<SyncObjectD3D11>(aHandle, aDevice);
|
|
||||||
#else
|
|
||||||
MOZ_ASSERT_UNREACHABLE();
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<TextureClient>
|
already_AddRefed<TextureClient>
|
||||||
TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
|
TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,6 +66,7 @@ class TextureClientPool;
|
||||||
#endif
|
#endif
|
||||||
class TextureForwarder;
|
class TextureForwarder;
|
||||||
class KeepAlive;
|
class KeepAlive;
|
||||||
|
class SyncObjectClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TextureClient is the abstraction that allows us to share data between the
|
* TextureClient is the abstraction that allows us to share data between the
|
||||||
|
@ -93,36 +94,6 @@ enum TextureAllocationFlags {
|
||||||
ALLOC_UPDATE_FROM_SURFACE = 1 << 7,
|
ALLOC_UPDATE_FROM_SURFACE = 1 << 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef XP_WIN
|
|
||||||
typedef void* SyncHandle;
|
|
||||||
#else
|
|
||||||
typedef uintptr_t SyncHandle;
|
|
||||||
#endif // XP_WIN
|
|
||||||
|
|
||||||
class SyncObject : public RefCounted<SyncObject>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObject)
|
|
||||||
virtual ~SyncObject() { }
|
|
||||||
|
|
||||||
static already_AddRefed<SyncObject> CreateSyncObject(SyncHandle aHandle
|
|
||||||
#ifdef XP_WIN
|
|
||||||
, ID3D11Device* aDevice = nullptr
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
enum class SyncType {
|
|
||||||
D3D11,
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual SyncType GetSyncType() = 0;
|
|
||||||
virtual void FinalizeFrame() = 0;
|
|
||||||
virtual bool IsSyncObjectValid() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SyncObject() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class may be used to asynchronously receive an update when the content
|
* This class may be used to asynchronously receive an update when the content
|
||||||
* drawn to this texture client is available for reading in CPU memory. This
|
* drawn to this texture client is available for reading in CPU memory. This
|
||||||
|
@ -305,7 +276,7 @@ public:
|
||||||
|
|
||||||
virtual bool ReadBack(TextureReadbackSink* aReadbackSink) { return false; }
|
virtual bool ReadBack(TextureReadbackSink* aReadbackSink) { return false; }
|
||||||
|
|
||||||
virtual void SyncWithObject(SyncObject* aFence) {};
|
virtual void SyncWithObject(SyncObjectClient* aSyncObject) {};
|
||||||
|
|
||||||
virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
|
virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
|
||||||
|
|
||||||
|
@ -614,7 +585,7 @@ public:
|
||||||
mReadbackSink = aReadbackSink;
|
mReadbackSink = aReadbackSink;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyncWithObject(SyncObject* aFence) { mData->SyncWithObject(aFence); }
|
void SyncWithObject(SyncObjectClient* aSyncObject) { mData->SyncWithObject(aSyncObject); }
|
||||||
|
|
||||||
LayersIPCChannel* GetAllocator() { return mAllocator; }
|
LayersIPCChannel* GetAllocator() { return mAllocator; }
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,9 @@ CompositorD3D11::GetTextureFactoryIdentifier()
|
||||||
ident.mMaxTextureSize = GetMaxTextureSize();
|
ident.mMaxTextureSize = GetMaxTextureSize();
|
||||||
ident.mParentProcessType = XRE_GetProcessType();
|
ident.mParentProcessType = XRE_GetProcessType();
|
||||||
ident.mParentBackend = LayersBackend::LAYERS_D3D11;
|
ident.mParentBackend = LayersBackend::LAYERS_D3D11;
|
||||||
ident.mSyncHandle = mAttachments->mSyncHandle;
|
if (mAttachments->mSyncObject) {
|
||||||
|
ident.mSyncHandle = mAttachments->mSyncObject->GetSyncHandle();
|
||||||
|
}
|
||||||
return ident;
|
return ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1057,29 +1059,12 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||||
|
|
||||||
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
|
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
|
||||||
|
|
||||||
if (mAttachments->mSyncTexture) {
|
if (mAttachments->mSyncObject) {
|
||||||
RefPtr<IDXGIKeyedMutex> mutex;
|
if (!mAttachments->mSyncObject->Synchronize()) {
|
||||||
mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
|
// It's timeout here. Since the timeout is related to the driver-removed,
|
||||||
|
// clear the render-bounding size to skip this frame.
|
||||||
MOZ_ASSERT(mutex);
|
*aRenderBoundsOut = IntRect();
|
||||||
{
|
return;
|
||||||
HRESULT hr;
|
|
||||||
AutoTextureLock lock(mutex, hr, 10000);
|
|
||||||
if (hr == WAIT_TIMEOUT) {
|
|
||||||
hr = mDevice->GetDeviceRemovedReason();
|
|
||||||
if (hr == S_OK) {
|
|
||||||
// There is no driver-removed event. Crash with this timeout.
|
|
||||||
MOZ_CRASH("GFX: D3D11 normal status timeout");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since the timeout is related to the driver-removed, clear the
|
|
||||||
// render-bounding size to skip this frame.
|
|
||||||
gfxCriticalNote << "GFX: D3D11 timeout with device-removed:" << gfx::hexa(hr);
|
|
||||||
*aRenderBoundsOut = IntRect();
|
|
||||||
return;
|
|
||||||
} else if (hr == WAIT_ABANDONED) {
|
|
||||||
gfxCriticalNote << "GFX: D3D11 abandoned sync";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,8 +1163,9 @@ CompositorD3D11::Present()
|
||||||
HRESULT hr = mSwapChain->QueryInterface((IDXGISwapChain1**)getter_AddRefs(chain));
|
HRESULT hr = mSwapChain->QueryInterface((IDXGISwapChain1**)getter_AddRefs(chain));
|
||||||
|
|
||||||
RefPtr<IDXGIKeyedMutex> mutex;
|
RefPtr<IDXGIKeyedMutex> mutex;
|
||||||
if (mUseMutexOnPresent && mAttachments->mSyncTexture) {
|
if (mUseMutexOnPresent && mAttachments->mSyncObject) {
|
||||||
mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
|
SyncObjectD3D11Host* d3dSyncObj = (SyncObjectD3D11Host*)mAttachments->mSyncObject.get();
|
||||||
|
mutex = d3dSyncObj->GetKeyedMutex();
|
||||||
MOZ_ASSERT(mutex);
|
MOZ_ASSERT(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,7 @@ using namespace gfx;
|
||||||
static const size_t kInitialMaximumTriangles = 64;
|
static const size_t kInitialMaximumTriangles = 64;
|
||||||
|
|
||||||
DeviceAttachmentsD3D11::DeviceAttachmentsD3D11(ID3D11Device* device)
|
DeviceAttachmentsD3D11::DeviceAttachmentsD3D11(ID3D11Device* device)
|
||||||
: mSyncHandle(0),
|
: mMaximumTriangles(kInitialMaximumTriangles),
|
||||||
mMaximumTriangles(kInitialMaximumTriangles),
|
|
||||||
mDevice(device),
|
mDevice(device),
|
||||||
mContinueInit(true),
|
mContinueInit(true),
|
||||||
mInitialized(false),
|
mInitialized(false),
|
||||||
|
@ -225,36 +224,13 @@ DeviceAttachmentsD3D11::InitSyncObject()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's okay to do this on Windows 8. But for now we'll just bail
|
MOZ_ASSERT(!mSyncObject);
|
||||||
// whenever we're using WARP.
|
MOZ_ASSERT(mDevice);
|
||||||
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1,
|
|
||||||
D3D11_BIND_SHADER_RESOURCE |
|
|
||||||
D3D11_BIND_RENDER_TARGET);
|
|
||||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
|
||||||
|
|
||||||
RefPtr<ID3D11Texture2D> texture;
|
mSyncObject = SyncObjectHost::CreateSyncObjectHost(mDevice);
|
||||||
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
|
MOZ_ASSERT(mSyncObject);
|
||||||
if (Failed(hr, "create sync texture")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
|
return mSyncObject->Init();
|
||||||
if (Failed(hr, "QI sync texture")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = mSyncTexture->GetSharedHandle(&mSyncHandle);
|
|
||||||
if (FAILED(hr) || !mSyncHandle) {
|
|
||||||
gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: "
|
|
||||||
<< hexa(hr);
|
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction("DeviceAttachmentsD3D11::InitSyncObject",
|
|
||||||
[] () -> void {
|
|
||||||
Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1);
|
|
||||||
}));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||||
#include "mozilla/layers/CompositorTypes.h"
|
#include "mozilla/layers/CompositorTypes.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
#include <dxgi1_2.h>
|
#include <dxgi1_2.h>
|
||||||
|
|
||||||
|
@ -70,8 +71,8 @@ public:
|
||||||
RefPtr<ID3D11BlendState> mNonPremulBlendState;
|
RefPtr<ID3D11BlendState> mNonPremulBlendState;
|
||||||
RefPtr<ID3D11BlendState> mComponentBlendState;
|
RefPtr<ID3D11BlendState> mComponentBlendState;
|
||||||
RefPtr<ID3D11BlendState> mDisabledBlendState;
|
RefPtr<ID3D11BlendState> mDisabledBlendState;
|
||||||
RefPtr<IDXGIResource> mSyncTexture;
|
|
||||||
HANDLE mSyncHandle;
|
RefPtr<SyncObjectHost> mSyncObject;
|
||||||
|
|
||||||
void SetDeviceReset() {
|
void SetDeviceReset() {
|
||||||
mDeviceReset = true;
|
mDeviceReset = true;
|
||||||
|
|
|
@ -1264,7 +1264,11 @@ MLGDeviceD3D11::GetTextureFactoryIdentifier() const
|
||||||
GetLayersBackend(),
|
GetLayersBackend(),
|
||||||
XRE_GetProcessType(),
|
XRE_GetProcessType(),
|
||||||
GetMaxTextureSize());
|
GetMaxTextureSize());
|
||||||
ident.mSyncHandle = mSyncHandle;
|
|
||||||
|
if (mSyncObject) {
|
||||||
|
ident.mSyncHandle = mSyncObject->GetSyncHandle();
|
||||||
|
}
|
||||||
|
|
||||||
return ident;
|
return ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1777,34 +1781,13 @@ MLGDeviceD3D11::SetPSTexturesNV12(uint32_t aSlot, TextureSource* aTexture)
|
||||||
bool
|
bool
|
||||||
MLGDeviceD3D11::InitSyncObject()
|
MLGDeviceD3D11::InitSyncObject()
|
||||||
{
|
{
|
||||||
CD3D11_TEXTURE2D_DESC desc(
|
MOZ_ASSERT(!mSyncObject);
|
||||||
DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1,
|
MOZ_ASSERT(mDevice);
|
||||||
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
|
||||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
|
||||||
|
|
||||||
RefPtr<ID3D11Texture2D> texture;
|
mSyncObject = SyncObjectHost::CreateSyncObjectHost(mDevice);
|
||||||
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
|
MOZ_ASSERT(mSyncObject);
|
||||||
if (FAILED(hr) || !texture) {
|
|
||||||
return Fail("FEATURE_FAILURE_SYNC_OBJECT",
|
|
||||||
"Could not create a sync texture: %x", hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
|
return mSyncObject->Init();
|
||||||
if (FAILED(hr) || !texture) {
|
|
||||||
return Fail("FEATURE_FAILURE_QI_SYNC_OBJECT",
|
|
||||||
"Could not QI sync texture: %x", hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = mSyncTexture->GetSharedHandle(&mSyncHandle);
|
|
||||||
if (FAILED(hr) || !mSyncHandle) {
|
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction("layers::MLGDeviceD3D11::InitSyncObject",
|
|
||||||
[] () -> void {
|
|
||||||
Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1);
|
|
||||||
}));
|
|
||||||
return Fail("FEATURE_FAILURE_GET_SHARED_HANDLE",
|
|
||||||
"Could not get sync texture shared handle: %x", hr);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1828,27 +1811,14 @@ MLGDeviceD3D11::GetDiagnostics(GPUStats* aStats)
|
||||||
bool
|
bool
|
||||||
MLGDeviceD3D11::Synchronize()
|
MLGDeviceD3D11::Synchronize()
|
||||||
{
|
{
|
||||||
RefPtr<IDXGIKeyedMutex> mutex;
|
MOZ_ASSERT(mSyncObject);
|
||||||
mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
|
|
||||||
|
|
||||||
{
|
if (mSyncObject) {
|
||||||
HRESULT hr;
|
if (!mSyncObject->Synchronize()) {
|
||||||
AutoTextureLock lock(mutex, hr, 10000);
|
// It's timeout or other error. Handle the device-reset here.
|
||||||
if (hr == WAIT_TIMEOUT) {
|
|
||||||
hr = mDevice->GetDeviceRemovedReason();
|
|
||||||
if (hr == S_OK) {
|
|
||||||
// There is no driver-removed event. Crash with this timeout.
|
|
||||||
MOZ_CRASH("GFX: D3D11 normal status timeout");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since the timeout is related to the driver-removed, clear the
|
|
||||||
// render-bounding size to skip this frame.
|
|
||||||
HandleDeviceReset("SyncObject");
|
HandleDeviceReset("SyncObject");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (hr == WAIT_ABANDONED) {
|
|
||||||
gfxCriticalNote << "GFX: AL_D3D11 abandoned sync";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
#ifndef mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
|
#ifndef mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
|
||||||
#define mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
|
#define mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
|
||||||
|
|
||||||
|
#include <d3d11_1.h>
|
||||||
|
|
||||||
#include "mozilla/layers/MLGDevice.h"
|
#include "mozilla/layers/MLGDevice.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include "mozilla/EnumeratedArray.h"
|
#include "mozilla/EnumeratedArray.h"
|
||||||
#include "nsTHashtable.h"
|
#include "nsTHashtable.h"
|
||||||
#include <d3d11_1.h>
|
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -305,8 +307,7 @@ private:
|
||||||
RefPtr<ID3D11RasterizerState> mRasterizerStateNoScissor;
|
RefPtr<ID3D11RasterizerState> mRasterizerStateNoScissor;
|
||||||
RefPtr<ID3D11RasterizerState> mRasterizerStateScissor;
|
RefPtr<ID3D11RasterizerState> mRasterizerStateScissor;
|
||||||
|
|
||||||
RefPtr<IDXGIResource> mSyncTexture;
|
RefPtr<SyncObjectHost> mSyncObject;
|
||||||
HANDLE mSyncHandle;
|
|
||||||
|
|
||||||
RefPtr<MLGBuffer> mUnitQuadVB;
|
RefPtr<MLGBuffer> mUnitQuadVB;
|
||||||
RefPtr<MLGBuffer> mUnitTriangleVB;
|
RefPtr<MLGBuffer> mUnitTriangleVB;
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "mozilla/gfx/gfxVars.h"
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
#include "mozilla/gfx/Logging.h"
|
#include "mozilla/gfx/Logging.h"
|
||||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||||
|
#include "mozilla/webrender/RenderD3D11TextureHostOGL.h"
|
||||||
|
#include "mozilla/webrender/RenderThread.h"
|
||||||
#include "mozilla/webrender/WebRenderAPI.h"
|
#include "mozilla/webrender/WebRenderAPI.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -355,15 +357,15 @@ DXGITextureData::FillInfo(TextureData::Info& aInfo) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
D3D11TextureData::SyncWithObject(SyncObject* aSyncObject)
|
D3D11TextureData::SyncWithObject(SyncObjectClient* aSyncObject)
|
||||||
{
|
{
|
||||||
if (!aSyncObject || mHasSynchronization) {
|
if (!aSyncObject || mHasSynchronization) {
|
||||||
// When we have per texture synchronization we sync using the keyed mutex.
|
// When we have per texture synchronization we sync using the keyed mutex.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
|
MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObjectClient::SyncType::D3D11);
|
||||||
SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
|
SyncObjectD3D11Client* sync = static_cast<SyncObjectD3D11Client*>(aSyncObject);
|
||||||
sync->RegisterTexture(mTexture);
|
sync->RegisterTexture(mTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -967,11 +969,42 @@ DXGITextureHostD3D11::AcquireTextureSource(CompositableTextureSourceRef& aTextur
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DXGITextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
|
||||||
|
{
|
||||||
|
RefPtr<wr::RenderTextureHost> texture =
|
||||||
|
new wr::RenderDXGITextureHostOGL(mHandle, mFormat, mSize);
|
||||||
|
|
||||||
|
wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DXGITextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
DXGITextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||||
const std::function<wr::ImageKey()>& aImageKeyAllocator)
|
const std::function<wr::ImageKey()>& aImageKeyAllocator)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this DXGITextureHostD3D11 type.");
|
MOZ_ASSERT(aImageKeys.IsEmpty());
|
||||||
|
|
||||||
|
switch (GetFormat()) {
|
||||||
|
case gfx::SurfaceFormat::R8G8B8X8:
|
||||||
|
case gfx::SurfaceFormat::R8G8B8A8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8A8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8X8: {
|
||||||
|
// 1 image key
|
||||||
|
aImageKeys.AppendElement(aImageKeyAllocator());
|
||||||
|
MOZ_ASSERT(aImageKeys.Length() == 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gfx::SurfaceFormat::NV12: {
|
||||||
|
// 2 image key
|
||||||
|
aImageKeys.AppendElement(aImageKeyAllocator());
|
||||||
|
aImageKeys.AppendElement(aImageKeyAllocator());
|
||||||
|
MOZ_ASSERT(aImageKeys.Length() == 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -979,7 +1012,44 @@ DXGITextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
|
||||||
Range<const wr::ImageKey>& aImageKeys,
|
Range<const wr::ImageKey>& aImageKeys,
|
||||||
const wr::ExternalImageId& aExtID)
|
const wr::ExternalImageId& aExtID)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this DXGITextureHostD3D11 type.");
|
MOZ_ASSERT(mHandle);
|
||||||
|
|
||||||
|
switch (mFormat) {
|
||||||
|
case gfx::SurfaceFormat::R8G8B8X8:
|
||||||
|
case gfx::SurfaceFormat::R8G8B8A8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8A8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8X8: {
|
||||||
|
MOZ_ASSERT(aImageKeys.length() == 1);
|
||||||
|
|
||||||
|
wr::ImageDescriptor descriptor(GetSize(), GetFormat());
|
||||||
|
aAPI->AddExternalImage(aImageKeys[0],
|
||||||
|
descriptor,
|
||||||
|
aExtID,
|
||||||
|
wr::WrExternalImageBufferType::Texture2DHandle,
|
||||||
|
0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gfx::SurfaceFormat::NV12: {
|
||||||
|
MOZ_ASSERT(aImageKeys.length() == 2);
|
||||||
|
|
||||||
|
wr::ImageDescriptor descriptor0(GetSize(), gfx::SurfaceFormat::A8);
|
||||||
|
wr::ImageDescriptor descriptor1(GetSize() / 2, gfx::SurfaceFormat::R8G8);
|
||||||
|
aAPI->AddExternalImage(aImageKeys[0],
|
||||||
|
descriptor0,
|
||||||
|
aExtID,
|
||||||
|
wr::WrExternalImageBufferType::TextureExternalHandle,
|
||||||
|
0);
|
||||||
|
aAPI->AddExternalImage(aImageKeys[1],
|
||||||
|
descriptor1,
|
||||||
|
aExtID,
|
||||||
|
wr::WrExternalImageBufferType::TextureExternalHandle,
|
||||||
|
1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -989,7 +1059,29 @@ DXGITextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
|
||||||
wr::ImageRendering aFilter,
|
wr::ImageRendering aFilter,
|
||||||
Range<const wr::ImageKey>& aImageKeys)
|
Range<const wr::ImageKey>& aImageKeys)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT_UNREACHABLE("No PushExternalImage() implementation for this DXGITextureHostD3D11 type.");
|
switch (GetFormat()) {
|
||||||
|
case gfx::SurfaceFormat::R8G8B8X8:
|
||||||
|
case gfx::SurfaceFormat::R8G8B8A8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8A8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8X8: {
|
||||||
|
MOZ_ASSERT(aImageKeys.length() == 1);
|
||||||
|
aBuilder.PushImage(aBounds, aClip, aFilter, aImageKeys[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gfx::SurfaceFormat::NV12: {
|
||||||
|
MOZ_ASSERT(aImageKeys.length() == 2);
|
||||||
|
aBuilder.PushNV12Image(aBounds,
|
||||||
|
aClip,
|
||||||
|
aImageKeys[0],
|
||||||
|
aImageKeys[1],
|
||||||
|
wr::WrYuvColorSpace::Rec601,
|
||||||
|
aFilter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
|
DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
|
||||||
|
@ -1134,11 +1226,21 @@ DXGIYCbCrTextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aText
|
||||||
return !!aTexture;
|
return !!aTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
|
||||||
|
{
|
||||||
|
// We use AddImage() directly. It's no corresponding RenderTextureHost.
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||||
const std::function<wr::ImageKey()>& aImageKeyAllocator)
|
const std::function<wr::ImageKey()>& aImageKeyAllocator)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this DXGIYCbCrTextureHostD3D11 type.");
|
MOZ_ASSERT(aImageKeys.IsEmpty());
|
||||||
|
|
||||||
|
// 1 image key
|
||||||
|
aImageKeys.AppendElement(aImageKeyAllocator());
|
||||||
|
MOZ_ASSERT(aImageKeys.Length() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1146,7 +1248,30 @@ DXGIYCbCrTextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
|
||||||
Range<const wr::ImageKey>& aImageKeys,
|
Range<const wr::ImageKey>& aImageKeys,
|
||||||
const wr::ExternalImageId& aExtID)
|
const wr::ExternalImageId& aExtID)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this DXGIYCbCrTextureHostD3D11 type.");
|
MOZ_ASSERT(mTextures[0] && mTextures[1] && mTextures[2]);
|
||||||
|
MOZ_ASSERT(aImageKeys.length() == 1);
|
||||||
|
|
||||||
|
// There are 3 A8 channel data in DXGIYCbCrTextureHostD3D11, but ANGLE doesn't
|
||||||
|
// support for converting the D3D A8 texture to OpenGL texture handle. So, we
|
||||||
|
// use the DataSourceSurface to get the raw buffer and push that raw buffer
|
||||||
|
// into WR using AddImage().
|
||||||
|
NS_WARNING("WR doesn't support DXGIYCbCrTextureHostD3D11 directly. It's a slower path.");
|
||||||
|
|
||||||
|
RefPtr<DataSourceSurface> dataSourceSurface = GetAsSurface();
|
||||||
|
if (!dataSourceSurface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DataSourceSurface::MappedSurface map;
|
||||||
|
if (!dataSourceSurface->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntSize size = dataSourceSurface->GetSize();
|
||||||
|
wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat());
|
||||||
|
auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
|
||||||
|
aAPI->AddImage(aImageKeys[0], descriptor, slice);
|
||||||
|
|
||||||
|
dataSourceSurface->Unmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1156,7 +1281,9 @@ DXGIYCbCrTextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
|
||||||
wr::ImageRendering aFilter,
|
wr::ImageRendering aFilter,
|
||||||
Range<const wr::ImageKey>& aImageKeys)
|
Range<const wr::ImageKey>& aImageKeys)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT_UNREACHABLE("No PushExternalImage() implementation for this DXGIYCbCrTextureHostD3D11 type.");
|
// 1 image key
|
||||||
|
MOZ_ASSERT(aImageKeys.length() == 1);
|
||||||
|
aBuilder.PushImage(aBounds, aClip, aFilter, aImageKeys[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -1398,17 +1525,6 @@ CompositingRenderTargetD3D11::GetSize() const
|
||||||
return TextureSourceD3D11::GetSize();
|
return TextureSourceD3D11::GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncObjectD3D11::SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice)
|
|
||||||
: mSyncHandle(aSyncHandle)
|
|
||||||
{
|
|
||||||
if (!aDevice) {
|
|
||||||
mD3D11Device = DeviceManagerDx::Get()->GetContentDevice();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mD3D11Device = aDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
ShouldDevCrashOnSyncInitFailure()
|
ShouldDevCrashOnSyncInitFailure()
|
||||||
{
|
{
|
||||||
|
@ -1424,18 +1540,107 @@ ShouldDevCrashOnSyncInitFailure()
|
||||||
!DeviceManagerDx::Get()->HasDeviceReset();
|
!DeviceManagerDx::Get()->HasDeviceReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyncObjectD3D11Host::SyncObjectD3D11Host(ID3D11Device* aDevice)
|
||||||
|
: mSyncHandle(0)
|
||||||
|
, mDevice(aDevice)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aDevice);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SyncObjectD3D11::Init()
|
SyncObjectD3D11Host::Init()
|
||||||
|
{
|
||||||
|
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1,
|
||||||
|
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
||||||
|
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||||
|
|
||||||
|
RefPtr<ID3D11Texture2D> texture;
|
||||||
|
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
|
||||||
|
if (FAILED(hr) || !texture) {
|
||||||
|
gfxWarning() << "Could not create a sync texture: " << gfx::hexa(hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
|
||||||
|
if (FAILED(hr) || !mSyncTexture) {
|
||||||
|
gfxWarning() << "Could not QI sync texture: " << gfx::hexa(hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
|
||||||
|
if (FAILED(hr) || !mKeyedMutex) {
|
||||||
|
gfxWarning() << "Could not QI keyed-mutex: " << gfx::hexa(hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = mSyncTexture->GetSharedHandle(&mSyncHandle);
|
||||||
|
if (FAILED(hr) || !mSyncHandle) {
|
||||||
|
NS_DispatchToMainThread(NS_NewRunnableFunction("layers::SyncObjectD3D11Renderer::Init",
|
||||||
|
[] () -> void {
|
||||||
|
Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1);
|
||||||
|
}));
|
||||||
|
gfxWarning() << "Could not get sync texture shared handle: " << gfx::hexa(hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncHandle
|
||||||
|
SyncObjectD3D11Host::GetSyncHandle()
|
||||||
|
{
|
||||||
|
return mSyncHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SyncObjectD3D11Host::Synchronize()
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
AutoTextureLock lock(mKeyedMutex, hr, 10000);
|
||||||
|
|
||||||
|
if (hr == WAIT_TIMEOUT) {
|
||||||
|
hr = mDevice->GetDeviceRemovedReason();
|
||||||
|
if (hr == S_OK) {
|
||||||
|
// There is no driver-removed event. Crash with this timeout.
|
||||||
|
MOZ_CRASH("GFX: D3D11 normal status timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the timeout is related to the driver-removed. Return false for
|
||||||
|
// error handling.
|
||||||
|
gfxCriticalNote << "GFX: D3D11 timeout with device-removed:" << gfx::hexa(hr);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (hr == WAIT_ABANDONED) {
|
||||||
|
gfxCriticalNote << "GFX: AL_D3D11 abandoned sync";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice)
|
||||||
|
: mSyncHandle(aSyncHandle)
|
||||||
|
{
|
||||||
|
if (!aDevice) {
|
||||||
|
mDevice = DeviceManagerDx::Get()->GetContentDevice();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDevice = aDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SyncObjectD3D11Client::Init()
|
||||||
{
|
{
|
||||||
if (mKeyedMutex) {
|
if (mKeyedMutex) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = mD3D11Device->OpenSharedResource(
|
HRESULT hr = mDevice->OpenSharedResource(
|
||||||
mSyncHandle,
|
mSyncHandle,
|
||||||
__uuidof(ID3D11Texture2D),
|
__uuidof(ID3D11Texture2D),
|
||||||
(void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture));
|
(void**)(ID3D11Texture2D**)getter_AddRefs(mSyncTexture));
|
||||||
if (FAILED(hr) || !mD3D11Texture) {
|
if (FAILED(hr) || !mSyncTexture) {
|
||||||
gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr);
|
gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr);
|
||||||
if (ShouldDevCrashOnSyncInitFailure()) {
|
if (ShouldDevCrashOnSyncInitFailure()) {
|
||||||
gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
|
gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
|
||||||
|
@ -1443,10 +1648,10 @@ SyncObjectD3D11::Init()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = mD3D11Texture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
|
hr = mSyncTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
|
||||||
if (FAILED(hr) || !mKeyedMutex) {
|
if (FAILED(hr) || !mKeyedMutex) {
|
||||||
// Leave both the critical error and MOZ_CRASH for now; the critical error lets
|
// Leave both the critical error and MOZ_CRASH for now; the critical error lets
|
||||||
// us "save" the hr value. We will probably eventuall replace this with gfxDevCrash.
|
// us "save" the hr value. We will probably eventually replace this with gfxDevCrash.
|
||||||
gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
|
gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
|
||||||
MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
|
MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
|
||||||
}
|
}
|
||||||
|
@ -1455,25 +1660,25 @@ SyncObjectD3D11::Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SyncObjectD3D11::RegisterTexture(ID3D11Texture2D* aTexture)
|
SyncObjectD3D11Client::RegisterTexture(ID3D11Texture2D* aTexture)
|
||||||
{
|
{
|
||||||
mD3D11SyncedTextures.push_back(aTexture);
|
mSyncedTextures.push_back(aTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SyncObjectD3D11::IsSyncObjectValid()
|
SyncObjectD3D11Client::IsSyncObjectValid()
|
||||||
{
|
{
|
||||||
RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
|
RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
|
||||||
if (!dev || (NS_IsMainThread() && dev != mD3D11Device)) {
|
if (!dev || (NS_IsMainThread() && dev != mDevice)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SyncObjectD3D11::FinalizeFrame()
|
SyncObjectD3D11Client::Synchronize()
|
||||||
{
|
{
|
||||||
if (!mD3D11SyncedTextures.size()) {
|
if (!mSyncedTextures.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!Init()) {
|
if (!Init()) {
|
||||||
|
@ -1496,7 +1701,7 @@ SyncObjectD3D11::FinalizeFrame()
|
||||||
box.back = box.bottom = box.right = 1;
|
box.back = box.bottom = box.right = 1;
|
||||||
|
|
||||||
RefPtr<ID3D11Device> dev;
|
RefPtr<ID3D11Device> dev;
|
||||||
mD3D11Texture->GetDevice(getter_AddRefs(dev));
|
mSyncTexture->GetDevice(getter_AddRefs(dev));
|
||||||
|
|
||||||
if (dev == DeviceManagerDx::Get()->GetContentDevice()) {
|
if (dev == DeviceManagerDx::Get()->GetContentDevice()) {
|
||||||
if (DeviceManagerDx::Get()->HasDeviceReset()) {
|
if (DeviceManagerDx::Get()->HasDeviceReset()) {
|
||||||
|
@ -1504,7 +1709,7 @@ SyncObjectD3D11::FinalizeFrame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev != mD3D11Device) {
|
if (dev != mDevice) {
|
||||||
gfxWarning() << "Attempt to sync texture from invalid device.";
|
gfxWarning() << "Attempt to sync texture from invalid device.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1512,11 +1717,11 @@ SyncObjectD3D11::FinalizeFrame()
|
||||||
RefPtr<ID3D11DeviceContext> ctx;
|
RefPtr<ID3D11DeviceContext> ctx;
|
||||||
dev->GetImmediateContext(getter_AddRefs(ctx));
|
dev->GetImmediateContext(getter_AddRefs(ctx));
|
||||||
|
|
||||||
for (auto iter = mD3D11SyncedTextures.begin(); iter != mD3D11SyncedTextures.end(); iter++) {
|
for (auto iter = mSyncedTextures.begin(); iter != mSyncedTextures.end(); iter++) {
|
||||||
ctx->CopySubresourceRegion(mD3D11Texture, 0, 0, 0, 0, *iter, 0, &box);
|
ctx->CopySubresourceRegion(mSyncTexture, 0, 0, 0, 0, *iter, 0, &box);
|
||||||
}
|
}
|
||||||
|
|
||||||
mD3D11SyncedTextures.clear();
|
mSyncedTextures.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/layers/Compositor.h"
|
#include "mozilla/layers/Compositor.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include "mozilla/layers/TextureClient.h"
|
#include "mozilla/layers/TextureClient.h"
|
||||||
#include "mozilla/layers/TextureHost.h"
|
#include "mozilla/layers/TextureHost.h"
|
||||||
#include "gfxWindowsPlatform.h"
|
#include "gfxWindowsPlatform.h"
|
||||||
|
@ -89,7 +90,7 @@ public:
|
||||||
TextureFlags aFlags,
|
TextureFlags aFlags,
|
||||||
TextureAllocationFlags aAllocFlags) const override;
|
TextureAllocationFlags aAllocFlags) const override;
|
||||||
|
|
||||||
virtual void SyncWithObject(SyncObject* aSync) override;
|
virtual void SyncWithObject(SyncObjectClient* aSyncObject) override;
|
||||||
|
|
||||||
ID3D11Texture2D* GetD3D11Texture() { return mTexture; }
|
ID3D11Texture2D* GetD3D11Texture() { return mTexture; }
|
||||||
|
|
||||||
|
@ -323,6 +324,8 @@ public:
|
||||||
|
|
||||||
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
|
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
|
||||||
|
|
||||||
|
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
|
||||||
|
|
||||||
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||||
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
||||||
|
|
||||||
|
@ -384,6 +387,8 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
|
||||||
|
|
||||||
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||||
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
||||||
|
|
||||||
|
@ -436,26 +441,49 @@ private:
|
||||||
RefPtr<ID3D11RenderTargetView> mRTView;
|
RefPtr<ID3D11RenderTargetView> mRTView;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyncObjectD3D11 : public SyncObject
|
class SyncObjectD3D11Host : public SyncObjectHost
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice);
|
explicit SyncObjectD3D11Host(ID3D11Device* aDevice);
|
||||||
virtual void FinalizeFrame();
|
|
||||||
virtual bool IsSyncObjectValid();
|
|
||||||
|
|
||||||
virtual SyncType GetSyncType() { return SyncType::D3D11; }
|
virtual bool Init() override;
|
||||||
|
|
||||||
|
virtual SyncHandle GetSyncHandle() override;
|
||||||
|
|
||||||
|
virtual bool Synchronize() override;
|
||||||
|
|
||||||
|
IDXGIKeyedMutex* GetKeyedMutex() { return mKeyedMutex.get(); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~SyncObjectD3D11Host() { }
|
||||||
|
|
||||||
|
SyncHandle mSyncHandle;
|
||||||
|
RefPtr<ID3D11Device> mDevice;
|
||||||
|
RefPtr<IDXGIResource> mSyncTexture;
|
||||||
|
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SyncObjectD3D11Client : public SyncObjectClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice);
|
||||||
|
|
||||||
|
virtual void Synchronize() override;
|
||||||
|
|
||||||
|
virtual bool IsSyncObjectValid() override;
|
||||||
|
|
||||||
|
virtual SyncType GetSyncType() override { return SyncType::D3D11; }
|
||||||
|
|
||||||
void RegisterTexture(ID3D11Texture2D* aTexture);
|
void RegisterTexture(ID3D11Texture2D* aTexture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Init();
|
bool Init();
|
||||||
|
|
||||||
private:
|
|
||||||
SyncHandle mSyncHandle;
|
SyncHandle mSyncHandle;
|
||||||
RefPtr<ID3D11Device> mD3D11Device;
|
RefPtr<ID3D11Device> mDevice;
|
||||||
RefPtr<ID3D11Texture2D> mD3D11Texture;
|
RefPtr<ID3D11Texture2D> mSyncTexture;
|
||||||
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
||||||
std::vector<ID3D11Texture2D*> mD3D11SyncedTextures;
|
std::vector<ID3D11Texture2D*> mSyncedTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)
|
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class SyncObject;
|
class SyncObjectClient;
|
||||||
class TextureForwarder;
|
class TextureForwarder;
|
||||||
class LayersIPCActor;
|
class LayersIPCActor;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
|
void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
|
||||||
|
|
||||||
SyncObject* GetSyncObject() { return mSyncObject; }
|
SyncObjectClient* GetSyncObject() { return mSyncObject; }
|
||||||
|
|
||||||
int32_t GetMaxTextureSize() const
|
int32_t GetMaxTextureSize() const
|
||||||
{
|
{
|
||||||
|
@ -86,7 +86,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TextureFactoryIdentifier mTextureFactoryIdentifier;
|
TextureFactoryIdentifier mTextureFactoryIdentifier;
|
||||||
RefPtr<SyncObject> mSyncObject;
|
RefPtr<SyncObjectClient> mSyncObject;
|
||||||
|
|
||||||
const int32_t mSerial;
|
const int32_t mSerial;
|
||||||
static mozilla::Atomic<int32_t> sSerialCounter;
|
static mozilla::Atomic<int32_t> sSerialCounter;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
|
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
|
||||||
#include "mozilla/layers/LayerTransactionChild.h"
|
#include "mozilla/layers/LayerTransactionChild.h"
|
||||||
#include "mozilla/layers/PTextureChild.h"
|
#include "mozilla/layers/PTextureChild.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include "ShadowLayerUtils.h"
|
#include "ShadowLayerUtils.h"
|
||||||
#include "mozilla/layers/TextureClient.h" // for TextureClient
|
#include "mozilla/layers/TextureClient.h" // for TextureClient
|
||||||
#include "mozilla/mozalloc.h" // for operator new, etc
|
#include "mozilla/mozalloc.h" // for operator new, etc
|
||||||
|
@ -175,7 +176,7 @@ KnowsCompositor::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier
|
||||||
{
|
{
|
||||||
mTextureFactoryIdentifier = aIdentifier;
|
mTextureFactoryIdentifier = aIdentifier;
|
||||||
|
|
||||||
mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
|
mSyncObject = SyncObjectClient::CreateSyncObjectClient(aIdentifier.mSyncHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
KnowsCompositor::KnowsCompositor()
|
KnowsCompositor::KnowsCompositor()
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "mozilla/gfx/Point.h"
|
#include "mozilla/gfx/Point.h"
|
||||||
#include "mozilla/gfx/Types.h"
|
#include "mozilla/gfx/Types.h"
|
||||||
#include "MaskOperation.h"
|
#include "MaskOperation.h"
|
||||||
|
#include "MLGDevice.h"
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "nsRefPtrHashtable.h"
|
#include "nsRefPtrHashtable.h"
|
||||||
#include "ShaderDefinitionsMLGPU.h"
|
#include "ShaderDefinitionsMLGPU.h"
|
||||||
|
|
|
@ -224,6 +224,7 @@ EXPORTS.mozilla.layers += [
|
||||||
'ShareableCanvasRenderer.h',
|
'ShareableCanvasRenderer.h',
|
||||||
'SourceSurfaceSharedData.h',
|
'SourceSurfaceSharedData.h',
|
||||||
'SourceSurfaceVolatileData.h',
|
'SourceSurfaceVolatileData.h',
|
||||||
|
'SyncObject.h',
|
||||||
'TextureSourceProvider.h',
|
'TextureSourceProvider.h',
|
||||||
'TextureWrapperImage.h',
|
'TextureWrapperImage.h',
|
||||||
'TransactionIdAllocator.h',
|
'TransactionIdAllocator.h',
|
||||||
|
@ -456,6 +457,7 @@ UNIFIED_SOURCES += [
|
||||||
'ShareableCanvasRenderer.cpp',
|
'ShareableCanvasRenderer.cpp',
|
||||||
'SourceSurfaceSharedData.cpp',
|
'SourceSurfaceSharedData.cpp',
|
||||||
'SourceSurfaceVolatileData.cpp',
|
'SourceSurfaceVolatileData.cpp',
|
||||||
|
'SyncObject.cpp',
|
||||||
'TextureSourceProvider.cpp',
|
'TextureSourceProvider.cpp',
|
||||||
'TextureWrapperImage.cpp',
|
'TextureWrapperImage.cpp',
|
||||||
'wr/AsyncImagePipelineManager.cpp',
|
'wr/AsyncImagePipelineManager.cpp',
|
||||||
|
|
|
@ -1436,7 +1436,11 @@ WebRenderBridgeParent::GetTextureFactoryIdentifier()
|
||||||
return TextureFactoryIdentifier(LayersBackend::LAYERS_WR,
|
return TextureFactoryIdentifier(LayersBackend::LAYERS_WR,
|
||||||
XRE_GetProcessType(),
|
XRE_GetProcessType(),
|
||||||
mApi->GetMaxTextureSize(),
|
mApi->GetMaxTextureSize(),
|
||||||
mApi->GetUseANGLE());
|
mApi->GetUseANGLE(),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
mApi->GetSyncHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
|
|
@ -18,7 +18,6 @@ WebRenderTextureHost::WebRenderTextureHost(const SurfaceDescriptor& aDesc,
|
||||||
wr::ExternalImageId& aExternalImageId)
|
wr::ExternalImageId& aExternalImageId)
|
||||||
: TextureHost(aFlags)
|
: TextureHost(aFlags)
|
||||||
, mExternalImageId(aExternalImageId)
|
, mExternalImageId(aExternalImageId)
|
||||||
, mIsWrappingNativeHandle(false)
|
|
||||||
{
|
{
|
||||||
// The wrapped textureHost will be used in WebRender, and the WebRender could
|
// The wrapped textureHost will be used in WebRender, and the WebRender could
|
||||||
// run at another thread. It's hard to control the life-time when gecko
|
// run at another thread. It's hard to control the life-time when gecko
|
||||||
|
@ -47,25 +46,6 @@ WebRenderTextureHost::CreateRenderTextureHost(const layers::SurfaceDescriptor& a
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aTexture);
|
MOZ_ASSERT(aTexture);
|
||||||
|
|
||||||
switch (aDesc.type()) {
|
|
||||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
|
||||||
mIsWrappingNativeHandle = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifdef XP_MACOSX
|
|
||||||
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
|
|
||||||
mIsWrappingNativeHandle = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
case SurfaceDescriptor::TSurfaceDescriptorGPUVideo: {
|
|
||||||
mIsWrappingNativeHandle = !aTexture->HasIntermediateBuffer();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
gfxCriticalError() << "No WR implement for texture type:" << aDesc.type();
|
|
||||||
}
|
|
||||||
|
|
||||||
aTexture->CreateRenderTexture(mExternalImageId);
|
aTexture->CreateRenderTexture(mExternalImageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,6 @@ public:
|
||||||
|
|
||||||
int32_t GetRGBStride();
|
int32_t GetRGBStride();
|
||||||
|
|
||||||
bool IsWrappingNativeHandle() { return mIsWrappingNativeHandle; }
|
|
||||||
|
|
||||||
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||||
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
||||||
|
|
||||||
|
@ -83,8 +81,6 @@ protected:
|
||||||
|
|
||||||
RefPtr<TextureHost> mWrappedTextureHost;
|
RefPtr<TextureHost> mWrappedTextureHost;
|
||||||
wr::ExternalImageId mExternalImageId;
|
wr::ExternalImageId mExternalImageId;
|
||||||
|
|
||||||
bool mIsWrappingNativeHandle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
|
|
|
@ -1100,11 +1100,13 @@ SizeDistance(gfxFontconfigFontEntry* aEntry,
|
||||||
void
|
void
|
||||||
gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||||
bool& aNeedsSyntheticBold)
|
bool& aNeedsSyntheticBold,
|
||||||
|
bool aIgnoreSizeTolerance)
|
||||||
{
|
{
|
||||||
gfxFontFamily::FindAllFontsForStyle(aFontStyle,
|
gfxFontFamily::FindAllFontsForStyle(aFontStyle,
|
||||||
aFontEntryList,
|
aFontEntryList,
|
||||||
aNeedsSyntheticBold);
|
aNeedsSyntheticBold,
|
||||||
|
aIgnoreSizeTolerance);
|
||||||
|
|
||||||
if (!mHasNonScalableFaces) {
|
if (!mHasNonScalableFaces) {
|
||||||
return;
|
return;
|
||||||
|
@ -1113,7 +1115,7 @@ gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||||
// Iterate over the the available fonts while compacting any groups
|
// Iterate over the the available fonts while compacting any groups
|
||||||
// of unscalable fonts with matching styles into a single entry
|
// of unscalable fonts with matching styles into a single entry
|
||||||
// corresponding to the closest available size. If the closest
|
// corresponding to the closest available size. If the closest
|
||||||
// available size is rejected for being outside tolernace, then the
|
// available size is rejected for being outside tolerance, then the
|
||||||
// entire group will be skipped.
|
// entire group will be skipped.
|
||||||
size_t skipped = 0;
|
size_t skipped = 0;
|
||||||
gfxFontconfigFontEntry* bestEntry = nullptr;
|
gfxFontconfigFontEntry* bestEntry = nullptr;
|
||||||
|
@ -1121,7 +1123,8 @@ gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||||
for (size_t i = 0; i < aFontEntryList.Length(); i++) {
|
for (size_t i = 0; i < aFontEntryList.Length(); i++) {
|
||||||
gfxFontconfigFontEntry* entry =
|
gfxFontconfigFontEntry* entry =
|
||||||
static_cast<gfxFontconfigFontEntry*>(aFontEntryList[i]);
|
static_cast<gfxFontconfigFontEntry*>(aFontEntryList[i]);
|
||||||
double dist = SizeDistance(entry, aFontStyle, mForceScalable);
|
double dist = SizeDistance(entry, aFontStyle,
|
||||||
|
mForceScalable || aIgnoreSizeTolerance);
|
||||||
// If the entry is scalable or has a style that does not match
|
// If the entry is scalable or has a style that does not match
|
||||||
// the group of unscalable fonts, then start a new group.
|
// the group of unscalable fonts, then start a new group.
|
||||||
if (dist < 0.0 ||
|
if (dist < 0.0 ||
|
||||||
|
@ -1766,7 +1769,7 @@ gfxFcPlatformFontList::GetFTLibrary()
|
||||||
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
|
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
|
||||||
gfxFontFamily* family = pfl->GetDefaultFont(&style);
|
gfxFontFamily* family = pfl->GetDefaultFont(&style);
|
||||||
NS_ASSERTION(family, "couldn't find a default font family");
|
NS_ASSERTION(family, "couldn't find a default font family");
|
||||||
gfxFontEntry* fe = family->FindFontForStyle(style, needsBold);
|
gfxFontEntry* fe = family->FindFontForStyle(style, needsBold, true);
|
||||||
if (!fe) {
|
if (!fe) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,8 @@ public:
|
||||||
void
|
void
|
||||||
FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||||
bool& aNeedsSyntheticBold) override;
|
bool& aNeedsSyntheticBold,
|
||||||
|
bool aIgnoreSizeTolerance) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~gfxFontconfigFontFamily();
|
virtual ~gfxFontconfigFontFamily();
|
||||||
|
|
|
@ -1101,10 +1101,12 @@ gfxFontFamily::HasOtherFamilyNames()
|
||||||
|
|
||||||
gfxFontEntry*
|
gfxFontEntry*
|
||||||
gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle,
|
gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle,
|
||||||
bool& aNeedsSyntheticBold)
|
bool& aNeedsSyntheticBold,
|
||||||
|
bool aIgnoreSizeTolerance)
|
||||||
{
|
{
|
||||||
AutoTArray<gfxFontEntry*,4> matched;
|
AutoTArray<gfxFontEntry*,4> matched;
|
||||||
FindAllFontsForStyle(aFontStyle, matched, aNeedsSyntheticBold);
|
FindAllFontsForStyle(aFontStyle, matched, aNeedsSyntheticBold,
|
||||||
|
aIgnoreSizeTolerance);
|
||||||
if (!matched.IsEmpty()) {
|
if (!matched.IsEmpty()) {
|
||||||
return matched[0];
|
return matched[0];
|
||||||
}
|
}
|
||||||
|
@ -1234,7 +1236,8 @@ WeightStyleStretchDistance(gfxFontEntry* aFontEntry,
|
||||||
void
|
void
|
||||||
gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||||
bool& aNeedsSyntheticBold)
|
bool& aNeedsSyntheticBold,
|
||||||
|
bool aIgnoreSizeTolerance)
|
||||||
{
|
{
|
||||||
if (!mHasStyles) {
|
if (!mHasStyles) {
|
||||||
FindStyleVariations(); // collect faces for the family, if not already done
|
FindStyleVariations(); // collect faces for the family, if not already done
|
||||||
|
@ -1469,7 +1472,7 @@ gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
|
||||||
gfxFontEntry *fe =
|
gfxFontEntry *fe =
|
||||||
FindFontForStyle(aMatchData->mStyle ? *aMatchData->mStyle
|
FindFontForStyle(aMatchData->mStyle ? *aMatchData->mStyle
|
||||||
: gfxFontStyle(),
|
: gfxFontStyle(),
|
||||||
needsBold);
|
needsBold, true);
|
||||||
|
|
||||||
if (fe && !fe->SkipDuringSystemFallback()) {
|
if (fe && !fe->SkipDuringSystemFallback()) {
|
||||||
int32_t rank = 0;
|
int32_t rank = 0;
|
||||||
|
|
|
@ -643,12 +643,14 @@ public:
|
||||||
// aNeedsSyntheticBold is set to true when synthetic bolding is
|
// aNeedsSyntheticBold is set to true when synthetic bolding is
|
||||||
// needed, false otherwise
|
// needed, false otherwise
|
||||||
gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
|
gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
|
||||||
bool& aNeedsSyntheticBold);
|
bool& aNeedsSyntheticBold,
|
||||||
|
bool aIgnoreSizeTolerance = false);
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||||
bool& aNeedsSyntheticBold);
|
bool& aNeedsSyntheticBold,
|
||||||
|
bool aIgnoreSizeTolerance = false);
|
||||||
|
|
||||||
// checks for a matching font within the family
|
// checks for a matching font within the family
|
||||||
// used as part of the font fallback process
|
// used as part of the font fallback process
|
||||||
|
|
|
@ -65,7 +65,7 @@ gfxTextRun::GlyphRunIterator::NextRun()
|
||||||
}
|
}
|
||||||
mGlyphRun = &mTextRun->mGlyphRunArray[mNextIndex];
|
mGlyphRun = &mTextRun->mGlyphRunArray[mNextIndex];
|
||||||
} else {
|
} else {
|
||||||
if (mNextIndex > 0) {
|
if (mNextIndex > 0 || !mTextRun->mSingleGlyphRun.mFont) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
glyphRunCount = 1;
|
glyphRunCount = 1;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "mozilla/dom/GamepadManager.h"
|
#include "mozilla/dom/GamepadManager.h"
|
||||||
#include "mozilla/dom/VRServiceTest.h"
|
#include "mozilla/dom/VRServiceTest.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
|
|
||||||
using layers::TextureClient;
|
using layers::TextureClient;
|
||||||
|
|
||||||
|
@ -61,7 +62,8 @@ VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
|
||||||
{
|
{
|
||||||
if (sVRManagerChildSingleton) {
|
if (sVRManagerChildSingleton) {
|
||||||
sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
|
sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
|
||||||
sVRManagerChildSingleton->mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
|
sVRManagerChildSingleton->mSyncObject =
|
||||||
|
layers::SyncObjectClient::CreateSyncObjectClient(aIdentifier.mSyncHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ class VREventObserver;
|
||||||
class VRMockDisplay;
|
class VRMockDisplay;
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
class SyncObjectClient;
|
||||||
class TextureClient;
|
class TextureClient;
|
||||||
}
|
}
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
|
@ -80,7 +81,7 @@ public:
|
||||||
|
|
||||||
static void IdentifyTextureHost(const layers::TextureFactoryIdentifier& aIdentifier);
|
static void IdentifyTextureHost(const layers::TextureFactoryIdentifier& aIdentifier);
|
||||||
layers::LayersBackend GetBackendType() const;
|
layers::LayersBackend GetBackendType() const;
|
||||||
layers::SyncObject* GetSyncObject() { return mSyncObject; }
|
layers::SyncObjectClient* GetSyncObject() { return mSyncObject; }
|
||||||
|
|
||||||
virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; }
|
virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; }
|
||||||
virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
|
virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
|
||||||
|
@ -194,7 +195,7 @@ private:
|
||||||
nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
|
nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
|
||||||
|
|
||||||
layers::LayersBackend mBackend;
|
layers::LayersBackend mBackend;
|
||||||
RefPtr<layers::SyncObject> mSyncObject;
|
RefPtr<layers::SyncObjectClient> mSyncObject;
|
||||||
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mGamepadPromiseList; // TODO: check if it can merge into one list?
|
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mGamepadPromiseList; // TODO: check if it can merge into one list?
|
||||||
uint32_t mPromiseID;
|
uint32_t mPromiseID;
|
||||||
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;
|
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;
|
||||||
|
|
|
@ -0,0 +1,256 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "RenderD3D11TextureHostOGL.h"
|
||||||
|
|
||||||
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
#include "GLLibraryEGL.h"
|
||||||
|
#include "GLContextEGL.h"
|
||||||
|
#include "mozilla/DebugOnly.h"
|
||||||
|
#include "mozilla/gfx/Logging.h"
|
||||||
|
#include "ScopedGLHelpers.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace wr {
|
||||||
|
|
||||||
|
static EGLint
|
||||||
|
GetEGLTextureFormat(gfx::SurfaceFormat aFormat)
|
||||||
|
{
|
||||||
|
switch (aFormat) {
|
||||||
|
case gfx::SurfaceFormat::B8G8R8A8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8X8:
|
||||||
|
case gfx::SurfaceFormat::R8G8B8A8:
|
||||||
|
case gfx::SurfaceFormat::R8G8B8X8:
|
||||||
|
case gfx::SurfaceFormat::A8R8G8B8:
|
||||||
|
case gfx::SurfaceFormat::X8R8G8B8:
|
||||||
|
return LOCAL_EGL_TEXTURE_RGBA;
|
||||||
|
case gfx::SurfaceFormat::R8G8B8:
|
||||||
|
case gfx::SurfaceFormat::B8G8R8:
|
||||||
|
return LOCAL_EGL_TEXTURE_RGB;
|
||||||
|
default:
|
||||||
|
gfxCriticalError() << "GetEGLTextureFormat(): unexpected texture format";
|
||||||
|
return LOCAL_EGL_TEXTURE_RGBA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderDXGITextureHostOGL::RenderDXGITextureHostOGL(WindowsHandle aHandle,
|
||||||
|
gfx::SurfaceFormat aFormat,
|
||||||
|
gfx::IntSize aSize)
|
||||||
|
: mHandle(aHandle)
|
||||||
|
, mTextureHandle{0}
|
||||||
|
, mSurface(0)
|
||||||
|
, mStream(0)
|
||||||
|
, mFormat(aFormat)
|
||||||
|
, mSize(aSize)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR_INHERITED(RenderDXGITextureHostOGL, RenderTextureHostOGL);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderDXGITextureHostOGL::~RenderDXGITextureHostOGL()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR_INHERITED(RenderDXGITextureHostOGL, RenderTextureHostOGL);
|
||||||
|
DeleteTextureHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RenderDXGITextureHostOGL::SetGLContext(gl::GLContext* aContext)
|
||||||
|
{
|
||||||
|
if (mGL.get() != aContext) {
|
||||||
|
// Release the texture handle in the previous gl context.
|
||||||
|
DeleteTextureHandle();
|
||||||
|
mGL = aContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RenderDXGITextureHostOGL::EnsureLockable()
|
||||||
|
{
|
||||||
|
if (mTextureHandle[0]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& egl = &gl::sEGLLibrary;
|
||||||
|
|
||||||
|
if (mFormat != gfx::SurfaceFormat::NV12) {
|
||||||
|
// The non-nv12 format.
|
||||||
|
// Use eglCreatePbufferFromClientBuffer get the gl handle from the d3d
|
||||||
|
// shared handle.
|
||||||
|
|
||||||
|
// Get gl texture handle from shared handle.
|
||||||
|
EGLint pbufferAttributes[] = {
|
||||||
|
LOCAL_EGL_WIDTH, mSize.width,
|
||||||
|
LOCAL_EGL_HEIGHT, mSize.height,
|
||||||
|
LOCAL_EGL_TEXTURE_TARGET, LOCAL_EGL_TEXTURE_2D,
|
||||||
|
LOCAL_EGL_TEXTURE_FORMAT, GetEGLTextureFormat(mFormat),
|
||||||
|
LOCAL_EGL_MIPMAP_TEXTURE, LOCAL_EGL_FALSE,
|
||||||
|
LOCAL_EGL_NONE
|
||||||
|
};
|
||||||
|
mSurface = egl->fCreatePbufferFromClientBuffer(egl->Display(),
|
||||||
|
LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
|
||||||
|
reinterpret_cast<EGLClientBuffer>(mHandle),
|
||||||
|
gl::GLContextEGL::Cast(mGL.get())->mConfig,
|
||||||
|
pbufferAttributes);
|
||||||
|
MOZ_ASSERT(mSurface);
|
||||||
|
|
||||||
|
// Query the keyed-mutex.
|
||||||
|
egl->fQuerySurfacePointerANGLE(egl->Display(),
|
||||||
|
mSurface,
|
||||||
|
LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE,
|
||||||
|
(void**)getter_AddRefs(mKeyedMutex));
|
||||||
|
|
||||||
|
mGL->fGenTextures(1, &mTextureHandle[0]);
|
||||||
|
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||||
|
mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextureHandle[0]);
|
||||||
|
mGL->TexParams_SetClampNoMips(LOCAL_GL_TEXTURE_2D);
|
||||||
|
egl->fBindTexImage(egl->Display(), mSurface, LOCAL_EGL_BACK_BUFFER);
|
||||||
|
} else {
|
||||||
|
// The nv12 format.
|
||||||
|
// The eglCreatePbufferFromClientBuffer doesn't support nv12 format, so we
|
||||||
|
// use EGLStream to get the converted gl handle from d3d nv12 texture.
|
||||||
|
|
||||||
|
// Fetch the D3D11 device.
|
||||||
|
EGLDeviceEXT eglDevice = nullptr;
|
||||||
|
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
|
||||||
|
MOZ_ASSERT(eglDevice);
|
||||||
|
ID3D11Device* device = nullptr;
|
||||||
|
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE, (EGLAttrib*)&device);
|
||||||
|
// There's a chance this might fail if we end up on d3d9 angle for some reason.
|
||||||
|
if (!device) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the NV12 D3D11 texture from shared handle.
|
||||||
|
if (FAILED(device->OpenSharedResource((HANDLE)mHandle,
|
||||||
|
__uuidof(ID3D11Texture2D),
|
||||||
|
(void**)(ID3D11Texture2D**)getter_AddRefs(mTexture)))) {
|
||||||
|
NS_WARNING("RenderDXGITextureHostOGL::Lock(): Failed to open shared texture");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
|
||||||
|
|
||||||
|
// Create the EGLStream.
|
||||||
|
mStream = egl->fCreateStreamKHR(egl->Display(), nullptr);
|
||||||
|
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
|
||||||
|
MOZ_ASSERT(mStream);
|
||||||
|
|
||||||
|
DebugOnly<EGLBoolean> eglResult;
|
||||||
|
|
||||||
|
// Setup the NV12 stream consumer/producer.
|
||||||
|
EGLAttrib consumerAttributes[] = {
|
||||||
|
LOCAL_EGL_COLOR_BUFFER_TYPE,
|
||||||
|
LOCAL_EGL_YUV_BUFFER_EXT,
|
||||||
|
LOCAL_EGL_YUV_NUMBER_OF_PLANES_EXT,
|
||||||
|
2,
|
||||||
|
LOCAL_EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
|
||||||
|
0,
|
||||||
|
LOCAL_EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
|
||||||
|
1,
|
||||||
|
LOCAL_EGL_NONE,
|
||||||
|
};
|
||||||
|
mGL->fGenTextures(2, mTextureHandle);
|
||||||
|
// We change the ActiveTexture texture unit here. Use ScopedBindTextureUnit
|
||||||
|
// to go back to the original status after this function.
|
||||||
|
gl::ScopedBindTextureUnit scopedBindTexture(mGL, LOCAL_GL_TEXTURE0);
|
||||||
|
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureHandle[0]);
|
||||||
|
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||||
|
mGL->fActiveTexture(LOCAL_GL_TEXTURE1);
|
||||||
|
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureHandle[1]);
|
||||||
|
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
|
||||||
|
MOZ_ALWAYS_TRUE(egl->fStreamConsumerGLTextureExternalAttribsNV(egl->Display(), mStream, consumerAttributes));
|
||||||
|
MOZ_ALWAYS_TRUE(egl->fCreateStreamProducerD3DTextureNV12ANGLE(egl->Display(), mStream, nullptr));
|
||||||
|
|
||||||
|
// Insert the NV12 texture.
|
||||||
|
MOZ_ALWAYS_TRUE(egl->fStreamPostD3DTextureNV12ANGLE(egl->Display(), mStream, (void*)mTexture.get(), nullptr));
|
||||||
|
|
||||||
|
// Now, we could check the stream status and use the NV12 gl handle.
|
||||||
|
EGLint state;
|
||||||
|
egl->fQueryStreamKHR(egl->Display(), mStream, LOCAL_EGL_STREAM_STATE_KHR, &state);
|
||||||
|
MOZ_ASSERT(state == LOCAL_EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR);
|
||||||
|
egl->fStreamConsumerAcquireKHR(egl->Display(), mStream);
|
||||||
|
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RenderDXGITextureHostOGL::Lock()
|
||||||
|
{
|
||||||
|
if (!EnsureLockable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mKeyedMutex) {
|
||||||
|
HRESULT hr = mKeyedMutex->AcquireSync(0, 100);
|
||||||
|
if (hr != S_OK) {
|
||||||
|
gfxCriticalError() << "RenderDXGITextureHostOGL AcquireSync timeout, hr=" << gfx::hexa(hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RenderDXGITextureHostOGL::Unlock()
|
||||||
|
{
|
||||||
|
if (mKeyedMutex) {
|
||||||
|
mKeyedMutex->ReleaseSync(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RenderDXGITextureHostOGL::DeleteTextureHandle()
|
||||||
|
{
|
||||||
|
if (mTextureHandle[0] != 0) {
|
||||||
|
if (mGL && mGL->MakeCurrent()) {
|
||||||
|
mGL->fDeleteTextures(2, mTextureHandle);
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 2; ++i) {
|
||||||
|
mTextureHandle[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& egl = &gl::sEGLLibrary;
|
||||||
|
if (mSurface) {
|
||||||
|
egl->fDestroySurface(egl->Display(), mSurface);
|
||||||
|
mSurface = 0;
|
||||||
|
}
|
||||||
|
if (mStream) {
|
||||||
|
egl->fStreamConsumerReleaseKHR(egl->Display(), mStream);
|
||||||
|
mStream = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTexture = nullptr;
|
||||||
|
mKeyedMutex = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint
|
||||||
|
RenderDXGITextureHostOGL::GetGLHandle(uint8_t aChannelIndex) const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mFormat != gfx::SurfaceFormat::NV12 || aChannelIndex < 2);
|
||||||
|
MOZ_ASSERT(mFormat == gfx::SurfaceFormat::NV12 || aChannelIndex < 1);
|
||||||
|
|
||||||
|
return mTextureHandle[aChannelIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::IntSize
|
||||||
|
RenderDXGITextureHostOGL::GetSize(uint8_t aChannelIndex) const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mFormat != gfx::SurfaceFormat::NV12 || aChannelIndex < 2);
|
||||||
|
MOZ_ASSERT(mFormat == gfx::SurfaceFormat::NV12 || aChannelIndex < 1);
|
||||||
|
|
||||||
|
if (aChannelIndex == 0) {
|
||||||
|
return mSize;
|
||||||
|
} else {
|
||||||
|
// The CbCr channel size is a half of Y channel size in NV12 format.
|
||||||
|
return mSize / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace wr
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef MOZILLA_GFX_RENDERD3D11TEXTUREHOSTOGL_H
|
||||||
|
#define MOZILLA_GFX_RENDERD3D11TEXTUREHOSTOGL_H
|
||||||
|
|
||||||
|
#include "RenderTextureHostOGL.h"
|
||||||
|
#include "GLTypes.h"
|
||||||
|
|
||||||
|
struct ID3D11Texture2D;
|
||||||
|
struct IDXGIKeyedMutex;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
namespace wr {
|
||||||
|
|
||||||
|
class RenderDXGITextureHostOGL final : public RenderTextureHostOGL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RenderDXGITextureHostOGL(WindowsHandle aHandle,
|
||||||
|
gfx::SurfaceFormat aFormat,
|
||||||
|
gfx::IntSize aSize);
|
||||||
|
|
||||||
|
virtual void SetGLContext(gl::GLContext* aContext) override;
|
||||||
|
|
||||||
|
virtual bool Lock() override;
|
||||||
|
virtual void Unlock() override;
|
||||||
|
|
||||||
|
virtual gfx::IntSize GetSize(uint8_t aChannelIndex) const;
|
||||||
|
virtual GLuint GetGLHandle(uint8_t aChannelIndex) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~RenderDXGITextureHostOGL();
|
||||||
|
|
||||||
|
bool EnsureLockable();
|
||||||
|
|
||||||
|
void DeleteTextureHandle();
|
||||||
|
|
||||||
|
RefPtr<gl::GLContext> mGL;
|
||||||
|
|
||||||
|
WindowsHandle mHandle;
|
||||||
|
RefPtr<ID3D11Texture2D> mTexture;
|
||||||
|
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
||||||
|
|
||||||
|
EGLSurface mSurface;
|
||||||
|
EGLStreamKHR mStream;
|
||||||
|
|
||||||
|
// We could use NV12 format for this texture. So, we might have 2 gl texture
|
||||||
|
// handles for Y and CbCr data.
|
||||||
|
GLuint mTextureHandle[2];
|
||||||
|
|
||||||
|
gfx::SurfaceFormat mFormat;
|
||||||
|
gfx::IntSize mSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace wr
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // MOZILLA_GFX_RENDERD3D11TEXTUREHOSTOGL_H
|
|
@ -9,6 +9,11 @@
|
||||||
#include "RenderTextureHost.h"
|
#include "RenderTextureHost.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
namespace gl {
|
||||||
|
class GLContext;
|
||||||
|
}
|
||||||
|
|
||||||
namespace wr {
|
namespace wr {
|
||||||
|
|
||||||
class RenderTextureHostOGL : public RenderTextureHost
|
class RenderTextureHostOGL : public RenderTextureHost
|
||||||
|
|
|
@ -71,6 +71,29 @@ RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
|
||||||
MOZ_ASSERT(mRenderer);
|
MOZ_ASSERT(mRenderer);
|
||||||
MOZ_ASSERT(mBridge);
|
MOZ_ASSERT(mBridge);
|
||||||
MOZ_COUNT_CTOR(RendererOGL);
|
MOZ_COUNT_CTOR(RendererOGL);
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
if (aGL->IsANGLE()) {
|
||||||
|
gl::GLLibraryEGL* egl = &gl::sEGLLibrary;
|
||||||
|
|
||||||
|
// Fetch the D3D11 device.
|
||||||
|
EGLDeviceEXT eglDevice = nullptr;
|
||||||
|
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
|
||||||
|
MOZ_ASSERT(eglDevice);
|
||||||
|
ID3D11Device* device = nullptr;
|
||||||
|
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE, (EGLAttrib*)&device);
|
||||||
|
MOZ_ASSERT(device);
|
||||||
|
|
||||||
|
mSyncObject = layers::SyncObjectHost::CreateSyncObjectHost(device);
|
||||||
|
if (mSyncObject) {
|
||||||
|
if (!mSyncObject->Init()) {
|
||||||
|
// Some errors occur. Clear the mSyncObject here.
|
||||||
|
// Then, there will be no texture synchronization.
|
||||||
|
mSyncObject = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererOGL::~RendererOGL()
|
RendererOGL::~RendererOGL()
|
||||||
|
@ -127,6 +150,12 @@ RendererOGL::Render()
|
||||||
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
|
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
|
||||||
|
|
||||||
auto size = mWidget->GetClientSize();
|
auto size = mWidget->GetClientSize();
|
||||||
|
|
||||||
|
if (mSyncObject) {
|
||||||
|
// XXX: if the synchronization is failed, we should handle the device reset.
|
||||||
|
mSyncObject->Synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
wr_renderer_render(mRenderer, size.width, size.height);
|
wr_renderer_render(mRenderer, size.width, size.height);
|
||||||
|
|
||||||
mGL->SwapBuffers();
|
mGL->SwapBuffers();
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#ifndef MOZILLA_LAYERS_RENDEREROGL_H
|
#ifndef MOZILLA_LAYERS_RENDEREROGL_H
|
||||||
#define MOZILLA_LAYERS_RENDEREROGL_H
|
#define MOZILLA_LAYERS_RENDEREROGL_H
|
||||||
|
|
||||||
|
#include "mozilla/layers/CompositorTypes.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include "mozilla/webrender/RenderThread.h"
|
#include "mozilla/webrender/RenderThread.h"
|
||||||
#include "mozilla/webrender/WebRenderTypes.h"
|
#include "mozilla/webrender/WebRenderTypes.h"
|
||||||
#include "mozilla/webrender/webrender_ffi.h"
|
#include "mozilla/webrender/webrender_ffi.h"
|
||||||
|
@ -78,6 +80,8 @@ public:
|
||||||
/// This can be called on the render thread only.
|
/// This can be called on the render thread only.
|
||||||
bool Resume();
|
bool Resume();
|
||||||
|
|
||||||
|
layers::SyncObjectHost* GetSyncObject() const { return mSyncObject.get(); }
|
||||||
|
|
||||||
layers::CompositorBridgeParentBase* GetCompositorBridge() { return mBridge; }
|
layers::CompositorBridgeParentBase* GetCompositorBridge() { return mBridge; }
|
||||||
|
|
||||||
wr::WrRenderedEpochs* FlushRenderedEpochs();
|
wr::WrRenderedEpochs* FlushRenderedEpochs();
|
||||||
|
@ -87,7 +91,6 @@ public:
|
||||||
wr::Renderer* GetRenderer() { return mRenderer; }
|
wr::Renderer* GetRenderer() { return mRenderer; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
RefPtr<RenderThread> mThread;
|
RefPtr<RenderThread> mThread;
|
||||||
RefPtr<gl::GLContext> mGL;
|
RefPtr<gl::GLContext> mGL;
|
||||||
RefPtr<widget::CompositorWidget> mWidget;
|
RefPtr<widget::CompositorWidget> mWidget;
|
||||||
|
@ -95,6 +98,7 @@ protected:
|
||||||
layers::CompositorBridgeParentBase* mBridge;
|
layers::CompositorBridgeParentBase* mBridge;
|
||||||
wr::WindowId mWindowId;
|
wr::WindowId mWindowId;
|
||||||
TimeStamp mFrameStartTime;
|
TimeStamp mFrameStartTime;
|
||||||
|
RefPtr<layers::SyncObjectHost> mSyncObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wr
|
} // namespace wr
|
||||||
|
|
|
@ -29,7 +29,8 @@ public:
|
||||||
RefPtr<widget::CompositorWidget>&& aWidget,
|
RefPtr<widget::CompositorWidget>&& aWidget,
|
||||||
layers::SynchronousTask* aTask,
|
layers::SynchronousTask* aTask,
|
||||||
bool aEnableProfiler,
|
bool aEnableProfiler,
|
||||||
LayoutDeviceIntSize aSize)
|
LayoutDeviceIntSize aSize,
|
||||||
|
layers::SyncHandle* aHandle)
|
||||||
: mRenderApi(aApi)
|
: mRenderApi(aApi)
|
||||||
, mMaxTextureSize(aMaxTextureSize)
|
, mMaxTextureSize(aMaxTextureSize)
|
||||||
, mUseANGLE(aUseANGLE)
|
, mUseANGLE(aUseANGLE)
|
||||||
|
@ -38,6 +39,7 @@ public:
|
||||||
, mTask(aTask)
|
, mTask(aTask)
|
||||||
, mEnableProfiler(aEnableProfiler)
|
, mEnableProfiler(aEnableProfiler)
|
||||||
, mSize(aSize)
|
, mSize(aSize)
|
||||||
|
, mSyncHandle(aHandle)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(NewRenderer);
|
MOZ_COUNT_CTOR(NewRenderer);
|
||||||
}
|
}
|
||||||
|
@ -91,6 +93,13 @@ public:
|
||||||
wr_renderer_set_external_image_handler(wrRenderer, &handler);
|
wr_renderer_set_external_image_handler(wrRenderer, &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (renderer) {
|
||||||
|
layers::SyncObjectHost* syncObj = renderer->GetSyncObject();
|
||||||
|
if (syncObj) {
|
||||||
|
*mSyncHandle = syncObj->GetSyncHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
aRenderThread.AddRenderer(aWindowId, Move(renderer));
|
aRenderThread.AddRenderer(aWindowId, Move(renderer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,6 +112,7 @@ private:
|
||||||
layers::SynchronousTask* mTask;
|
layers::SynchronousTask* mTask;
|
||||||
bool mEnableProfiler;
|
bool mEnableProfiler;
|
||||||
LayoutDeviceIntSize mSize;
|
LayoutDeviceIntSize mSize;
|
||||||
|
layers::SyncHandle* mSyncHandle;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoveRenderer : public RendererEvent
|
class RemoveRenderer : public RendererEvent
|
||||||
|
@ -146,13 +156,15 @@ WebRenderAPI::Create(bool aEnableProfiler,
|
||||||
wr::RenderApi* renderApi = nullptr;
|
wr::RenderApi* renderApi = nullptr;
|
||||||
GLint maxTextureSize = 0;
|
GLint maxTextureSize = 0;
|
||||||
bool useANGLE = false;
|
bool useANGLE = false;
|
||||||
|
layers::SyncHandle syncHandle = 0;
|
||||||
|
|
||||||
// Dispatch a synchronous task because the RenderApi object needs to be created
|
// Dispatch a synchronous task because the RenderApi object needs to be created
|
||||||
// on the render thread. If need be we could delay waiting on this task until
|
// on the render thread. If need be we could delay waiting on this task until
|
||||||
// the next time we need to access the RenderApi object.
|
// the next time we need to access the RenderApi object.
|
||||||
layers::SynchronousTask task("Create Renderer");
|
layers::SynchronousTask task("Create Renderer");
|
||||||
auto event = MakeUnique<NewRenderer>(&renderApi, aBridge, &maxTextureSize, &useANGLE,
|
auto event = MakeUnique<NewRenderer>(&renderApi, aBridge, &maxTextureSize, &useANGLE,
|
||||||
Move(aWidget), &task, aEnableProfiler, aSize);
|
Move(aWidget), &task, aEnableProfiler, aSize,
|
||||||
|
&syncHandle);
|
||||||
RenderThread::Get()->RunEvent(id, Move(event));
|
RenderThread::Get()->RunEvent(id, Move(event));
|
||||||
|
|
||||||
task.Wait();
|
task.Wait();
|
||||||
|
@ -161,7 +173,7 @@ WebRenderAPI::Create(bool aEnableProfiler,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RefPtr<WebRenderAPI>(new WebRenderAPI(renderApi, id, maxTextureSize, useANGLE)).forget();
|
return RefPtr<WebRenderAPI>(new WebRenderAPI(renderApi, id, maxTextureSize, useANGLE, syncHandle)).forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
wr::WrIdNamespace
|
wr::WrIdNamespace
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "mozilla/AlreadyAddRefed.h"
|
#include "mozilla/AlreadyAddRefed.h"
|
||||||
|
#include "mozilla/layers/SyncObject.h"
|
||||||
#include "mozilla/Range.h"
|
#include "mozilla/Range.h"
|
||||||
#include "mozilla/webrender/webrender_ffi.h"
|
#include "mozilla/webrender/webrender_ffi.h"
|
||||||
#include "mozilla/webrender/WebRenderTypes.h"
|
#include "mozilla/webrender/WebRenderTypes.h"
|
||||||
|
@ -122,13 +123,15 @@ public:
|
||||||
wr::WrIdNamespace GetNamespace();
|
wr::WrIdNamespace GetNamespace();
|
||||||
GLint GetMaxTextureSize() const { return mMaxTextureSize; }
|
GLint GetMaxTextureSize() const { return mMaxTextureSize; }
|
||||||
bool GetUseANGLE() const { return mUseANGLE; }
|
bool GetUseANGLE() const { return mUseANGLE; }
|
||||||
|
layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
WebRenderAPI(wr::RenderApi* aRawApi, wr::WindowId aId, GLint aMaxTextureSize, bool aUseANGLE)
|
WebRenderAPI(wr::RenderApi* aRawApi, wr::WindowId aId, GLint aMaxTextureSize, bool aUseANGLE, layers::SyncHandle aSyncHandle)
|
||||||
: mRenderApi(aRawApi)
|
: mRenderApi(aRawApi)
|
||||||
, mId(aId)
|
, mId(aId)
|
||||||
, mMaxTextureSize(aMaxTextureSize)
|
, mMaxTextureSize(aMaxTextureSize)
|
||||||
, mUseANGLE(aUseANGLE)
|
, mUseANGLE(aUseANGLE)
|
||||||
|
, mSyncHandle(aSyncHandle)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~WebRenderAPI();
|
~WebRenderAPI();
|
||||||
|
@ -139,6 +142,7 @@ protected:
|
||||||
wr::WindowId mId;
|
wr::WindowId mId;
|
||||||
GLint mMaxTextureSize;
|
GLint mMaxTextureSize;
|
||||||
bool mUseANGLE;
|
bool mUseANGLE;
|
||||||
|
layers::SyncHandle mSyncHandle;
|
||||||
|
|
||||||
friend class DisplayListBuilder;
|
friend class DisplayListBuilder;
|
||||||
friend class layers::WebRenderBridgeParent;
|
friend class layers::WebRenderBridgeParent;
|
||||||
|
|
|
@ -37,6 +37,15 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||||
'RenderMacIOSurfaceTextureHostOGL.cpp',
|
'RenderMacIOSurfaceTextureHostOGL.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
|
||||||
|
DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
|
||||||
|
EXPORTS.mozilla.webrender += [
|
||||||
|
'RenderD3D11TextureHostOGL.h',
|
||||||
|
]
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
'RenderD3D11TextureHostOGL.cpp',
|
||||||
|
]
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
|
@ -127,6 +127,33 @@ GetProxyStubType(JSContext* cx, HandleObject obj, HandleId id)
|
||||||
return ProxyStubType::DOMUnshadowed;
|
return ProxyStubType::DOMUnshadowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
|
||||||
|
bool* nameOrSymbol)
|
||||||
|
{
|
||||||
|
*nameOrSymbol = false;
|
||||||
|
|
||||||
|
if (!idval.isString() && !idval.isSymbol())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!ValueToId<CanGC>(cx, idval, id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!JSID_IS_STRING(id) && !JSID_IS_SYMBOL(id)) {
|
||||||
|
id.set(JSID_VOID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t dummy;
|
||||||
|
if (JSID_IS_STRING(id) && JSID_TO_ATOM(id)->isIndex(&dummy)) {
|
||||||
|
id.set(JSID_VOID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nameOrSymbol = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GetPropIRGenerator::tryAttachStub()
|
GetPropIRGenerator::tryAttachStub()
|
||||||
{
|
{
|
||||||
|
@ -272,6 +299,99 @@ GetPropIRGenerator::tryAttachIdempotentStub()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsCacheableProtoChain(JSObject* obj, JSObject* holder)
|
||||||
|
{
|
||||||
|
while (obj != holder) {
|
||||||
|
/*
|
||||||
|
* We cannot assume that we find the holder object on the prototype
|
||||||
|
* chain and must check for null proto. The prototype chain can be
|
||||||
|
* altered during the lookupProperty call.
|
||||||
|
*/
|
||||||
|
JSObject* proto = obj->staticPrototype();
|
||||||
|
if (!proto || !proto->isNative())
|
||||||
|
return false;
|
||||||
|
obj = proto;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsCacheableGetPropReadSlot(JSObject* obj, JSObject* holder, PropertyResult prop)
|
||||||
|
{
|
||||||
|
if (!prop || !IsCacheableProtoChain(obj, holder))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Shape* shape = prop.shape();
|
||||||
|
if (!shape->hasSlot() || !shape->hasDefaultGetter())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsCacheableGetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
|
||||||
|
{
|
||||||
|
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->getterValue().toObject().is<JSFunction>())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
|
||||||
|
if (!getter.isNative())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (getter.isClassConstructor())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check for a getter that has jitinfo and whose jitinfo says it's
|
||||||
|
// OK with both inner and outer objects.
|
||||||
|
if (getter.jitInfo() && !getter.jitInfo()->needsOuterizedThisObject())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// For getters that need the WindowProxy (instead of the Window) as this
|
||||||
|
// object, don't cache if obj is the Window, since our cache will pass that
|
||||||
|
// instead of the WindowProxy.
|
||||||
|
return !IsWindow(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsCacheableGetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
|
||||||
|
bool* isTemporarilyUnoptimizable = nullptr)
|
||||||
|
{
|
||||||
|
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->getterValue().toObject().is<JSFunction>())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// See IsCacheableGetPropCallNative.
|
||||||
|
if (IsWindow(obj))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
|
||||||
|
if (getter.isNative())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!getter.hasJITCode()) {
|
||||||
|
if (isTemporarilyUnoptimizable)
|
||||||
|
*isTemporarilyUnoptimizable = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getter.isClassConstructor())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id,
|
IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id,
|
||||||
jsbytecode* pc, GetPropertyResultFlags resultFlags)
|
jsbytecode* pc, GetPropertyResultFlags resultFlags)
|
||||||
|
@ -327,7 +447,7 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
|
||||||
}
|
}
|
||||||
shape.set(prop.maybeShape());
|
shape.set(prop.maybeShape());
|
||||||
|
|
||||||
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop))
|
if (IsCacheableGetPropReadSlot(obj, holder, prop))
|
||||||
return CanAttachReadSlot;
|
return CanAttachReadSlot;
|
||||||
|
|
||||||
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags))
|
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags))
|
||||||
|
@ -1866,8 +1986,7 @@ GetNameIRGenerator::tryAttachGlobalNameValue(ObjOperandId objId, HandleId id)
|
||||||
// prototype. Ignore the global lexical scope as it doesn't figure
|
// prototype. Ignore the global lexical scope as it doesn't figure
|
||||||
// into the prototype chain. We guard on the global lexical
|
// into the prototype chain. We guard on the global lexical
|
||||||
// scope's shape independently.
|
// scope's shape independently.
|
||||||
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(&globalLexical->global(), holder,
|
if (!IsCacheableGetPropReadSlot(&globalLexical->global(), holder, PropertyResult(shape)))
|
||||||
PropertyResult(shape)))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Shape guard for global lexical.
|
// Shape guard for global lexical.
|
||||||
|
@ -1987,7 +2106,7 @@ GetNameIRGenerator::tryAttachEnvironmentName(ObjOperandId objId, HandleId id)
|
||||||
}
|
}
|
||||||
|
|
||||||
holder = &env->as<NativeObject>();
|
holder = &env->as<NativeObject>();
|
||||||
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(holder, holder, PropertyResult(shape)))
|
if (!IsCacheableGetPropReadSlot(holder, holder, PropertyResult(shape)))
|
||||||
return false;
|
return false;
|
||||||
if (holder->getSlot(shape->slot()).isMagic())
|
if (holder->getSlot(shape->slot()).isMagic())
|
||||||
return false;
|
return false;
|
||||||
|
@ -2827,6 +2946,63 @@ SetPropIRGenerator::trackNotAttached()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
|
||||||
|
{
|
||||||
|
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->hasSetterValue())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSFunction& setter = shape->setterObject()->as<JSFunction>();
|
||||||
|
if (!setter.isNative())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (setter.isClassConstructor())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (setter.jitInfo() && !setter.jitInfo()->needsOuterizedThisObject())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return !IsWindow(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
|
||||||
|
bool* isTemporarilyUnoptimizable = nullptr)
|
||||||
|
{
|
||||||
|
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (IsWindow(obj))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->hasSetterValue())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSFunction& setter = shape->setterObject()->as<JSFunction>();
|
||||||
|
if (setter.isNative())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!setter.hasJITCode()) {
|
||||||
|
if (isTemporarilyUnoptimizable)
|
||||||
|
*isTemporarilyUnoptimizable = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setter.isClassConstructor())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CanAttachSetter(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id,
|
CanAttachSetter(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id,
|
||||||
MutableHandleObject holder, MutableHandleShape propShape,
|
MutableHandleObject holder, MutableHandleShape propShape,
|
||||||
|
|
|
@ -101,186 +101,6 @@ jit::GetReturnAddressToIonCode(JSContext* cx)
|
||||||
return returnAddr;
|
return returnAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: This differs from IsCacheableProtoChain in BaselineIC.cpp in that
|
|
||||||
// Ion caches can deal with objects on the proto chain that have uncacheable
|
|
||||||
// prototypes.
|
|
||||||
bool
|
|
||||||
jit::IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder)
|
|
||||||
{
|
|
||||||
while (obj != holder) {
|
|
||||||
/*
|
|
||||||
* We cannot assume that we find the holder object on the prototype
|
|
||||||
* chain and must check for null proto. The prototype chain can be
|
|
||||||
* altered during the lookupProperty call.
|
|
||||||
*/
|
|
||||||
JSObject* proto = obj->staticPrototype();
|
|
||||||
if (!proto || !proto->isNative())
|
|
||||||
return false;
|
|
||||||
obj = proto;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
jit::IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder, PropertyResult prop)
|
|
||||||
{
|
|
||||||
if (!prop || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Shape* shape = prop.shape();
|
|
||||||
if (!shape->hasSlot() || !shape->hasDefaultGetter())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
jit::IsCacheableGetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
|
|
||||||
{
|
|
||||||
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->getterValue().toObject().is<JSFunction>())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
|
|
||||||
if (!getter.isNative())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (getter.isClassConstructor())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check for a getter that has jitinfo and whose jitinfo says it's
|
|
||||||
// OK with both inner and outer objects.
|
|
||||||
if (getter.jitInfo() && !getter.jitInfo()->needsOuterizedThisObject())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// For getters that need the WindowProxy (instead of the Window) as this
|
|
||||||
// object, don't cache if obj is the Window, since our cache will pass that
|
|
||||||
// instead of the WindowProxy.
|
|
||||||
return !IsWindow(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
jit::IsCacheableGetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
|
|
||||||
bool* isTemporarilyUnoptimizable)
|
|
||||||
{
|
|
||||||
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->getterValue().toObject().is<JSFunction>())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// See IsCacheableGetPropCallNative.
|
|
||||||
if (IsWindow(obj))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
|
|
||||||
if (getter.isNative())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!getter.hasJITCode()) {
|
|
||||||
if (isTemporarilyUnoptimizable)
|
|
||||||
*isTemporarilyUnoptimizable = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getter.isClassConstructor())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
jit::ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
|
|
||||||
bool* nameOrSymbol)
|
|
||||||
{
|
|
||||||
*nameOrSymbol = false;
|
|
||||||
|
|
||||||
if (!idval.isString() && !idval.isSymbol())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!ValueToId<CanGC>(cx, idval, id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!JSID_IS_STRING(id) && !JSID_IS_SYMBOL(id)) {
|
|
||||||
id.set(JSID_VOID);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t dummy;
|
|
||||||
if (JSID_IS_STRING(id) && JSID_TO_ATOM(id)->isIndex(&dummy)) {
|
|
||||||
id.set(JSID_VOID);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
*nameOrSymbol = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
jit::IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
|
|
||||||
{
|
|
||||||
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->hasSetterValue())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JSFunction& setter = shape->setterObject()->as<JSFunction>();
|
|
||||||
if (!setter.isNative())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (setter.isClassConstructor())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (setter.jitInfo() && !setter.jitInfo()->needsOuterizedThisObject())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return !IsWindow(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
jit::IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
|
|
||||||
bool* isTemporarilyUnoptimizable)
|
|
||||||
{
|
|
||||||
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (IsWindow(obj))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->hasSetterValue())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JSFunction& setter = shape->setterObject()->as<JSFunction>();
|
|
||||||
if (setter.isNative())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!setter.hasJITCode()) {
|
|
||||||
if (isTemporarilyUnoptimizable)
|
|
||||||
*isTemporarilyUnoptimizable = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setter.isClassConstructor())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
jit::EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,
|
jit::EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,
|
||||||
Register elements, BaseObjectElementIndex target)
|
Register elements, BaseObjectElementIndex target)
|
||||||
|
|
|
@ -26,21 +26,6 @@
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace jit {
|
namespace jit {
|
||||||
|
|
||||||
bool IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder);
|
|
||||||
bool IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder,
|
|
||||||
PropertyResult prop);
|
|
||||||
|
|
||||||
bool IsCacheableGetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
|
|
||||||
bool* isTemporarilyUnoptimizable = nullptr);
|
|
||||||
bool IsCacheableGetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape);
|
|
||||||
|
|
||||||
bool IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
|
|
||||||
bool* isTemporarilyUnoptimizable = nullptr);
|
|
||||||
bool IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape);
|
|
||||||
|
|
||||||
bool ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
|
|
||||||
bool* nameOrSymbol);
|
|
||||||
|
|
||||||
void* GetReturnAddressToIonCode(JSContext* cx);
|
void* GetReturnAddressToIonCode(JSContext* cx);
|
||||||
|
|
||||||
void EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,
|
void EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIFactory.h"
|
#include "nsIFactory.h"
|
||||||
#include "nsIScriptError.h"
|
#include "nsIScriptError.h"
|
||||||
|
#include "nsISensitiveInfoHiddenURI.h"
|
||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "nsStyleUtil.h"
|
#include "nsStyleUtil.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||||
|
|
||||||
|
@ -37,12 +39,9 @@ public:
|
||||||
if (mURI != aURI) {
|
if (mURI != aURI) {
|
||||||
mURI = aURI;
|
mURI = aURI;
|
||||||
|
|
||||||
nsAutoCString cSpec;
|
if (NS_FAILED(NS_GetSanitizedURIStringFromURI(mURI, mSpec))) {
|
||||||
nsresult rv = mURI->GetSpec(cSpec);
|
mSpec.AssignLiteral("[nsIURI::GetSpec failed]");
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
cSpec.AssignLiteral("[nsIURI::GetSpec failed]");
|
|
||||||
}
|
}
|
||||||
CopyUTF8toUTF16(cSpec, mSpec);
|
|
||||||
}
|
}
|
||||||
return mSpec;
|
return mSpec;
|
||||||
}
|
}
|
||||||
|
@ -219,14 +218,16 @@ ErrorReporter::OutputError()
|
||||||
do_CreateInstance(sScriptErrorFactory, &rv);
|
do_CreateInstance(sScriptErrorFactory, &rv);
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
rv = errorObject->InitWithWindowID(mError,
|
// It is safe to used InitWithSanitizedSource because mFileName is
|
||||||
mFileName,
|
// an already anonymized uri spec.
|
||||||
mErrorLine,
|
rv = errorObject->InitWithSanitizedSource(mError,
|
||||||
mErrorLineNumber,
|
mFileName,
|
||||||
mErrorColNumber,
|
mErrorLine,
|
||||||
nsIScriptError::warningFlag,
|
mErrorLineNumber,
|
||||||
"CSS Parser",
|
mErrorColNumber,
|
||||||
mInnerWindowID);
|
nsIScriptError::warningFlag,
|
||||||
|
"CSS Parser",
|
||||||
|
mInnerWindowID);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
sConsoleService->LogMessage(errorObject);
|
sConsoleService->LogMessage(errorObject);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2179,6 +2179,10 @@ pref("network.http.throttle.resume-for", 100);
|
||||||
// response has finished. Prevents resuming too soon during an active page load
|
// response has finished. Prevents resuming too soon during an active page load
|
||||||
// at which sub-resource reqeusts quickly come and go.
|
// at which sub-resource reqeusts quickly come and go.
|
||||||
pref("network.http.throttle.resume-background-in", 1000);
|
pref("network.http.throttle.resume-background-in", 1000);
|
||||||
|
// After the last transaction activation or last data chunk response we only
|
||||||
|
// throttle for this period of time. This prevents comet and unresponsive
|
||||||
|
// http requests to engage long-standing throttling.
|
||||||
|
pref("network.http.throttle.time-window", 3000);
|
||||||
|
|
||||||
// Give higher priority to requests resulting from a user interaction event
|
// Give higher priority to requests resulting from a user interaction event
|
||||||
// like click-to-play, image fancy-box zoom, navigation.
|
// like click-to-play, image fancy-box zoom, navigation.
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "nsIRedirectChannelRegistrar.h"
|
#include "nsIRedirectChannelRegistrar.h"
|
||||||
#include "nsIRequestObserverProxy.h"
|
#include "nsIRequestObserverProxy.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
|
#include "nsISensitiveInfoHiddenURI.h"
|
||||||
#include "nsISimpleStreamListener.h"
|
#include "nsISimpleStreamListener.h"
|
||||||
#include "nsISocketProvider.h"
|
#include "nsISocketProvider.h"
|
||||||
#include "nsISocketProviderService.h"
|
#include "nsISocketProviderService.h"
|
||||||
|
@ -1578,6 +1579,26 @@ NS_NewURI(nsIURI **result,
|
||||||
return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI, ioService);
|
return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI, ioService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
NS_GetSanitizedURIStringFromURI(nsIURI *aUri, nsAString &aSanitizedSpec)
|
||||||
|
{
|
||||||
|
aSanitizedSpec.Truncate();
|
||||||
|
|
||||||
|
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(aUri);
|
||||||
|
nsAutoCString cSpec;
|
||||||
|
nsresult rv;
|
||||||
|
if (safeUri) {
|
||||||
|
rv = safeUri->GetSensitiveInfoHiddenSpec(cSpec);
|
||||||
|
} else {
|
||||||
|
rv = aUri->GetSpec(cSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
aSanitizedSpec.Assign(NS_ConvertUTF8toUTF16(cSpec));
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **outResult,
|
NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **outResult,
|
||||||
const nsACString &aSpec)
|
const nsACString &aSpec)
|
||||||
|
|
|
@ -100,6 +100,9 @@ nsresult NS_NewFileURI(nsIURI **result,
|
||||||
nsIFile *spec,
|
nsIFile *spec,
|
||||||
nsIIOService *ioService = nullptr); // pass in nsIIOService to optimize callers
|
nsIIOService *ioService = nullptr); // pass in nsIIOService to optimize callers
|
||||||
|
|
||||||
|
nsresult NS_GetSanitizedURIStringFromURI(nsIURI *aUri,
|
||||||
|
nsAString &aSanitizedSpec);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* How to create a new Channel, using NS_NewChannel,
|
* How to create a new Channel, using NS_NewChannel,
|
||||||
* NS_NewChannelWithTriggeringPrincipal,
|
* NS_NewChannelWithTriggeringPrincipal,
|
||||||
|
|
|
@ -2494,16 +2494,13 @@ HttpBaseChannel::AddSecurityMessage(const nsAString &aMessageTag,
|
||||||
errorText);
|
errorText);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsAutoCString spec;
|
|
||||||
if (mURI) {
|
|
||||||
spec = mURI->GetSpecOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
|
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
|
||||||
error->InitWithWindowID(errorText, NS_ConvertUTF8toUTF16(spec),
|
error->InitWithSourceURI(errorText, mURI,
|
||||||
EmptyString(), 0, 0, nsIScriptError::warningFlag,
|
EmptyString(), 0, 0,
|
||||||
NS_ConvertUTF16toUTF8(aMessageCategory),
|
nsIScriptError::warningFlag,
|
||||||
innerWindowID);
|
NS_ConvertUTF16toUTF8(aMessageCategory),
|
||||||
|
innerWindowID);
|
||||||
|
|
||||||
console->LogMessage(error);
|
console->LogMessage(error);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
@ -1580,14 +1580,14 @@ nsCORSListenerProxy::LogBlockedCORSRequest(uint64_t aInnerWindowID,
|
||||||
// query innerWindowID and log to web console, otherwise log to
|
// query innerWindowID and log to web console, otherwise log to
|
||||||
// the error to the browser console.
|
// the error to the browser console.
|
||||||
if (aInnerWindowID > 0) {
|
if (aInnerWindowID > 0) {
|
||||||
rv = scriptError->InitWithWindowID(aMessage,
|
rv = scriptError->InitWithSanitizedSource(aMessage,
|
||||||
EmptyString(), // sourceName
|
EmptyString(), // sourceName
|
||||||
EmptyString(), // sourceLine
|
EmptyString(), // sourceLine
|
||||||
0, // lineNumber
|
0, // lineNumber
|
||||||
0, // columnNumber
|
0, // columnNumber
|
||||||
nsIScriptError::warningFlag,
|
nsIScriptError::warningFlag,
|
||||||
"CORS",
|
"CORS",
|
||||||
aInnerWindowID);
|
aInnerWindowID);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rv = scriptError->Init(aMessage,
|
rv = scriptError->Init(aMessage,
|
||||||
|
|
|
@ -119,6 +119,7 @@ nsHttpConnectionMgr::nsHttpConnectionMgr()
|
||||||
, mThrottleSuspendFor(0)
|
, mThrottleSuspendFor(0)
|
||||||
, mThrottleResumeFor(0)
|
, mThrottleResumeFor(0)
|
||||||
, mThrottleResumeIn(0)
|
, mThrottleResumeIn(0)
|
||||||
|
, mThrottleTimeWindow(0)
|
||||||
, mIsShuttingDown(false)
|
, mIsShuttingDown(false)
|
||||||
, mNumActiveConns(0)
|
, mNumActiveConns(0)
|
||||||
, mNumIdleConns(0)
|
, mNumIdleConns(0)
|
||||||
|
@ -175,7 +176,8 @@ nsHttpConnectionMgr::Init(uint16_t maxUrgentExcessiveConns,
|
||||||
bool throttleEnabled,
|
bool throttleEnabled,
|
||||||
uint32_t throttleSuspendFor,
|
uint32_t throttleSuspendFor,
|
||||||
uint32_t throttleResumeFor,
|
uint32_t throttleResumeFor,
|
||||||
uint32_t throttleResumeIn)
|
uint32_t throttleResumeIn,
|
||||||
|
uint32_t throttleTimeWindow)
|
||||||
{
|
{
|
||||||
LOG(("nsHttpConnectionMgr::Init\n"));
|
LOG(("nsHttpConnectionMgr::Init\n"));
|
||||||
|
|
||||||
|
@ -192,6 +194,7 @@ nsHttpConnectionMgr::Init(uint16_t maxUrgentExcessiveConns,
|
||||||
mThrottleSuspendFor = throttleSuspendFor;
|
mThrottleSuspendFor = throttleSuspendFor;
|
||||||
mThrottleResumeFor = throttleResumeFor;
|
mThrottleResumeFor = throttleResumeFor;
|
||||||
mThrottleResumeIn = throttleResumeIn;
|
mThrottleResumeIn = throttleResumeIn;
|
||||||
|
mThrottleTimeWindow = TimeDuration::FromMilliseconds(throttleTimeWindow);
|
||||||
|
|
||||||
mIsShuttingDown = false;
|
mIsShuttingDown = false;
|
||||||
}
|
}
|
||||||
|
@ -2831,6 +2834,9 @@ nsHttpConnectionMgr::OnMsgUpdateParam(int32_t inParam, ARefBase *)
|
||||||
case THROTTLING_RESUME_IN:
|
case THROTTLING_RESUME_IN:
|
||||||
mThrottleResumeIn = value;
|
mThrottleResumeIn = value;
|
||||||
break;
|
break;
|
||||||
|
case THROTTLING_TIME_WINDOW:
|
||||||
|
mThrottleTimeWindow = TimeDuration::FromMilliseconds(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
NS_NOTREACHED("unexpected parameter name");
|
NS_NOTREACHED("unexpected parameter name");
|
||||||
}
|
}
|
||||||
|
@ -2929,6 +2935,30 @@ void nsHttpConnectionMgr::SetThrottlingEnabled(bool aEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nsHttpConnectionMgr::InThrottlingTimeWindow()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||||
|
|
||||||
|
if (mThrottlingWindowEndsAt.IsNull()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return TimeStamp::NowLoRes() <= mThrottlingWindowEndsAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsHttpConnectionMgr::TouchThrottlingTimeWindow(bool aEnsureTicker)
|
||||||
|
{
|
||||||
|
LOG(("nsHttpConnectionMgr::TouchThrottlingTimeWindow"));
|
||||||
|
|
||||||
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||||
|
|
||||||
|
mThrottlingWindowEndsAt = TimeStamp::NowLoRes() + mThrottleTimeWindow;
|
||||||
|
|
||||||
|
if (!mThrottleTicker &&
|
||||||
|
MOZ_LIKELY(aEnsureTicker) && MOZ_LIKELY(mThrottleEnabled)) {
|
||||||
|
EnsureThrottleTickerIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nsHttpConnectionMgr::LogActiveTransactions(char operation)
|
void nsHttpConnectionMgr::LogActiveTransactions(char operation)
|
||||||
{
|
{
|
||||||
if (!LOG_ENABLED()) {
|
if (!LOG_ENABLED()) {
|
||||||
|
@ -2961,30 +2991,39 @@ void nsHttpConnectionMgr::LogActiveTransactions(char operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled)
|
nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||||
|
|
||||||
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
||||||
|
bool throttled = aTrans->EligibleForThrottling();
|
||||||
|
|
||||||
nsTArray<RefPtr<nsHttpTransaction>> *transactions =
|
nsTArray<RefPtr<nsHttpTransaction>> *transactions =
|
||||||
mActiveTransactions[aThrottled].LookupOrAdd(tabId);
|
mActiveTransactions[throttled].LookupOrAdd(tabId);
|
||||||
|
|
||||||
MOZ_ASSERT(!transactions->Contains(aTrans));
|
MOZ_ASSERT(!transactions->Contains(aTrans));
|
||||||
|
|
||||||
transactions->AppendElement(aTrans);
|
transactions->AppendElement(aTrans);
|
||||||
|
|
||||||
LOG(("nsHttpConnectionMgr::AddActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d",
|
LOG(("nsHttpConnectionMgr::AddActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d",
|
||||||
aTrans, tabId, tabId == mCurrentTopLevelOuterContentWindowId, aThrottled));
|
aTrans, tabId, tabId == mCurrentTopLevelOuterContentWindowId, throttled));
|
||||||
LogActiveTransactions('+');
|
LogActiveTransactions('+');
|
||||||
|
|
||||||
if (tabId == mCurrentTopLevelOuterContentWindowId) {
|
if (tabId == mCurrentTopLevelOuterContentWindowId) {
|
||||||
mActiveTabTransactionsExist = true;
|
mActiveTabTransactionsExist = true;
|
||||||
if (!aThrottled) {
|
if (!throttled) {
|
||||||
mActiveTabUnthrottledTransactionsExist = true;
|
mActiveTabUnthrottledTransactionsExist = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shift the throttling window to the future (actually, makes sure
|
||||||
|
// that throttling will engage when there is anything to throttle.)
|
||||||
|
// The |false| argument means we don't need this call to ensure
|
||||||
|
// the ticker, since we do it just below. Calling
|
||||||
|
// EnsureThrottleTickerIfNeeded directly does a bit more than call
|
||||||
|
// from inside of TouchThrottlingTimeWindow.
|
||||||
|
TouchThrottlingTimeWindow(false);
|
||||||
|
|
||||||
if (!mThrottleEnabled) {
|
if (!mThrottleEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2993,15 +3032,17 @@ nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans, bool aThro
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled)
|
nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans,
|
||||||
|
Maybe<bool> const& aOverride)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||||
|
|
||||||
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
||||||
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
|
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
|
||||||
|
bool throttled = aOverride.valueOr(aTrans->EligibleForThrottling());
|
||||||
|
|
||||||
nsTArray<RefPtr<nsHttpTransaction>> *transactions =
|
nsTArray<RefPtr<nsHttpTransaction>> *transactions =
|
||||||
mActiveTransactions[aThrottled].Get(tabId);
|
mActiveTransactions[throttled].Get(tabId);
|
||||||
|
|
||||||
if (!transactions || !transactions->RemoveElement(aTrans)) {
|
if (!transactions || !transactions->RemoveElement(aTrans)) {
|
||||||
// Was not tracked as active, probably just ignore.
|
// Was not tracked as active, probably just ignore.
|
||||||
|
@ -3009,7 +3050,7 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("nsHttpConnectionMgr::RemoveActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d",
|
LOG(("nsHttpConnectionMgr::RemoveActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d",
|
||||||
aTrans, tabId, forActiveTab, aThrottled));
|
aTrans, tabId, forActiveTab, throttled));
|
||||||
|
|
||||||
if (!transactions->IsEmpty()) {
|
if (!transactions->IsEmpty()) {
|
||||||
// There are still transactions of the type, hence nothing in the throttling conditions
|
// There are still transactions of the type, hence nothing in the throttling conditions
|
||||||
|
@ -3020,16 +3061,16 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
|
||||||
}
|
}
|
||||||
|
|
||||||
// To optimize the following logic, always remove the entry when the array is empty.
|
// To optimize the following logic, always remove the entry when the array is empty.
|
||||||
mActiveTransactions[aThrottled].Remove(tabId);
|
mActiveTransactions[throttled].Remove(tabId);
|
||||||
LogActiveTransactions('-');
|
LogActiveTransactions('-');
|
||||||
|
|
||||||
if (forActiveTab) {
|
if (forActiveTab) {
|
||||||
// Update caches of the active tab transaction existence, since it's now affected
|
// Update caches of the active tab transaction existence, since it's now affected
|
||||||
if (!aThrottled) {
|
if (!throttled) {
|
||||||
mActiveTabUnthrottledTransactionsExist = false;
|
mActiveTabUnthrottledTransactionsExist = false;
|
||||||
}
|
}
|
||||||
if (mActiveTabTransactionsExist) {
|
if (mActiveTabTransactionsExist) {
|
||||||
mActiveTabTransactionsExist = mActiveTransactions[!aThrottled].Contains(tabId);
|
mActiveTabTransactionsExist = mActiveTransactions[!throttled].Contains(tabId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3067,7 +3108,7 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
|
||||||
// There are only trottled transactions for the active tab.
|
// There are only trottled transactions for the active tab.
|
||||||
// If the last transaction we just removed was a non-throttled for the active tab
|
// If the last transaction we just removed was a non-throttled for the active tab
|
||||||
// we can wake the throttled transactions for the active tab.
|
// we can wake the throttled transactions for the active tab.
|
||||||
if (forActiveTab && !aThrottled) {
|
if (forActiveTab && !throttled) {
|
||||||
LOG((" resuming throttled for active tab"));
|
LOG((" resuming throttled for active tab"));
|
||||||
ResumeReadOf(mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId));
|
ResumeReadOf(mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId));
|
||||||
}
|
}
|
||||||
|
@ -3094,16 +3135,21 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHttpConnectionMgr::MoveActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled)
|
nsHttpConnectionMgr::UpdateActiveTransaction(nsHttpTransaction * aTrans)
|
||||||
{
|
{
|
||||||
LOG(("nsHttpConnectionMgr::MoveActiveTransaction ENTER t=%p", aTrans));
|
LOG(("nsHttpConnectionMgr::UpdateActiveTransaction ENTER t=%p", aTrans));
|
||||||
AddActiveTransaction(aTrans, aThrottled);
|
|
||||||
RemoveActiveTransaction(aTrans, !aThrottled);
|
AddActiveTransaction(aTrans);
|
||||||
LOG(("nsHttpConnectionMgr::MoveActiveTransaction EXIT t=%p", aTrans));
|
|
||||||
|
Maybe<bool> reversed;
|
||||||
|
reversed.emplace(!aTrans->EligibleForThrottling());
|
||||||
|
RemoveActiveTransaction(aTrans, reversed);
|
||||||
|
|
||||||
|
LOG(("nsHttpConnectionMgr::UpdateActiveTransaction EXIT t=%p", aTrans));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans, bool aThrottled)
|
nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||||
|
|
||||||
|
@ -3113,43 +3159,62 @@ nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans, bool aThrottl
|
||||||
|
|
||||||
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
||||||
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
|
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
|
||||||
|
bool throttled = aTrans->EligibleForThrottling();
|
||||||
|
|
||||||
if (mActiveTabTransactionsExist) {
|
bool stop = [=]() {
|
||||||
if (!tabId) {
|
if (mActiveTabTransactionsExist) {
|
||||||
// Chrome initiated and unidentified transactions just respect
|
if (!tabId) {
|
||||||
// their throttle flag, when something for the active tab is happening.
|
// Chrome initiated and unidentified transactions just respect
|
||||||
return aThrottled;
|
// their throttle flag, when something for the active tab is happening.
|
||||||
|
// This also includes downloads.
|
||||||
|
return throttled;
|
||||||
|
}
|
||||||
|
if (!forActiveTab) {
|
||||||
|
// This is a background tab request, we want them to always throttle
|
||||||
|
// when there are transactions running for the ative tab.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mActiveTabUnthrottledTransactionsExist) {
|
||||||
|
// Unthrottled transactions for the active tab take precedence
|
||||||
|
return throttled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (!forActiveTab) {
|
|
||||||
// This is a background tab request, we want them to always throttle.
|
MOZ_ASSERT(!forActiveTab);
|
||||||
|
|
||||||
|
if (mDelayedResumeReadTimer) {
|
||||||
|
// If this timer exists, background transactions are scheduled to be woken
|
||||||
|
// after a delay, hence leave them asleep.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (mActiveTabUnthrottledTransactionsExist) {
|
|
||||||
// Unthrottled transactions for the active tab take precedence
|
if (!mActiveTransactions[false].IsEmpty()) {
|
||||||
return aThrottled;
|
// This means there are unthrottled active transactions for background tabs.
|
||||||
|
// If we are here, there can't be any transactions for the active tab.
|
||||||
|
// (If there is no transaction for a tab id, there is no entry for it in
|
||||||
|
// the hashtable.)
|
||||||
|
return throttled;
|
||||||
}
|
}
|
||||||
// This is a throttled transaction for the active tab and there are no
|
|
||||||
// unthrottled for the active tab, just let go on full fuel.
|
// There are only unthrottled transactions for background tabs: don't throttle.
|
||||||
|
return false;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (forActiveTab && !stop) {
|
||||||
|
// This active-tab transaction is allowed to read even though
|
||||||
|
// we are in the middle of "stop reading" interval. Hence,
|
||||||
|
// prolong the throttle time window to make sure all 'lower-decks'
|
||||||
|
// transactions will actually throttle.
|
||||||
|
TouchThrottlingTimeWindow();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(!forActiveTab);
|
// Only stop reading when in the 3 seconds throttle time window.
|
||||||
|
// This window is prolonged (restarted) by a call to TouchThrottlingTimeWindow.
|
||||||
if (mDelayedResumeReadTimer) {
|
return stop && InThrottlingTimeWindow();
|
||||||
// If this timer exists, background transactions are scheduled to be woken
|
|
||||||
// after a delay.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mActiveTransactions[false].IsEmpty()) {
|
|
||||||
// This means there are unthrottled active transactions for background tabs.
|
|
||||||
// If we are here, there can't be any transactions for the active tab.
|
|
||||||
// (If there is no transaction for a tab id, there is no entry for it in the hashtable.)
|
|
||||||
return aThrottled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There are only unthrottled transactions for background tabs: don't throttle.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsHttpConnectionMgr::IsConnEntryUnderPressure(nsHttpConnectionInfo *connInfo)
|
bool nsHttpConnectionMgr::IsConnEntryUnderPressure(nsHttpConnectionInfo *connInfo)
|
||||||
|
@ -3257,7 +3322,7 @@ nsHttpConnectionMgr::ThrottlerTick()
|
||||||
// throttle them again until the background-resume delay passes.
|
// throttle them again until the background-resume delay passes.
|
||||||
if (!mThrottlingInhibitsReading &&
|
if (!mThrottlingInhibitsReading &&
|
||||||
!mDelayedResumeReadTimer &&
|
!mDelayedResumeReadTimer &&
|
||||||
!IsThrottleTickerNeeded()) {
|
(!IsThrottleTickerNeeded() || !InThrottlingTimeWindow())) {
|
||||||
LOG((" last tick"));
|
LOG((" last tick"));
|
||||||
mThrottleTicker = nullptr;
|
mThrottleTicker = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,8 @@ public:
|
||||||
THROTTLING_ENABLED,
|
THROTTLING_ENABLED,
|
||||||
THROTTLING_SUSPEND_FOR,
|
THROTTLING_SUSPEND_FOR,
|
||||||
THROTTLING_RESUME_FOR,
|
THROTTLING_RESUME_FOR,
|
||||||
THROTTLING_RESUME_IN
|
THROTTLING_RESUME_IN,
|
||||||
|
THROTTLING_TIME_WINDOW
|
||||||
};
|
};
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
@ -77,7 +78,8 @@ public:
|
||||||
bool throttleEnabled,
|
bool throttleEnabled,
|
||||||
uint32_t throttleSuspendFor,
|
uint32_t throttleSuspendFor,
|
||||||
uint32_t throttleResumeFor,
|
uint32_t throttleResumeFor,
|
||||||
uint32_t throttleResumeIn);
|
uint32_t throttleResumeIn,
|
||||||
|
uint32_t throttleTimeWindow);
|
||||||
MOZ_MUST_USE nsresult Shutdown();
|
MOZ_MUST_USE nsresult Shutdown();
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
@ -217,15 +219,22 @@ public:
|
||||||
nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId);
|
nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId);
|
||||||
|
|
||||||
// tracks and untracks active transactions according their throttle status
|
// tracks and untracks active transactions according their throttle status
|
||||||
void AddActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled);
|
void AddActiveTransaction(nsHttpTransaction* aTrans);
|
||||||
void RemoveActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled);
|
void RemoveActiveTransaction(nsHttpTransaction* aTrans,
|
||||||
void MoveActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled);
|
Maybe<bool> const& aOverride = Nothing());
|
||||||
|
void UpdateActiveTransaction(nsHttpTransaction* aTrans);
|
||||||
|
|
||||||
// called by nsHttpTransaction::WriteSegments. decides whether the transaction
|
// called by nsHttpTransaction::WriteSegments. decides whether the transaction
|
||||||
// should stop reading data based on: the throttling ticker status, overall
|
// should stop reading data based on: the throttling ticker status, overall
|
||||||
// status of all active transactions regarding active tab and respective
|
// status of all active transactions regarding active tab and respective
|
||||||
// throttling state.
|
// throttling state.
|
||||||
bool ShouldStopReading(nsHttpTransaction* aTrans, bool aThrottled);
|
bool ShouldStopReading(nsHttpTransaction* aTrans);
|
||||||
|
|
||||||
|
// prolongs the throttling time window to now + the window preferred size
|
||||||
|
// called when:
|
||||||
|
// - any transaction is activated
|
||||||
|
// - or when a currently unthrottled transaction for the active window receives data
|
||||||
|
void TouchThrottlingTimeWindow(bool aEnsureTicker = true);
|
||||||
|
|
||||||
// return true iff the connection has pending transactions for the active tab.
|
// return true iff the connection has pending transactions for the active tab.
|
||||||
// it's mainly used to disallow throttling (stop reading) of a response
|
// it's mainly used to disallow throttling (stop reading) of a response
|
||||||
|
@ -519,6 +528,7 @@ private:
|
||||||
uint32_t mThrottleSuspendFor;
|
uint32_t mThrottleSuspendFor;
|
||||||
uint32_t mThrottleResumeFor;
|
uint32_t mThrottleResumeFor;
|
||||||
uint32_t mThrottleResumeIn;
|
uint32_t mThrottleResumeIn;
|
||||||
|
TimeDuration mThrottleTimeWindow;
|
||||||
Atomic<bool, mozilla::Relaxed> mIsShuttingDown;
|
Atomic<bool, mozilla::Relaxed> mIsShuttingDown;
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
@ -689,6 +699,12 @@ private:
|
||||||
// Called on a pref change
|
// Called on a pref change
|
||||||
void SetThrottlingEnabled(bool aEnable);
|
void SetThrottlingEnabled(bool aEnable);
|
||||||
|
|
||||||
|
// we only want to throttle for a limited amount of time after a new
|
||||||
|
// active transaction is added so that we don't block downloads on comet,
|
||||||
|
// socket and any kind of longstanding requests that don't need bandwidth.
|
||||||
|
// these methods track this time.
|
||||||
|
bool InThrottlingTimeWindow();
|
||||||
|
|
||||||
// Two hashtalbes keeping track of active transactions regarding window id and throttling.
|
// Two hashtalbes keeping track of active transactions regarding window id and throttling.
|
||||||
// Used by the throttling algorithm to obtain number of transactions for the active tab
|
// Used by the throttling algorithm to obtain number of transactions for the active tab
|
||||||
// and for inactive tabs according their throttle status.
|
// and for inactive tabs according their throttle status.
|
||||||
|
@ -698,6 +714,8 @@ private:
|
||||||
// Whether we are inside the "stop reading" interval, altered by the throttle ticker
|
// Whether we are inside the "stop reading" interval, altered by the throttle ticker
|
||||||
bool mThrottlingInhibitsReading;
|
bool mThrottlingInhibitsReading;
|
||||||
|
|
||||||
|
TimeStamp mThrottlingWindowEndsAt;
|
||||||
|
|
||||||
// ticker for the 'stop reading'/'resume reading' signal
|
// ticker for the 'stop reading'/'resume reading' signal
|
||||||
nsCOMPtr<nsITimer> mThrottleTicker;
|
nsCOMPtr<nsITimer> mThrottleTicker;
|
||||||
// Checks if the combination of active transactions requires the ticker.
|
// Checks if the combination of active transactions requires the ticker.
|
||||||
|
|
|
@ -196,6 +196,7 @@ nsHttpHandler::nsHttpHandler()
|
||||||
, mThrottleSuspendFor(3000)
|
, mThrottleSuspendFor(3000)
|
||||||
, mThrottleResumeFor(200)
|
, mThrottleResumeFor(200)
|
||||||
, mThrottleResumeIn(400)
|
, mThrottleResumeIn(400)
|
||||||
|
, mThrottleTimeWindow(3000)
|
||||||
, mUrgentStartEnabled(true)
|
, mUrgentStartEnabled(true)
|
||||||
, mRedirectionLimit(10)
|
, mRedirectionLimit(10)
|
||||||
, mPhishyUserPassLength(1)
|
, mPhishyUserPassLength(1)
|
||||||
|
@ -590,7 +591,8 @@ nsHttpHandler::InitConnectionMgr()
|
||||||
mThrottleEnabled,
|
mThrottleEnabled,
|
||||||
mThrottleSuspendFor,
|
mThrottleSuspendFor,
|
||||||
mThrottleResumeFor,
|
mThrottleResumeFor,
|
||||||
mThrottleResumeIn);
|
mThrottleResumeIn,
|
||||||
|
mThrottleTimeWindow);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1636,6 +1638,15 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PREF_CHANGED(HTTP_PREF("throttle.time-window"))) {
|
||||||
|
rv = prefs->GetIntPref(HTTP_PREF("throttle.time-window"), &val);
|
||||||
|
mThrottleTimeWindow = (uint32_t)clamped(val, 0, 120000);
|
||||||
|
if (NS_SUCCEEDED(rv) && mConnMgr) {
|
||||||
|
Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_TIME_WINDOW,
|
||||||
|
mThrottleTimeWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (PREF_CHANGED(HTTP_PREF("on_click_priority"))) {
|
if (PREF_CHANGED(HTTP_PREF("on_click_priority"))) {
|
||||||
Unused << prefs->GetBoolPref(HTTP_PREF("on_click_priority"), &mUrgentStartEnabled);
|
Unused << prefs->GetBoolPref(HTTP_PREF("on_click_priority"), &mUrgentStartEnabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -460,6 +460,7 @@ private:
|
||||||
uint32_t mThrottleSuspendFor;
|
uint32_t mThrottleSuspendFor;
|
||||||
uint32_t mThrottleResumeFor;
|
uint32_t mThrottleResumeFor;
|
||||||
uint32_t mThrottleResumeIn;
|
uint32_t mThrottleResumeIn;
|
||||||
|
uint32_t mThrottleTimeWindow;
|
||||||
|
|
||||||
bool mUrgentStartEnabled;
|
bool mUrgentStartEnabled;
|
||||||
|
|
||||||
|
|
|
@ -173,13 +173,13 @@ void nsHttpTransaction::ResumeReading()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsHttpTransaction::EligibleForThrottling()
|
bool nsHttpTransaction::EligibleForThrottling() const
|
||||||
{
|
{
|
||||||
return (mClassOfService & (nsIClassOfService::Throttleable |
|
return (mClassOfService & (nsIClassOfService::Throttleable |
|
||||||
nsIClassOfService::DontThrottle |
|
nsIClassOfService::DontThrottle |
|
||||||
nsIClassOfService::Leader |
|
nsIClassOfService::Leader |
|
||||||
nsIClassOfService::Unblocked)) ==
|
nsIClassOfService::Unblocked)) ==
|
||||||
nsIClassOfService::Throttleable;
|
nsIClassOfService::Throttleable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsHttpTransaction::SetClassOfService(uint32_t cos)
|
void nsHttpTransaction::SetClassOfService(uint32_t cos)
|
||||||
|
@ -190,9 +190,9 @@ void nsHttpTransaction::SetClassOfService(uint32_t cos)
|
||||||
|
|
||||||
if (mConnection && wasThrottling != isThrottling) {
|
if (mConnection && wasThrottling != isThrottling) {
|
||||||
// Do nothing until we are actually activated. For now
|
// Do nothing until we are actually activated. For now
|
||||||
// only remember the throttle flag. Call to MoveActiveTransaction
|
// only remember the throttle flag. Call to UpdateActiveTransaction
|
||||||
// would add this transaction to the list too early.
|
// would add this transaction to the list too early.
|
||||||
gHttpHandler->ConnMgr()->MoveActiveTransaction(this, isThrottling);
|
gHttpHandler->ConnMgr()->UpdateActiveTransaction(this);
|
||||||
|
|
||||||
if (mReadingStopped && !isThrottling) {
|
if (mReadingStopped && !isThrottling) {
|
||||||
ResumeReading();
|
ResumeReading();
|
||||||
|
@ -526,8 +526,7 @@ nsHttpTransaction::OnActivated(bool h2)
|
||||||
}
|
}
|
||||||
|
|
||||||
mActivated = true;
|
mActivated = true;
|
||||||
gHttpHandler->ConnMgr()->AddActiveTransaction(
|
gHttpHandler->ConnMgr()->AddActiveTransaction(this);
|
||||||
this, mClassOfService & nsIClassOfService::Throttleable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -841,15 +840,25 @@ bool nsHttpTransaction::ShouldStopReading()
|
||||||
if (mActivatedAsH2) {
|
if (mActivatedAsH2) {
|
||||||
// Throttling feature is now disabled for http/2 transactions
|
// Throttling feature is now disabled for http/2 transactions
|
||||||
// because of bug 1367861. The logic around mActivatedAsH2
|
// because of bug 1367861. The logic around mActivatedAsH2
|
||||||
// will be removed when that is fixed
|
// will be removed when that is fixed.
|
||||||
|
//
|
||||||
|
// Calling ShouldStopReading on the manager just to make sure
|
||||||
|
// the throttling time window is correctly updated by this transaction.
|
||||||
|
Unused << gHttpHandler->ConnMgr()->ShouldStopReading(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mClassOfService & nsIClassOfService::DontThrottle) {
|
if (mClassOfService & nsIClassOfService::DontThrottle) {
|
||||||
|
// We deliberately don't touch the throttling window here since
|
||||||
|
// DontThrottle requests are expected to be long-standing media
|
||||||
|
// streams and would just unnecessarily block running downloads.
|
||||||
|
// If we want to ballance bandwidth for media responses against
|
||||||
|
// running downloads, we need to find something smarter like
|
||||||
|
// changing the suspend/resume throttling intervals at-runtime.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gHttpHandler->ConnMgr()->ShouldStopReading(this, EligibleForThrottling())) {
|
if (!gHttpHandler->ConnMgr()->ShouldStopReading(this)) {
|
||||||
// We are not obligated to throttle
|
// We are not obligated to throttle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -943,8 +952,7 @@ nsHttpTransaction::Close(nsresult reason)
|
||||||
this, static_cast<uint32_t>(reason)));
|
this, static_cast<uint32_t>(reason)));
|
||||||
|
|
||||||
if (!mClosed) {
|
if (!mClosed) {
|
||||||
gHttpHandler->ConnMgr()->RemoveActiveTransaction(
|
gHttpHandler->ConnMgr()->RemoveActiveTransaction(this);
|
||||||
this, mClassOfService & nsIClassOfService::Throttleable);
|
|
||||||
mActivated = false;
|
mActivated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -394,8 +394,8 @@ public:
|
||||||
void ResumeReading();
|
void ResumeReading();
|
||||||
|
|
||||||
// This examins classification of this transaction whether the Throttleable class
|
// This examins classification of this transaction whether the Throttleable class
|
||||||
// has been set while Leader or Unblocked are not.
|
// has been set while Leader, Unblocked, DontThrottle has not.
|
||||||
bool EligibleForThrottling();
|
bool EligibleForThrottling() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mSubmittedRatePacing;
|
bool mSubmittedRatePacing;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[parse-input-arguments-018.html]
|
[parse-input-arguments-018.html]
|
||||||
type: reftest
|
type: reftest
|
||||||
expected:
|
expected:
|
||||||
if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
|
if (os == "mac"): FAIL
|
||||||
if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
|
|
||||||
|
|
|
@ -10,32 +10,35 @@ const DIALOG_URL = "chrome://payments/content/paymentRequest.xhtml";
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(this,
|
||||||
|
"paymentSrv",
|
||||||
|
"@mozilla.org/dom/payments/payment-request-service;1",
|
||||||
|
"nsIPaymentRequestService");
|
||||||
|
|
||||||
function PaymentUIService() {}
|
function PaymentUIService() {}
|
||||||
|
|
||||||
PaymentUIService.prototype = {
|
PaymentUIService.prototype = {
|
||||||
classID: Components.ID("{01f8bd55-9017-438b-85ec-7c15d2b35cdc}"),
|
classID: Components.ID("{01f8bd55-9017-438b-85ec-7c15d2b35cdc}"),
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||||
|
|
||||||
canMakePayment(requestId) {
|
|
||||||
let canMakeResponse = Cc["@mozilla.org/dom/payments/payment-canmake-action-response;1"]
|
|
||||||
.createInstance(Ci.nsIPaymentCanMakeActionResponse);
|
|
||||||
canMakeResponse.init(requestId, false);
|
|
||||||
return canMakeResponse.QueryInterface(Ci.nsIPaymentActionResponse);
|
|
||||||
},
|
|
||||||
|
|
||||||
showPayment(requestId) {
|
showPayment(requestId) {
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
abortPayment(requestId) {
|
abortPayment(requestId) {
|
||||||
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"]
|
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"]
|
||||||
.createInstance(Ci.nsIPaymentAbortActionResponse);
|
.createInstance(Ci.nsIPaymentAbortActionResponse);
|
||||||
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
|
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
|
||||||
return abortResponse.QueryInterface(Ci.nsIPaymentActionResponse);
|
paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
},
|
},
|
||||||
|
|
||||||
completePayment(requestId) {
|
completePayment(requestId) {
|
||||||
return null;
|
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]
|
||||||
|
.createInstance(Ci.nsIPaymentCompleteActionResponse);
|
||||||
|
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLTETE_SUCCEEDED);
|
||||||
|
paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||||
|
},
|
||||||
|
|
||||||
|
updatePayment(requestId) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,15 +72,13 @@ LogMessage(const nsAString &aMessage, nsIURI* aSourceURI, const nsAString &aSour
|
||||||
nsCOMPtr<nsIScriptError> error = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
nsCOMPtr<nsIScriptError> error = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
||||||
NS_ENSURE_TRUE(error, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_TRUE(error, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
nsCString sourceName = aSourceURI->GetSpecOrDefault();
|
|
||||||
|
|
||||||
uint64_t windowID = 0;
|
uint64_t windowID = 0;
|
||||||
GetWindowIDFromContext(aContext, &windowID);
|
GetWindowIDFromContext(aContext, &windowID);
|
||||||
|
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
error->InitWithWindowID(aMessage, NS_ConvertUTF8toUTF16(sourceName),
|
error->InitWithSourceURI(aMessage, aSourceURI,
|
||||||
aSourceSample, 0, 0, nsIScriptError::errorFlag,
|
aSourceSample, 0, 0, nsIScriptError::errorFlag,
|
||||||
"JavaScript", windowID);
|
"JavaScript", windowID);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||||
|
|
|
@ -720,46 +720,52 @@ AddPseudoEntry(uint32_t aFeatures, NotNull<RacyThreadInfo*> aRacyInfo,
|
||||||
MOZ_ASSERT(entry.kind() == js::ProfileEntry::Kind::CPP_NORMAL ||
|
MOZ_ASSERT(entry.kind() == js::ProfileEntry::Kind::CPP_NORMAL ||
|
||||||
entry.kind() == js::ProfileEntry::Kind::JS_NORMAL);
|
entry.kind() == js::ProfileEntry::Kind::JS_NORMAL);
|
||||||
|
|
||||||
|
const char* label = entry.label();
|
||||||
const char* dynamicString = entry.dynamicString();
|
const char* dynamicString = entry.dynamicString();
|
||||||
|
bool isChromeJSEntry = false;
|
||||||
int lineno = -1;
|
int lineno = -1;
|
||||||
|
|
||||||
// XXX: it's unclear why the computation of lineno should depend on
|
if (entry.isJs()) {
|
||||||
// |dynamicString|. Perhaps it shouldn't?
|
// There are two kinds of JS frames that get pushed onto the PseudoStack.
|
||||||
|
//
|
||||||
|
// - label = "", dynamic string = <something>
|
||||||
|
// - label = "js::RunScript", dynamic string = nullptr
|
||||||
|
//
|
||||||
|
// The line number is only interesting for the first case.
|
||||||
|
if (label[0] == '\0') {
|
||||||
|
MOZ_ASSERT(dynamicString);
|
||||||
|
|
||||||
if (dynamicString) {
|
|
||||||
bool isChromeJSEntry = false;
|
|
||||||
if (entry.isJs()) {
|
|
||||||
// We call entry.script() repeatedly -- rather than storing the result in
|
// We call entry.script() repeatedly -- rather than storing the result in
|
||||||
// a local variable in order -- to avoid rooting hazards.
|
// a local variable in order -- to avoid rooting hazards.
|
||||||
if (entry.script()) {
|
if (entry.script()) {
|
||||||
isChromeJSEntry = IsChromeJSScript(entry.script());
|
isChromeJSEntry = IsChromeJSScript(entry.script());
|
||||||
if (!entry.pc()) {
|
if (entry.pc()) {
|
||||||
|
lineno = JS_PCToLineNumber(entry.script(), entry.pc());
|
||||||
|
} else {
|
||||||
// The JIT only allows the top-most entry to have a nullptr pc.
|
// The JIT only allows the top-most entry to have a nullptr pc.
|
||||||
MOZ_ASSERT(&entry == &aRacyInfo->entries[aRacyInfo->stackSize() - 1]);
|
MOZ_ASSERT(&entry == &aRacyInfo->entries[aRacyInfo->stackSize() - 1]);
|
||||||
} else {
|
|
||||||
lineno = JS_PCToLineNumber(entry.script(), entry.pc());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
lineno = entry.line();
|
MOZ_ASSERT(strcmp(label, "js::RunScript") == 0 && !dynamicString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(entry.isCpp());
|
||||||
|
lineno = entry.line();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dynamicString) {
|
||||||
// Adjust the dynamic string as necessary.
|
// Adjust the dynamic string as necessary.
|
||||||
if (ProfilerFeature::HasPrivacy(aFeatures) && !isChromeJSEntry) {
|
if (ProfilerFeature::HasPrivacy(aFeatures) && !isChromeJSEntry) {
|
||||||
dynamicString = "(private)";
|
dynamicString = "(private)";
|
||||||
} else if (strlen(dynamicString) >= ProfileBuffer::kMaxFrameKeyLength) {
|
} else if (strlen(dynamicString) >= ProfileBuffer::kMaxFrameKeyLength) {
|
||||||
dynamicString = "(too long)";
|
dynamicString = "(too long)";
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
// XXX: Bug 1010578. Don't assume a CPP entry and try to get the line for
|
|
||||||
// js entries as well.
|
|
||||||
if (entry.isCpp()) {
|
|
||||||
lineno = entry.line();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aCollector.CollectCodeLocation(entry.label(), dynamicString, lineno,
|
aCollector.CollectCodeLocation(label, dynamicString, lineno,
|
||||||
Some(entry.category()));
|
Some(entry.category()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче