зеркало из 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) {
|
||||
whitelist.push(
|
||||
// Bug 1343824
|
||||
|
|
|
@ -63,11 +63,6 @@ function getTopWin(skipPopups) {
|
|||
allowPopups: !skipPopups});
|
||||
}
|
||||
|
||||
function openTopWin(url) {
|
||||
/* deprecated */
|
||||
openUILinkIn(url, "current");
|
||||
}
|
||||
|
||||
function getBoolPref(prefname, def) {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(prefname);
|
||||
|
|
|
@ -400,9 +400,8 @@
|
|||
@RESPATH@/components/nsSearchService.js
|
||||
@RESPATH@/components/nsSearchSuggestions.js
|
||||
@RESPATH@/components/nsSidebar.js
|
||||
#if defined(NIGHTLY_BUILD) && defined(MOZ_BUILD_APP_IS_BROWSER)
|
||||
@RESPATH@/components/payments.manifest
|
||||
#endif
|
||||
@RESPATH@/components/paymentUIService.js
|
||||
@RESPATH@/components/passwordmgr.manifest
|
||||
@RESPATH@/components/nsLoginInfo.js
|
||||
@RESPATH@/components/nsLoginManager.js
|
||||
|
|
|
@ -4105,20 +4105,26 @@ nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText,
|
|||
nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
|
||||
}
|
||||
}
|
||||
if (spec.IsEmpty() && aURI) {
|
||||
spec = aURI->GetSpecOrDefault();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptError> errorObject =
|
||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = errorObject->InitWithWindowID(aErrorText,
|
||||
NS_ConvertUTF8toUTF16(spec), // file name
|
||||
aSourceLine,
|
||||
aLineNumber, aColumnNumber,
|
||||
aErrorFlags, aCategory,
|
||||
aInnerWindowID);
|
||||
if (!spec.IsEmpty()) {
|
||||
rv = errorObject->InitWithWindowID(aErrorText,
|
||||
NS_ConvertUTF8toUTF16(spec), // file name
|
||||
aSourceLine,
|
||||
aLineNumber, aColumnNumber,
|
||||
aErrorFlags, aCategory,
|
||||
aInnerWindowID);
|
||||
} else {
|
||||
rv = errorObject->InitWithSourceURI(aErrorText,
|
||||
aURI,
|
||||
aSourceLine,
|
||||
aLineNumber, aColumnNumber,
|
||||
aErrorFlags, aCategory,
|
||||
aInnerWindowID);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return sConsoleService->LogMessage(errorObject);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsISupports.idl"
|
||||
#include "nsIArray.idl"
|
||||
#include "nsIConsoleMessage.idl"
|
||||
interface nsIURI;
|
||||
|
||||
%{C++
|
||||
#include "nsStringGlue.h" // for nsDependentCString
|
||||
|
@ -97,8 +98,17 @@ interface nsIScriptError : nsIConsoleMessage
|
|||
in string category);
|
||||
|
||||
/* This should be called instead of nsIScriptError.init to
|
||||
initialize with a window id. The window id should be for the
|
||||
inner window associated with this error. */
|
||||
* initialize with a window id. The window id should be for the
|
||||
* 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,
|
||||
in AString sourceName,
|
||||
in AString sourceLine,
|
||||
|
@ -107,8 +117,33 @@ interface nsIScriptError : nsIConsoleMessage
|
|||
in uint32_t flags,
|
||||
in ACString category,
|
||||
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++
|
||||
// This overload allows passing a literal string for category.
|
||||
// These overloads allow passing a literal string for category.
|
||||
template<uint32_t N>
|
||||
nsresult InitWithWindowID(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
|
@ -123,6 +158,38 @@ interface nsIScriptError : nsIConsoleMessage
|
|||
return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
|
||||
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)) &&
|
||||
!pass.IsEmpty())
|
||||
{
|
||||
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(uri);
|
||||
|
||||
nsAutoCString loc;
|
||||
if (safeUri && NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc)))
|
||||
aSourceNameDest.Assign(NS_ConvertUTF8toUTF16(loc));
|
||||
NS_GetSanitizedURIStringFromURI(uri, aSourceNameDest);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
|
@ -228,15 +255,49 @@ nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
|||
const nsACString& category,
|
||||
uint64_t aInnerWindowID)
|
||||
{
|
||||
mMessage.Assign(message);
|
||||
InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
|
||||
category, aInnerWindowID);
|
||||
AssignSourceNameHelper(mSourceName, sourceName);
|
||||
mLineNumber = lineNumber;
|
||||
mSourceLine.Assign(sourceLine);
|
||||
mColumnNumber = columnNumber;
|
||||
mFlags = flags;
|
||||
mCategory = category;
|
||||
mTimeStamp = JS_Now() / 1000;
|
||||
mInnerWindowID = aInnerWindowID;
|
||||
|
||||
if (aInnerWindowID && NS_IsMainThread())
|
||||
InitializeOnMainThread();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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())
|
||||
InitializeOnMainThread();
|
||||
|
|
|
@ -53,6 +53,12 @@ protected:
|
|||
void
|
||||
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;
|
||||
nsString mMessage;
|
||||
nsString mMessageName;
|
||||
|
|
|
@ -6,12 +6,18 @@
|
|||
#include "nsISupports.idl"
|
||||
#include "nsIPaymentActionResponse.idl"
|
||||
|
||||
[scriptable, uuid(ea008d0c-9e9f-411f-a6c5-a62106ba7ab9)]
|
||||
[scriptable, uuid(01f8bd55-9017-438b-85ec-7c15d2b35cdc)]
|
||||
interface nsIPaymentUIService : nsISupports
|
||||
{
|
||||
nsIPaymentActionResponse canMakePayment(in AString requestId);
|
||||
nsIPaymentActionResponse showPayment(in AString requestId);
|
||||
nsIPaymentActionResponse abortPayment(in AString requestId);
|
||||
nsIPaymentActionResponse completePayment(in AString requestId);
|
||||
nsIPaymentActionResponse updatePayment(in AString requestId);
|
||||
void showPayment(in AString requestId);
|
||||
void abortPayment(in AString requestId);
|
||||
void completePayment(in AString requestId);
|
||||
void 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 =
|
||||
ownerDoc ? nsContentUtils::LayerManagerForDocument(ownerDoc) : nullptr;
|
||||
RefPtr<KnowsCompositor> knows =
|
||||
layerManager ? layerManager->AsShadowForwarder() : nullptr;
|
||||
layerManager ? layerManager->AsKnowsCompositor() : nullptr;
|
||||
return knows.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -643,7 +643,7 @@ private:
|
|||
RefPtr<MFTDecoder> mTransform;
|
||||
RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
|
||||
RefPtr<ID3D11VideoDecoder> mDecoder;
|
||||
RefPtr<layers::SyncObject> mSyncObject;
|
||||
RefPtr<layers::SyncObjectClient> mSyncObject;
|
||||
GUID mDecoderGUID;
|
||||
uint32_t mWidth = 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
|
||||
// DXVA does not seem to accept IDXGIKeyedMutex textures as input.
|
||||
mSyncObject =
|
||||
layers::SyncObject::CreateSyncObject(layers::ImageBridgeChild::GetSingleton()->
|
||||
GetTextureFactoryIdentifier().mSyncHandle,
|
||||
mDevice);
|
||||
layers::SyncObjectClient::CreateSyncObjectClient(
|
||||
layers::ImageBridgeChild::GetSingleton()->
|
||||
GetTextureFactoryIdentifier().mSyncHandle,
|
||||
mDevice);
|
||||
}
|
||||
} else {
|
||||
mTextureClientAllocator =
|
||||
|
@ -723,8 +724,9 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
|
|||
// and because it allows color conversion ocurring directly from this texture
|
||||
// DXVA does not seem to accept IDXGIKeyedMutex textures as input.
|
||||
mSyncObject =
|
||||
layers::SyncObject::CreateSyncObject(aKnowsCompositor->GetTextureFactoryIdentifier().mSyncHandle,
|
||||
mDevice);
|
||||
layers::SyncObjectClient::CreateSyncObjectClient(
|
||||
aKnowsCompositor->GetTextureFactoryIdentifier().mSyncHandle,
|
||||
mDevice);
|
||||
}
|
||||
}
|
||||
mTextureClientAllocator->SetMaxPoolSize(5);
|
||||
|
@ -882,7 +884,8 @@ D3D11DXVA2Manager::CreateOutputSample(RefPtr<IMFSample>& aSample,
|
|||
__uuidof(ID3D11Texture2D), aTexture, 0, FALSE, getter_AddRefs(buffer));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
sample->AddBuffer(buffer);
|
||||
hr = sample->AddBuffer(buffer);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
aSample = sample;
|
||||
return S_OK;
|
||||
|
@ -952,6 +955,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
|
|||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
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
|
||||
// is null. It's better to avoid that crash.
|
||||
client->SyncWithObject(mSyncObject);
|
||||
mSyncObject->FinalizeFrame();
|
||||
mSyncObject->Synchronize();
|
||||
}
|
||||
|
||||
image.forget(aOutImage);
|
||||
|
|
|
@ -449,7 +449,10 @@ WMFVideoMFTManager::InitializeDXVA()
|
|||
}
|
||||
MOZ_ASSERT(!mDXVA2Manager);
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
|
@ -934,7 +937,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
// Blocks until decoded sample is produced by the deoder.
|
||||
// Blocks until decoded sample is produced by the decoder.
|
||||
HRESULT
|
||||
WMFVideoMFTManager::Output(int64_t aStreamOffset,
|
||||
RefPtr<MediaData>& aOutData)
|
||||
|
|
|
@ -353,9 +353,7 @@ BasicCardService::DecodeBasicCardData(const nsAString& aData,
|
|||
#undef EncodeBasicCardProperty
|
||||
#undef EncodeAddressProperty
|
||||
#undef DecodeBasicCardProperty
|
||||
#undef DecodeBasicCardCardNumber
|
||||
#undef DecodeAddressProperty
|
||||
#undef DecodeAddressLine
|
||||
#undef AMEX
|
||||
#undef CARTEBANCAIRE
|
||||
#undef DINERS
|
||||
|
|
|
@ -148,84 +148,41 @@ PaymentRequestService::SetTestingUIService(nsIPaymentUIService* aUIService)
|
|||
}
|
||||
|
||||
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;
|
||||
if (mTestingUIService) {
|
||||
switch (aActionType) {
|
||||
case nsIPaymentActionRequest::CANMAKE_ACTION: {
|
||||
rv = mTestingUIService->CanMakePayment(aRequestId, getter_AddRefs(response));
|
||||
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;
|
||||
}
|
||||
}
|
||||
uiService = mTestingUIService;
|
||||
} else {
|
||||
uiService = do_GetService(NS_PAYMENT_UI_SERVICE_CONTRACT_ID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(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) {
|
||||
rv = RespondPayment(response);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
switch (aActionType) {
|
||||
case nsIPaymentActionRequest::SHOW_ACTION: {
|
||||
rv = uiService->ShowPayment(aRequestId);
|
||||
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;
|
||||
}
|
||||
|
@ -305,31 +262,25 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
|||
* registered third party payment apps.
|
||||
*/
|
||||
case nsIPaymentActionRequest::CANMAKE_ACTION: {
|
||||
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
|
||||
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
|
||||
MOZ_ASSERT(canMakeResponse);
|
||||
if (IsBasicCardPayment(requestId)) {
|
||||
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
|
||||
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
|
||||
MOZ_ASSERT(canMakeResponse);
|
||||
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 {
|
||||
rv = CallTestingUIAction(requestId, type);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = canMakeResponse->Init(requestId, false);
|
||||
}
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* TODO: Launch/inform payment UI here once the UI module is implemented.
|
||||
*/
|
||||
case nsIPaymentActionRequest::SHOW_ACTION: {
|
||||
if (mShowingRequest) {
|
||||
nsCOMPtr<nsIPaymentResponseData> responseData =
|
||||
|
@ -356,7 +307,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
|||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = CallTestingUIAction(requestId, type);
|
||||
rv = LaunchUIAction(requestId, type);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -365,7 +316,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
|||
}
|
||||
case nsIPaymentActionRequest::ABORT_ACTION:
|
||||
case nsIPaymentActionRequest::COMPLETE_ACTION: {
|
||||
rv = CallTestingUIAction(requestId, type);
|
||||
rv = LaunchUIAction(requestId, type);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -390,7 +341,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
|||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = CallTestingUIAction(requestId, type);
|
||||
rv = LaunchUIAction(requestId, type);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ private:
|
|||
|
||||
// this method is only used for testing
|
||||
nsresult
|
||||
CallTestingUIAction(const nsAString& aRequestId, uint32_t aActionType);
|
||||
LaunchUIAction(const nsAString& aRequestId, uint32_t aActionType);
|
||||
|
||||
bool
|
||||
IsBasicCardPayment(const nsAString& aRequestId);
|
||||
|
|
|
@ -41,20 +41,17 @@ function abortPaymentResponse(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);
|
||||
paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
}
|
||||
|
||||
function completePaymentResponse(requestId) {
|
||||
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
|
||||
createInstance(Ci.nsIPaymentCompleteActionResponse);
|
||||
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
|
||||
return completeResponse;
|
||||
paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
}
|
||||
|
||||
const detailedResponseUI = {
|
||||
canMakePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
showPayment: function(requestId) {
|
||||
try {
|
||||
basiccardResponseData.initData("Bill A. Pacheco", // cardholderName
|
||||
|
@ -73,20 +70,16 @@ const detailedResponseUI = {
|
|||
"Bill A. Pacheco", // payer name
|
||||
"", // payer email
|
||||
""); // payer phone
|
||||
return showResponse;
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
abortPayment: abortPaymentResponse,
|
||||
completePayment: completePaymentResponse,
|
||||
updatePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
const simpleResponseUI = {
|
||||
canMakePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
showPayment: function(requestId) {
|
||||
try {
|
||||
basiccardResponseData.initData("", // cardholderName
|
||||
|
@ -105,12 +98,11 @@ const simpleResponseUI = {
|
|||
"Bill A. Pacheco", // payer name
|
||||
"", // payer email
|
||||
""); // payer phone
|
||||
return showResponse;
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
abortPayment: abortPaymentResponse,
|
||||
completePayment: completePaymentResponse,
|
||||
updatePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
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 = {
|
||||
shippingOptionChanged: false,
|
||||
canMakePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
showPayment: function(requestId) {
|
||||
paymentSrv.changeShippingAddress(requestId, shippingAddress);
|
||||
return null;
|
||||
},
|
||||
abortPayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
completePayment: function(requestId) {
|
||||
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
|
||||
createInstance(Ci.nsIPaymentCompleteActionResponse);
|
||||
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
|
||||
return completeResponse;
|
||||
paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
updatePayment: function(requestId) {
|
||||
let showResponse = null;
|
||||
|
@ -87,16 +82,13 @@ const NormalUIService = {
|
|||
"Bill A. Pacheco", // payer name
|
||||
"", // payer email
|
||||
""); // payer phone
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
}
|
||||
return showResponse;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
const RejectUIService = {
|
||||
canMakePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
showPayment: function(requestId) {
|
||||
const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
|
||||
createInstance(Ci.nsIGeneralResponseData);
|
||||
|
@ -115,34 +107,24 @@ const RejectUIService = {
|
|||
"", // payer name
|
||||
"", // payer email
|
||||
""); // payer phone
|
||||
|
||||
return showResponse;
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
abortPayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
completePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
updatePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
const ErrorUIService = {
|
||||
canMakePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
showPayment: function(requestId) {
|
||||
paymentSrv.changeShippingOption(requestId, "");
|
||||
return null;
|
||||
},
|
||||
abortPayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
completePayment: function(requestId) {
|
||||
return null;
|
||||
},
|
||||
updatePayment: function(requestId) {
|
||||
let payRequest = paymentSrv.getPaymentRequestById(requestId);
|
||||
|
@ -168,8 +150,7 @@ const ErrorUIService = {
|
|||
"", // payer name
|
||||
"", // payer email
|
||||
""); // payer phone
|
||||
|
||||
return showResponse;
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ scheme = https
|
|||
support-files =
|
||||
simple_payment_request.html
|
||||
BasiccardChromeScript.js
|
||||
CanMakePaymentChromeScript.js
|
||||
ConstructorChromeScript.js
|
||||
GeneralChromeScript.js
|
||||
ShowPaymentChromeScript.js
|
||||
|
||||
[test_abortPayment.html]
|
||||
|
|
|
@ -13,6 +13,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345367
|
|||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gUrl = SimpleTest.getTestFileURL('GeneralChromeScript.js');
|
||||
var gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||
|
||||
const defaultMethods = [{
|
||||
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() {
|
||||
testBeforeShow()
|
||||
.then(testAfterShow)
|
||||
.then(SimpleTest.finish)
|
||||
.then(teardown)
|
||||
.catch( e => {
|
||||
ok(false, "Unexpected error: " + e.name);
|
||||
SimpleTest.finish();
|
||||
|
|
|
@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
|
|||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gUrl = SimpleTest.getTestFileURL('CanMakePaymentChromeScript.js');
|
||||
var gUrl = SimpleTest.getTestFileURL('GeneralChromeScript.js');
|
||||
var gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||
|
||||
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() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
|
||||
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();
|
||||
}).catch((err) => {
|
||||
ok(false, "Expected no error, but got '" + err.name +"'.");
|
||||
|
@ -118,7 +135,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
|
|||
}
|
||||
|
||||
function runTests() {
|
||||
testSimple()
|
||||
testDefaultAction()
|
||||
.then(testSimple)
|
||||
.then(testAfterShow)
|
||||
.then(testAfterAbort)
|
||||
.then(testNotAllowed)
|
||||
|
|
|
@ -330,10 +330,12 @@ FramingChecker::ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem,
|
|||
break;
|
||||
}
|
||||
|
||||
rv = errorObject->InitWithWindowID(msg, EmptyString(), EmptyString(), 0, 0,
|
||||
nsIScriptError::errorFlag,
|
||||
"X-Frame-Options",
|
||||
topInnerWindow->WindowID());
|
||||
// It is ok to use InitWithSanitizedSource, because the source string is
|
||||
// empty.
|
||||
rv = errorObject->InitWithSanitizedSource(msg, EmptyString(), EmptyString(),
|
||||
0, 0, nsIScriptError::errorFlag,
|
||||
"X-Frame-Options",
|
||||
topInnerWindow->WindowID());
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6221,6 +6221,26 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
|||
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;
|
||||
mStatus = aStatus;
|
||||
|
||||
|
@ -6229,12 +6249,6 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
|||
if (aStatus == Closing) {
|
||||
Close();
|
||||
}
|
||||
|
||||
// Make sure the hybrid event target stops dispatching runnables
|
||||
// once we reaching the killing state.
|
||||
if (aStatus == Killing) {
|
||||
mWorkerHybridEventTarget->ForgetWorkerPrivate(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (mCrossThreadDispatcher) {
|
||||
|
|
|
@ -339,9 +339,6 @@ XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
|
|||
|
||||
bool isChrome = false;
|
||||
if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
|
||||
nsAutoCString spec;
|
||||
if (mDocumentURI)
|
||||
mDocumentURI->GetSpec(spec);
|
||||
|
||||
nsAutoString error;
|
||||
error.AssignLiteral("Cross site loading using document.load is no "
|
||||
|
@ -353,14 +350,15 @@ XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
|
|||
return false;
|
||||
}
|
||||
|
||||
rv = errorObject->InitWithWindowID(error,
|
||||
NS_ConvertUTF8toUTF16(spec),
|
||||
EmptyString(),
|
||||
0, 0, nsIScriptError::warningFlag,
|
||||
"DOM",
|
||||
callingDoc ?
|
||||
callingDoc->InnerWindowID() :
|
||||
this->InnerWindowID());
|
||||
rv = errorObject->InitWithSourceURI(error,
|
||||
mDocumentURI,
|
||||
EmptyString(),
|
||||
0, 0,
|
||||
nsIScriptError::warningFlag,
|
||||
"DOM",
|
||||
callingDoc ?
|
||||
callingDoc->InnerWindowID() :
|
||||
this->InnerWindowID());
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
|
|
|
@ -57,7 +57,6 @@ static const char* sEGLExtensionNames[] = {
|
|||
"EGL_KHR_create_context",
|
||||
"EGL_KHR_stream",
|
||||
"EGL_KHR_stream_consumer_gltexture",
|
||||
"EGL_EXT_device_base",
|
||||
"EGL_EXT_device_query",
|
||||
"EGL_NV_stream_consumer_gltexture_yuv",
|
||||
"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)) {
|
||||
const GLLibraryLoader::SymLoadStruct queryDisplaySymbols[] = {
|
||||
SYMBOL(QueryDisplayAttribEXT),
|
||||
SYMBOL(QueryDeviceAttribEXT),
|
||||
END_OF_SYMBOLS
|
||||
};
|
||||
|
|
|
@ -108,7 +108,6 @@ public:
|
|||
KHR_create_context,
|
||||
KHR_stream,
|
||||
KHR_stream_consumer_gltexture,
|
||||
EXT_device_base,
|
||||
EXT_device_query,
|
||||
NV_stream_consumer_gltexture_yuv,
|
||||
ANGLE_stream_producer_d3d_texture_nv12,
|
||||
|
@ -292,8 +291,8 @@ public:
|
|||
EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) const
|
||||
WRAP( fCreateStreamKHR(dpy, attrib_list) )
|
||||
|
||||
EGLStreamKHR fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const
|
||||
WRAP( fDestroyStreamKHR(dpy, stream) )
|
||||
EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const
|
||||
WRAP( fDestroyStreamKHR(dpy, stream) )
|
||||
|
||||
EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint* value) const
|
||||
WRAP( fQueryStreamKHR(dpy, stream, attribute, value) )
|
||||
|
@ -305,11 +304,10 @@ public:
|
|||
EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) const
|
||||
WRAP( fStreamConsumerReleaseKHR(dpy, stream) )
|
||||
|
||||
// EXT_device_base
|
||||
// EXT_device_query
|
||||
EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib* value) const
|
||||
WRAP( fQueryDisplayAttribEXT(dpy, attribute, value) )
|
||||
|
||||
// EXT_device_query
|
||||
EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib* value) const
|
||||
WRAP( fQueryDeviceAttribEXT(device, attribute, value) )
|
||||
|
||||
|
@ -454,7 +452,7 @@ private:
|
|||
EGLint (GLAPIENTRY * fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
|
||||
//KHR_stream
|
||||
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,
|
||||
EGLStreamKHR stream,
|
||||
EGLenum attribute,
|
||||
|
@ -464,11 +462,10 @@ private:
|
|||
EGLStreamKHR stream);
|
||||
EGLBoolean (GLAPIENTRY * fStreamConsumerReleaseKHR)(EGLDisplay dpy,
|
||||
EGLStreamKHR stream);
|
||||
// EXT_device_base
|
||||
// EXT_device_query
|
||||
EGLBoolean (GLAPIENTRY * fQueryDisplayAttribEXT)(EGLDisplay dpy,
|
||||
EGLint attribute,
|
||||
EGLAttrib* value);
|
||||
// EXT_device_query
|
||||
EGLBoolean (GLAPIENTRY * fQueryDeviceAttribEXT)(EGLDeviceEXT device,
|
||||
EGLint attribute,
|
||||
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/LayerTransactionChild.h"
|
||||
#include "mozilla/layers/PersistentBufferProvider.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
#include "ClientReadbackLayer.h" // for ClientReadbackLayer
|
||||
#include "nsAString.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
@ -728,7 +729,7 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
|
|||
if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
|
||||
if (mForwarder->GetSyncObject() &&
|
||||
mForwarder->GetSyncObject()->IsSyncObjectValid()) {
|
||||
mForwarder->GetSyncObject()->FinalizeFrame();
|
||||
mForwarder->GetSyncObject()->Synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1745,25 +1745,6 @@ UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData)
|
|||
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>
|
||||
TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
|
||||
{
|
||||
|
|
|
@ -66,6 +66,7 @@ class TextureClientPool;
|
|||
#endif
|
||||
class TextureForwarder;
|
||||
class KeepAlive;
|
||||
class SyncObjectClient;
|
||||
|
||||
/**
|
||||
* TextureClient is the abstraction that allows us to share data between the
|
||||
|
@ -93,36 +94,6 @@ enum TextureAllocationFlags {
|
|||
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
|
||||
* 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 void SyncWithObject(SyncObject* aFence) {};
|
||||
virtual void SyncWithObject(SyncObjectClient* aSyncObject) {};
|
||||
|
||||
virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
|
||||
|
||||
|
@ -614,7 +585,7 @@ public:
|
|||
mReadbackSink = aReadbackSink;
|
||||
}
|
||||
|
||||
void SyncWithObject(SyncObject* aFence) { mData->SyncWithObject(aFence); }
|
||||
void SyncWithObject(SyncObjectClient* aSyncObject) { mData->SyncWithObject(aSyncObject); }
|
||||
|
||||
LayersIPCChannel* GetAllocator() { return mAllocator; }
|
||||
|
||||
|
|
|
@ -298,7 +298,9 @@ CompositorD3D11::GetTextureFactoryIdentifier()
|
|||
ident.mMaxTextureSize = GetMaxTextureSize();
|
||||
ident.mParentProcessType = XRE_GetProcessType();
|
||||
ident.mParentBackend = LayersBackend::LAYERS_D3D11;
|
||||
ident.mSyncHandle = mAttachments->mSyncHandle;
|
||||
if (mAttachments->mSyncObject) {
|
||||
ident.mSyncHandle = mAttachments->mSyncObject->GetSyncHandle();
|
||||
}
|
||||
return ident;
|
||||
}
|
||||
|
||||
|
@ -1057,29 +1059,12 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
|
|||
|
||||
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
|
||||
|
||||
if (mAttachments->mSyncTexture) {
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
|
||||
|
||||
MOZ_ASSERT(mutex);
|
||||
{
|
||||
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";
|
||||
}
|
||||
if (mAttachments->mSyncObject) {
|
||||
if (!mAttachments->mSyncObject->Synchronize()) {
|
||||
// It's timeout here. Since the timeout is related to the driver-removed,
|
||||
// clear the render-bounding size to skip this frame.
|
||||
*aRenderBoundsOut = IntRect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1178,8 +1163,9 @@ CompositorD3D11::Present()
|
|||
HRESULT hr = mSwapChain->QueryInterface((IDXGISwapChain1**)getter_AddRefs(chain));
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
if (mUseMutexOnPresent && mAttachments->mSyncTexture) {
|
||||
mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
|
||||
if (mUseMutexOnPresent && mAttachments->mSyncObject) {
|
||||
SyncObjectD3D11Host* d3dSyncObj = (SyncObjectD3D11Host*)mAttachments->mSyncObject.get();
|
||||
mutex = d3dSyncObj->GetKeyedMutex();
|
||||
MOZ_ASSERT(mutex);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@ using namespace gfx;
|
|||
static const size_t kInitialMaximumTriangles = 64;
|
||||
|
||||
DeviceAttachmentsD3D11::DeviceAttachmentsD3D11(ID3D11Device* device)
|
||||
: mSyncHandle(0),
|
||||
mMaximumTriangles(kInitialMaximumTriangles),
|
||||
: mMaximumTriangles(kInitialMaximumTriangles),
|
||||
mDevice(device),
|
||||
mContinueInit(true),
|
||||
mInitialized(false),
|
||||
|
@ -225,36 +224,13 @@ DeviceAttachmentsD3D11::InitSyncObject()
|
|||
return true;
|
||||
}
|
||||
|
||||
// It's okay to do this on Windows 8. But for now we'll just bail
|
||||
// whenever we're using WARP.
|
||||
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;
|
||||
MOZ_ASSERT(!mSyncObject);
|
||||
MOZ_ASSERT(mDevice);
|
||||
|
||||
RefPtr<ID3D11Texture2D> texture;
|
||||
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
|
||||
if (Failed(hr, "create sync texture")) {
|
||||
return false;
|
||||
}
|
||||
mSyncObject = SyncObjectHost::CreateSyncObjectHost(mDevice);
|
||||
MOZ_ASSERT(mSyncObject);
|
||||
|
||||
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
|
||||
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;
|
||||
return mSyncObject->Init();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
#include <d3d11.h>
|
||||
#include <dxgi1_2.h>
|
||||
|
||||
|
@ -70,8 +71,8 @@ public:
|
|||
RefPtr<ID3D11BlendState> mNonPremulBlendState;
|
||||
RefPtr<ID3D11BlendState> mComponentBlendState;
|
||||
RefPtr<ID3D11BlendState> mDisabledBlendState;
|
||||
RefPtr<IDXGIResource> mSyncTexture;
|
||||
HANDLE mSyncHandle;
|
||||
|
||||
RefPtr<SyncObjectHost> mSyncObject;
|
||||
|
||||
void SetDeviceReset() {
|
||||
mDeviceReset = true;
|
||||
|
|
|
@ -1264,7 +1264,11 @@ MLGDeviceD3D11::GetTextureFactoryIdentifier() const
|
|||
GetLayersBackend(),
|
||||
XRE_GetProcessType(),
|
||||
GetMaxTextureSize());
|
||||
ident.mSyncHandle = mSyncHandle;
|
||||
|
||||
if (mSyncObject) {
|
||||
ident.mSyncHandle = mSyncObject->GetSyncHandle();
|
||||
}
|
||||
|
||||
return ident;
|
||||
}
|
||||
|
||||
|
@ -1777,34 +1781,13 @@ MLGDeviceD3D11::SetPSTexturesNV12(uint32_t aSlot, TextureSource* aTexture)
|
|||
bool
|
||||
MLGDeviceD3D11::InitSyncObject()
|
||||
{
|
||||
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;
|
||||
MOZ_ASSERT(!mSyncObject);
|
||||
MOZ_ASSERT(mDevice);
|
||||
|
||||
RefPtr<ID3D11Texture2D> texture;
|
||||
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
|
||||
if (FAILED(hr) || !texture) {
|
||||
return Fail("FEATURE_FAILURE_SYNC_OBJECT",
|
||||
"Could not create a sync texture: %x", hr);
|
||||
}
|
||||
mSyncObject = SyncObjectHost::CreateSyncObjectHost(mDevice);
|
||||
MOZ_ASSERT(mSyncObject);
|
||||
|
||||
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
|
||||
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;
|
||||
return mSyncObject->Init();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1828,27 +1811,14 @@ MLGDeviceD3D11::GetDiagnostics(GPUStats* aStats)
|
|||
bool
|
||||
MLGDeviceD3D11::Synchronize()
|
||||
{
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
|
||||
MOZ_ASSERT(mSyncObject);
|
||||
|
||||
{
|
||||
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.
|
||||
if (mSyncObject) {
|
||||
if (!mSyncObject->Synchronize()) {
|
||||
// It's timeout or other error. Handle the device-reset here.
|
||||
HandleDeviceReset("SyncObject");
|
||||
return false;
|
||||
}
|
||||
if (hr == WAIT_ABANDONED) {
|
||||
gfxCriticalNote << "GFX: AL_D3D11 abandoned sync";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
#ifndef 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/SyncObject.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include <d3d11_1.h>
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -305,8 +307,7 @@ private:
|
|||
RefPtr<ID3D11RasterizerState> mRasterizerStateNoScissor;
|
||||
RefPtr<ID3D11RasterizerState> mRasterizerStateScissor;
|
||||
|
||||
RefPtr<IDXGIResource> mSyncTexture;
|
||||
HANDLE mSyncHandle;
|
||||
RefPtr<SyncObjectHost> mSyncObject;
|
||||
|
||||
RefPtr<MLGBuffer> mUnitQuadVB;
|
||||
RefPtr<MLGBuffer> mUnitTriangleVB;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/webrender/RenderD3D11TextureHostOGL.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -355,15 +357,15 @@ DXGITextureData::FillInfo(TextureData::Info& aInfo) const
|
|||
}
|
||||
|
||||
void
|
||||
D3D11TextureData::SyncWithObject(SyncObject* aSyncObject)
|
||||
D3D11TextureData::SyncWithObject(SyncObjectClient* aSyncObject)
|
||||
{
|
||||
if (!aSyncObject || mHasSynchronization) {
|
||||
// When we have per texture synchronization we sync using the keyed mutex.
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
|
||||
SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
|
||||
MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObjectClient::SyncType::D3D11);
|
||||
SyncObjectD3D11Client* sync = static_cast<SyncObjectD3D11Client*>(aSyncObject);
|
||||
sync->RegisterTexture(mTexture);
|
||||
}
|
||||
|
||||
|
@ -967,11 +969,42 @@ DXGITextureHostD3D11::AcquireTextureSource(CompositableTextureSourceRef& aTextur
|
|||
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
|
||||
DXGITextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||
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
|
||||
|
@ -979,7 +1012,44 @@ DXGITextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
|
|||
Range<const wr::ImageKey>& aImageKeys,
|
||||
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
|
||||
|
@ -989,7 +1059,29 @@ DXGITextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
|
|||
wr::ImageRendering aFilter,
|
||||
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,
|
||||
|
@ -1134,11 +1226,21 @@ DXGIYCbCrTextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aText
|
|||
return !!aTexture;
|
||||
}
|
||||
|
||||
void
|
||||
DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
|
||||
{
|
||||
// We use AddImage() directly. It's no corresponding RenderTextureHost.
|
||||
}
|
||||
|
||||
void
|
||||
DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||
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
|
||||
|
@ -1146,7 +1248,30 @@ DXGIYCbCrTextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
|
|||
Range<const wr::ImageKey>& aImageKeys,
|
||||
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
|
||||
|
@ -1156,7 +1281,9 @@ DXGIYCbCrTextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
|
|||
wr::ImageRendering aFilter,
|
||||
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
|
||||
|
@ -1398,17 +1525,6 @@ CompositingRenderTargetD3D11::GetSize() const
|
|||
return TextureSourceD3D11::GetSize();
|
||||
}
|
||||
|
||||
SyncObjectD3D11::SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice)
|
||||
: mSyncHandle(aSyncHandle)
|
||||
{
|
||||
if (!aDevice) {
|
||||
mD3D11Device = DeviceManagerDx::Get()->GetContentDevice();
|
||||
return;
|
||||
}
|
||||
|
||||
mD3D11Device = aDevice;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ShouldDevCrashOnSyncInitFailure()
|
||||
{
|
||||
|
@ -1424,18 +1540,107 @@ ShouldDevCrashOnSyncInitFailure()
|
|||
!DeviceManagerDx::Get()->HasDeviceReset();
|
||||
}
|
||||
|
||||
SyncObjectD3D11Host::SyncObjectD3D11Host(ID3D11Device* aDevice)
|
||||
: mSyncHandle(0)
|
||||
, mDevice(aDevice)
|
||||
{
|
||||
MOZ_ASSERT(aDevice);
|
||||
}
|
||||
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT hr = mD3D11Device->OpenSharedResource(
|
||||
HRESULT hr = mDevice->OpenSharedResource(
|
||||
mSyncHandle,
|
||||
__uuidof(ID3D11Texture2D),
|
||||
(void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture));
|
||||
if (FAILED(hr) || !mD3D11Texture) {
|
||||
(void**)(ID3D11Texture2D**)getter_AddRefs(mSyncTexture));
|
||||
if (FAILED(hr) || !mSyncTexture) {
|
||||
gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr);
|
||||
if (ShouldDevCrashOnSyncInitFailure()) {
|
||||
gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
|
||||
|
@ -1443,10 +1648,10 @@ SyncObjectD3D11::Init()
|
|||
return false;
|
||||
}
|
||||
|
||||
hr = mD3D11Texture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
|
||||
hr = mSyncTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
|
||||
if (FAILED(hr) || !mKeyedMutex) {
|
||||
// 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);
|
||||
MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
|
||||
}
|
||||
|
@ -1455,25 +1660,25 @@ SyncObjectD3D11::Init()
|
|||
}
|
||||
|
||||
void
|
||||
SyncObjectD3D11::RegisterTexture(ID3D11Texture2D* aTexture)
|
||||
SyncObjectD3D11Client::RegisterTexture(ID3D11Texture2D* aTexture)
|
||||
{
|
||||
mD3D11SyncedTextures.push_back(aTexture);
|
||||
mSyncedTextures.push_back(aTexture);
|
||||
}
|
||||
|
||||
bool
|
||||
SyncObjectD3D11::IsSyncObjectValid()
|
||||
SyncObjectD3D11Client::IsSyncObjectValid()
|
||||
{
|
||||
RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
|
||||
if (!dev || (NS_IsMainThread() && dev != mD3D11Device)) {
|
||||
if (!dev || (NS_IsMainThread() && dev != mDevice)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SyncObjectD3D11::FinalizeFrame()
|
||||
SyncObjectD3D11Client::Synchronize()
|
||||
{
|
||||
if (!mD3D11SyncedTextures.size()) {
|
||||
if (!mSyncedTextures.size()) {
|
||||
return;
|
||||
}
|
||||
if (!Init()) {
|
||||
|
@ -1496,7 +1701,7 @@ SyncObjectD3D11::FinalizeFrame()
|
|||
box.back = box.bottom = box.right = 1;
|
||||
|
||||
RefPtr<ID3D11Device> dev;
|
||||
mD3D11Texture->GetDevice(getter_AddRefs(dev));
|
||||
mSyncTexture->GetDevice(getter_AddRefs(dev));
|
||||
|
||||
if (dev == DeviceManagerDx::Get()->GetContentDevice()) {
|
||||
if (DeviceManagerDx::Get()->HasDeviceReset()) {
|
||||
|
@ -1504,7 +1709,7 @@ SyncObjectD3D11::FinalizeFrame()
|
|||
}
|
||||
}
|
||||
|
||||
if (dev != mD3D11Device) {
|
||||
if (dev != mDevice) {
|
||||
gfxWarning() << "Attempt to sync texture from invalid device.";
|
||||
return;
|
||||
}
|
||||
|
@ -1512,11 +1717,11 @@ SyncObjectD3D11::FinalizeFrame()
|
|||
RefPtr<ID3D11DeviceContext> ctx;
|
||||
dev->GetImmediateContext(getter_AddRefs(ctx));
|
||||
|
||||
for (auto iter = mD3D11SyncedTextures.begin(); iter != mD3D11SyncedTextures.end(); iter++) {
|
||||
ctx->CopySubresourceRegion(mD3D11Texture, 0, 0, 0, 0, *iter, 0, &box);
|
||||
for (auto iter = mSyncedTextures.begin(); iter != mSyncedTextures.end(); iter++) {
|
||||
ctx->CopySubresourceRegion(mSyncTexture, 0, 0, 0, 0, *iter, 0, &box);
|
||||
}
|
||||
|
||||
mD3D11SyncedTextures.clear();
|
||||
mSyncedTextures.clear();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/layers/Compositor.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/TextureHost.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
@ -89,7 +90,7 @@ public:
|
|||
TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags) const override;
|
||||
|
||||
virtual void SyncWithObject(SyncObject* aSync) override;
|
||||
virtual void SyncWithObject(SyncObjectClient* aSyncObject) override;
|
||||
|
||||
ID3D11Texture2D* GetD3D11Texture() { return mTexture; }
|
||||
|
||||
|
@ -323,6 +324,8 @@ public:
|
|||
|
||||
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
|
||||
|
||||
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
|
||||
|
||||
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
||||
|
||||
|
@ -384,6 +387,8 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
|
||||
|
||||
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
||||
|
||||
|
@ -436,26 +441,49 @@ private:
|
|||
RefPtr<ID3D11RenderTargetView> mRTView;
|
||||
};
|
||||
|
||||
class SyncObjectD3D11 : public SyncObject
|
||||
class SyncObjectD3D11Host : public SyncObjectHost
|
||||
{
|
||||
public:
|
||||
explicit SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice);
|
||||
virtual void FinalizeFrame();
|
||||
virtual bool IsSyncObjectValid();
|
||||
explicit SyncObjectD3D11Host(ID3D11Device* aDevice);
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
bool Init();
|
||||
|
||||
private:
|
||||
SyncHandle mSyncHandle;
|
||||
RefPtr<ID3D11Device> mD3D11Device;
|
||||
RefPtr<ID3D11Texture2D> mD3D11Texture;
|
||||
RefPtr<ID3D11Device> mDevice;
|
||||
RefPtr<ID3D11Texture2D> mSyncTexture;
|
||||
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
||||
std::vector<ID3D11Texture2D*> mD3D11SyncedTextures;
|
||||
std::vector<ID3D11Texture2D*> mSyncedTextures;
|
||||
};
|
||||
|
||||
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class SyncObject;
|
||||
class SyncObjectClient;
|
||||
class TextureForwarder;
|
||||
class LayersIPCActor;
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
|||
|
||||
void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
|
||||
|
||||
SyncObject* GetSyncObject() { return mSyncObject; }
|
||||
SyncObjectClient* GetSyncObject() { return mSyncObject; }
|
||||
|
||||
int32_t GetMaxTextureSize() const
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ public:
|
|||
|
||||
protected:
|
||||
TextureFactoryIdentifier mTextureFactoryIdentifier;
|
||||
RefPtr<SyncObject> mSyncObject;
|
||||
RefPtr<SyncObjectClient> mSyncObject;
|
||||
|
||||
const int32_t mSerial;
|
||||
static mozilla::Atomic<int32_t> sSerialCounter;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
|
||||
#include "mozilla/layers/LayerTransactionChild.h"
|
||||
#include "mozilla/layers/PTextureChild.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
#include "ShadowLayerUtils.h"
|
||||
#include "mozilla/layers/TextureClient.h" // for TextureClient
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc
|
||||
|
@ -175,7 +176,7 @@ KnowsCompositor::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier
|
|||
{
|
||||
mTextureFactoryIdentifier = aIdentifier;
|
||||
|
||||
mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
|
||||
mSyncObject = SyncObjectClient::CreateSyncObjectClient(aIdentifier.mSyncHandle);
|
||||
}
|
||||
|
||||
KnowsCompositor::KnowsCompositor()
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "MaskOperation.h"
|
||||
#include "MLGDevice.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "ShaderDefinitionsMLGPU.h"
|
||||
|
|
|
@ -224,6 +224,7 @@ EXPORTS.mozilla.layers += [
|
|||
'ShareableCanvasRenderer.h',
|
||||
'SourceSurfaceSharedData.h',
|
||||
'SourceSurfaceVolatileData.h',
|
||||
'SyncObject.h',
|
||||
'TextureSourceProvider.h',
|
||||
'TextureWrapperImage.h',
|
||||
'TransactionIdAllocator.h',
|
||||
|
@ -456,6 +457,7 @@ UNIFIED_SOURCES += [
|
|||
'ShareableCanvasRenderer.cpp',
|
||||
'SourceSurfaceSharedData.cpp',
|
||||
'SourceSurfaceVolatileData.cpp',
|
||||
'SyncObject.cpp',
|
||||
'TextureSourceProvider.cpp',
|
||||
'TextureWrapperImage.cpp',
|
||||
'wr/AsyncImagePipelineManager.cpp',
|
||||
|
|
|
@ -1436,7 +1436,11 @@ WebRenderBridgeParent::GetTextureFactoryIdentifier()
|
|||
return TextureFactoryIdentifier(LayersBackend::LAYERS_WR,
|
||||
XRE_GetProcessType(),
|
||||
mApi->GetMaxTextureSize(),
|
||||
mApi->GetUseANGLE());
|
||||
mApi->GetUseANGLE(),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
mApi->GetSyncHandle());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -18,7 +18,6 @@ WebRenderTextureHost::WebRenderTextureHost(const SurfaceDescriptor& aDesc,
|
|||
wr::ExternalImageId& aExternalImageId)
|
||||
: TextureHost(aFlags)
|
||||
, mExternalImageId(aExternalImageId)
|
||||
, mIsWrappingNativeHandle(false)
|
||||
{
|
||||
// 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
|
||||
|
@ -47,25 +46,6 @@ WebRenderTextureHost::CreateRenderTextureHost(const layers::SurfaceDescriptor& a
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,6 @@ public:
|
|||
|
||||
int32_t GetRGBStride();
|
||||
|
||||
bool IsWrappingNativeHandle() { return mIsWrappingNativeHandle; }
|
||||
|
||||
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
|
||||
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
|
||||
|
||||
|
@ -83,8 +81,6 @@ protected:
|
|||
|
||||
RefPtr<TextureHost> mWrappedTextureHost;
|
||||
wr::ExternalImageId mExternalImageId;
|
||||
|
||||
bool mIsWrappingNativeHandle;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -1100,11 +1100,13 @@ SizeDistance(gfxFontconfigFontEntry* aEntry,
|
|||
void
|
||||
gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||
bool& aNeedsSyntheticBold)
|
||||
bool& aNeedsSyntheticBold,
|
||||
bool aIgnoreSizeTolerance)
|
||||
{
|
||||
gfxFontFamily::FindAllFontsForStyle(aFontStyle,
|
||||
aFontEntryList,
|
||||
aNeedsSyntheticBold);
|
||||
aNeedsSyntheticBold,
|
||||
aIgnoreSizeTolerance);
|
||||
|
||||
if (!mHasNonScalableFaces) {
|
||||
return;
|
||||
|
@ -1113,7 +1115,7 @@ gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
|||
// Iterate over the the available fonts while compacting any groups
|
||||
// of unscalable fonts with matching styles into a single entry
|
||||
// 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.
|
||||
size_t skipped = 0;
|
||||
gfxFontconfigFontEntry* bestEntry = nullptr;
|
||||
|
@ -1121,7 +1123,8 @@ gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
|||
for (size_t i = 0; i < aFontEntryList.Length(); i++) {
|
||||
gfxFontconfigFontEntry* entry =
|
||||
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
|
||||
// the group of unscalable fonts, then start a new group.
|
||||
if (dist < 0.0 ||
|
||||
|
@ -1766,7 +1769,7 @@ gfxFcPlatformFontList::GetFTLibrary()
|
|||
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
|
||||
gfxFontFamily* family = pfl->GetDefaultFont(&style);
|
||||
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) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -196,7 +196,8 @@ public:
|
|||
void
|
||||
FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||
bool& aNeedsSyntheticBold) override;
|
||||
bool& aNeedsSyntheticBold,
|
||||
bool aIgnoreSizeTolerance) override;
|
||||
|
||||
protected:
|
||||
virtual ~gfxFontconfigFontFamily();
|
||||
|
|
|
@ -1101,10 +1101,12 @@ gfxFontFamily::HasOtherFamilyNames()
|
|||
|
||||
gfxFontEntry*
|
||||
gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle,
|
||||
bool& aNeedsSyntheticBold)
|
||||
bool& aNeedsSyntheticBold,
|
||||
bool aIgnoreSizeTolerance)
|
||||
{
|
||||
AutoTArray<gfxFontEntry*,4> matched;
|
||||
FindAllFontsForStyle(aFontStyle, matched, aNeedsSyntheticBold);
|
||||
FindAllFontsForStyle(aFontStyle, matched, aNeedsSyntheticBold,
|
||||
aIgnoreSizeTolerance);
|
||||
if (!matched.IsEmpty()) {
|
||||
return matched[0];
|
||||
}
|
||||
|
@ -1234,7 +1236,8 @@ WeightStyleStretchDistance(gfxFontEntry* aFontEntry,
|
|||
void
|
||||
gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||
bool& aNeedsSyntheticBold)
|
||||
bool& aNeedsSyntheticBold,
|
||||
bool aIgnoreSizeTolerance)
|
||||
{
|
||||
if (!mHasStyles) {
|
||||
FindStyleVariations(); // collect faces for the family, if not already done
|
||||
|
@ -1469,7 +1472,7 @@ gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
|
|||
gfxFontEntry *fe =
|
||||
FindFontForStyle(aMatchData->mStyle ? *aMatchData->mStyle
|
||||
: gfxFontStyle(),
|
||||
needsBold);
|
||||
needsBold, true);
|
||||
|
||||
if (fe && !fe->SkipDuringSystemFallback()) {
|
||||
int32_t rank = 0;
|
||||
|
|
|
@ -643,12 +643,14 @@ public:
|
|||
// aNeedsSyntheticBold is set to true when synthetic bolding is
|
||||
// needed, false otherwise
|
||||
gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
|
||||
bool& aNeedsSyntheticBold);
|
||||
bool& aNeedsSyntheticBold,
|
||||
bool aIgnoreSizeTolerance = false);
|
||||
|
||||
virtual void
|
||||
FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
|
||||
nsTArray<gfxFontEntry*>& aFontEntryList,
|
||||
bool& aNeedsSyntheticBold);
|
||||
bool& aNeedsSyntheticBold,
|
||||
bool aIgnoreSizeTolerance = false);
|
||||
|
||||
// checks for a matching font within the family
|
||||
// used as part of the font fallback process
|
||||
|
|
|
@ -65,7 +65,7 @@ gfxTextRun::GlyphRunIterator::NextRun()
|
|||
}
|
||||
mGlyphRun = &mTextRun->mGlyphRunArray[mNextIndex];
|
||||
} else {
|
||||
if (mNextIndex > 0) {
|
||||
if (mNextIndex > 0 || !mTextRun->mSingleGlyphRun.mFont) {
|
||||
return false;
|
||||
}
|
||||
glyphRunCount = 1;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/GamepadManager.h"
|
||||
#include "mozilla/dom/VRServiceTest.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
|
||||
using layers::TextureClient;
|
||||
|
||||
|
@ -61,7 +62,8 @@ VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
|
|||
{
|
||||
if (sVRManagerChildSingleton) {
|
||||
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;
|
||||
} // namespace dom
|
||||
namespace layers {
|
||||
class SyncObjectClient;
|
||||
class TextureClient;
|
||||
}
|
||||
namespace gfx {
|
||||
|
@ -80,7 +81,7 @@ public:
|
|||
|
||||
static void IdentifyTextureHost(const layers::TextureFactoryIdentifier& aIdentifier);
|
||||
layers::LayersBackend GetBackendType() const;
|
||||
layers::SyncObject* GetSyncObject() { return mSyncObject; }
|
||||
layers::SyncObjectClient* GetSyncObject() { return mSyncObject; }
|
||||
|
||||
virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; }
|
||||
virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
|
||||
|
@ -194,7 +195,7 @@ private:
|
|||
nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
|
||||
|
||||
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?
|
||||
uint32_t mPromiseID;
|
||||
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"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
|
||||
namespace wr {
|
||||
|
||||
class RenderTextureHostOGL : public RenderTextureHost
|
||||
|
|
|
@ -71,6 +71,29 @@ RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
|
|||
MOZ_ASSERT(mRenderer);
|
||||
MOZ_ASSERT(mBridge);
|
||||
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()
|
||||
|
@ -127,6 +150,12 @@ RendererOGL::Render()
|
|||
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
|
||||
|
||||
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);
|
||||
|
||||
mGL->SwapBuffers();
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef 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/WebRenderTypes.h"
|
||||
#include "mozilla/webrender/webrender_ffi.h"
|
||||
|
@ -78,6 +80,8 @@ public:
|
|||
/// This can be called on the render thread only.
|
||||
bool Resume();
|
||||
|
||||
layers::SyncObjectHost* GetSyncObject() const { return mSyncObject.get(); }
|
||||
|
||||
layers::CompositorBridgeParentBase* GetCompositorBridge() { return mBridge; }
|
||||
|
||||
wr::WrRenderedEpochs* FlushRenderedEpochs();
|
||||
|
@ -87,7 +91,6 @@ public:
|
|||
wr::Renderer* GetRenderer() { return mRenderer; }
|
||||
|
||||
protected:
|
||||
|
||||
RefPtr<RenderThread> mThread;
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
RefPtr<widget::CompositorWidget> mWidget;
|
||||
|
@ -95,6 +98,7 @@ protected:
|
|||
layers::CompositorBridgeParentBase* mBridge;
|
||||
wr::WindowId mWindowId;
|
||||
TimeStamp mFrameStartTime;
|
||||
RefPtr<layers::SyncObjectHost> mSyncObject;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
|
|
@ -29,7 +29,8 @@ public:
|
|||
RefPtr<widget::CompositorWidget>&& aWidget,
|
||||
layers::SynchronousTask* aTask,
|
||||
bool aEnableProfiler,
|
||||
LayoutDeviceIntSize aSize)
|
||||
LayoutDeviceIntSize aSize,
|
||||
layers::SyncHandle* aHandle)
|
||||
: mRenderApi(aApi)
|
||||
, mMaxTextureSize(aMaxTextureSize)
|
||||
, mUseANGLE(aUseANGLE)
|
||||
|
@ -38,6 +39,7 @@ public:
|
|||
, mTask(aTask)
|
||||
, mEnableProfiler(aEnableProfiler)
|
||||
, mSize(aSize)
|
||||
, mSyncHandle(aHandle)
|
||||
{
|
||||
MOZ_COUNT_CTOR(NewRenderer);
|
||||
}
|
||||
|
@ -91,6 +93,13 @@ public:
|
|||
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));
|
||||
}
|
||||
|
||||
|
@ -103,6 +112,7 @@ private:
|
|||
layers::SynchronousTask* mTask;
|
||||
bool mEnableProfiler;
|
||||
LayoutDeviceIntSize mSize;
|
||||
layers::SyncHandle* mSyncHandle;
|
||||
};
|
||||
|
||||
class RemoveRenderer : public RendererEvent
|
||||
|
@ -146,13 +156,15 @@ WebRenderAPI::Create(bool aEnableProfiler,
|
|||
wr::RenderApi* renderApi = nullptr;
|
||||
GLint maxTextureSize = 0;
|
||||
bool useANGLE = false;
|
||||
layers::SyncHandle syncHandle = 0;
|
||||
|
||||
// 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
|
||||
// the next time we need to access the RenderApi object.
|
||||
layers::SynchronousTask task("Create Renderer");
|
||||
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));
|
||||
|
||||
task.Wait();
|
||||
|
@ -161,7 +173,7 @@ WebRenderAPI::Create(bool aEnableProfiler,
|
|||
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
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/webrender/webrender_ffi.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
|
@ -122,13 +123,15 @@ public:
|
|||
wr::WrIdNamespace GetNamespace();
|
||||
GLint GetMaxTextureSize() const { return mMaxTextureSize; }
|
||||
bool GetUseANGLE() const { return mUseANGLE; }
|
||||
layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
|
||||
|
||||
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)
|
||||
, mId(aId)
|
||||
, mMaxTextureSize(aMaxTextureSize)
|
||||
, mUseANGLE(aUseANGLE)
|
||||
, mSyncHandle(aSyncHandle)
|
||||
{}
|
||||
|
||||
~WebRenderAPI();
|
||||
|
@ -139,6 +142,7 @@ protected:
|
|||
wr::WindowId mId;
|
||||
GLint mMaxTextureSize;
|
||||
bool mUseANGLE;
|
||||
layers::SyncHandle mSyncHandle;
|
||||
|
||||
friend class DisplayListBuilder;
|
||||
friend class layers::WebRenderBridgeParent;
|
||||
|
|
|
@ -37,6 +37,15 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
|||
'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')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
|
@ -127,6 +127,33 @@ GetProxyStubType(JSContext* cx, HandleObject obj, HandleId id)
|
|||
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
|
||||
GetPropIRGenerator::tryAttachStub()
|
||||
{
|
||||
|
@ -272,6 +299,99 @@ GetPropIRGenerator::tryAttachIdempotentStub()
|
|||
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
|
||||
IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id,
|
||||
jsbytecode* pc, GetPropertyResultFlags resultFlags)
|
||||
|
@ -327,7 +447,7 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
|
|||
}
|
||||
shape.set(prop.maybeShape());
|
||||
|
||||
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop))
|
||||
if (IsCacheableGetPropReadSlot(obj, holder, prop))
|
||||
return CanAttachReadSlot;
|
||||
|
||||
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
|
||||
// into the prototype chain. We guard on the global lexical
|
||||
// scope's shape independently.
|
||||
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(&globalLexical->global(), holder,
|
||||
PropertyResult(shape)))
|
||||
if (!IsCacheableGetPropReadSlot(&globalLexical->global(), holder, PropertyResult(shape)))
|
||||
return false;
|
||||
|
||||
// Shape guard for global lexical.
|
||||
|
@ -1987,7 +2106,7 @@ GetNameIRGenerator::tryAttachEnvironmentName(ObjOperandId objId, HandleId id)
|
|||
}
|
||||
|
||||
holder = &env->as<NativeObject>();
|
||||
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(holder, holder, PropertyResult(shape)))
|
||||
if (!IsCacheableGetPropReadSlot(holder, holder, PropertyResult(shape)))
|
||||
return false;
|
||||
if (holder->getSlot(shape->slot()).isMagic())
|
||||
return false;
|
||||
|
@ -2827,6 +2946,63 @@ SetPropIRGenerator::trackNotAttached()
|
|||
#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
|
||||
CanAttachSetter(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id,
|
||||
MutableHandleObject holder, MutableHandleShape propShape,
|
||||
|
|
|
@ -101,186 +101,6 @@ jit::GetReturnAddressToIonCode(JSContext* cx)
|
|||
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
|
||||
jit::EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,
|
||||
Register elements, BaseObjectElementIndex target)
|
||||
|
|
|
@ -26,21 +26,6 @@
|
|||
namespace js {
|
||||
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 EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsISensitiveInfoHiddenURI.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#ifdef CSS_REPORT_PARSE_ERRORS
|
||||
|
||||
|
@ -37,12 +39,9 @@ public:
|
|||
if (mURI != aURI) {
|
||||
mURI = aURI;
|
||||
|
||||
nsAutoCString cSpec;
|
||||
nsresult rv = mURI->GetSpec(cSpec);
|
||||
if (NS_FAILED(rv)) {
|
||||
cSpec.AssignLiteral("[nsIURI::GetSpec failed]");
|
||||
if (NS_FAILED(NS_GetSanitizedURIStringFromURI(mURI, mSpec))) {
|
||||
mSpec.AssignLiteral("[nsIURI::GetSpec failed]");
|
||||
}
|
||||
CopyUTF8toUTF16(cSpec, mSpec);
|
||||
}
|
||||
return mSpec;
|
||||
}
|
||||
|
@ -219,14 +218,16 @@ ErrorReporter::OutputError()
|
|||
do_CreateInstance(sScriptErrorFactory, &rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = errorObject->InitWithWindowID(mError,
|
||||
mFileName,
|
||||
mErrorLine,
|
||||
mErrorLineNumber,
|
||||
mErrorColNumber,
|
||||
nsIScriptError::warningFlag,
|
||||
"CSS Parser",
|
||||
mInnerWindowID);
|
||||
// It is safe to used InitWithSanitizedSource because mFileName is
|
||||
// an already anonymized uri spec.
|
||||
rv = errorObject->InitWithSanitizedSource(mError,
|
||||
mFileName,
|
||||
mErrorLine,
|
||||
mErrorLineNumber,
|
||||
mErrorColNumber,
|
||||
nsIScriptError::warningFlag,
|
||||
"CSS Parser",
|
||||
mInnerWindowID);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
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
|
||||
// at which sub-resource reqeusts quickly come and go.
|
||||
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
|
||||
// like click-to-play, image fancy-box zoom, navigation.
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsIRedirectChannelRegistrar.h"
|
||||
#include "nsIRequestObserverProxy.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISensitiveInfoHiddenURI.h"
|
||||
#include "nsISimpleStreamListener.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsISocketProviderService.h"
|
||||
|
@ -1578,6 +1579,26 @@ NS_NewURI(nsIURI **result,
|
|||
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
|
||||
NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **outResult,
|
||||
const nsACString &aSpec)
|
||||
|
|
|
@ -100,6 +100,9 @@ nsresult NS_NewFileURI(nsIURI **result,
|
|||
nsIFile *spec,
|
||||
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,
|
||||
* NS_NewChannelWithTriggeringPrincipal,
|
||||
|
|
|
@ -2494,16 +2494,13 @@ HttpBaseChannel::AddSecurityMessage(const nsAString &aMessageTag,
|
|||
errorText);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString spec;
|
||||
if (mURI) {
|
||||
spec = mURI->GetSpecOrDefault();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
|
||||
error->InitWithWindowID(errorText, NS_ConvertUTF8toUTF16(spec),
|
||||
EmptyString(), 0, 0, nsIScriptError::warningFlag,
|
||||
NS_ConvertUTF16toUTF8(aMessageCategory),
|
||||
innerWindowID);
|
||||
error->InitWithSourceURI(errorText, mURI,
|
||||
EmptyString(), 0, 0,
|
||||
nsIScriptError::warningFlag,
|
||||
NS_ConvertUTF16toUTF8(aMessageCategory),
|
||||
innerWindowID);
|
||||
|
||||
console->LogMessage(error);
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -1580,14 +1580,14 @@ nsCORSListenerProxy::LogBlockedCORSRequest(uint64_t aInnerWindowID,
|
|||
// query innerWindowID and log to web console, otherwise log to
|
||||
// the error to the browser console.
|
||||
if (aInnerWindowID > 0) {
|
||||
rv = scriptError->InitWithWindowID(aMessage,
|
||||
EmptyString(), // sourceName
|
||||
EmptyString(), // sourceLine
|
||||
0, // lineNumber
|
||||
0, // columnNumber
|
||||
nsIScriptError::warningFlag,
|
||||
"CORS",
|
||||
aInnerWindowID);
|
||||
rv = scriptError->InitWithSanitizedSource(aMessage,
|
||||
EmptyString(), // sourceName
|
||||
EmptyString(), // sourceLine
|
||||
0, // lineNumber
|
||||
0, // columnNumber
|
||||
nsIScriptError::warningFlag,
|
||||
"CORS",
|
||||
aInnerWindowID);
|
||||
}
|
||||
else {
|
||||
rv = scriptError->Init(aMessage,
|
||||
|
|
|
@ -119,6 +119,7 @@ nsHttpConnectionMgr::nsHttpConnectionMgr()
|
|||
, mThrottleSuspendFor(0)
|
||||
, mThrottleResumeFor(0)
|
||||
, mThrottleResumeIn(0)
|
||||
, mThrottleTimeWindow(0)
|
||||
, mIsShuttingDown(false)
|
||||
, mNumActiveConns(0)
|
||||
, mNumIdleConns(0)
|
||||
|
@ -175,7 +176,8 @@ nsHttpConnectionMgr::Init(uint16_t maxUrgentExcessiveConns,
|
|||
bool throttleEnabled,
|
||||
uint32_t throttleSuspendFor,
|
||||
uint32_t throttleResumeFor,
|
||||
uint32_t throttleResumeIn)
|
||||
uint32_t throttleResumeIn,
|
||||
uint32_t throttleTimeWindow)
|
||||
{
|
||||
LOG(("nsHttpConnectionMgr::Init\n"));
|
||||
|
||||
|
@ -192,6 +194,7 @@ nsHttpConnectionMgr::Init(uint16_t maxUrgentExcessiveConns,
|
|||
mThrottleSuspendFor = throttleSuspendFor;
|
||||
mThrottleResumeFor = throttleResumeFor;
|
||||
mThrottleResumeIn = throttleResumeIn;
|
||||
mThrottleTimeWindow = TimeDuration::FromMilliseconds(throttleTimeWindow);
|
||||
|
||||
mIsShuttingDown = false;
|
||||
}
|
||||
|
@ -2831,6 +2834,9 @@ nsHttpConnectionMgr::OnMsgUpdateParam(int32_t inParam, ARefBase *)
|
|||
case THROTTLING_RESUME_IN:
|
||||
mThrottleResumeIn = value;
|
||||
break;
|
||||
case THROTTLING_TIME_WINDOW:
|
||||
mThrottleTimeWindow = TimeDuration::FromMilliseconds(value);
|
||||
break;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
if (!LOG_ENABLED()) {
|
||||
|
@ -2961,30 +2991,39 @@ void nsHttpConnectionMgr::LogActiveTransactions(char operation)
|
|||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled)
|
||||
nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans)
|
||||
{
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
||||
bool throttled = aTrans->EligibleForThrottling();
|
||||
|
||||
nsTArray<RefPtr<nsHttpTransaction>> *transactions =
|
||||
mActiveTransactions[aThrottled].LookupOrAdd(tabId);
|
||||
mActiveTransactions[throttled].LookupOrAdd(tabId);
|
||||
|
||||
MOZ_ASSERT(!transactions->Contains(aTrans));
|
||||
|
||||
transactions->AppendElement(aTrans);
|
||||
|
||||
LOG(("nsHttpConnectionMgr::AddActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d",
|
||||
aTrans, tabId, tabId == mCurrentTopLevelOuterContentWindowId, aThrottled));
|
||||
aTrans, tabId, tabId == mCurrentTopLevelOuterContentWindowId, throttled));
|
||||
LogActiveTransactions('+');
|
||||
|
||||
if (tabId == mCurrentTopLevelOuterContentWindowId) {
|
||||
mActiveTabTransactionsExist = true;
|
||||
if (!aThrottled) {
|
||||
if (!throttled) {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
@ -2993,15 +3032,17 @@ nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans, bool aThro
|
|||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled)
|
||||
nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans,
|
||||
Maybe<bool> const& aOverride)
|
||||
{
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
||||
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
|
||||
bool throttled = aOverride.valueOr(aTrans->EligibleForThrottling());
|
||||
|
||||
nsTArray<RefPtr<nsHttpTransaction>> *transactions =
|
||||
mActiveTransactions[aThrottled].Get(tabId);
|
||||
mActiveTransactions[throttled].Get(tabId);
|
||||
|
||||
if (!transactions || !transactions->RemoveElement(aTrans)) {
|
||||
// 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",
|
||||
aTrans, tabId, forActiveTab, aThrottled));
|
||||
aTrans, tabId, forActiveTab, throttled));
|
||||
|
||||
if (!transactions->IsEmpty()) {
|
||||
// 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.
|
||||
mActiveTransactions[aThrottled].Remove(tabId);
|
||||
mActiveTransactions[throttled].Remove(tabId);
|
||||
LogActiveTransactions('-');
|
||||
|
||||
if (forActiveTab) {
|
||||
// Update caches of the active tab transaction existence, since it's now affected
|
||||
if (!aThrottled) {
|
||||
if (!throttled) {
|
||||
mActiveTabUnthrottledTransactionsExist = false;
|
||||
}
|
||||
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.
|
||||
// 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.
|
||||
if (forActiveTab && !aThrottled) {
|
||||
if (forActiveTab && !throttled) {
|
||||
LOG((" resuming throttled for active tab"));
|
||||
ResumeReadOf(mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId));
|
||||
}
|
||||
|
@ -3094,16 +3135,21 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
|
|||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::MoveActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled)
|
||||
nsHttpConnectionMgr::UpdateActiveTransaction(nsHttpTransaction * aTrans)
|
||||
{
|
||||
LOG(("nsHttpConnectionMgr::MoveActiveTransaction ENTER t=%p", aTrans));
|
||||
AddActiveTransaction(aTrans, aThrottled);
|
||||
RemoveActiveTransaction(aTrans, !aThrottled);
|
||||
LOG(("nsHttpConnectionMgr::MoveActiveTransaction EXIT t=%p", aTrans));
|
||||
LOG(("nsHttpConnectionMgr::UpdateActiveTransaction ENTER t=%p", aTrans));
|
||||
|
||||
AddActiveTransaction(aTrans);
|
||||
|
||||
Maybe<bool> reversed;
|
||||
reversed.emplace(!aTrans->EligibleForThrottling());
|
||||
RemoveActiveTransaction(aTrans, reversed);
|
||||
|
||||
LOG(("nsHttpConnectionMgr::UpdateActiveTransaction EXIT t=%p", aTrans));
|
||||
}
|
||||
|
||||
bool
|
||||
nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans, bool aThrottled)
|
||||
nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans)
|
||||
{
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
|
@ -3113,43 +3159,62 @@ nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans, bool aThrottl
|
|||
|
||||
uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
|
||||
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
|
||||
bool throttled = aTrans->EligibleForThrottling();
|
||||
|
||||
if (mActiveTabTransactionsExist) {
|
||||
if (!tabId) {
|
||||
// Chrome initiated and unidentified transactions just respect
|
||||
// their throttle flag, when something for the active tab is happening.
|
||||
return aThrottled;
|
||||
bool stop = [=]() {
|
||||
if (mActiveTabTransactionsExist) {
|
||||
if (!tabId) {
|
||||
// Chrome initiated and unidentified transactions just respect
|
||||
// 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;
|
||||
}
|
||||
if (mActiveTabUnthrottledTransactionsExist) {
|
||||
// Unthrottled transactions for the active tab take precedence
|
||||
return aThrottled;
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!forActiveTab);
|
||||
|
||||
if (mDelayedResumeReadTimer) {
|
||||
// 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;
|
||||
// Only stop reading when in the 3 seconds throttle time window.
|
||||
// This window is prolonged (restarted) by a call to TouchThrottlingTimeWindow.
|
||||
return stop && InThrottlingTimeWindow();
|
||||
}
|
||||
|
||||
bool nsHttpConnectionMgr::IsConnEntryUnderPressure(nsHttpConnectionInfo *connInfo)
|
||||
|
@ -3257,7 +3322,7 @@ nsHttpConnectionMgr::ThrottlerTick()
|
|||
// throttle them again until the background-resume delay passes.
|
||||
if (!mThrottlingInhibitsReading &&
|
||||
!mDelayedResumeReadTimer &&
|
||||
!IsThrottleTickerNeeded()) {
|
||||
(!IsThrottleTickerNeeded() || !InThrottlingTimeWindow())) {
|
||||
LOG((" last tick"));
|
||||
mThrottleTicker = nullptr;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,8 @@ public:
|
|||
THROTTLING_ENABLED,
|
||||
THROTTLING_SUSPEND_FOR,
|
||||
THROTTLING_RESUME_FOR,
|
||||
THROTTLING_RESUME_IN
|
||||
THROTTLING_RESUME_IN,
|
||||
THROTTLING_TIME_WINDOW
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -77,7 +78,8 @@ public:
|
|||
bool throttleEnabled,
|
||||
uint32_t throttleSuspendFor,
|
||||
uint32_t throttleResumeFor,
|
||||
uint32_t throttleResumeIn);
|
||||
uint32_t throttleResumeIn,
|
||||
uint32_t throttleTimeWindow);
|
||||
MOZ_MUST_USE nsresult Shutdown();
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -217,15 +219,22 @@ public:
|
|||
nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId);
|
||||
|
||||
// tracks and untracks active transactions according their throttle status
|
||||
void AddActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled);
|
||||
void RemoveActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled);
|
||||
void MoveActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled);
|
||||
void AddActiveTransaction(nsHttpTransaction* aTrans);
|
||||
void RemoveActiveTransaction(nsHttpTransaction* aTrans,
|
||||
Maybe<bool> const& aOverride = Nothing());
|
||||
void UpdateActiveTransaction(nsHttpTransaction* aTrans);
|
||||
|
||||
// called by nsHttpTransaction::WriteSegments. decides whether the transaction
|
||||
// should stop reading data based on: the throttling ticker status, overall
|
||||
// status of all active transactions regarding active tab and respective
|
||||
// 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.
|
||||
// it's mainly used to disallow throttling (stop reading) of a response
|
||||
|
@ -519,6 +528,7 @@ private:
|
|||
uint32_t mThrottleSuspendFor;
|
||||
uint32_t mThrottleResumeFor;
|
||||
uint32_t mThrottleResumeIn;
|
||||
TimeDuration mThrottleTimeWindow;
|
||||
Atomic<bool, mozilla::Relaxed> mIsShuttingDown;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -689,6 +699,12 @@ private:
|
|||
// Called on a pref change
|
||||
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.
|
||||
// Used by the throttling algorithm to obtain number of transactions for the active tab
|
||||
// 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
|
||||
bool mThrottlingInhibitsReading;
|
||||
|
||||
TimeStamp mThrottlingWindowEndsAt;
|
||||
|
||||
// ticker for the 'stop reading'/'resume reading' signal
|
||||
nsCOMPtr<nsITimer> mThrottleTicker;
|
||||
// Checks if the combination of active transactions requires the ticker.
|
||||
|
|
|
@ -196,6 +196,7 @@ nsHttpHandler::nsHttpHandler()
|
|||
, mThrottleSuspendFor(3000)
|
||||
, mThrottleResumeFor(200)
|
||||
, mThrottleResumeIn(400)
|
||||
, mThrottleTimeWindow(3000)
|
||||
, mUrgentStartEnabled(true)
|
||||
, mRedirectionLimit(10)
|
||||
, mPhishyUserPassLength(1)
|
||||
|
@ -590,7 +591,8 @@ nsHttpHandler::InitConnectionMgr()
|
|||
mThrottleEnabled,
|
||||
mThrottleSuspendFor,
|
||||
mThrottleResumeFor,
|
||||
mThrottleResumeIn);
|
||||
mThrottleResumeIn,
|
||||
mThrottleTimeWindow);
|
||||
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"))) {
|
||||
Unused << prefs->GetBoolPref(HTTP_PREF("on_click_priority"), &mUrgentStartEnabled);
|
||||
}
|
||||
|
|
|
@ -460,6 +460,7 @@ private:
|
|||
uint32_t mThrottleSuspendFor;
|
||||
uint32_t mThrottleResumeFor;
|
||||
uint32_t mThrottleResumeIn;
|
||||
uint32_t mThrottleTimeWindow;
|
||||
|
||||
bool mUrgentStartEnabled;
|
||||
|
||||
|
|
|
@ -173,13 +173,13 @@ void nsHttpTransaction::ResumeReading()
|
|||
}
|
||||
}
|
||||
|
||||
bool nsHttpTransaction::EligibleForThrottling()
|
||||
bool nsHttpTransaction::EligibleForThrottling() const
|
||||
{
|
||||
return (mClassOfService & (nsIClassOfService::Throttleable |
|
||||
nsIClassOfService::DontThrottle |
|
||||
nsIClassOfService::Leader |
|
||||
nsIClassOfService::Unblocked)) ==
|
||||
nsIClassOfService::Throttleable;
|
||||
return (mClassOfService & (nsIClassOfService::Throttleable |
|
||||
nsIClassOfService::DontThrottle |
|
||||
nsIClassOfService::Leader |
|
||||
nsIClassOfService::Unblocked)) ==
|
||||
nsIClassOfService::Throttleable;
|
||||
}
|
||||
|
||||
void nsHttpTransaction::SetClassOfService(uint32_t cos)
|
||||
|
@ -190,9 +190,9 @@ void nsHttpTransaction::SetClassOfService(uint32_t cos)
|
|||
|
||||
if (mConnection && wasThrottling != isThrottling) {
|
||||
// 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.
|
||||
gHttpHandler->ConnMgr()->MoveActiveTransaction(this, isThrottling);
|
||||
gHttpHandler->ConnMgr()->UpdateActiveTransaction(this);
|
||||
|
||||
if (mReadingStopped && !isThrottling) {
|
||||
ResumeReading();
|
||||
|
@ -526,8 +526,7 @@ nsHttpTransaction::OnActivated(bool h2)
|
|||
}
|
||||
|
||||
mActivated = true;
|
||||
gHttpHandler->ConnMgr()->AddActiveTransaction(
|
||||
this, mClassOfService & nsIClassOfService::Throttleable);
|
||||
gHttpHandler->ConnMgr()->AddActiveTransaction(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -841,15 +840,25 @@ bool nsHttpTransaction::ShouldStopReading()
|
|||
if (mActivatedAsH2) {
|
||||
// Throttling feature is now disabled for http/2 transactions
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!gHttpHandler->ConnMgr()->ShouldStopReading(this, EligibleForThrottling())) {
|
||||
if (!gHttpHandler->ConnMgr()->ShouldStopReading(this)) {
|
||||
// We are not obligated to throttle
|
||||
return false;
|
||||
}
|
||||
|
@ -943,8 +952,7 @@ nsHttpTransaction::Close(nsresult reason)
|
|||
this, static_cast<uint32_t>(reason)));
|
||||
|
||||
if (!mClosed) {
|
||||
gHttpHandler->ConnMgr()->RemoveActiveTransaction(
|
||||
this, mClassOfService & nsIClassOfService::Throttleable);
|
||||
gHttpHandler->ConnMgr()->RemoveActiveTransaction(this);
|
||||
mActivated = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -394,8 +394,8 @@ public:
|
|||
void ResumeReading();
|
||||
|
||||
// This examins classification of this transaction whether the Throttleable class
|
||||
// has been set while Leader or Unblocked are not.
|
||||
bool EligibleForThrottling();
|
||||
// has been set while Leader, Unblocked, DontThrottle has not.
|
||||
bool EligibleForThrottling() const;
|
||||
|
||||
private:
|
||||
bool mSubmittedRatePacing;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[parse-input-arguments-018.html]
|
||||
type: reftest
|
||||
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 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
|
||||
|
|
|
@ -10,32 +10,35 @@ const DIALOG_URL = "chrome://payments/content/paymentRequest.xhtml";
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"paymentSrv",
|
||||
"@mozilla.org/dom/payments/payment-request-service;1",
|
||||
"nsIPaymentRequestService");
|
||||
|
||||
function PaymentUIService() {}
|
||||
|
||||
PaymentUIService.prototype = {
|
||||
classID: Components.ID("{01f8bd55-9017-438b-85ec-7c15d2b35cdc}"),
|
||||
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) {
|
||||
return null;
|
||||
},
|
||||
|
||||
abortPayment(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);
|
||||
paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
|
||||
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);
|
||||
NS_ENSURE_TRUE(error, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCString sourceName = aSourceURI->GetSpecOrDefault();
|
||||
|
||||
uint64_t windowID = 0;
|
||||
GetWindowIDFromContext(aContext, &windowID);
|
||||
|
||||
nsresult rv =
|
||||
error->InitWithWindowID(aMessage, NS_ConvertUTF8toUTF16(sourceName),
|
||||
aSourceSample, 0, 0, nsIScriptError::errorFlag,
|
||||
"JavaScript", windowID);
|
||||
error->InitWithSourceURI(aMessage, aSourceURI,
|
||||
aSourceSample, 0, 0, nsIScriptError::errorFlag,
|
||||
"JavaScript", windowID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
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 ||
|
||||
entry.kind() == js::ProfileEntry::Kind::JS_NORMAL);
|
||||
|
||||
const char* label = entry.label();
|
||||
const char* dynamicString = entry.dynamicString();
|
||||
bool isChromeJSEntry = false;
|
||||
int lineno = -1;
|
||||
|
||||
// XXX: it's unclear why the computation of lineno should depend on
|
||||
// |dynamicString|. Perhaps it shouldn't?
|
||||
if (entry.isJs()) {
|
||||
// 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
|
||||
// a local variable in order -- to avoid rooting hazards.
|
||||
if (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.
|
||||
MOZ_ASSERT(&entry == &aRacyInfo->entries[aRacyInfo->stackSize() - 1]);
|
||||
} else {
|
||||
lineno = JS_PCToLineNumber(entry.script(), entry.pc());
|
||||
}
|
||||
}
|
||||
|
||||
} 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.
|
||||
if (ProfilerFeature::HasPrivacy(aFeatures) && !isChromeJSEntry) {
|
||||
dynamicString = "(private)";
|
||||
} else if (strlen(dynamicString) >= ProfileBuffer::kMaxFrameKeyLength) {
|
||||
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()));
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче