Merge inbound to central, a=merge

MozReview-Commit-ID: 5tBON9YUdAO
This commit is contained in:
Wes Kocher 2017-08-07 15:23:46 -07:00
Родитель 29bdf7c482 344ab75b2d
Коммит cf8f3268a1
79 изменённых файлов: 1662 добавлений и 860 удалений

Просмотреть файл

@ -174,14 +174,6 @@ var whitelist = [
]; ];
// Temporary whitelisted while WebPayments in construction
// See Bug 1381141
if (AppConstants.NIGHTLY_BUILD && AppConstants.MOZ_BUILD_APP == "browser") {
whitelist.push(
{file: "chrome://payments/content/paymentRequest.xhtml"}
);
}
if (!AppConstants.MOZ_PHOTON_THEME) { if (!AppConstants.MOZ_PHOTON_THEME) {
whitelist.push( whitelist.push(
// Bug 1343824 // Bug 1343824

Просмотреть файл

@ -63,11 +63,6 @@ function getTopWin(skipPopups) {
allowPopups: !skipPopups}); allowPopups: !skipPopups});
} }
function openTopWin(url) {
/* deprecated */
openUILinkIn(url, "current");
}
function getBoolPref(prefname, def) { function getBoolPref(prefname, def) {
try { try {
return Services.prefs.getBoolPref(prefname); return Services.prefs.getBoolPref(prefname);

Просмотреть файл

@ -400,9 +400,8 @@
@RESPATH@/components/nsSearchService.js @RESPATH@/components/nsSearchService.js
@RESPATH@/components/nsSearchSuggestions.js @RESPATH@/components/nsSearchSuggestions.js
@RESPATH@/components/nsSidebar.js @RESPATH@/components/nsSidebar.js
#if defined(NIGHTLY_BUILD) && defined(MOZ_BUILD_APP_IS_BROWSER)
@RESPATH@/components/payments.manifest @RESPATH@/components/payments.manifest
#endif @RESPATH@/components/paymentUIService.js
@RESPATH@/components/passwordmgr.manifest @RESPATH@/components/passwordmgr.manifest
@RESPATH@/components/nsLoginInfo.js @RESPATH@/components/nsLoginInfo.js
@RESPATH@/components/nsLoginManager.js @RESPATH@/components/nsLoginManager.js

Просмотреть файл

@ -4105,20 +4105,26 @@ nsContentUtils::ReportToConsoleByWindowID(const nsAString& aErrorText,
nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber); nsJSUtils::GetCallingLocation(cx, spec, &aLineNumber, &aColumnNumber);
} }
} }
if (spec.IsEmpty() && aURI) {
spec = aURI->GetSpecOrDefault();
}
nsCOMPtr<nsIScriptError> errorObject = nsCOMPtr<nsIScriptError> errorObject =
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = errorObject->InitWithWindowID(aErrorText, if (!spec.IsEmpty()) {
NS_ConvertUTF8toUTF16(spec), // file name rv = errorObject->InitWithWindowID(aErrorText,
aSourceLine, NS_ConvertUTF8toUTF16(spec), // file name
aLineNumber, aColumnNumber, aSourceLine,
aErrorFlags, aCategory, aLineNumber, aColumnNumber,
aInnerWindowID); aErrorFlags, aCategory,
aInnerWindowID);
} else {
rv = errorObject->InitWithSourceURI(aErrorText,
aURI,
aSourceLine,
aLineNumber, aColumnNumber,
aErrorFlags, aCategory,
aInnerWindowID);
}
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return sConsoleService->LogMessage(errorObject); return sConsoleService->LogMessage(errorObject);

Просмотреть файл

@ -11,6 +11,7 @@
#include "nsISupports.idl" #include "nsISupports.idl"
#include "nsIArray.idl" #include "nsIArray.idl"
#include "nsIConsoleMessage.idl" #include "nsIConsoleMessage.idl"
interface nsIURI;
%{C++ %{C++
#include "nsStringGlue.h" // for nsDependentCString #include "nsStringGlue.h" // for nsDependentCString
@ -97,8 +98,17 @@ interface nsIScriptError : nsIConsoleMessage
in string category); in string category);
/* This should be called instead of nsIScriptError.init to /* This should be called instead of nsIScriptError.init to
initialize with a window id. The window id should be for the * initialize with a window id. The window id should be for the
inner window associated with this error. */ * inner window associated with this error.
*
* This function will check whether sourceName is a uri and sanitize it if
* needed. If you know the source name is sanitized already, use
* initWithSanitizedSource.
* A "sanitized" source name means that passwords are not shown. It will
* use the sensitiveInfoHiddenSpec function of nsIURI interface, that is
* replacing paswords with ***
* (e.g. https://USERNAME:****@example.com/some/path).
*/
void initWithWindowID(in AString message, void initWithWindowID(in AString message,
in AString sourceName, in AString sourceName,
in AString sourceLine, in AString sourceLine,
@ -107,8 +117,33 @@ interface nsIScriptError : nsIConsoleMessage
in uint32_t flags, in uint32_t flags,
in ACString category, in ACString category,
in unsigned long long innerWindowID); in unsigned long long innerWindowID);
/* This is the same function as initWithWindowID, but it expects an already
* sanitized sourceName.
* Please use it only if sourceName string is already sanitized.
*/
void initWithSanitizedSource(in AString message,
in AString sourceName,
in AString sourceLine,
in uint32_t lineNumber,
in uint32_t columnNumber,
in uint32_t flags,
in ACString category,
in unsigned long long innerWindowID);
/* This is the same function as initWithWindowID with an uri as a source parameter.
*/
void initWithSourceURI(in AString message,
in nsIURI sourceURI,
in AString sourceLine,
in uint32_t lineNumber,
in uint32_t columnNumber,
in uint32_t flags,
in ACString category,
in unsigned long long innerWindowID);
%{C++ %{C++
// This overload allows passing a literal string for category. // These overloads allow passing a literal string for category.
template<uint32_t N> template<uint32_t N>
nsresult InitWithWindowID(const nsAString& message, nsresult InitWithWindowID(const nsAString& message,
const nsAString& sourceName, const nsAString& sourceName,
@ -123,6 +158,38 @@ interface nsIScriptError : nsIConsoleMessage
return InitWithWindowID(message, sourceName, sourceLine, lineNumber, return InitWithWindowID(message, sourceName, sourceLine, lineNumber,
columnNumber, flags, category, aInnerWindowID); columnNumber, flags, category, aInnerWindowID);
} }
template<uint32_t N>
nsresult InitWithSanitizedSource(const nsAString& message,
const nsAString& sourceName,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const char (&c)[N],
uint64_t aInnerWindowID)
{
nsDependentCString category(c, N - 1);
return InitWithSanitizedSource(message, sourceName, sourceLine,
lineNumber, columnNumber, flags,
category, aInnerWindowID);
}
template<uint32_t N>
nsresult InitWithSourceURI(const nsAString& message,
nsIURI* sourceURI,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const char (&c)[N],
uint64_t aInnerWindowID)
{
nsDependentCString category(c, N - 1);
return InitWithSourceURI(message, sourceURI, sourceLine,
lineNumber, columnNumber, flags,
category, aInnerWindowID);
}
%} %}
}; };

Просмотреть файл

@ -210,14 +210,41 @@ AssignSourceNameHelper(nsString& aSourceNameDest, const nsAString& aSourceNameSr
NS_SUCCEEDED(uri->GetPassword(pass)) && NS_SUCCEEDED(uri->GetPassword(pass)) &&
!pass.IsEmpty()) !pass.IsEmpty())
{ {
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(uri); NS_GetSanitizedURIStringFromURI(uri, aSourceNameDest);
nsAutoCString loc;
if (safeUri && NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc)))
aSourceNameDest.Assign(NS_ConvertUTF8toUTF16(loc));
} }
} }
static void
AssignSourceNameHelper(nsIURI* aSourceURI, nsString& aSourceNameDest)
{
if (!aSourceURI)
return;
if (NS_FAILED(NS_GetSanitizedURIStringFromURI(aSourceURI,
aSourceNameDest))) {
aSourceNameDest.AssignLiteral("[nsIURI::GetSpec failed]");
}
}
void
nsScriptErrorBase::InitializationHelper(const nsAString& message,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const nsACString& category,
uint64_t aInnerWindowID)
{
mMessage.Assign(message);
mLineNumber = lineNumber;
mSourceLine.Assign(sourceLine);
mColumnNumber = columnNumber;
mFlags = flags;
mCategory = category;
mTimeStamp = JS_Now() / 1000;
mInnerWindowID = aInnerWindowID;
}
NS_IMETHODIMP NS_IMETHODIMP
nsScriptErrorBase::InitWithWindowID(const nsAString& message, nsScriptErrorBase::InitWithWindowID(const nsAString& message,
const nsAString& sourceName, const nsAString& sourceName,
@ -228,15 +255,49 @@ nsScriptErrorBase::InitWithWindowID(const nsAString& message,
const nsACString& category, const nsACString& category,
uint64_t aInnerWindowID) uint64_t aInnerWindowID)
{ {
mMessage.Assign(message); InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
category, aInnerWindowID);
AssignSourceNameHelper(mSourceName, sourceName); AssignSourceNameHelper(mSourceName, sourceName);
mLineNumber = lineNumber;
mSourceLine.Assign(sourceLine); if (aInnerWindowID && NS_IsMainThread())
mColumnNumber = columnNumber; InitializeOnMainThread();
mFlags = flags;
mCategory = category; return NS_OK;
mTimeStamp = JS_Now() / 1000; }
mInnerWindowID = aInnerWindowID;
NS_IMETHODIMP
nsScriptErrorBase::InitWithSanitizedSource(const nsAString& message,
const nsAString& sourceName,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const nsACString& category,
uint64_t aInnerWindowID)
{
InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
category, aInnerWindowID);
mSourceName = sourceName;
if (aInnerWindowID && NS_IsMainThread())
InitializeOnMainThread();
return NS_OK;
}
NS_IMETHODIMP
nsScriptErrorBase::InitWithSourceURI(const nsAString& message,
nsIURI *sourceURI,
const nsAString& sourceLine,
uint32_t lineNumber,
uint32_t columnNumber,
uint32_t flags,
const nsACString& category,
uint64_t aInnerWindowID)
{
InitializationHelper(message, sourceLine, lineNumber, columnNumber, flags,
category, aInnerWindowID);
AssignSourceNameHelper(sourceURI, mSourceName);
if (aInnerWindowID && NS_IsMainThread()) if (aInnerWindowID && NS_IsMainThread())
InitializeOnMainThread(); InitializeOnMainThread();

Просмотреть файл

@ -53,6 +53,12 @@ protected:
void void
InitializeOnMainThread(); InitializeOnMainThread();
void InitializationHelper(const nsAString& message,
const nsAString& sourceLine, uint32_t lineNumber,
uint32_t columnNumber, uint32_t flags,
const nsACString& category,
uint64_t aInnerWindowID);
nsCOMArray<nsIScriptErrorNote> mNotes; nsCOMArray<nsIScriptErrorNote> mNotes;
nsString mMessage; nsString mMessage;
nsString mMessageName; nsString mMessageName;

Просмотреть файл

@ -6,12 +6,18 @@
#include "nsISupports.idl" #include "nsISupports.idl"
#include "nsIPaymentActionResponse.idl" #include "nsIPaymentActionResponse.idl"
[scriptable, uuid(ea008d0c-9e9f-411f-a6c5-a62106ba7ab9)] [scriptable, uuid(01f8bd55-9017-438b-85ec-7c15d2b35cdc)]
interface nsIPaymentUIService : nsISupports interface nsIPaymentUIService : nsISupports
{ {
nsIPaymentActionResponse canMakePayment(in AString requestId); void showPayment(in AString requestId);
nsIPaymentActionResponse showPayment(in AString requestId); void abortPayment(in AString requestId);
nsIPaymentActionResponse abortPayment(in AString requestId); void completePayment(in AString requestId);
nsIPaymentActionResponse completePayment(in AString requestId); void updatePayment(in AString requestId);
nsIPaymentActionResponse updatePayment(in AString requestId);
}; };
%{C++
#define NS_PAYMENT_UI_SERVICE_CID \
{ 0x01f8bd55, 0x9017, 0x438b, { 0x85, 0xec, 0x7c, 0x15, 0xd2, 0xb3, 0x5c, 0xdc } }
#define NS_PAYMENT_UI_SERVICE_CONTRACT_ID \
"@mozilla.org/dom/payments/payment-ui-service;1"
%}

Просмотреть файл

@ -1227,7 +1227,7 @@ MediaDecoder::GetCompositor()
RefPtr<LayerManager> layerManager = RefPtr<LayerManager> layerManager =
ownerDoc ? nsContentUtils::LayerManagerForDocument(ownerDoc) : nullptr; ownerDoc ? nsContentUtils::LayerManagerForDocument(ownerDoc) : nullptr;
RefPtr<KnowsCompositor> knows = RefPtr<KnowsCompositor> knows =
layerManager ? layerManager->AsShadowForwarder() : nullptr; layerManager ? layerManager->AsKnowsCompositor() : nullptr;
return knows.forget(); return knows.forget();
} }

Просмотреть файл

@ -643,7 +643,7 @@ private:
RefPtr<MFTDecoder> mTransform; RefPtr<MFTDecoder> mTransform;
RefPtr<D3D11RecycleAllocator> mTextureClientAllocator; RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
RefPtr<ID3D11VideoDecoder> mDecoder; RefPtr<ID3D11VideoDecoder> mDecoder;
RefPtr<layers::SyncObject> mSyncObject; RefPtr<layers::SyncObjectClient> mSyncObject;
GUID mDecoderGUID; GUID mDecoderGUID;
uint32_t mWidth = 0; uint32_t mWidth = 0;
uint32_t mHeight = 0; uint32_t mHeight = 0;
@ -711,9 +711,10 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
// and because it allows color conversion ocurring directly from this texture // and because it allows color conversion ocurring directly from this texture
// DXVA does not seem to accept IDXGIKeyedMutex textures as input. // DXVA does not seem to accept IDXGIKeyedMutex textures as input.
mSyncObject = mSyncObject =
layers::SyncObject::CreateSyncObject(layers::ImageBridgeChild::GetSingleton()-> layers::SyncObjectClient::CreateSyncObjectClient(
GetTextureFactoryIdentifier().mSyncHandle, layers::ImageBridgeChild::GetSingleton()->
mDevice); GetTextureFactoryIdentifier().mSyncHandle,
mDevice);
} }
} else { } else {
mTextureClientAllocator = mTextureClientAllocator =
@ -723,8 +724,9 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
// and because it allows color conversion ocurring directly from this texture // and because it allows color conversion ocurring directly from this texture
// DXVA does not seem to accept IDXGIKeyedMutex textures as input. // DXVA does not seem to accept IDXGIKeyedMutex textures as input.
mSyncObject = mSyncObject =
layers::SyncObject::CreateSyncObject(aKnowsCompositor->GetTextureFactoryIdentifier().mSyncHandle, layers::SyncObjectClient::CreateSyncObjectClient(
mDevice); aKnowsCompositor->GetTextureFactoryIdentifier().mSyncHandle,
mDevice);
} }
} }
mTextureClientAllocator->SetMaxPoolSize(5); mTextureClientAllocator->SetMaxPoolSize(5);
@ -882,7 +884,8 @@ D3D11DXVA2Manager::CreateOutputSample(RefPtr<IMFSample>& aSample,
__uuidof(ID3D11Texture2D), aTexture, 0, FALSE, getter_AddRefs(buffer)); __uuidof(ID3D11Texture2D), aTexture, 0, FALSE, getter_AddRefs(buffer));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr); NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
sample->AddBuffer(buffer); hr = sample->AddBuffer(buffer);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
aSample = sample; aSample = sample;
return S_OK; return S_OK;
@ -952,6 +955,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
NS_ENSURE_TRUE(SUCCEEDED(hr), hr); NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
hr = mTransform->Output(&sample); hr = mTransform->Output(&sample);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
} }
} }
@ -959,7 +963,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
// It appears some race-condition may allow us to arrive here even when mSyncObject // It appears some race-condition may allow us to arrive here even when mSyncObject
// is null. It's better to avoid that crash. // is null. It's better to avoid that crash.
client->SyncWithObject(mSyncObject); client->SyncWithObject(mSyncObject);
mSyncObject->FinalizeFrame(); mSyncObject->Synchronize();
} }
image.forget(aOutImage); image.forget(aOutImage);

Просмотреть файл

@ -449,7 +449,10 @@ WMFVideoMFTManager::InitializeDXVA()
} }
MOZ_ASSERT(!mDXVA2Manager); MOZ_ASSERT(!mDXVA2Manager);
LayersBackend backend = GetCompositorBackendType(mKnowsCompositor); LayersBackend backend = GetCompositorBackendType(mKnowsCompositor);
if (backend != LayersBackend::LAYERS_D3D11) { bool useANGLE =
mKnowsCompositor ? mKnowsCompositor->GetCompositorUseANGLE() : false;
bool wrWithANGLE = (backend == LayersBackend::LAYERS_WR) && useANGLE;
if (backend != LayersBackend::LAYERS_D3D11 && !wrWithANGLE) {
mDXVAFailureReason.AssignLiteral("Unsupported layers backend"); mDXVAFailureReason.AssignLiteral("Unsupported layers backend");
return false; return false;
} }
@ -934,7 +937,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample,
return S_OK; return S_OK;
} }
// Blocks until decoded sample is produced by the deoder. // Blocks until decoded sample is produced by the decoder.
HRESULT HRESULT
WMFVideoMFTManager::Output(int64_t aStreamOffset, WMFVideoMFTManager::Output(int64_t aStreamOffset,
RefPtr<MediaData>& aOutData) RefPtr<MediaData>& aOutData)

Просмотреть файл

@ -353,9 +353,7 @@ BasicCardService::DecodeBasicCardData(const nsAString& aData,
#undef EncodeBasicCardProperty #undef EncodeBasicCardProperty
#undef EncodeAddressProperty #undef EncodeAddressProperty
#undef DecodeBasicCardProperty #undef DecodeBasicCardProperty
#undef DecodeBasicCardCardNumber
#undef DecodeAddressProperty #undef DecodeAddressProperty
#undef DecodeAddressLine
#undef AMEX #undef AMEX
#undef CARTEBANCAIRE #undef CARTEBANCAIRE
#undef DINERS #undef DINERS

Просмотреть файл

@ -148,84 +148,41 @@ PaymentRequestService::SetTestingUIService(nsIPaymentUIService* aUIService)
} }
nsresult nsresult
PaymentRequestService::CallTestingUIAction(const nsAString& aRequestId, uint32_t aActionType) PaymentRequestService::LaunchUIAction(const nsAString& aRequestId, uint32_t aActionType)
{ {
nsCOMPtr<nsIPaymentActionResponse> response; nsCOMPtr<nsIPaymentUIService> uiService;
nsresult rv; nsresult rv;
if (mTestingUIService) { if (mTestingUIService) {
switch (aActionType) { uiService = mTestingUIService;
case nsIPaymentActionRequest::CANMAKE_ACTION: { } else {
rv = mTestingUIService->CanMakePayment(aRequestId, getter_AddRefs(response)); uiService = do_GetService(NS_PAYMENT_UI_SERVICE_CONTRACT_ID, &rv);
break;
}
case nsIPaymentActionRequest::SHOW_ACTION: {
rv = mTestingUIService->ShowPayment(aRequestId, getter_AddRefs(response));
break;
}
case nsIPaymentActionRequest::ABORT_ACTION: {
rv = mTestingUIService->AbortPayment(aRequestId, getter_AddRefs(response));
break;
}
case nsIPaymentActionRequest::COMPLETE_ACTION: {
rv = mTestingUIService->CompletePayment(aRequestId, getter_AddRefs(response));
break;
}
case nsIPaymentActionRequest::UPDATE_ACTION: {
rv = mTestingUIService->UpdatePayment(aRequestId, getter_AddRefs(response));
break;
}
default : {
return NS_ERROR_FAILURE;
}
}
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
} else {
// Since there is no UI implementation and no testing UI Service is registered,
// set false response for canMakePayment(), ABORT_SUCCEEDED for abort() and
// COMPLETE_SUCCEEDED for complete().
switch (aActionType) {
case nsIPaymentActionRequest::CANMAKE_ACTION: {
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(canMakeResponse);
rv = canMakeResponse->Init(aRequestId, false);
NS_ENSURE_SUCCESS(rv, rv);
response = do_QueryInterface(canMakeResponse);
MOZ_ASSERT(response);
break;
}
case nsIPaymentActionRequest::ABORT_ACTION: {
nsCOMPtr<nsIPaymentAbortActionResponse> abortResponse =
do_CreateInstance(NS_PAYMENT_ABORT_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(abortResponse);
rv = abortResponse->Init(aRequestId, nsIPaymentActionResponse::ABORT_SUCCEEDED);
NS_ENSURE_SUCCESS(rv, rv);
response = do_QueryInterface(abortResponse);
MOZ_ASSERT(response);
break;
}
case nsIPaymentActionRequest::COMPLETE_ACTION: {
nsCOMPtr<nsIPaymentCompleteActionResponse> completeResponse =
do_CreateInstance(NS_PAYMENT_COMPLETE_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(completeResponse);
rv = completeResponse->Init(aRequestId, nsIPaymentActionResponse::COMPLETE_SUCCEEDED);
NS_ENSURE_SUCCESS(rv, rv);
response = do_QueryInterface(completeResponse);
MOZ_ASSERT(response);
break;
}
default : {
break;
}
}
} }
if (response) { switch (aActionType) {
rv = RespondPayment(response); case nsIPaymentActionRequest::SHOW_ACTION: {
if (NS_WARN_IF(NS_FAILED(rv))) { rv = uiService->ShowPayment(aRequestId);
return rv; break;
} }
case nsIPaymentActionRequest::ABORT_ACTION: {
rv = uiService->AbortPayment(aRequestId);
break;
}
case nsIPaymentActionRequest::COMPLETE_ACTION: {
rv = uiService->CompletePayment(aRequestId);
break;
}
case nsIPaymentActionRequest::UPDATE_ACTION: {
rv = uiService->UpdatePayment(aRequestId);
break;
}
default : {
return NS_ERROR_FAILURE;
}
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
} }
return NS_OK; return NS_OK;
} }
@ -305,31 +262,25 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
* registered third party payment apps. * registered third party payment apps.
*/ */
case nsIPaymentActionRequest::CANMAKE_ACTION: { case nsIPaymentActionRequest::CANMAKE_ACTION: {
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(canMakeResponse);
if (IsBasicCardPayment(requestId)) { if (IsBasicCardPayment(requestId)) {
nsCOMPtr<nsIPaymentCanMakeActionResponse> canMakeResponse =
do_CreateInstance(NS_PAYMENT_CANMAKE_ACTION_RESPONSE_CONTRACT_ID);
MOZ_ASSERT(canMakeResponse);
rv = canMakeResponse->Init(requestId, true); rv = canMakeResponse->Init(requestId, true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIPaymentActionResponse> response = do_QueryInterface(canMakeResponse);
MOZ_ASSERT(response);
rv = RespondPayment(response);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else { } else {
rv = CallTestingUIAction(requestId, type); rv = canMakeResponse->Init(requestId, false);
if (NS_WARN_IF(NS_FAILED(rv))) { }
return NS_ERROR_FAILURE; if (NS_WARN_IF(NS_FAILED(rv))) {
} return rv;
}
nsCOMPtr<nsIPaymentActionResponse> response = do_QueryInterface(canMakeResponse);
MOZ_ASSERT(response);
rv = RespondPayment(response);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
} }
break; break;
} }
/*
* TODO: Launch/inform payment UI here once the UI module is implemented.
*/
case nsIPaymentActionRequest::SHOW_ACTION: { case nsIPaymentActionRequest::SHOW_ACTION: {
if (mShowingRequest) { if (mShowingRequest) {
nsCOMPtr<nsIPaymentResponseData> responseData = nsCOMPtr<nsIPaymentResponseData> responseData =
@ -356,7 +307,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
rv = CallTestingUIAction(requestId, type); rv = LaunchUIAction(requestId, type);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -365,7 +316,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
} }
case nsIPaymentActionRequest::ABORT_ACTION: case nsIPaymentActionRequest::ABORT_ACTION:
case nsIPaymentActionRequest::COMPLETE_ACTION: { case nsIPaymentActionRequest::COMPLETE_ACTION: {
rv = CallTestingUIAction(requestId, type); rv = LaunchUIAction(requestId, type);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -390,7 +341,7 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
rv = CallTestingUIAction(requestId, type); rv = LaunchUIAction(requestId, type);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

Просмотреть файл

@ -44,7 +44,7 @@ private:
// this method is only used for testing // this method is only used for testing
nsresult nsresult
CallTestingUIAction(const nsAString& aRequestId, uint32_t aActionType); LaunchUIAction(const nsAString& aRequestId, uint32_t aActionType);
bool bool
IsBasicCardPayment(const nsAString& aRequestId); IsBasicCardPayment(const nsAString& aRequestId);

Просмотреть файл

@ -41,20 +41,17 @@ function abortPaymentResponse(requestId) {
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"]. let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"].
createInstance(Ci.nsIPaymentAbortActionResponse); createInstance(Ci.nsIPaymentAbortActionResponse);
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED); abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
return abortResponse.QueryInterface(Ci.nsIPaymentActionResponse); paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse));
} }
function completePaymentResponse(requestId) { function completePaymentResponse(requestId) {
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]. let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
createInstance(Ci.nsIPaymentCompleteActionResponse); createInstance(Ci.nsIPaymentCompleteActionResponse);
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED); completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
return completeResponse; paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
} }
const detailedResponseUI = { const detailedResponseUI = {
canMakePayment: function(requestId) {
return null;
},
showPayment: function(requestId) { showPayment: function(requestId) {
try { try {
basiccardResponseData.initData("Bill A. Pacheco", // cardholderName basiccardResponseData.initData("Bill A. Pacheco", // cardholderName
@ -73,20 +70,16 @@ const detailedResponseUI = {
"Bill A. Pacheco", // payer name "Bill A. Pacheco", // payer name
"", // payer email "", // payer email
""); // payer phone ""); // payer phone
return showResponse; paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
}, },
abortPayment: abortPaymentResponse, abortPayment: abortPaymentResponse,
completePayment: completePaymentResponse, completePayment: completePaymentResponse,
updatePayment: function(requestId) { updatePayment: function(requestId) {
return null;
}, },
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
}; };
const simpleResponseUI = { const simpleResponseUI = {
canMakePayment: function(requestId) {
return null;
},
showPayment: function(requestId) { showPayment: function(requestId) {
try { try {
basiccardResponseData.initData("", // cardholderName basiccardResponseData.initData("", // cardholderName
@ -105,12 +98,11 @@ const simpleResponseUI = {
"Bill A. Pacheco", // payer name "Bill A. Pacheco", // payer name
"", // payer email "", // payer email
""); // payer phone ""); // payer phone
return showResponse; paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
}, },
abortPayment: abortPaymentResponse, abortPayment: abortPaymentResponse,
completePayment: completePaymentResponse, completePayment: completePaymentResponse,
updatePayment: function(requestId) { updatePayment: function(requestId) {
return null;
}, },
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
}; };

Просмотреть файл

@ -1,39 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const DummyUIService = {
canMakePayment: function(requestId) {
let canMakeResponse = Cc["@mozilla.org/dom/payments/payment-canmake-action-response;1"].
createInstance(Ci.nsIPaymentCanMakeActionResponse);
canMakeResponse.init(requestId, true);
return canMakeResponse.QueryInterface(Ci.nsIPaymentActionResponse);
},
showPayment: function(requestId) {
return null;
},
abortPayment: function(requestId) {
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"].
createInstance(Ci.nsIPaymentAbortActionResponse);
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
return abortResponse.QueryInterface(Ci.nsIPaymentActionResponse);
},
completePayment: function(requestId) {
return null;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
};
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
paymentSrv.setTestingUIService(DummyUIService.QueryInterface(Ci.nsIPaymentUIService));
addMessageListener('teardown', function() {
paymentSrv.cleanup();
paymentSrv.setTestingUIService(null);
sendAsyncMessage('teardown-complete');
});

Просмотреть файл

@ -0,0 +1,16 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
addMessageListener("teardown", function() {
paymentSrv.cleanup();
paymentSrv.setTestingUIService(null);
sendAsyncMessage('teardown-complete');
});

Просмотреть файл

@ -33,21 +33,16 @@ shippingAddress.init("USA", // country
const NormalUIService = { const NormalUIService = {
shippingOptionChanged: false, shippingOptionChanged: false,
canMakePayment: function(requestId) {
return null;
},
showPayment: function(requestId) { showPayment: function(requestId) {
paymentSrv.changeShippingAddress(requestId, shippingAddress); paymentSrv.changeShippingAddress(requestId, shippingAddress);
return null;
}, },
abortPayment: function(requestId) { abortPayment: function(requestId) {
return null;
}, },
completePayment: function(requestId) { completePayment: function(requestId) {
let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]. let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"].
createInstance(Ci.nsIPaymentCompleteActionResponse); createInstance(Ci.nsIPaymentCompleteActionResponse);
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED); completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED);
return completeResponse; paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
}, },
updatePayment: function(requestId) { updatePayment: function(requestId) {
let showResponse = null; let showResponse = null;
@ -87,16 +82,13 @@ const NormalUIService = {
"Bill A. Pacheco", // payer name "Bill A. Pacheco", // payer name
"", // payer email "", // payer email
""); // payer phone ""); // payer phone
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
} }
return showResponse;
}, },
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
}; };
const RejectUIService = { const RejectUIService = {
canMakePayment: function(requestId) {
return null;
},
showPayment: function(requestId) { showPayment: function(requestId) {
const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"]. const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
createInstance(Ci.nsIGeneralResponseData); createInstance(Ci.nsIGeneralResponseData);
@ -115,34 +107,24 @@ const RejectUIService = {
"", // payer name "", // payer name
"", // payer email "", // payer email
""); // payer phone ""); // payer phone
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
return showResponse;
}, },
abortPayment: function(requestId) { abortPayment: function(requestId) {
return null;
}, },
completePayment: function(requestId) { completePayment: function(requestId) {
return null;
}, },
updatePayment: function(requestId) { updatePayment: function(requestId) {
return null;
}, },
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
}; };
const ErrorUIService = { const ErrorUIService = {
canMakePayment: function(requestId) {
return null;
},
showPayment: function(requestId) { showPayment: function(requestId) {
paymentSrv.changeShippingOption(requestId, ""); paymentSrv.changeShippingOption(requestId, "");
return null;
}, },
abortPayment: function(requestId) { abortPayment: function(requestId) {
return null;
}, },
completePayment: function(requestId) { completePayment: function(requestId) {
return null;
}, },
updatePayment: function(requestId) { updatePayment: function(requestId) {
let payRequest = paymentSrv.getPaymentRequestById(requestId); let payRequest = paymentSrv.getPaymentRequestById(requestId);
@ -168,8 +150,7 @@ const ErrorUIService = {
"", // payer name "", // payer name
"", // payer email "", // payer email
""); // payer phone ""); // payer phone
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
return showResponse;
}, },
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),

Просмотреть файл

@ -5,8 +5,8 @@ scheme = https
support-files = support-files =
simple_payment_request.html simple_payment_request.html
BasiccardChromeScript.js BasiccardChromeScript.js
CanMakePaymentChromeScript.js
ConstructorChromeScript.js ConstructorChromeScript.js
GeneralChromeScript.js
ShowPaymentChromeScript.js ShowPaymentChromeScript.js
[test_abortPayment.html] [test_abortPayment.html]

Просмотреть файл

@ -13,6 +13,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345367
"use strict"; "use strict";
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
var gUrl = SimpleTest.getTestFileURL('GeneralChromeScript.js');
var gScript = SpecialPowers.loadChromeScript(gUrl);
const defaultMethods = [{ const defaultMethods = [{
supportedMethods: "basic-card", supportedMethods: "basic-card",
}]; }];
@ -54,10 +57,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345367
}); });
} }
function teardown() {
gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
gScript.destroy();
SimpleTest.finish();
});
gScript.sendAsyncMessage("teardown");
}
function runTests() { function runTests() {
testBeforeShow() testBeforeShow()
.then(testAfterShow) .then(testAfterShow)
.then(SimpleTest.finish) .then(teardown)
.catch( e => { .catch( e => {
ok(false, "Unexpected error: " + e.name); ok(false, "Unexpected error: " + e.name);
SimpleTest.finish(); SimpleTest.finish();

Просмотреть файл

@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
"use strict"; "use strict";
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
var gUrl = SimpleTest.getTestFileURL('CanMakePaymentChromeScript.js'); var gUrl = SimpleTest.getTestFileURL('GeneralChromeScript.js');
var gScript = SpecialPowers.loadChromeScript(gUrl); var gScript = SpecialPowers.loadChromeScript(gUrl);
const defaultMethods = [{ const defaultMethods = [{
@ -29,11 +29,28 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
}, },
}; };
const nonsupportedMethods = [{
supportedMethods: "testing-payment-method",
}];
function testDefaultAction() {
return new Promise((resolve, reject) => {
const payRequest = new PaymentRequest(nonsupportedMethods, defaultDetails);
payRequest.canMakePayment().then((result) => {
ok(!result, "Should be resolved with false, but got " + result + ".");
resolve();
}).catch((err) => {
ok(false, "Expected no error, but got '" + err.name +"'.");
resolve();
});
});
}
function testSimple() { function testSimple() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const payRequest = new PaymentRequest(defaultMethods, defaultDetails); const payRequest = new PaymentRequest(defaultMethods, defaultDetails);
payRequest.canMakePayment().then((result) => { payRequest.canMakePayment().then((result) => {
ok(result, "Should be resolved with true, but got false."); ok(result, "Should be resolved with true, but got " + result + ".");
resolve(); resolve();
}).catch((err) => { }).catch((err) => {
ok(false, "Expected no error, but got '" + err.name +"'."); ok(false, "Expected no error, but got '" + err.name +"'.");
@ -118,7 +135,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1345365
} }
function runTests() { function runTests() {
testSimple() testDefaultAction()
.then(testSimple)
.then(testAfterShow) .then(testAfterShow)
.then(testAfterAbort) .then(testAfterAbort)
.then(testNotAllowed) .then(testNotAllowed)

Просмотреть файл

@ -330,10 +330,12 @@ FramingChecker::ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem,
break; break;
} }
rv = errorObject->InitWithWindowID(msg, EmptyString(), EmptyString(), 0, 0, // It is ok to use InitWithSanitizedSource, because the source string is
nsIScriptError::errorFlag, // empty.
"X-Frame-Options", rv = errorObject->InitWithSanitizedSource(msg, EmptyString(), EmptyString(),
topInnerWindow->WindowID()); 0, 0, nsIScriptError::errorFlag,
"X-Frame-Options",
topInnerWindow->WindowID());
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return; return;
} }

Просмотреть файл

@ -6221,6 +6221,26 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
return true; return true;
} }
// Make sure the hybrid event target stops dispatching runnables
// once we reaching the killing state.
if (aStatus == Killing) {
// To avoid deadlock we always acquire the event target mutex before the
// worker private mutex. (We do it in this order because this is what
// workers best for event dispatching.) To enforce that order here we
// need to unlock the worker private mutex before we lock the event target
// mutex in ForgetWorkerPrivate.
{
MutexAutoUnlock unlock(mMutex);
mWorkerHybridEventTarget->ForgetWorkerPrivate(this);
}
// Check the status code again in case another NotifyInternal came in
// while we were unlocked above.
if (mStatus >= aStatus) {
return true;
}
}
previousStatus = mStatus; previousStatus = mStatus;
mStatus = aStatus; mStatus = aStatus;
@ -6229,12 +6249,6 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
if (aStatus == Closing) { if (aStatus == Closing) {
Close(); Close();
} }
// Make sure the hybrid event target stops dispatching runnables
// once we reaching the killing state.
if (aStatus == Killing) {
mWorkerHybridEventTarget->ForgetWorkerPrivate(this);
}
} }
if (mCrossThreadDispatcher) { if (mCrossThreadDispatcher) {

Просмотреть файл

@ -339,9 +339,6 @@ XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
bool isChrome = false; bool isChrome = false;
if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) { if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
nsAutoCString spec;
if (mDocumentURI)
mDocumentURI->GetSpec(spec);
nsAutoString error; nsAutoString error;
error.AssignLiteral("Cross site loading using document.load is no " error.AssignLiteral("Cross site loading using document.load is no "
@ -353,14 +350,15 @@ XMLDocument::Load(const nsAString& aUrl, CallerType aCallerType,
return false; return false;
} }
rv = errorObject->InitWithWindowID(error, rv = errorObject->InitWithSourceURI(error,
NS_ConvertUTF8toUTF16(spec), mDocumentURI,
EmptyString(), EmptyString(),
0, 0, nsIScriptError::warningFlag, 0, 0,
"DOM", nsIScriptError::warningFlag,
callingDoc ? "DOM",
callingDoc->InnerWindowID() : callingDoc ?
this->InnerWindowID()); callingDoc->InnerWindowID() :
this->InnerWindowID());
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
aRv.Throw(rv); aRv.Throw(rv);

Просмотреть файл

@ -57,7 +57,6 @@ static const char* sEGLExtensionNames[] = {
"EGL_KHR_create_context", "EGL_KHR_create_context",
"EGL_KHR_stream", "EGL_KHR_stream",
"EGL_KHR_stream_consumer_gltexture", "EGL_KHR_stream_consumer_gltexture",
"EGL_EXT_device_base",
"EGL_EXT_device_query", "EGL_EXT_device_query",
"EGL_NV_stream_consumer_gltexture_yuv", "EGL_NV_stream_consumer_gltexture_yuv",
"EGL_ANGLE_stream_producer_d3d_texture_nv12", "EGL_ANGLE_stream_producer_d3d_texture_nv12",
@ -627,19 +626,9 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId
} }
} }
if (IsExtensionSupported(EXT_device_base)) {
const GLLibraryLoader::SymLoadStruct deviceBaseSymbols[] = {
SYMBOL(QueryDisplayAttribEXT),
END_OF_SYMBOLS
};
if (!fnLoadSymbols(deviceBaseSymbols)) {
NS_ERROR("EGL supports EXT_device_base without exposing its functions!");
MarkExtensionUnsupported(EXT_device_base);
}
}
if (IsExtensionSupported(EXT_device_query)) { if (IsExtensionSupported(EXT_device_query)) {
const GLLibraryLoader::SymLoadStruct queryDisplaySymbols[] = { const GLLibraryLoader::SymLoadStruct queryDisplaySymbols[] = {
SYMBOL(QueryDisplayAttribEXT),
SYMBOL(QueryDeviceAttribEXT), SYMBOL(QueryDeviceAttribEXT),
END_OF_SYMBOLS END_OF_SYMBOLS
}; };

Просмотреть файл

@ -108,7 +108,6 @@ public:
KHR_create_context, KHR_create_context,
KHR_stream, KHR_stream,
KHR_stream_consumer_gltexture, KHR_stream_consumer_gltexture,
EXT_device_base,
EXT_device_query, EXT_device_query,
NV_stream_consumer_gltexture_yuv, NV_stream_consumer_gltexture_yuv,
ANGLE_stream_producer_d3d_texture_nv12, ANGLE_stream_producer_d3d_texture_nv12,
@ -292,8 +291,8 @@ public:
EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) const EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) const
WRAP( fCreateStreamKHR(dpy, attrib_list) ) WRAP( fCreateStreamKHR(dpy, attrib_list) )
EGLStreamKHR fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP( fDestroyStreamKHR(dpy, stream) ) WRAP( fDestroyStreamKHR(dpy, stream) )
EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint* value) const EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint* value) const
WRAP( fQueryStreamKHR(dpy, stream, attribute, value) ) WRAP( fQueryStreamKHR(dpy, stream, attribute, value) )
@ -305,11 +304,10 @@ public:
EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) const EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP( fStreamConsumerReleaseKHR(dpy, stream) ) WRAP( fStreamConsumerReleaseKHR(dpy, stream) )
// EXT_device_base // EXT_device_query
EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib* value) const EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib* value) const
WRAP( fQueryDisplayAttribEXT(dpy, attribute, value) ) WRAP( fQueryDisplayAttribEXT(dpy, attribute, value) )
// EXT_device_query
EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib* value) const EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib* value) const
WRAP( fQueryDeviceAttribEXT(device, attribute, value) ) WRAP( fQueryDeviceAttribEXT(device, attribute, value) )
@ -454,7 +452,7 @@ private:
EGLint (GLAPIENTRY * fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync); EGLint (GLAPIENTRY * fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
//KHR_stream //KHR_stream
EGLStreamKHR (GLAPIENTRY * fCreateStreamKHR)(EGLDisplay dpy, const EGLint* attrib_list); EGLStreamKHR (GLAPIENTRY * fCreateStreamKHR)(EGLDisplay dpy, const EGLint* attrib_list);
EGLStreamKHR (GLAPIENTRY * fDestroyStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream); EGLBoolean (GLAPIENTRY * fDestroyStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream);
EGLBoolean (GLAPIENTRY * fQueryStreamKHR)(EGLDisplay dpy, EGLBoolean (GLAPIENTRY * fQueryStreamKHR)(EGLDisplay dpy,
EGLStreamKHR stream, EGLStreamKHR stream,
EGLenum attribute, EGLenum attribute,
@ -464,11 +462,10 @@ private:
EGLStreamKHR stream); EGLStreamKHR stream);
EGLBoolean (GLAPIENTRY * fStreamConsumerReleaseKHR)(EGLDisplay dpy, EGLBoolean (GLAPIENTRY * fStreamConsumerReleaseKHR)(EGLDisplay dpy,
EGLStreamKHR stream); EGLStreamKHR stream);
// EXT_device_base // EXT_device_query
EGLBoolean (GLAPIENTRY * fQueryDisplayAttribEXT)(EGLDisplay dpy, EGLBoolean (GLAPIENTRY * fQueryDisplayAttribEXT)(EGLDisplay dpy,
EGLint attribute, EGLint attribute,
EGLAttrib* value); EGLAttrib* value);
// EXT_device_query
EGLBoolean (GLAPIENTRY * fQueryDeviceAttribEXT)(EGLDeviceEXT device, EGLBoolean (GLAPIENTRY * fQueryDeviceAttribEXT)(EGLDeviceEXT device,
EGLint attribute, EGLint attribute,
EGLAttrib* value); EGLAttrib* value);

49
gfx/layers/SyncObject.cpp Normal file
Просмотреть файл

@ -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

73
gfx/layers/SyncObject.h Normal file
Просмотреть файл

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_LAYERS_SYNCOBJECT_H
#define MOZILLA_GFX_LAYERS_SYNCOBJECT_H
#include "mozilla/RefCounted.h"
struct ID3D11Device;
namespace mozilla {
namespace layers {
#ifdef XP_WIN
typedef void* SyncHandle;
#else
typedef uintptr_t SyncHandle;
#endif // XP_WIN
class SyncObjectHost : public RefCounted<SyncObjectHost>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectHost)
virtual ~SyncObjectHost() { }
static already_AddRefed<SyncObjectHost> CreateSyncObjectHost(
#ifdef XP_WIN
ID3D11Device* aDevice = nullptr
#endif
);
virtual bool Init() = 0;
virtual SyncHandle GetSyncHandle() = 0;
virtual bool Synchronize() = 0;
protected:
SyncObjectHost() { }
};
class SyncObjectClient : public RefCounted<SyncObjectClient>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectClient)
virtual ~SyncObjectClient() { }
static already_AddRefed<SyncObjectClient> CreateSyncObjectClient(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice = nullptr
#endif
);
enum class SyncType {
D3D11,
};
virtual SyncType GetSyncType() = 0;
virtual void Synchronize() = 0;
virtual bool IsSyncObjectValid() = 0;
protected:
SyncObjectClient() { }
};
} // namespace layers
} // namespace mozilla
#endif //MOZILLA_GFX_LAYERS_SYNCOBJECT_H

Просмотреть файл

@ -20,6 +20,7 @@
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/LayerTransactionChild.h" #include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/PersistentBufferProvider.h" #include "mozilla/layers/PersistentBufferProvider.h"
#include "mozilla/layers/SyncObject.h"
#include "ClientReadbackLayer.h" // for ClientReadbackLayer #include "ClientReadbackLayer.h" // for ClientReadbackLayer
#include "nsAString.h" #include "nsAString.h"
#include "nsDisplayList.h" #include "nsDisplayList.h"
@ -728,7 +729,7 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
if (mForwarder->GetSyncObject() && if (mForwarder->GetSyncObject() &&
mForwarder->GetSyncObject()->IsSyncObjectValid()) { mForwarder->GetSyncObject()->IsSyncObjectValid()) {
mForwarder->GetSyncObject()->FinalizeFrame(); mForwarder->GetSyncObject()->Synchronize();
} }
} }

Просмотреть файл

@ -1745,25 +1745,6 @@ UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData)
return true; return true;
} }
already_AddRefed<SyncObject>
SyncObject::CreateSyncObject(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice
#endif
)
{
if (!aHandle) {
return nullptr;
}
#ifdef XP_WIN
return MakeAndAddRef<SyncObjectD3D11>(aHandle, aDevice);
#else
MOZ_ASSERT_UNREACHABLE();
return nullptr;
#endif
}
already_AddRefed<TextureClient> already_AddRefed<TextureClient>
TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator) TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
{ {

Просмотреть файл

@ -66,6 +66,7 @@ class TextureClientPool;
#endif #endif
class TextureForwarder; class TextureForwarder;
class KeepAlive; class KeepAlive;
class SyncObjectClient;
/** /**
* TextureClient is the abstraction that allows us to share data between the * TextureClient is the abstraction that allows us to share data between the
@ -93,36 +94,6 @@ enum TextureAllocationFlags {
ALLOC_UPDATE_FROM_SURFACE = 1 << 7, ALLOC_UPDATE_FROM_SURFACE = 1 << 7,
}; };
#ifdef XP_WIN
typedef void* SyncHandle;
#else
typedef uintptr_t SyncHandle;
#endif // XP_WIN
class SyncObject : public RefCounted<SyncObject>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObject)
virtual ~SyncObject() { }
static already_AddRefed<SyncObject> CreateSyncObject(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice = nullptr
#endif
);
enum class SyncType {
D3D11,
};
virtual SyncType GetSyncType() = 0;
virtual void FinalizeFrame() = 0;
virtual bool IsSyncObjectValid() = 0;
protected:
SyncObject() { }
};
/** /**
* This class may be used to asynchronously receive an update when the content * This class may be used to asynchronously receive an update when the content
* drawn to this texture client is available for reading in CPU memory. This * drawn to this texture client is available for reading in CPU memory. This
@ -305,7 +276,7 @@ public:
virtual bool ReadBack(TextureReadbackSink* aReadbackSink) { return false; } virtual bool ReadBack(TextureReadbackSink* aReadbackSink) { return false; }
virtual void SyncWithObject(SyncObject* aFence) {}; virtual void SyncWithObject(SyncObjectClient* aSyncObject) {};
virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; } virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
@ -614,7 +585,7 @@ public:
mReadbackSink = aReadbackSink; mReadbackSink = aReadbackSink;
} }
void SyncWithObject(SyncObject* aFence) { mData->SyncWithObject(aFence); } void SyncWithObject(SyncObjectClient* aSyncObject) { mData->SyncWithObject(aSyncObject); }
LayersIPCChannel* GetAllocator() { return mAllocator; } LayersIPCChannel* GetAllocator() { return mAllocator; }

Просмотреть файл

@ -298,7 +298,9 @@ CompositorD3D11::GetTextureFactoryIdentifier()
ident.mMaxTextureSize = GetMaxTextureSize(); ident.mMaxTextureSize = GetMaxTextureSize();
ident.mParentProcessType = XRE_GetProcessType(); ident.mParentProcessType = XRE_GetProcessType();
ident.mParentBackend = LayersBackend::LAYERS_D3D11; ident.mParentBackend = LayersBackend::LAYERS_D3D11;
ident.mSyncHandle = mAttachments->mSyncHandle; if (mAttachments->mSyncObject) {
ident.mSyncHandle = mAttachments->mSyncObject->GetSyncHandle();
}
return ident; return ident;
} }
@ -1057,29 +1059,12 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF); mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
if (mAttachments->mSyncTexture) { if (mAttachments->mSyncObject) {
RefPtr<IDXGIKeyedMutex> mutex; if (!mAttachments->mSyncObject->Synchronize()) {
mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex)); // It's timeout here. Since the timeout is related to the driver-removed,
// clear the render-bounding size to skip this frame.
MOZ_ASSERT(mutex); *aRenderBoundsOut = IntRect();
{ return;
HRESULT hr;
AutoTextureLock lock(mutex, hr, 10000);
if (hr == WAIT_TIMEOUT) {
hr = mDevice->GetDeviceRemovedReason();
if (hr == S_OK) {
// There is no driver-removed event. Crash with this timeout.
MOZ_CRASH("GFX: D3D11 normal status timeout");
}
// Since the timeout is related to the driver-removed, clear the
// render-bounding size to skip this frame.
gfxCriticalNote << "GFX: D3D11 timeout with device-removed:" << gfx::hexa(hr);
*aRenderBoundsOut = IntRect();
return;
} else if (hr == WAIT_ABANDONED) {
gfxCriticalNote << "GFX: D3D11 abandoned sync";
}
} }
} }
@ -1178,8 +1163,9 @@ CompositorD3D11::Present()
HRESULT hr = mSwapChain->QueryInterface((IDXGISwapChain1**)getter_AddRefs(chain)); HRESULT hr = mSwapChain->QueryInterface((IDXGISwapChain1**)getter_AddRefs(chain));
RefPtr<IDXGIKeyedMutex> mutex; RefPtr<IDXGIKeyedMutex> mutex;
if (mUseMutexOnPresent && mAttachments->mSyncTexture) { if (mUseMutexOnPresent && mAttachments->mSyncObject) {
mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex)); SyncObjectD3D11Host* d3dSyncObj = (SyncObjectD3D11Host*)mAttachments->mSyncObject.get();
mutex = d3dSyncObj->GetKeyedMutex();
MOZ_ASSERT(mutex); MOZ_ASSERT(mutex);
} }

Просмотреть файл

@ -18,8 +18,7 @@ using namespace gfx;
static const size_t kInitialMaximumTriangles = 64; static const size_t kInitialMaximumTriangles = 64;
DeviceAttachmentsD3D11::DeviceAttachmentsD3D11(ID3D11Device* device) DeviceAttachmentsD3D11::DeviceAttachmentsD3D11(ID3D11Device* device)
: mSyncHandle(0), : mMaximumTriangles(kInitialMaximumTriangles),
mMaximumTriangles(kInitialMaximumTriangles),
mDevice(device), mDevice(device),
mContinueInit(true), mContinueInit(true),
mInitialized(false), mInitialized(false),
@ -225,36 +224,13 @@ DeviceAttachmentsD3D11::InitSyncObject()
return true; return true;
} }
// It's okay to do this on Windows 8. But for now we'll just bail MOZ_ASSERT(!mSyncObject);
// whenever we're using WARP. MOZ_ASSERT(mDevice);
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1,
D3D11_BIND_SHADER_RESOURCE |
D3D11_BIND_RENDER_TARGET);
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
RefPtr<ID3D11Texture2D> texture; mSyncObject = SyncObjectHost::CreateSyncObjectHost(mDevice);
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)); MOZ_ASSERT(mSyncObject);
if (Failed(hr, "create sync texture")) {
return false;
}
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture)); return mSyncObject->Init();
if (Failed(hr, "QI sync texture")) {
return false;
}
hr = mSyncTexture->GetSharedHandle(&mSyncHandle);
if (FAILED(hr) || !mSyncHandle) {
gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: "
<< hexa(hr);
NS_DispatchToMainThread(NS_NewRunnableFunction("DeviceAttachmentsD3D11::InitSyncObject",
[] () -> void {
Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1);
}));
return false;
}
return true;
} }
bool bool

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/SyncObject.h"
#include <d3d11.h> #include <d3d11.h>
#include <dxgi1_2.h> #include <dxgi1_2.h>
@ -70,8 +71,8 @@ public:
RefPtr<ID3D11BlendState> mNonPremulBlendState; RefPtr<ID3D11BlendState> mNonPremulBlendState;
RefPtr<ID3D11BlendState> mComponentBlendState; RefPtr<ID3D11BlendState> mComponentBlendState;
RefPtr<ID3D11BlendState> mDisabledBlendState; RefPtr<ID3D11BlendState> mDisabledBlendState;
RefPtr<IDXGIResource> mSyncTexture;
HANDLE mSyncHandle; RefPtr<SyncObjectHost> mSyncObject;
void SetDeviceReset() { void SetDeviceReset() {
mDeviceReset = true; mDeviceReset = true;

Просмотреть файл

@ -1264,7 +1264,11 @@ MLGDeviceD3D11::GetTextureFactoryIdentifier() const
GetLayersBackend(), GetLayersBackend(),
XRE_GetProcessType(), XRE_GetProcessType(),
GetMaxTextureSize()); GetMaxTextureSize());
ident.mSyncHandle = mSyncHandle;
if (mSyncObject) {
ident.mSyncHandle = mSyncObject->GetSyncHandle();
}
return ident; return ident;
} }
@ -1777,34 +1781,13 @@ MLGDeviceD3D11::SetPSTexturesNV12(uint32_t aSlot, TextureSource* aTexture)
bool bool
MLGDeviceD3D11::InitSyncObject() MLGDeviceD3D11::InitSyncObject()
{ {
CD3D11_TEXTURE2D_DESC desc( MOZ_ASSERT(!mSyncObject);
DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1, MOZ_ASSERT(mDevice);
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
RefPtr<ID3D11Texture2D> texture; mSyncObject = SyncObjectHost::CreateSyncObjectHost(mDevice);
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)); MOZ_ASSERT(mSyncObject);
if (FAILED(hr) || !texture) {
return Fail("FEATURE_FAILURE_SYNC_OBJECT",
"Could not create a sync texture: %x", hr);
}
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture)); return mSyncObject->Init();
if (FAILED(hr) || !texture) {
return Fail("FEATURE_FAILURE_QI_SYNC_OBJECT",
"Could not QI sync texture: %x", hr);
}
hr = mSyncTexture->GetSharedHandle(&mSyncHandle);
if (FAILED(hr) || !mSyncHandle) {
NS_DispatchToMainThread(NS_NewRunnableFunction("layers::MLGDeviceD3D11::InitSyncObject",
[] () -> void {
Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1);
}));
return Fail("FEATURE_FAILURE_GET_SHARED_HANDLE",
"Could not get sync texture shared handle: %x", hr);
}
return true;
} }
void void
@ -1828,27 +1811,14 @@ MLGDeviceD3D11::GetDiagnostics(GPUStats* aStats)
bool bool
MLGDeviceD3D11::Synchronize() MLGDeviceD3D11::Synchronize()
{ {
RefPtr<IDXGIKeyedMutex> mutex; MOZ_ASSERT(mSyncObject);
mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
{ if (mSyncObject) {
HRESULT hr; if (!mSyncObject->Synchronize()) {
AutoTextureLock lock(mutex, hr, 10000); // It's timeout or other error. Handle the device-reset here.
if (hr == WAIT_TIMEOUT) {
hr = mDevice->GetDeviceRemovedReason();
if (hr == S_OK) {
// There is no driver-removed event. Crash with this timeout.
MOZ_CRASH("GFX: D3D11 normal status timeout");
}
// Since the timeout is related to the driver-removed, clear the
// render-bounding size to skip this frame.
HandleDeviceReset("SyncObject"); HandleDeviceReset("SyncObject");
return false; return false;
} }
if (hr == WAIT_ABANDONED) {
gfxCriticalNote << "GFX: AL_D3D11 abandoned sync";
}
} }
return true; return true;

Просмотреть файл

@ -6,10 +6,12 @@
#ifndef mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h #ifndef mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
#define mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h #define mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
#include <d3d11_1.h>
#include "mozilla/layers/MLGDevice.h" #include "mozilla/layers/MLGDevice.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/EnumeratedArray.h" #include "mozilla/EnumeratedArray.h"
#include "nsTHashtable.h" #include "nsTHashtable.h"
#include <d3d11_1.h>
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
namespace mozilla { namespace mozilla {
@ -305,8 +307,7 @@ private:
RefPtr<ID3D11RasterizerState> mRasterizerStateNoScissor; RefPtr<ID3D11RasterizerState> mRasterizerStateNoScissor;
RefPtr<ID3D11RasterizerState> mRasterizerStateScissor; RefPtr<ID3D11RasterizerState> mRasterizerStateScissor;
RefPtr<IDXGIResource> mSyncTexture; RefPtr<SyncObjectHost> mSyncObject;
HANDLE mSyncHandle;
RefPtr<MLGBuffer> mUnitQuadVB; RefPtr<MLGBuffer> mUnitQuadVB;
RefPtr<MLGBuffer> mUnitTriangleVB; RefPtr<MLGBuffer> mUnitTriangleVB;

Просмотреть файл

@ -16,6 +16,8 @@
#include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/Logging.h" #include "mozilla/gfx/Logging.h"
#include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/webrender/RenderD3D11TextureHostOGL.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/webrender/WebRenderAPI.h" #include "mozilla/webrender/WebRenderAPI.h"
namespace mozilla { namespace mozilla {
@ -355,15 +357,15 @@ DXGITextureData::FillInfo(TextureData::Info& aInfo) const
} }
void void
D3D11TextureData::SyncWithObject(SyncObject* aSyncObject) D3D11TextureData::SyncWithObject(SyncObjectClient* aSyncObject)
{ {
if (!aSyncObject || mHasSynchronization) { if (!aSyncObject || mHasSynchronization) {
// When we have per texture synchronization we sync using the keyed mutex. // When we have per texture synchronization we sync using the keyed mutex.
return; return;
} }
MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11); MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObjectClient::SyncType::D3D11);
SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject); SyncObjectD3D11Client* sync = static_cast<SyncObjectD3D11Client*>(aSyncObject);
sync->RegisterTexture(mTexture); sync->RegisterTexture(mTexture);
} }
@ -967,11 +969,42 @@ DXGITextureHostD3D11::AcquireTextureSource(CompositableTextureSourceRef& aTextur
return true; return true;
} }
void
DXGITextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
{
RefPtr<wr::RenderTextureHost> texture =
new wr::RenderDXGITextureHostOGL(mHandle, mFormat, mSize);
wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
}
void void
DXGITextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, DXGITextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
const std::function<wr::ImageKey()>& aImageKeyAllocator) const std::function<wr::ImageKey()>& aImageKeyAllocator)
{ {
MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this DXGITextureHostD3D11 type."); MOZ_ASSERT(aImageKeys.IsEmpty());
switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8: {
// 1 image key
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 1);
break;
}
case gfx::SurfaceFormat::NV12: {
// 2 image key
aImageKeys.AppendElement(aImageKeyAllocator());
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 2);
break;
}
default: {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
}
} }
void void
@ -979,7 +1012,44 @@ DXGITextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys, Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) const wr::ExternalImageId& aExtID)
{ {
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this DXGITextureHostD3D11 type."); MOZ_ASSERT(mHandle);
switch (mFormat) {
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8: {
MOZ_ASSERT(aImageKeys.length() == 1);
wr::ImageDescriptor descriptor(GetSize(), GetFormat());
aAPI->AddExternalImage(aImageKeys[0],
descriptor,
aExtID,
wr::WrExternalImageBufferType::Texture2DHandle,
0);
break;
}
case gfx::SurfaceFormat::NV12: {
MOZ_ASSERT(aImageKeys.length() == 2);
wr::ImageDescriptor descriptor0(GetSize(), gfx::SurfaceFormat::A8);
wr::ImageDescriptor descriptor1(GetSize() / 2, gfx::SurfaceFormat::R8G8);
aAPI->AddExternalImage(aImageKeys[0],
descriptor0,
aExtID,
wr::WrExternalImageBufferType::TextureExternalHandle,
0);
aAPI->AddExternalImage(aImageKeys[1],
descriptor1,
aExtID,
wr::WrExternalImageBufferType::TextureExternalHandle,
1);
break;
}
default: {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
}
} }
void void
@ -989,7 +1059,29 @@ DXGITextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) Range<const wr::ImageKey>& aImageKeys)
{ {
MOZ_ASSERT_UNREACHABLE("No PushExternalImage() implementation for this DXGITextureHostD3D11 type."); switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8: {
MOZ_ASSERT(aImageKeys.length() == 1);
aBuilder.PushImage(aBounds, aClip, aFilter, aImageKeys[0]);
break;
}
case gfx::SurfaceFormat::NV12: {
MOZ_ASSERT(aImageKeys.length() == 2);
aBuilder.PushNV12Image(aBounds,
aClip,
aImageKeys[0],
aImageKeys[1],
wr::WrYuvColorSpace::Rec601,
aFilter);
break;
}
default: {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
}
} }
DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags, DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
@ -1134,11 +1226,21 @@ DXGIYCbCrTextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aText
return !!aTexture; return !!aTexture;
} }
void
DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
{
// We use AddImage() directly. It's no corresponding RenderTextureHost.
}
void void
DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
const std::function<wr::ImageKey()>& aImageKeyAllocator) const std::function<wr::ImageKey()>& aImageKeyAllocator)
{ {
MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this DXGIYCbCrTextureHostD3D11 type."); MOZ_ASSERT(aImageKeys.IsEmpty());
// 1 image key
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 1);
} }
void void
@ -1146,7 +1248,30 @@ DXGIYCbCrTextureHostD3D11::AddWRImage(wr::WebRenderAPI* aAPI,
Range<const wr::ImageKey>& aImageKeys, Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) const wr::ExternalImageId& aExtID)
{ {
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this DXGIYCbCrTextureHostD3D11 type."); MOZ_ASSERT(mTextures[0] && mTextures[1] && mTextures[2]);
MOZ_ASSERT(aImageKeys.length() == 1);
// There are 3 A8 channel data in DXGIYCbCrTextureHostD3D11, but ANGLE doesn't
// support for converting the D3D A8 texture to OpenGL texture handle. So, we
// use the DataSourceSurface to get the raw buffer and push that raw buffer
// into WR using AddImage().
NS_WARNING("WR doesn't support DXGIYCbCrTextureHostD3D11 directly. It's a slower path.");
RefPtr<DataSourceSurface> dataSourceSurface = GetAsSurface();
if (!dataSourceSurface) {
return;
}
DataSourceSurface::MappedSurface map;
if (!dataSourceSurface->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
return;
}
IntSize size = dataSourceSurface->GetSize();
wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat());
auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
aAPI->AddImage(aImageKeys[0], descriptor, slice);
dataSourceSurface->Unmap();
} }
void void
@ -1156,7 +1281,9 @@ DXGIYCbCrTextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) Range<const wr::ImageKey>& aImageKeys)
{ {
MOZ_ASSERT_UNREACHABLE("No PushExternalImage() implementation for this DXGIYCbCrTextureHostD3D11 type."); // 1 image key
MOZ_ASSERT(aImageKeys.length() == 1);
aBuilder.PushImage(aBounds, aClip, aFilter, aImageKeys[0]);
} }
bool bool
@ -1398,17 +1525,6 @@ CompositingRenderTargetD3D11::GetSize() const
return TextureSourceD3D11::GetSize(); return TextureSourceD3D11::GetSize();
} }
SyncObjectD3D11::SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice)
: mSyncHandle(aSyncHandle)
{
if (!aDevice) {
mD3D11Device = DeviceManagerDx::Get()->GetContentDevice();
return;
}
mD3D11Device = aDevice;
}
static inline bool static inline bool
ShouldDevCrashOnSyncInitFailure() ShouldDevCrashOnSyncInitFailure()
{ {
@ -1424,18 +1540,107 @@ ShouldDevCrashOnSyncInitFailure()
!DeviceManagerDx::Get()->HasDeviceReset(); !DeviceManagerDx::Get()->HasDeviceReset();
} }
SyncObjectD3D11Host::SyncObjectD3D11Host(ID3D11Device* aDevice)
: mSyncHandle(0)
, mDevice(aDevice)
{
MOZ_ASSERT(aDevice);
}
bool bool
SyncObjectD3D11::Init() SyncObjectD3D11Host::Init()
{
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
RefPtr<ID3D11Texture2D> texture;
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
if (FAILED(hr) || !texture) {
gfxWarning() << "Could not create a sync texture: " << gfx::hexa(hr);
return false;
}
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
if (FAILED(hr) || !mSyncTexture) {
gfxWarning() << "Could not QI sync texture: " << gfx::hexa(hr);
return false;
}
hr = mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
if (FAILED(hr) || !mKeyedMutex) {
gfxWarning() << "Could not QI keyed-mutex: " << gfx::hexa(hr);
return false;
}
hr = mSyncTexture->GetSharedHandle(&mSyncHandle);
if (FAILED(hr) || !mSyncHandle) {
NS_DispatchToMainThread(NS_NewRunnableFunction("layers::SyncObjectD3D11Renderer::Init",
[] () -> void {
Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1);
}));
gfxWarning() << "Could not get sync texture shared handle: " << gfx::hexa(hr);
return false;
}
return true;
}
SyncHandle
SyncObjectD3D11Host::GetSyncHandle()
{
return mSyncHandle;
}
bool
SyncObjectD3D11Host::Synchronize()
{
HRESULT hr;
AutoTextureLock lock(mKeyedMutex, hr, 10000);
if (hr == WAIT_TIMEOUT) {
hr = mDevice->GetDeviceRemovedReason();
if (hr == S_OK) {
// There is no driver-removed event. Crash with this timeout.
MOZ_CRASH("GFX: D3D11 normal status timeout");
}
// Since the timeout is related to the driver-removed. Return false for
// error handling.
gfxCriticalNote << "GFX: D3D11 timeout with device-removed:" << gfx::hexa(hr);
return false;
}
if (hr == WAIT_ABANDONED) {
gfxCriticalNote << "GFX: AL_D3D11 abandoned sync";
}
return true;
}
SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice)
: mSyncHandle(aSyncHandle)
{
if (!aDevice) {
mDevice = DeviceManagerDx::Get()->GetContentDevice();
return;
}
mDevice = aDevice;
}
bool
SyncObjectD3D11Client::Init()
{ {
if (mKeyedMutex) { if (mKeyedMutex) {
return true; return true;
} }
HRESULT hr = mD3D11Device->OpenSharedResource( HRESULT hr = mDevice->OpenSharedResource(
mSyncHandle, mSyncHandle,
__uuidof(ID3D11Texture2D), __uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture)); (void**)(ID3D11Texture2D**)getter_AddRefs(mSyncTexture));
if (FAILED(hr) || !mD3D11Texture) { if (FAILED(hr) || !mSyncTexture) {
gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr); gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr);
if (ShouldDevCrashOnSyncInitFailure()) { if (ShouldDevCrashOnSyncInitFailure()) {
gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr); gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
@ -1443,10 +1648,10 @@ SyncObjectD3D11::Init()
return false; return false;
} }
hr = mD3D11Texture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex)); hr = mSyncTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
if (FAILED(hr) || !mKeyedMutex) { if (FAILED(hr) || !mKeyedMutex) {
// Leave both the critical error and MOZ_CRASH for now; the critical error lets // Leave both the critical error and MOZ_CRASH for now; the critical error lets
// us "save" the hr value. We will probably eventuall replace this with gfxDevCrash. // us "save" the hr value. We will probably eventually replace this with gfxDevCrash.
gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr); gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex"); MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
} }
@ -1455,25 +1660,25 @@ SyncObjectD3D11::Init()
} }
void void
SyncObjectD3D11::RegisterTexture(ID3D11Texture2D* aTexture) SyncObjectD3D11Client::RegisterTexture(ID3D11Texture2D* aTexture)
{ {
mD3D11SyncedTextures.push_back(aTexture); mSyncedTextures.push_back(aTexture);
} }
bool bool
SyncObjectD3D11::IsSyncObjectValid() SyncObjectD3D11Client::IsSyncObjectValid()
{ {
RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice(); RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
if (!dev || (NS_IsMainThread() && dev != mD3D11Device)) { if (!dev || (NS_IsMainThread() && dev != mDevice)) {
return false; return false;
} }
return true; return true;
} }
void void
SyncObjectD3D11::FinalizeFrame() SyncObjectD3D11Client::Synchronize()
{ {
if (!mD3D11SyncedTextures.size()) { if (!mSyncedTextures.size()) {
return; return;
} }
if (!Init()) { if (!Init()) {
@ -1496,7 +1701,7 @@ SyncObjectD3D11::FinalizeFrame()
box.back = box.bottom = box.right = 1; box.back = box.bottom = box.right = 1;
RefPtr<ID3D11Device> dev; RefPtr<ID3D11Device> dev;
mD3D11Texture->GetDevice(getter_AddRefs(dev)); mSyncTexture->GetDevice(getter_AddRefs(dev));
if (dev == DeviceManagerDx::Get()->GetContentDevice()) { if (dev == DeviceManagerDx::Get()->GetContentDevice()) {
if (DeviceManagerDx::Get()->HasDeviceReset()) { if (DeviceManagerDx::Get()->HasDeviceReset()) {
@ -1504,7 +1709,7 @@ SyncObjectD3D11::FinalizeFrame()
} }
} }
if (dev != mD3D11Device) { if (dev != mDevice) {
gfxWarning() << "Attempt to sync texture from invalid device."; gfxWarning() << "Attempt to sync texture from invalid device.";
return; return;
} }
@ -1512,11 +1717,11 @@ SyncObjectD3D11::FinalizeFrame()
RefPtr<ID3D11DeviceContext> ctx; RefPtr<ID3D11DeviceContext> ctx;
dev->GetImmediateContext(getter_AddRefs(ctx)); dev->GetImmediateContext(getter_AddRefs(ctx));
for (auto iter = mD3D11SyncedTextures.begin(); iter != mD3D11SyncedTextures.end(); iter++) { for (auto iter = mSyncedTextures.begin(); iter != mSyncedTextures.end(); iter++) {
ctx->CopySubresourceRegion(mD3D11Texture, 0, 0, 0, 0, *iter, 0, &box); ctx->CopySubresourceRegion(mSyncTexture, 0, 0, 0, 0, *iter, 0, &box);
} }
mD3D11SyncedTextures.clear(); mSyncedTextures.clear();
} }
uint32_t uint32_t

Просмотреть файл

@ -8,6 +8,7 @@
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/layers/Compositor.h" #include "mozilla/layers/Compositor.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/layers/TextureClient.h" #include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureHost.h" #include "mozilla/layers/TextureHost.h"
#include "gfxWindowsPlatform.h" #include "gfxWindowsPlatform.h"
@ -89,7 +90,7 @@ public:
TextureFlags aFlags, TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const override; TextureAllocationFlags aAllocFlags) const override;
virtual void SyncWithObject(SyncObject* aSync) override; virtual void SyncWithObject(SyncObjectClient* aSyncObject) override;
ID3D11Texture2D* GetD3D11Texture() { return mTexture; } ID3D11Texture2D* GetD3D11Texture() { return mTexture; }
@ -323,6 +324,8 @@ public:
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override; virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
const std::function<wr::ImageKey()>& aImageKeyAllocator) override; const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
@ -384,6 +387,8 @@ public:
return nullptr; return nullptr;
} }
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
const std::function<wr::ImageKey()>& aImageKeyAllocator) override; const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
@ -436,26 +441,49 @@ private:
RefPtr<ID3D11RenderTargetView> mRTView; RefPtr<ID3D11RenderTargetView> mRTView;
}; };
class SyncObjectD3D11 : public SyncObject class SyncObjectD3D11Host : public SyncObjectHost
{ {
public: public:
explicit SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice); explicit SyncObjectD3D11Host(ID3D11Device* aDevice);
virtual void FinalizeFrame();
virtual bool IsSyncObjectValid();
virtual SyncType GetSyncType() { return SyncType::D3D11; } virtual bool Init() override;
virtual SyncHandle GetSyncHandle() override;
virtual bool Synchronize() override;
IDXGIKeyedMutex* GetKeyedMutex() { return mKeyedMutex.get(); };
private:
virtual ~SyncObjectD3D11Host() { }
SyncHandle mSyncHandle;
RefPtr<ID3D11Device> mDevice;
RefPtr<IDXGIResource> mSyncTexture;
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
};
class SyncObjectD3D11Client : public SyncObjectClient
{
public:
explicit SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice);
virtual void Synchronize() override;
virtual bool IsSyncObjectValid() override;
virtual SyncType GetSyncType() override { return SyncType::D3D11; }
void RegisterTexture(ID3D11Texture2D* aTexture); void RegisterTexture(ID3D11Texture2D* aTexture);
private: private:
bool Init(); bool Init();
private:
SyncHandle mSyncHandle; SyncHandle mSyncHandle;
RefPtr<ID3D11Device> mD3D11Device; RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11Texture2D> mD3D11Texture; RefPtr<ID3D11Texture2D> mSyncTexture;
RefPtr<IDXGIKeyedMutex> mKeyedMutex; RefPtr<IDXGIKeyedMutex> mKeyedMutex;
std::vector<ID3D11Texture2D*> mD3D11SyncedTextures; std::vector<ID3D11Texture2D*> mSyncedTextures;
}; };
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel) inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)

Просмотреть файл

@ -13,7 +13,7 @@
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
class SyncObject; class SyncObjectClient;
class TextureForwarder; class TextureForwarder;
class LayersIPCActor; class LayersIPCActor;
@ -30,7 +30,7 @@ public:
void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier); void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
SyncObject* GetSyncObject() { return mSyncObject; } SyncObjectClient* GetSyncObject() { return mSyncObject; }
int32_t GetMaxTextureSize() const int32_t GetMaxTextureSize() const
{ {
@ -86,7 +86,7 @@ public:
protected: protected:
TextureFactoryIdentifier mTextureFactoryIdentifier; TextureFactoryIdentifier mTextureFactoryIdentifier;
RefPtr<SyncObject> mSyncObject; RefPtr<SyncObjectClient> mSyncObject;
const int32_t mSerial; const int32_t mSerial;
static mozilla::Atomic<int32_t> sSerialCounter; static mozilla::Atomic<int32_t> sSerialCounter;

Просмотреть файл

@ -32,6 +32,7 @@
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
#include "mozilla/layers/LayerTransactionChild.h" #include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/PTextureChild.h" #include "mozilla/layers/PTextureChild.h"
#include "mozilla/layers/SyncObject.h"
#include "ShadowLayerUtils.h" #include "ShadowLayerUtils.h"
#include "mozilla/layers/TextureClient.h" // for TextureClient #include "mozilla/layers/TextureClient.h" // for TextureClient
#include "mozilla/mozalloc.h" // for operator new, etc #include "mozilla/mozalloc.h" // for operator new, etc
@ -175,7 +176,7 @@ KnowsCompositor::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier
{ {
mTextureFactoryIdentifier = aIdentifier; mTextureFactoryIdentifier = aIdentifier;
mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle); mSyncObject = SyncObjectClient::CreateSyncObjectClient(aIdentifier.mSyncHandle);
} }
KnowsCompositor::KnowsCompositor() KnowsCompositor::KnowsCompositor()

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/gfx/Point.h" #include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Types.h" #include "mozilla/gfx/Types.h"
#include "MaskOperation.h" #include "MaskOperation.h"
#include "MLGDevice.h"
#include "nsDataHashtable.h" #include "nsDataHashtable.h"
#include "nsRefPtrHashtable.h" #include "nsRefPtrHashtable.h"
#include "ShaderDefinitionsMLGPU.h" #include "ShaderDefinitionsMLGPU.h"

Просмотреть файл

@ -224,6 +224,7 @@ EXPORTS.mozilla.layers += [
'ShareableCanvasRenderer.h', 'ShareableCanvasRenderer.h',
'SourceSurfaceSharedData.h', 'SourceSurfaceSharedData.h',
'SourceSurfaceVolatileData.h', 'SourceSurfaceVolatileData.h',
'SyncObject.h',
'TextureSourceProvider.h', 'TextureSourceProvider.h',
'TextureWrapperImage.h', 'TextureWrapperImage.h',
'TransactionIdAllocator.h', 'TransactionIdAllocator.h',
@ -456,6 +457,7 @@ UNIFIED_SOURCES += [
'ShareableCanvasRenderer.cpp', 'ShareableCanvasRenderer.cpp',
'SourceSurfaceSharedData.cpp', 'SourceSurfaceSharedData.cpp',
'SourceSurfaceVolatileData.cpp', 'SourceSurfaceVolatileData.cpp',
'SyncObject.cpp',
'TextureSourceProvider.cpp', 'TextureSourceProvider.cpp',
'TextureWrapperImage.cpp', 'TextureWrapperImage.cpp',
'wr/AsyncImagePipelineManager.cpp', 'wr/AsyncImagePipelineManager.cpp',

Просмотреть файл

@ -1436,7 +1436,11 @@ WebRenderBridgeParent::GetTextureFactoryIdentifier()
return TextureFactoryIdentifier(LayersBackend::LAYERS_WR, return TextureFactoryIdentifier(LayersBackend::LAYERS_WR,
XRE_GetProcessType(), XRE_GetProcessType(),
mApi->GetMaxTextureSize(), mApi->GetMaxTextureSize(),
mApi->GetUseANGLE()); mApi->GetUseANGLE(),
false,
false,
false,
mApi->GetSyncHandle());
} }
uint32_t uint32_t

Просмотреть файл

@ -18,7 +18,6 @@ WebRenderTextureHost::WebRenderTextureHost(const SurfaceDescriptor& aDesc,
wr::ExternalImageId& aExternalImageId) wr::ExternalImageId& aExternalImageId)
: TextureHost(aFlags) : TextureHost(aFlags)
, mExternalImageId(aExternalImageId) , mExternalImageId(aExternalImageId)
, mIsWrappingNativeHandle(false)
{ {
// The wrapped textureHost will be used in WebRender, and the WebRender could // The wrapped textureHost will be used in WebRender, and the WebRender could
// run at another thread. It's hard to control the life-time when gecko // run at another thread. It's hard to control the life-time when gecko
@ -47,25 +46,6 @@ WebRenderTextureHost::CreateRenderTextureHost(const layers::SurfaceDescriptor& a
{ {
MOZ_ASSERT(aTexture); MOZ_ASSERT(aTexture);
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
mIsWrappingNativeHandle = false;
break;
}
#ifdef XP_MACOSX
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
mIsWrappingNativeHandle = true;
break;
}
#endif
case SurfaceDescriptor::TSurfaceDescriptorGPUVideo: {
mIsWrappingNativeHandle = !aTexture->HasIntermediateBuffer();
break;
}
default:
gfxCriticalError() << "No WR implement for texture type:" << aDesc.type();
}
aTexture->CreateRenderTexture(mExternalImageId); aTexture->CreateRenderTexture(mExternalImageId);
} }

Просмотреть файл

@ -63,8 +63,6 @@ public:
int32_t GetRGBStride(); int32_t GetRGBStride();
bool IsWrappingNativeHandle() { return mIsWrappingNativeHandle; }
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
const std::function<wr::ImageKey()>& aImageKeyAllocator) override; const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
@ -83,8 +81,6 @@ protected:
RefPtr<TextureHost> mWrappedTextureHost; RefPtr<TextureHost> mWrappedTextureHost;
wr::ExternalImageId mExternalImageId; wr::ExternalImageId mExternalImageId;
bool mIsWrappingNativeHandle;
}; };
} // namespace layers } // namespace layers

Просмотреть файл

@ -1100,11 +1100,13 @@ SizeDistance(gfxFontconfigFontEntry* aEntry,
void void
gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle, gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
nsTArray<gfxFontEntry*>& aFontEntryList, nsTArray<gfxFontEntry*>& aFontEntryList,
bool& aNeedsSyntheticBold) bool& aNeedsSyntheticBold,
bool aIgnoreSizeTolerance)
{ {
gfxFontFamily::FindAllFontsForStyle(aFontStyle, gfxFontFamily::FindAllFontsForStyle(aFontStyle,
aFontEntryList, aFontEntryList,
aNeedsSyntheticBold); aNeedsSyntheticBold,
aIgnoreSizeTolerance);
if (!mHasNonScalableFaces) { if (!mHasNonScalableFaces) {
return; return;
@ -1113,7 +1115,7 @@ gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
// Iterate over the the available fonts while compacting any groups // Iterate over the the available fonts while compacting any groups
// of unscalable fonts with matching styles into a single entry // of unscalable fonts with matching styles into a single entry
// corresponding to the closest available size. If the closest // corresponding to the closest available size. If the closest
// available size is rejected for being outside tolernace, then the // available size is rejected for being outside tolerance, then the
// entire group will be skipped. // entire group will be skipped.
size_t skipped = 0; size_t skipped = 0;
gfxFontconfigFontEntry* bestEntry = nullptr; gfxFontconfigFontEntry* bestEntry = nullptr;
@ -1121,7 +1123,8 @@ gfxFontconfigFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
for (size_t i = 0; i < aFontEntryList.Length(); i++) { for (size_t i = 0; i < aFontEntryList.Length(); i++) {
gfxFontconfigFontEntry* entry = gfxFontconfigFontEntry* entry =
static_cast<gfxFontconfigFontEntry*>(aFontEntryList[i]); static_cast<gfxFontconfigFontEntry*>(aFontEntryList[i]);
double dist = SizeDistance(entry, aFontStyle, mForceScalable); double dist = SizeDistance(entry, aFontStyle,
mForceScalable || aIgnoreSizeTolerance);
// If the entry is scalable or has a style that does not match // If the entry is scalable or has a style that does not match
// the group of unscalable fonts, then start a new group. // the group of unscalable fonts, then start a new group.
if (dist < 0.0 || if (dist < 0.0 ||
@ -1766,7 +1769,7 @@ gfxFcPlatformFontList::GetFTLibrary()
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
gfxFontFamily* family = pfl->GetDefaultFont(&style); gfxFontFamily* family = pfl->GetDefaultFont(&style);
NS_ASSERTION(family, "couldn't find a default font family"); NS_ASSERTION(family, "couldn't find a default font family");
gfxFontEntry* fe = family->FindFontForStyle(style, needsBold); gfxFontEntry* fe = family->FindFontForStyle(style, needsBold, true);
if (!fe) { if (!fe) {
return nullptr; return nullptr;
} }

Просмотреть файл

@ -196,7 +196,8 @@ public:
void void
FindAllFontsForStyle(const gfxFontStyle& aFontStyle, FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
nsTArray<gfxFontEntry*>& aFontEntryList, nsTArray<gfxFontEntry*>& aFontEntryList,
bool& aNeedsSyntheticBold) override; bool& aNeedsSyntheticBold,
bool aIgnoreSizeTolerance) override;
protected: protected:
virtual ~gfxFontconfigFontFamily(); virtual ~gfxFontconfigFontFamily();

Просмотреть файл

@ -1101,10 +1101,12 @@ gfxFontFamily::HasOtherFamilyNames()
gfxFontEntry* gfxFontEntry*
gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle, gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle,
bool& aNeedsSyntheticBold) bool& aNeedsSyntheticBold,
bool aIgnoreSizeTolerance)
{ {
AutoTArray<gfxFontEntry*,4> matched; AutoTArray<gfxFontEntry*,4> matched;
FindAllFontsForStyle(aFontStyle, matched, aNeedsSyntheticBold); FindAllFontsForStyle(aFontStyle, matched, aNeedsSyntheticBold,
aIgnoreSizeTolerance);
if (!matched.IsEmpty()) { if (!matched.IsEmpty()) {
return matched[0]; return matched[0];
} }
@ -1234,7 +1236,8 @@ WeightStyleStretchDistance(gfxFontEntry* aFontEntry,
void void
gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle, gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
nsTArray<gfxFontEntry*>& aFontEntryList, nsTArray<gfxFontEntry*>& aFontEntryList,
bool& aNeedsSyntheticBold) bool& aNeedsSyntheticBold,
bool aIgnoreSizeTolerance)
{ {
if (!mHasStyles) { if (!mHasStyles) {
FindStyleVariations(); // collect faces for the family, if not already done FindStyleVariations(); // collect faces for the family, if not already done
@ -1469,7 +1472,7 @@ gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData)
gfxFontEntry *fe = gfxFontEntry *fe =
FindFontForStyle(aMatchData->mStyle ? *aMatchData->mStyle FindFontForStyle(aMatchData->mStyle ? *aMatchData->mStyle
: gfxFontStyle(), : gfxFontStyle(),
needsBold); needsBold, true);
if (fe && !fe->SkipDuringSystemFallback()) { if (fe && !fe->SkipDuringSystemFallback()) {
int32_t rank = 0; int32_t rank = 0;

Просмотреть файл

@ -643,12 +643,14 @@ public:
// aNeedsSyntheticBold is set to true when synthetic bolding is // aNeedsSyntheticBold is set to true when synthetic bolding is
// needed, false otherwise // needed, false otherwise
gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle, gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
bool& aNeedsSyntheticBold); bool& aNeedsSyntheticBold,
bool aIgnoreSizeTolerance = false);
virtual void virtual void
FindAllFontsForStyle(const gfxFontStyle& aFontStyle, FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
nsTArray<gfxFontEntry*>& aFontEntryList, nsTArray<gfxFontEntry*>& aFontEntryList,
bool& aNeedsSyntheticBold); bool& aNeedsSyntheticBold,
bool aIgnoreSizeTolerance = false);
// checks for a matching font within the family // checks for a matching font within the family
// used as part of the font fallback process // used as part of the font fallback process

Просмотреть файл

@ -65,7 +65,7 @@ gfxTextRun::GlyphRunIterator::NextRun()
} }
mGlyphRun = &mTextRun->mGlyphRunArray[mNextIndex]; mGlyphRun = &mTextRun->mGlyphRunArray[mNextIndex];
} else { } else {
if (mNextIndex > 0) { if (mNextIndex > 0 || !mTextRun->mSingleGlyphRun.mFont) {
return false; return false;
} }
glyphRunCount = 1; glyphRunCount = 1;

Просмотреть файл

@ -19,6 +19,7 @@
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "mozilla/dom/GamepadManager.h" #include "mozilla/dom/GamepadManager.h"
#include "mozilla/dom/VRServiceTest.h" #include "mozilla/dom/VRServiceTest.h"
#include "mozilla/layers/SyncObject.h"
using layers::TextureClient; using layers::TextureClient;
@ -61,7 +62,8 @@ VRManagerChild::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
{ {
if (sVRManagerChildSingleton) { if (sVRManagerChildSingleton) {
sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend; sVRManagerChildSingleton->mBackend = aIdentifier.mParentBackend;
sVRManagerChildSingleton->mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle); sVRManagerChildSingleton->mSyncObject =
layers::SyncObjectClient::CreateSyncObjectClient(aIdentifier.mSyncHandle);
} }
} }

Просмотреть файл

@ -25,6 +25,7 @@ class VREventObserver;
class VRMockDisplay; class VRMockDisplay;
} // namespace dom } // namespace dom
namespace layers { namespace layers {
class SyncObjectClient;
class TextureClient; class TextureClient;
} }
namespace gfx { namespace gfx {
@ -80,7 +81,7 @@ public:
static void IdentifyTextureHost(const layers::TextureFactoryIdentifier& aIdentifier); static void IdentifyTextureHost(const layers::TextureFactoryIdentifier& aIdentifier);
layers::LayersBackend GetBackendType() const; layers::LayersBackend GetBackendType() const;
layers::SyncObject* GetSyncObject() { return mSyncObject; } layers::SyncObjectClient* GetSyncObject() { return mSyncObject; }
virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; } virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; }
virtual base::ProcessId GetParentPid() const override { return OtherPid(); } virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
@ -194,7 +195,7 @@ private:
nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled; nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
layers::LayersBackend mBackend; layers::LayersBackend mBackend;
RefPtr<layers::SyncObject> mSyncObject; RefPtr<layers::SyncObjectClient> mSyncObject;
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mGamepadPromiseList; // TODO: check if it can merge into one list? nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mGamepadPromiseList; // TODO: check if it can merge into one list?
uint32_t mPromiseID; uint32_t mPromiseID;
nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList; nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;

Просмотреть файл

@ -0,0 +1,256 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RenderD3D11TextureHostOGL.h"
#include <d3d11.h>
#include "GLLibraryEGL.h"
#include "GLContextEGL.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/gfx/Logging.h"
#include "ScopedGLHelpers.h"
namespace mozilla {
namespace wr {
static EGLint
GetEGLTextureFormat(gfx::SurfaceFormat aFormat)
{
switch (aFormat) {
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8:
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::A8R8G8B8:
case gfx::SurfaceFormat::X8R8G8B8:
return LOCAL_EGL_TEXTURE_RGBA;
case gfx::SurfaceFormat::R8G8B8:
case gfx::SurfaceFormat::B8G8R8:
return LOCAL_EGL_TEXTURE_RGB;
default:
gfxCriticalError() << "GetEGLTextureFormat(): unexpected texture format";
return LOCAL_EGL_TEXTURE_RGBA;
}
}
RenderDXGITextureHostOGL::RenderDXGITextureHostOGL(WindowsHandle aHandle,
gfx::SurfaceFormat aFormat,
gfx::IntSize aSize)
: mHandle(aHandle)
, mTextureHandle{0}
, mSurface(0)
, mStream(0)
, mFormat(aFormat)
, mSize(aSize)
{
MOZ_COUNT_CTOR_INHERITED(RenderDXGITextureHostOGL, RenderTextureHostOGL);
}
RenderDXGITextureHostOGL::~RenderDXGITextureHostOGL()
{
MOZ_COUNT_DTOR_INHERITED(RenderDXGITextureHostOGL, RenderTextureHostOGL);
DeleteTextureHandle();
}
void
RenderDXGITextureHostOGL::SetGLContext(gl::GLContext* aContext)
{
if (mGL.get() != aContext) {
// Release the texture handle in the previous gl context.
DeleteTextureHandle();
mGL = aContext;
}
}
bool
RenderDXGITextureHostOGL::EnsureLockable()
{
if (mTextureHandle[0]) {
return true;
}
const auto& egl = &gl::sEGLLibrary;
if (mFormat != gfx::SurfaceFormat::NV12) {
// The non-nv12 format.
// Use eglCreatePbufferFromClientBuffer get the gl handle from the d3d
// shared handle.
// Get gl texture handle from shared handle.
EGLint pbufferAttributes[] = {
LOCAL_EGL_WIDTH, mSize.width,
LOCAL_EGL_HEIGHT, mSize.height,
LOCAL_EGL_TEXTURE_TARGET, LOCAL_EGL_TEXTURE_2D,
LOCAL_EGL_TEXTURE_FORMAT, GetEGLTextureFormat(mFormat),
LOCAL_EGL_MIPMAP_TEXTURE, LOCAL_EGL_FALSE,
LOCAL_EGL_NONE
};
mSurface = egl->fCreatePbufferFromClientBuffer(egl->Display(),
LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
reinterpret_cast<EGLClientBuffer>(mHandle),
gl::GLContextEGL::Cast(mGL.get())->mConfig,
pbufferAttributes);
MOZ_ASSERT(mSurface);
// Query the keyed-mutex.
egl->fQuerySurfacePointerANGLE(egl->Display(),
mSurface,
LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE,
(void**)getter_AddRefs(mKeyedMutex));
mGL->fGenTextures(1, &mTextureHandle[0]);
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextureHandle[0]);
mGL->TexParams_SetClampNoMips(LOCAL_GL_TEXTURE_2D);
egl->fBindTexImage(egl->Display(), mSurface, LOCAL_EGL_BACK_BUFFER);
} else {
// The nv12 format.
// The eglCreatePbufferFromClientBuffer doesn't support nv12 format, so we
// use EGLStream to get the converted gl handle from d3d nv12 texture.
// Fetch the D3D11 device.
EGLDeviceEXT eglDevice = nullptr;
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
MOZ_ASSERT(eglDevice);
ID3D11Device* device = nullptr;
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE, (EGLAttrib*)&device);
// There's a chance this might fail if we end up on d3d9 angle for some reason.
if (!device) {
return false;
}
// Get the NV12 D3D11 texture from shared handle.
if (FAILED(device->OpenSharedResource((HANDLE)mHandle,
__uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)getter_AddRefs(mTexture)))) {
NS_WARNING("RenderDXGITextureHostOGL::Lock(): Failed to open shared texture");
return false;
}
mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
// Create the EGLStream.
mStream = egl->fCreateStreamKHR(egl->Display(), nullptr);
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
MOZ_ASSERT(mStream);
DebugOnly<EGLBoolean> eglResult;
// Setup the NV12 stream consumer/producer.
EGLAttrib consumerAttributes[] = {
LOCAL_EGL_COLOR_BUFFER_TYPE,
LOCAL_EGL_YUV_BUFFER_EXT,
LOCAL_EGL_YUV_NUMBER_OF_PLANES_EXT,
2,
LOCAL_EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
0,
LOCAL_EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
1,
LOCAL_EGL_NONE,
};
mGL->fGenTextures(2, mTextureHandle);
// We change the ActiveTexture texture unit here. Use ScopedBindTextureUnit
// to go back to the original status after this function.
gl::ScopedBindTextureUnit scopedBindTexture(mGL, LOCAL_GL_TEXTURE0);
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureHandle[0]);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
mGL->fActiveTexture(LOCAL_GL_TEXTURE1);
mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mTextureHandle[1]);
mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
MOZ_ALWAYS_TRUE(egl->fStreamConsumerGLTextureExternalAttribsNV(egl->Display(), mStream, consumerAttributes));
MOZ_ALWAYS_TRUE(egl->fCreateStreamProducerD3DTextureNV12ANGLE(egl->Display(), mStream, nullptr));
// Insert the NV12 texture.
MOZ_ALWAYS_TRUE(egl->fStreamPostD3DTextureNV12ANGLE(egl->Display(), mStream, (void*)mTexture.get(), nullptr));
// Now, we could check the stream status and use the NV12 gl handle.
EGLint state;
egl->fQueryStreamKHR(egl->Display(), mStream, LOCAL_EGL_STREAM_STATE_KHR, &state);
MOZ_ASSERT(state == LOCAL_EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR);
egl->fStreamConsumerAcquireKHR(egl->Display(), mStream);
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
}
return true;
}
bool
RenderDXGITextureHostOGL::Lock()
{
if (!EnsureLockable()) {
return false;
}
if (mKeyedMutex) {
HRESULT hr = mKeyedMutex->AcquireSync(0, 100);
if (hr != S_OK) {
gfxCriticalError() << "RenderDXGITextureHostOGL AcquireSync timeout, hr=" << gfx::hexa(hr);
return false;
}
}
return true;
}
void
RenderDXGITextureHostOGL::Unlock()
{
if (mKeyedMutex) {
mKeyedMutex->ReleaseSync(0);
}
}
void
RenderDXGITextureHostOGL::DeleteTextureHandle()
{
if (mTextureHandle[0] != 0) {
if (mGL && mGL->MakeCurrent()) {
mGL->fDeleteTextures(2, mTextureHandle);
}
for(int i = 0; i < 2; ++i) {
mTextureHandle[i] = 0;
}
const auto& egl = &gl::sEGLLibrary;
if (mSurface) {
egl->fDestroySurface(egl->Display(), mSurface);
mSurface = 0;
}
if (mStream) {
egl->fStreamConsumerReleaseKHR(egl->Display(), mStream);
mStream = 0;
}
mTexture = nullptr;
mKeyedMutex = nullptr;
}
}
GLuint
RenderDXGITextureHostOGL::GetGLHandle(uint8_t aChannelIndex) const
{
MOZ_ASSERT(mFormat != gfx::SurfaceFormat::NV12 || aChannelIndex < 2);
MOZ_ASSERT(mFormat == gfx::SurfaceFormat::NV12 || aChannelIndex < 1);
return mTextureHandle[aChannelIndex];
}
gfx::IntSize
RenderDXGITextureHostOGL::GetSize(uint8_t aChannelIndex) const
{
MOZ_ASSERT(mFormat != gfx::SurfaceFormat::NV12 || aChannelIndex < 2);
MOZ_ASSERT(mFormat == gfx::SurfaceFormat::NV12 || aChannelIndex < 1);
if (aChannelIndex == 0) {
return mSize;
} else {
// The CbCr channel size is a half of Y channel size in NV12 format.
return mSize / 2;
}
}
} // namespace wr
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_RENDERD3D11TEXTUREHOSTOGL_H
#define MOZILLA_GFX_RENDERD3D11TEXTUREHOSTOGL_H
#include "RenderTextureHostOGL.h"
#include "GLTypes.h"
struct ID3D11Texture2D;
struct IDXGIKeyedMutex;
namespace mozilla {
namespace wr {
class RenderDXGITextureHostOGL final : public RenderTextureHostOGL
{
public:
explicit RenderDXGITextureHostOGL(WindowsHandle aHandle,
gfx::SurfaceFormat aFormat,
gfx::IntSize aSize);
virtual void SetGLContext(gl::GLContext* aContext) override;
virtual bool Lock() override;
virtual void Unlock() override;
virtual gfx::IntSize GetSize(uint8_t aChannelIndex) const;
virtual GLuint GetGLHandle(uint8_t aChannelIndex) const;
private:
virtual ~RenderDXGITextureHostOGL();
bool EnsureLockable();
void DeleteTextureHandle();
RefPtr<gl::GLContext> mGL;
WindowsHandle mHandle;
RefPtr<ID3D11Texture2D> mTexture;
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
EGLSurface mSurface;
EGLStreamKHR mStream;
// We could use NV12 format for this texture. So, we might have 2 gl texture
// handles for Y and CbCr data.
GLuint mTextureHandle[2];
gfx::SurfaceFormat mFormat;
gfx::IntSize mSize;
};
} // namespace wr
} // namespace mozilla
#endif // MOZILLA_GFX_RENDERD3D11TEXTUREHOSTOGL_H

Просмотреть файл

@ -9,6 +9,11 @@
#include "RenderTextureHost.h" #include "RenderTextureHost.h"
namespace mozilla { namespace mozilla {
namespace gl {
class GLContext;
}
namespace wr { namespace wr {
class RenderTextureHostOGL : public RenderTextureHost class RenderTextureHostOGL : public RenderTextureHost

Просмотреть файл

@ -71,6 +71,29 @@ RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
MOZ_ASSERT(mRenderer); MOZ_ASSERT(mRenderer);
MOZ_ASSERT(mBridge); MOZ_ASSERT(mBridge);
MOZ_COUNT_CTOR(RendererOGL); MOZ_COUNT_CTOR(RendererOGL);
#ifdef XP_WIN
if (aGL->IsANGLE()) {
gl::GLLibraryEGL* egl = &gl::sEGLLibrary;
// Fetch the D3D11 device.
EGLDeviceEXT eglDevice = nullptr;
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
MOZ_ASSERT(eglDevice);
ID3D11Device* device = nullptr;
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE, (EGLAttrib*)&device);
MOZ_ASSERT(device);
mSyncObject = layers::SyncObjectHost::CreateSyncObjectHost(device);
if (mSyncObject) {
if (!mSyncObject->Init()) {
// Some errors occur. Clear the mSyncObject here.
// Then, there will be no texture synchronization.
mSyncObject = nullptr;
}
}
}
#endif
} }
RendererOGL::~RendererOGL() RendererOGL::~RendererOGL()
@ -127,6 +150,12 @@ RendererOGL::Render()
// XXX set clear color if MOZ_WIDGET_ANDROID is defined. // XXX set clear color if MOZ_WIDGET_ANDROID is defined.
auto size = mWidget->GetClientSize(); auto size = mWidget->GetClientSize();
if (mSyncObject) {
// XXX: if the synchronization is failed, we should handle the device reset.
mSyncObject->Synchronize();
}
wr_renderer_render(mRenderer, size.width, size.height); wr_renderer_render(mRenderer, size.width, size.height);
mGL->SwapBuffers(); mGL->SwapBuffers();

Просмотреть файл

@ -7,6 +7,8 @@
#ifndef MOZILLA_LAYERS_RENDEREROGL_H #ifndef MOZILLA_LAYERS_RENDEREROGL_H
#define MOZILLA_LAYERS_RENDEREROGL_H #define MOZILLA_LAYERS_RENDEREROGL_H
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/webrender/RenderThread.h" #include "mozilla/webrender/RenderThread.h"
#include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/webrender/webrender_ffi.h" #include "mozilla/webrender/webrender_ffi.h"
@ -78,6 +80,8 @@ public:
/// This can be called on the render thread only. /// This can be called on the render thread only.
bool Resume(); bool Resume();
layers::SyncObjectHost* GetSyncObject() const { return mSyncObject.get(); }
layers::CompositorBridgeParentBase* GetCompositorBridge() { return mBridge; } layers::CompositorBridgeParentBase* GetCompositorBridge() { return mBridge; }
wr::WrRenderedEpochs* FlushRenderedEpochs(); wr::WrRenderedEpochs* FlushRenderedEpochs();
@ -87,7 +91,6 @@ public:
wr::Renderer* GetRenderer() { return mRenderer; } wr::Renderer* GetRenderer() { return mRenderer; }
protected: protected:
RefPtr<RenderThread> mThread; RefPtr<RenderThread> mThread;
RefPtr<gl::GLContext> mGL; RefPtr<gl::GLContext> mGL;
RefPtr<widget::CompositorWidget> mWidget; RefPtr<widget::CompositorWidget> mWidget;
@ -95,6 +98,7 @@ protected:
layers::CompositorBridgeParentBase* mBridge; layers::CompositorBridgeParentBase* mBridge;
wr::WindowId mWindowId; wr::WindowId mWindowId;
TimeStamp mFrameStartTime; TimeStamp mFrameStartTime;
RefPtr<layers::SyncObjectHost> mSyncObject;
}; };
} // namespace wr } // namespace wr

Просмотреть файл

@ -29,7 +29,8 @@ public:
RefPtr<widget::CompositorWidget>&& aWidget, RefPtr<widget::CompositorWidget>&& aWidget,
layers::SynchronousTask* aTask, layers::SynchronousTask* aTask,
bool aEnableProfiler, bool aEnableProfiler,
LayoutDeviceIntSize aSize) LayoutDeviceIntSize aSize,
layers::SyncHandle* aHandle)
: mRenderApi(aApi) : mRenderApi(aApi)
, mMaxTextureSize(aMaxTextureSize) , mMaxTextureSize(aMaxTextureSize)
, mUseANGLE(aUseANGLE) , mUseANGLE(aUseANGLE)
@ -38,6 +39,7 @@ public:
, mTask(aTask) , mTask(aTask)
, mEnableProfiler(aEnableProfiler) , mEnableProfiler(aEnableProfiler)
, mSize(aSize) , mSize(aSize)
, mSyncHandle(aHandle)
{ {
MOZ_COUNT_CTOR(NewRenderer); MOZ_COUNT_CTOR(NewRenderer);
} }
@ -91,6 +93,13 @@ public:
wr_renderer_set_external_image_handler(wrRenderer, &handler); wr_renderer_set_external_image_handler(wrRenderer, &handler);
} }
if (renderer) {
layers::SyncObjectHost* syncObj = renderer->GetSyncObject();
if (syncObj) {
*mSyncHandle = syncObj->GetSyncHandle();
}
}
aRenderThread.AddRenderer(aWindowId, Move(renderer)); aRenderThread.AddRenderer(aWindowId, Move(renderer));
} }
@ -103,6 +112,7 @@ private:
layers::SynchronousTask* mTask; layers::SynchronousTask* mTask;
bool mEnableProfiler; bool mEnableProfiler;
LayoutDeviceIntSize mSize; LayoutDeviceIntSize mSize;
layers::SyncHandle* mSyncHandle;
}; };
class RemoveRenderer : public RendererEvent class RemoveRenderer : public RendererEvent
@ -146,13 +156,15 @@ WebRenderAPI::Create(bool aEnableProfiler,
wr::RenderApi* renderApi = nullptr; wr::RenderApi* renderApi = nullptr;
GLint maxTextureSize = 0; GLint maxTextureSize = 0;
bool useANGLE = false; bool useANGLE = false;
layers::SyncHandle syncHandle = 0;
// Dispatch a synchronous task because the RenderApi object needs to be created // Dispatch a synchronous task because the RenderApi object needs to be created
// on the render thread. If need be we could delay waiting on this task until // on the render thread. If need be we could delay waiting on this task until
// the next time we need to access the RenderApi object. // the next time we need to access the RenderApi object.
layers::SynchronousTask task("Create Renderer"); layers::SynchronousTask task("Create Renderer");
auto event = MakeUnique<NewRenderer>(&renderApi, aBridge, &maxTextureSize, &useANGLE, auto event = MakeUnique<NewRenderer>(&renderApi, aBridge, &maxTextureSize, &useANGLE,
Move(aWidget), &task, aEnableProfiler, aSize); Move(aWidget), &task, aEnableProfiler, aSize,
&syncHandle);
RenderThread::Get()->RunEvent(id, Move(event)); RenderThread::Get()->RunEvent(id, Move(event));
task.Wait(); task.Wait();
@ -161,7 +173,7 @@ WebRenderAPI::Create(bool aEnableProfiler,
return nullptr; return nullptr;
} }
return RefPtr<WebRenderAPI>(new WebRenderAPI(renderApi, id, maxTextureSize, useANGLE)).forget(); return RefPtr<WebRenderAPI>(new WebRenderAPI(renderApi, id, maxTextureSize, useANGLE, syncHandle)).forget();
} }
wr::WrIdNamespace wr::WrIdNamespace

Просмотреть файл

@ -11,6 +11,7 @@
#include <unordered_map> #include <unordered_map>
#include "mozilla/AlreadyAddRefed.h" #include "mozilla/AlreadyAddRefed.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/Range.h" #include "mozilla/Range.h"
#include "mozilla/webrender/webrender_ffi.h" #include "mozilla/webrender/webrender_ffi.h"
#include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/webrender/WebRenderTypes.h"
@ -122,13 +123,15 @@ public:
wr::WrIdNamespace GetNamespace(); wr::WrIdNamespace GetNamespace();
GLint GetMaxTextureSize() const { return mMaxTextureSize; } GLint GetMaxTextureSize() const { return mMaxTextureSize; }
bool GetUseANGLE() const { return mUseANGLE; } bool GetUseANGLE() const { return mUseANGLE; }
layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
protected: protected:
WebRenderAPI(wr::RenderApi* aRawApi, wr::WindowId aId, GLint aMaxTextureSize, bool aUseANGLE) WebRenderAPI(wr::RenderApi* aRawApi, wr::WindowId aId, GLint aMaxTextureSize, bool aUseANGLE, layers::SyncHandle aSyncHandle)
: mRenderApi(aRawApi) : mRenderApi(aRawApi)
, mId(aId) , mId(aId)
, mMaxTextureSize(aMaxTextureSize) , mMaxTextureSize(aMaxTextureSize)
, mUseANGLE(aUseANGLE) , mUseANGLE(aUseANGLE)
, mSyncHandle(aSyncHandle)
{} {}
~WebRenderAPI(); ~WebRenderAPI();
@ -139,6 +142,7 @@ protected:
wr::WindowId mId; wr::WindowId mId;
GLint mMaxTextureSize; GLint mMaxTextureSize;
bool mUseANGLE; bool mUseANGLE;
layers::SyncHandle mSyncHandle;
friend class DisplayListBuilder; friend class DisplayListBuilder;
friend class layers::WebRenderBridgeParent; friend class layers::WebRenderBridgeParent;

Просмотреть файл

@ -37,6 +37,15 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
'RenderMacIOSurfaceTextureHostOGL.cpp', 'RenderMacIOSurfaceTextureHostOGL.cpp',
] ]
if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
EXPORTS.mozilla.webrender += [
'RenderD3D11TextureHostOGL.h',
]
UNIFIED_SOURCES += [
'RenderD3D11TextureHostOGL.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild') include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul' FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -127,6 +127,33 @@ GetProxyStubType(JSContext* cx, HandleObject obj, HandleId id)
return ProxyStubType::DOMUnshadowed; return ProxyStubType::DOMUnshadowed;
} }
static bool
ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
bool* nameOrSymbol)
{
*nameOrSymbol = false;
if (!idval.isString() && !idval.isSymbol())
return true;
if (!ValueToId<CanGC>(cx, idval, id))
return false;
if (!JSID_IS_STRING(id) && !JSID_IS_SYMBOL(id)) {
id.set(JSID_VOID);
return true;
}
uint32_t dummy;
if (JSID_IS_STRING(id) && JSID_TO_ATOM(id)->isIndex(&dummy)) {
id.set(JSID_VOID);
return true;
}
*nameOrSymbol = true;
return true;
}
bool bool
GetPropIRGenerator::tryAttachStub() GetPropIRGenerator::tryAttachStub()
{ {
@ -272,6 +299,99 @@ GetPropIRGenerator::tryAttachIdempotentStub()
return false; return false;
} }
static bool
IsCacheableProtoChain(JSObject* obj, JSObject* holder)
{
while (obj != holder) {
/*
* We cannot assume that we find the holder object on the prototype
* chain and must check for null proto. The prototype chain can be
* altered during the lookupProperty call.
*/
JSObject* proto = obj->staticPrototype();
if (!proto || !proto->isNative())
return false;
obj = proto;
}
return true;
}
static bool
IsCacheableGetPropReadSlot(JSObject* obj, JSObject* holder, PropertyResult prop)
{
if (!prop || !IsCacheableProtoChain(obj, holder))
return false;
Shape* shape = prop.shape();
if (!shape->hasSlot() || !shape->hasDefaultGetter())
return false;
return true;
}
static bool
IsCacheableGetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
{
if (!shape || !IsCacheableProtoChain(obj, holder))
return false;
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
return false;
if (!shape->getterValue().toObject().is<JSFunction>())
return false;
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
if (!getter.isNative())
return false;
if (getter.isClassConstructor())
return false;
// Check for a getter that has jitinfo and whose jitinfo says it's
// OK with both inner and outer objects.
if (getter.jitInfo() && !getter.jitInfo()->needsOuterizedThisObject())
return true;
// For getters that need the WindowProxy (instead of the Window) as this
// object, don't cache if obj is the Window, since our cache will pass that
// instead of the WindowProxy.
return !IsWindow(obj);
}
static bool
IsCacheableGetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
bool* isTemporarilyUnoptimizable = nullptr)
{
if (!shape || !IsCacheableProtoChain(obj, holder))
return false;
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
return false;
if (!shape->getterValue().toObject().is<JSFunction>())
return false;
// See IsCacheableGetPropCallNative.
if (IsWindow(obj))
return false;
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
if (getter.isNative())
return false;
if (!getter.hasJITCode()) {
if (isTemporarilyUnoptimizable)
*isTemporarilyUnoptimizable = true;
return false;
}
if (getter.isClassConstructor())
return false;
return true;
}
static bool static bool
IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id, IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* shape, jsid id,
jsbytecode* pc, GetPropertyResultFlags resultFlags) jsbytecode* pc, GetPropertyResultFlags resultFlags)
@ -327,7 +447,7 @@ CanAttachNativeGetProp(JSContext* cx, HandleObject obj, HandleId id,
} }
shape.set(prop.maybeShape()); shape.set(prop.maybeShape());
if (IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop)) if (IsCacheableGetPropReadSlot(obj, holder, prop))
return CanAttachReadSlot; return CanAttachReadSlot;
if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags)) if (IsCacheableNoProperty(cx, obj, holder, shape, id, pc, resultFlags))
@ -1866,8 +1986,7 @@ GetNameIRGenerator::tryAttachGlobalNameValue(ObjOperandId objId, HandleId id)
// prototype. Ignore the global lexical scope as it doesn't figure // prototype. Ignore the global lexical scope as it doesn't figure
// into the prototype chain. We guard on the global lexical // into the prototype chain. We guard on the global lexical
// scope's shape independently. // scope's shape independently.
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(&globalLexical->global(), holder, if (!IsCacheableGetPropReadSlot(&globalLexical->global(), holder, PropertyResult(shape)))
PropertyResult(shape)))
return false; return false;
// Shape guard for global lexical. // Shape guard for global lexical.
@ -1987,7 +2106,7 @@ GetNameIRGenerator::tryAttachEnvironmentName(ObjOperandId objId, HandleId id)
} }
holder = &env->as<NativeObject>(); holder = &env->as<NativeObject>();
if (!IsCacheableGetPropReadSlotForIonOrCacheIR(holder, holder, PropertyResult(shape))) if (!IsCacheableGetPropReadSlot(holder, holder, PropertyResult(shape)))
return false; return false;
if (holder->getSlot(shape->slot()).isMagic()) if (holder->getSlot(shape->slot()).isMagic())
return false; return false;
@ -2827,6 +2946,63 @@ SetPropIRGenerator::trackNotAttached()
#endif #endif
} }
static bool
IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
{
if (!shape || !IsCacheableProtoChain(obj, holder))
return false;
if (!shape->hasSetterValue())
return false;
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
return false;
JSFunction& setter = shape->setterObject()->as<JSFunction>();
if (!setter.isNative())
return false;
if (setter.isClassConstructor())
return false;
if (setter.jitInfo() && !setter.jitInfo()->needsOuterizedThisObject())
return true;
return !IsWindow(obj);
}
static bool
IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
bool* isTemporarilyUnoptimizable = nullptr)
{
if (!shape || !IsCacheableProtoChain(obj, holder))
return false;
if (IsWindow(obj))
return false;
if (!shape->hasSetterValue())
return false;
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
return false;
JSFunction& setter = shape->setterObject()->as<JSFunction>();
if (setter.isNative())
return false;
if (!setter.hasJITCode()) {
if (isTemporarilyUnoptimizable)
*isTemporarilyUnoptimizable = true;
return false;
}
if (setter.isClassConstructor())
return false;
return true;
}
static bool static bool
CanAttachSetter(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id, CanAttachSetter(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleId id,
MutableHandleObject holder, MutableHandleShape propShape, MutableHandleObject holder, MutableHandleShape propShape,

Просмотреть файл

@ -101,186 +101,6 @@ jit::GetReturnAddressToIonCode(JSContext* cx)
return returnAddr; return returnAddr;
} }
// Note: This differs from IsCacheableProtoChain in BaselineIC.cpp in that
// Ion caches can deal with objects on the proto chain that have uncacheable
// prototypes.
bool
jit::IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder)
{
while (obj != holder) {
/*
* We cannot assume that we find the holder object on the prototype
* chain and must check for null proto. The prototype chain can be
* altered during the lookupProperty call.
*/
JSObject* proto = obj->staticPrototype();
if (!proto || !proto->isNative())
return false;
obj = proto;
}
return true;
}
bool
jit::IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder, PropertyResult prop)
{
if (!prop || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
return false;
Shape* shape = prop.shape();
if (!shape->hasSlot() || !shape->hasDefaultGetter())
return false;
return true;
}
bool
jit::IsCacheableGetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
{
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
return false;
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
return false;
if (!shape->getterValue().toObject().is<JSFunction>())
return false;
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
if (!getter.isNative())
return false;
if (getter.isClassConstructor())
return false;
// Check for a getter that has jitinfo and whose jitinfo says it's
// OK with both inner and outer objects.
if (getter.jitInfo() && !getter.jitInfo()->needsOuterizedThisObject())
return true;
// For getters that need the WindowProxy (instead of the Window) as this
// object, don't cache if obj is the Window, since our cache will pass that
// instead of the WindowProxy.
return !IsWindow(obj);
}
bool
jit::IsCacheableGetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
bool* isTemporarilyUnoptimizable)
{
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
return false;
if (!shape->hasGetterValue() || !shape->getterValue().isObject())
return false;
if (!shape->getterValue().toObject().is<JSFunction>())
return false;
// See IsCacheableGetPropCallNative.
if (IsWindow(obj))
return false;
JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
if (getter.isNative())
return false;
if (!getter.hasJITCode()) {
if (isTemporarilyUnoptimizable)
*isTemporarilyUnoptimizable = true;
return false;
}
if (getter.isClassConstructor())
return false;
return true;
}
bool
jit::ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
bool* nameOrSymbol)
{
*nameOrSymbol = false;
if (!idval.isString() && !idval.isSymbol())
return true;
if (!ValueToId<CanGC>(cx, idval, id))
return false;
if (!JSID_IS_STRING(id) && !JSID_IS_SYMBOL(id)) {
id.set(JSID_VOID);
return true;
}
uint32_t dummy;
if (JSID_IS_STRING(id) && JSID_TO_ATOM(id)->isIndex(&dummy)) {
id.set(JSID_VOID);
return true;
}
*nameOrSymbol = true;
return true;
}
bool
jit::IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape)
{
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
return false;
if (!shape->hasSetterValue())
return false;
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
return false;
JSFunction& setter = shape->setterObject()->as<JSFunction>();
if (!setter.isNative())
return false;
if (setter.isClassConstructor())
return false;
if (setter.jitInfo() && !setter.jitInfo()->needsOuterizedThisObject())
return true;
return !IsWindow(obj);
}
bool
jit::IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
bool* isTemporarilyUnoptimizable)
{
if (!shape || !IsCacheableProtoChainForIonOrCacheIR(obj, holder))
return false;
if (IsWindow(obj))
return false;
if (!shape->hasSetterValue())
return false;
if (!shape->setterObject() || !shape->setterObject()->is<JSFunction>())
return false;
JSFunction& setter = shape->setterObject()->as<JSFunction>();
if (setter.isNative())
return false;
if (!setter.hasJITCode()) {
if (isTemporarilyUnoptimizable)
*isTemporarilyUnoptimizable = true;
return false;
}
if (setter.isClassConstructor())
return false;
return true;
}
void void
jit::EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value, jit::EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,
Register elements, BaseObjectElementIndex target) Register elements, BaseObjectElementIndex target)

Просмотреть файл

@ -26,21 +26,6 @@
namespace js { namespace js {
namespace jit { namespace jit {
bool IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder);
bool IsCacheableGetPropReadSlotForIonOrCacheIR(JSObject* obj, JSObject* holder,
PropertyResult prop);
bool IsCacheableGetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
bool* isTemporarilyUnoptimizable = nullptr);
bool IsCacheableGetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape);
bool IsCacheableSetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shape,
bool* isTemporarilyUnoptimizable = nullptr);
bool IsCacheableSetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape);
bool ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
bool* nameOrSymbol);
void* GetReturnAddressToIonCode(JSContext* cx); void* GetReturnAddressToIonCode(JSContext* cx);
void EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value, void EmitIonStoreDenseElement(MacroAssembler& masm, const ConstantOrRegister& value,

Просмотреть файл

@ -17,10 +17,12 @@
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIFactory.h" #include "nsIFactory.h"
#include "nsIScriptError.h" #include "nsIScriptError.h"
#include "nsISensitiveInfoHiddenURI.h"
#include "nsIStringBundle.h" #include "nsIStringBundle.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsStyleUtil.h" #include "nsStyleUtil.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsNetUtil.h"
#ifdef CSS_REPORT_PARSE_ERRORS #ifdef CSS_REPORT_PARSE_ERRORS
@ -37,12 +39,9 @@ public:
if (mURI != aURI) { if (mURI != aURI) {
mURI = aURI; mURI = aURI;
nsAutoCString cSpec; if (NS_FAILED(NS_GetSanitizedURIStringFromURI(mURI, mSpec))) {
nsresult rv = mURI->GetSpec(cSpec); mSpec.AssignLiteral("[nsIURI::GetSpec failed]");
if (NS_FAILED(rv)) {
cSpec.AssignLiteral("[nsIURI::GetSpec failed]");
} }
CopyUTF8toUTF16(cSpec, mSpec);
} }
return mSpec; return mSpec;
} }
@ -219,14 +218,16 @@ ErrorReporter::OutputError()
do_CreateInstance(sScriptErrorFactory, &rv); do_CreateInstance(sScriptErrorFactory, &rv);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = errorObject->InitWithWindowID(mError, // It is safe to used InitWithSanitizedSource because mFileName is
mFileName, // an already anonymized uri spec.
mErrorLine, rv = errorObject->InitWithSanitizedSource(mError,
mErrorLineNumber, mFileName,
mErrorColNumber, mErrorLine,
nsIScriptError::warningFlag, mErrorLineNumber,
"CSS Parser", mErrorColNumber,
mInnerWindowID); nsIScriptError::warningFlag,
"CSS Parser",
mInnerWindowID);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
sConsoleService->LogMessage(errorObject); sConsoleService->LogMessage(errorObject);
} }

Просмотреть файл

@ -2179,6 +2179,10 @@ pref("network.http.throttle.resume-for", 100);
// response has finished. Prevents resuming too soon during an active page load // response has finished. Prevents resuming too soon during an active page load
// at which sub-resource reqeusts quickly come and go. // at which sub-resource reqeusts quickly come and go.
pref("network.http.throttle.resume-background-in", 1000); pref("network.http.throttle.resume-background-in", 1000);
// After the last transaction activation or last data chunk response we only
// throttle for this period of time. This prevents comet and unresponsive
// http requests to engage long-standing throttling.
pref("network.http.throttle.time-window", 3000);
// Give higher priority to requests resulting from a user interaction event // Give higher priority to requests resulting from a user interaction event
// like click-to-play, image fancy-box zoom, navigation. // like click-to-play, image fancy-box zoom, navigation.

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsIRedirectChannelRegistrar.h" #include "nsIRedirectChannelRegistrar.h"
#include "nsIRequestObserverProxy.h" #include "nsIRequestObserverProxy.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
#include "nsISensitiveInfoHiddenURI.h"
#include "nsISimpleStreamListener.h" #include "nsISimpleStreamListener.h"
#include "nsISocketProvider.h" #include "nsISocketProvider.h"
#include "nsISocketProviderService.h" #include "nsISocketProviderService.h"
@ -1578,6 +1579,26 @@ NS_NewURI(nsIURI **result,
return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI, ioService); return NS_NewURI(result, nsDependentCString(spec), nullptr, baseURI, ioService);
} }
nsresult
NS_GetSanitizedURIStringFromURI(nsIURI *aUri, nsAString &aSanitizedSpec)
{
aSanitizedSpec.Truncate();
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(aUri);
nsAutoCString cSpec;
nsresult rv;
if (safeUri) {
rv = safeUri->GetSensitiveInfoHiddenSpec(cSpec);
} else {
rv = aUri->GetSpec(cSpec);
}
if (NS_SUCCEEDED(rv)) {
aSanitizedSpec.Assign(NS_ConvertUTF8toUTF16(cSpec));
}
return rv;
}
nsresult nsresult
NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **outResult, NS_LoadPersistentPropertiesFromURISpec(nsIPersistentProperties **outResult,
const nsACString &aSpec) const nsACString &aSpec)

Просмотреть файл

@ -100,6 +100,9 @@ nsresult NS_NewFileURI(nsIURI **result,
nsIFile *spec, nsIFile *spec,
nsIIOService *ioService = nullptr); // pass in nsIIOService to optimize callers nsIIOService *ioService = nullptr); // pass in nsIIOService to optimize callers
nsresult NS_GetSanitizedURIStringFromURI(nsIURI *aUri,
nsAString &aSanitizedSpec);
/* /*
* How to create a new Channel, using NS_NewChannel, * How to create a new Channel, using NS_NewChannel,
* NS_NewChannelWithTriggeringPrincipal, * NS_NewChannelWithTriggeringPrincipal,

Просмотреть файл

@ -2494,16 +2494,13 @@ HttpBaseChannel::AddSecurityMessage(const nsAString &aMessageTag,
errorText); errorText);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString spec;
if (mURI) {
spec = mURI->GetSpecOrDefault();
}
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
error->InitWithWindowID(errorText, NS_ConvertUTF8toUTF16(spec), error->InitWithSourceURI(errorText, mURI,
EmptyString(), 0, 0, nsIScriptError::warningFlag, EmptyString(), 0, 0,
NS_ConvertUTF16toUTF8(aMessageCategory), nsIScriptError::warningFlag,
innerWindowID); NS_ConvertUTF16toUTF8(aMessageCategory),
innerWindowID);
console->LogMessage(error); console->LogMessage(error);
return NS_OK; return NS_OK;

Просмотреть файл

@ -1580,14 +1580,14 @@ nsCORSListenerProxy::LogBlockedCORSRequest(uint64_t aInnerWindowID,
// query innerWindowID and log to web console, otherwise log to // query innerWindowID and log to web console, otherwise log to
// the error to the browser console. // the error to the browser console.
if (aInnerWindowID > 0) { if (aInnerWindowID > 0) {
rv = scriptError->InitWithWindowID(aMessage, rv = scriptError->InitWithSanitizedSource(aMessage,
EmptyString(), // sourceName EmptyString(), // sourceName
EmptyString(), // sourceLine EmptyString(), // sourceLine
0, // lineNumber 0, // lineNumber
0, // columnNumber 0, // columnNumber
nsIScriptError::warningFlag, nsIScriptError::warningFlag,
"CORS", "CORS",
aInnerWindowID); aInnerWindowID);
} }
else { else {
rv = scriptError->Init(aMessage, rv = scriptError->Init(aMessage,

Просмотреть файл

@ -119,6 +119,7 @@ nsHttpConnectionMgr::nsHttpConnectionMgr()
, mThrottleSuspendFor(0) , mThrottleSuspendFor(0)
, mThrottleResumeFor(0) , mThrottleResumeFor(0)
, mThrottleResumeIn(0) , mThrottleResumeIn(0)
, mThrottleTimeWindow(0)
, mIsShuttingDown(false) , mIsShuttingDown(false)
, mNumActiveConns(0) , mNumActiveConns(0)
, mNumIdleConns(0) , mNumIdleConns(0)
@ -175,7 +176,8 @@ nsHttpConnectionMgr::Init(uint16_t maxUrgentExcessiveConns,
bool throttleEnabled, bool throttleEnabled,
uint32_t throttleSuspendFor, uint32_t throttleSuspendFor,
uint32_t throttleResumeFor, uint32_t throttleResumeFor,
uint32_t throttleResumeIn) uint32_t throttleResumeIn,
uint32_t throttleTimeWindow)
{ {
LOG(("nsHttpConnectionMgr::Init\n")); LOG(("nsHttpConnectionMgr::Init\n"));
@ -192,6 +194,7 @@ nsHttpConnectionMgr::Init(uint16_t maxUrgentExcessiveConns,
mThrottleSuspendFor = throttleSuspendFor; mThrottleSuspendFor = throttleSuspendFor;
mThrottleResumeFor = throttleResumeFor; mThrottleResumeFor = throttleResumeFor;
mThrottleResumeIn = throttleResumeIn; mThrottleResumeIn = throttleResumeIn;
mThrottleTimeWindow = TimeDuration::FromMilliseconds(throttleTimeWindow);
mIsShuttingDown = false; mIsShuttingDown = false;
} }
@ -2831,6 +2834,9 @@ nsHttpConnectionMgr::OnMsgUpdateParam(int32_t inParam, ARefBase *)
case THROTTLING_RESUME_IN: case THROTTLING_RESUME_IN:
mThrottleResumeIn = value; mThrottleResumeIn = value;
break; break;
case THROTTLING_TIME_WINDOW:
mThrottleTimeWindow = TimeDuration::FromMilliseconds(value);
break;
default: default:
NS_NOTREACHED("unexpected parameter name"); NS_NOTREACHED("unexpected parameter name");
} }
@ -2929,6 +2935,30 @@ void nsHttpConnectionMgr::SetThrottlingEnabled(bool aEnable)
} }
} }
bool nsHttpConnectionMgr::InThrottlingTimeWindow()
{
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if (mThrottlingWindowEndsAt.IsNull()) {
return true;
}
return TimeStamp::NowLoRes() <= mThrottlingWindowEndsAt;
}
void nsHttpConnectionMgr::TouchThrottlingTimeWindow(bool aEnsureTicker)
{
LOG(("nsHttpConnectionMgr::TouchThrottlingTimeWindow"));
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
mThrottlingWindowEndsAt = TimeStamp::NowLoRes() + mThrottleTimeWindow;
if (!mThrottleTicker &&
MOZ_LIKELY(aEnsureTicker) && MOZ_LIKELY(mThrottleEnabled)) {
EnsureThrottleTickerIfNeeded();
}
}
void nsHttpConnectionMgr::LogActiveTransactions(char operation) void nsHttpConnectionMgr::LogActiveTransactions(char operation)
{ {
if (!LOG_ENABLED()) { if (!LOG_ENABLED()) {
@ -2961,30 +2991,39 @@ void nsHttpConnectionMgr::LogActiveTransactions(char operation)
} }
void void
nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled) nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans)
{ {
MOZ_ASSERT(OnSocketThread(), "not on socket thread"); MOZ_ASSERT(OnSocketThread(), "not on socket thread");
uint64_t tabId = aTrans->TopLevelOuterContentWindowId(); uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
bool throttled = aTrans->EligibleForThrottling();
nsTArray<RefPtr<nsHttpTransaction>> *transactions = nsTArray<RefPtr<nsHttpTransaction>> *transactions =
mActiveTransactions[aThrottled].LookupOrAdd(tabId); mActiveTransactions[throttled].LookupOrAdd(tabId);
MOZ_ASSERT(!transactions->Contains(aTrans)); MOZ_ASSERT(!transactions->Contains(aTrans));
transactions->AppendElement(aTrans); transactions->AppendElement(aTrans);
LOG(("nsHttpConnectionMgr::AddActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d", LOG(("nsHttpConnectionMgr::AddActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d",
aTrans, tabId, tabId == mCurrentTopLevelOuterContentWindowId, aThrottled)); aTrans, tabId, tabId == mCurrentTopLevelOuterContentWindowId, throttled));
LogActiveTransactions('+'); LogActiveTransactions('+');
if (tabId == mCurrentTopLevelOuterContentWindowId) { if (tabId == mCurrentTopLevelOuterContentWindowId) {
mActiveTabTransactionsExist = true; mActiveTabTransactionsExist = true;
if (!aThrottled) { if (!throttled) {
mActiveTabUnthrottledTransactionsExist = true; mActiveTabUnthrottledTransactionsExist = true;
} }
} }
// Shift the throttling window to the future (actually, makes sure
// that throttling will engage when there is anything to throttle.)
// The |false| argument means we don't need this call to ensure
// the ticker, since we do it just below. Calling
// EnsureThrottleTickerIfNeeded directly does a bit more than call
// from inside of TouchThrottlingTimeWindow.
TouchThrottlingTimeWindow(false);
if (!mThrottleEnabled) { if (!mThrottleEnabled) {
return; return;
} }
@ -2993,15 +3032,17 @@ nsHttpConnectionMgr::AddActiveTransaction(nsHttpTransaction * aTrans, bool aThro
} }
void void
nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled) nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans,
Maybe<bool> const& aOverride)
{ {
MOZ_ASSERT(OnSocketThread(), "not on socket thread"); MOZ_ASSERT(OnSocketThread(), "not on socket thread");
uint64_t tabId = aTrans->TopLevelOuterContentWindowId(); uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId; bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
bool throttled = aOverride.valueOr(aTrans->EligibleForThrottling());
nsTArray<RefPtr<nsHttpTransaction>> *transactions = nsTArray<RefPtr<nsHttpTransaction>> *transactions =
mActiveTransactions[aThrottled].Get(tabId); mActiveTransactions[throttled].Get(tabId);
if (!transactions || !transactions->RemoveElement(aTrans)) { if (!transactions || !transactions->RemoveElement(aTrans)) {
// Was not tracked as active, probably just ignore. // Was not tracked as active, probably just ignore.
@ -3009,7 +3050,7 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
} }
LOG(("nsHttpConnectionMgr::RemoveActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d", LOG(("nsHttpConnectionMgr::RemoveActiveTransaction t=%p tabid=%" PRIx64 "(%d) thr=%d",
aTrans, tabId, forActiveTab, aThrottled)); aTrans, tabId, forActiveTab, throttled));
if (!transactions->IsEmpty()) { if (!transactions->IsEmpty()) {
// There are still transactions of the type, hence nothing in the throttling conditions // There are still transactions of the type, hence nothing in the throttling conditions
@ -3020,16 +3061,16 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
} }
// To optimize the following logic, always remove the entry when the array is empty. // To optimize the following logic, always remove the entry when the array is empty.
mActiveTransactions[aThrottled].Remove(tabId); mActiveTransactions[throttled].Remove(tabId);
LogActiveTransactions('-'); LogActiveTransactions('-');
if (forActiveTab) { if (forActiveTab) {
// Update caches of the active tab transaction existence, since it's now affected // Update caches of the active tab transaction existence, since it's now affected
if (!aThrottled) { if (!throttled) {
mActiveTabUnthrottledTransactionsExist = false; mActiveTabUnthrottledTransactionsExist = false;
} }
if (mActiveTabTransactionsExist) { if (mActiveTabTransactionsExist) {
mActiveTabTransactionsExist = mActiveTransactions[!aThrottled].Contains(tabId); mActiveTabTransactionsExist = mActiveTransactions[!throttled].Contains(tabId);
} }
} }
@ -3067,7 +3108,7 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
// There are only trottled transactions for the active tab. // There are only trottled transactions for the active tab.
// If the last transaction we just removed was a non-throttled for the active tab // If the last transaction we just removed was a non-throttled for the active tab
// we can wake the throttled transactions for the active tab. // we can wake the throttled transactions for the active tab.
if (forActiveTab && !aThrottled) { if (forActiveTab && !throttled) {
LOG((" resuming throttled for active tab")); LOG((" resuming throttled for active tab"));
ResumeReadOf(mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId)); ResumeReadOf(mActiveTransactions[true].Get(mCurrentTopLevelOuterContentWindowId));
} }
@ -3094,16 +3135,21 @@ nsHttpConnectionMgr::RemoveActiveTransaction(nsHttpTransaction * aTrans, bool aT
} }
void void
nsHttpConnectionMgr::MoveActiveTransaction(nsHttpTransaction * aTrans, bool aThrottled) nsHttpConnectionMgr::UpdateActiveTransaction(nsHttpTransaction * aTrans)
{ {
LOG(("nsHttpConnectionMgr::MoveActiveTransaction ENTER t=%p", aTrans)); LOG(("nsHttpConnectionMgr::UpdateActiveTransaction ENTER t=%p", aTrans));
AddActiveTransaction(aTrans, aThrottled);
RemoveActiveTransaction(aTrans, !aThrottled); AddActiveTransaction(aTrans);
LOG(("nsHttpConnectionMgr::MoveActiveTransaction EXIT t=%p", aTrans));
Maybe<bool> reversed;
reversed.emplace(!aTrans->EligibleForThrottling());
RemoveActiveTransaction(aTrans, reversed);
LOG(("nsHttpConnectionMgr::UpdateActiveTransaction EXIT t=%p", aTrans));
} }
bool bool
nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans, bool aThrottled) nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans)
{ {
MOZ_ASSERT(OnSocketThread(), "not on socket thread"); MOZ_ASSERT(OnSocketThread(), "not on socket thread");
@ -3113,43 +3159,62 @@ nsHttpConnectionMgr::ShouldStopReading(nsHttpTransaction * aTrans, bool aThrottl
uint64_t tabId = aTrans->TopLevelOuterContentWindowId(); uint64_t tabId = aTrans->TopLevelOuterContentWindowId();
bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId; bool forActiveTab = tabId == mCurrentTopLevelOuterContentWindowId;
bool throttled = aTrans->EligibleForThrottling();
if (mActiveTabTransactionsExist) { bool stop = [=]() {
if (!tabId) { if (mActiveTabTransactionsExist) {
// Chrome initiated and unidentified transactions just respect if (!tabId) {
// their throttle flag, when something for the active tab is happening. // Chrome initiated and unidentified transactions just respect
return aThrottled; // their throttle flag, when something for the active tab is happening.
// This also includes downloads.
return throttled;
}
if (!forActiveTab) {
// This is a background tab request, we want them to always throttle
// when there are transactions running for the ative tab.
return true;
}
if (mActiveTabUnthrottledTransactionsExist) {
// Unthrottled transactions for the active tab take precedence
return throttled;
}
return false;
} }
if (!forActiveTab) {
// This is a background tab request, we want them to always throttle. MOZ_ASSERT(!forActiveTab);
if (mDelayedResumeReadTimer) {
// If this timer exists, background transactions are scheduled to be woken
// after a delay, hence leave them asleep.
return true; return true;
} }
if (mActiveTabUnthrottledTransactionsExist) {
// Unthrottled transactions for the active tab take precedence if (!mActiveTransactions[false].IsEmpty()) {
return aThrottled; // This means there are unthrottled active transactions for background tabs.
// If we are here, there can't be any transactions for the active tab.
// (If there is no transaction for a tab id, there is no entry for it in
// the hashtable.)
return throttled;
} }
// This is a throttled transaction for the active tab and there are no
// unthrottled for the active tab, just let go on full fuel. // There are only unthrottled transactions for background tabs: don't throttle.
return false;
}();
if (forActiveTab && !stop) {
// This active-tab transaction is allowed to read even though
// we are in the middle of "stop reading" interval. Hence,
// prolong the throttle time window to make sure all 'lower-decks'
// transactions will actually throttle.
TouchThrottlingTimeWindow();
return false; return false;
} }
MOZ_ASSERT(!forActiveTab); // Only stop reading when in the 3 seconds throttle time window.
// This window is prolonged (restarted) by a call to TouchThrottlingTimeWindow.
if (mDelayedResumeReadTimer) { return stop && InThrottlingTimeWindow();
// If this timer exists, background transactions are scheduled to be woken
// after a delay.
return true;
}
if (!mActiveTransactions[false].IsEmpty()) {
// This means there are unthrottled active transactions for background tabs.
// If we are here, there can't be any transactions for the active tab.
// (If there is no transaction for a tab id, there is no entry for it in the hashtable.)
return aThrottled;
}
// There are only unthrottled transactions for background tabs: don't throttle.
return false;
} }
bool nsHttpConnectionMgr::IsConnEntryUnderPressure(nsHttpConnectionInfo *connInfo) bool nsHttpConnectionMgr::IsConnEntryUnderPressure(nsHttpConnectionInfo *connInfo)
@ -3257,7 +3322,7 @@ nsHttpConnectionMgr::ThrottlerTick()
// throttle them again until the background-resume delay passes. // throttle them again until the background-resume delay passes.
if (!mThrottlingInhibitsReading && if (!mThrottlingInhibitsReading &&
!mDelayedResumeReadTimer && !mDelayedResumeReadTimer &&
!IsThrottleTickerNeeded()) { (!IsThrottleTickerNeeded() || !InThrottlingTimeWindow())) {
LOG((" last tick")); LOG((" last tick"));
mThrottleTicker = nullptr; mThrottleTicker = nullptr;
} }

Просмотреть файл

@ -60,7 +60,8 @@ public:
THROTTLING_ENABLED, THROTTLING_ENABLED,
THROTTLING_SUSPEND_FOR, THROTTLING_SUSPEND_FOR,
THROTTLING_RESUME_FOR, THROTTLING_RESUME_FOR,
THROTTLING_RESUME_IN THROTTLING_RESUME_IN,
THROTTLING_TIME_WINDOW
}; };
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -77,7 +78,8 @@ public:
bool throttleEnabled, bool throttleEnabled,
uint32_t throttleSuspendFor, uint32_t throttleSuspendFor,
uint32_t throttleResumeFor, uint32_t throttleResumeFor,
uint32_t throttleResumeIn); uint32_t throttleResumeIn,
uint32_t throttleTimeWindow);
MOZ_MUST_USE nsresult Shutdown(); MOZ_MUST_USE nsresult Shutdown();
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -217,15 +219,22 @@ public:
nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId); nsresult UpdateCurrentTopLevelOuterContentWindowId(uint64_t aWindowId);
// tracks and untracks active transactions according their throttle status // tracks and untracks active transactions according their throttle status
void AddActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled); void AddActiveTransaction(nsHttpTransaction* aTrans);
void RemoveActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled); void RemoveActiveTransaction(nsHttpTransaction* aTrans,
void MoveActiveTransaction(nsHttpTransaction* aTrans, bool aThrottled); Maybe<bool> const& aOverride = Nothing());
void UpdateActiveTransaction(nsHttpTransaction* aTrans);
// called by nsHttpTransaction::WriteSegments. decides whether the transaction // called by nsHttpTransaction::WriteSegments. decides whether the transaction
// should stop reading data based on: the throttling ticker status, overall // should stop reading data based on: the throttling ticker status, overall
// status of all active transactions regarding active tab and respective // status of all active transactions regarding active tab and respective
// throttling state. // throttling state.
bool ShouldStopReading(nsHttpTransaction* aTrans, bool aThrottled); bool ShouldStopReading(nsHttpTransaction* aTrans);
// prolongs the throttling time window to now + the window preferred size
// called when:
// - any transaction is activated
// - or when a currently unthrottled transaction for the active window receives data
void TouchThrottlingTimeWindow(bool aEnsureTicker = true);
// return true iff the connection has pending transactions for the active tab. // return true iff the connection has pending transactions for the active tab.
// it's mainly used to disallow throttling (stop reading) of a response // it's mainly used to disallow throttling (stop reading) of a response
@ -519,6 +528,7 @@ private:
uint32_t mThrottleSuspendFor; uint32_t mThrottleSuspendFor;
uint32_t mThrottleResumeFor; uint32_t mThrottleResumeFor;
uint32_t mThrottleResumeIn; uint32_t mThrottleResumeIn;
TimeDuration mThrottleTimeWindow;
Atomic<bool, mozilla::Relaxed> mIsShuttingDown; Atomic<bool, mozilla::Relaxed> mIsShuttingDown;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -689,6 +699,12 @@ private:
// Called on a pref change // Called on a pref change
void SetThrottlingEnabled(bool aEnable); void SetThrottlingEnabled(bool aEnable);
// we only want to throttle for a limited amount of time after a new
// active transaction is added so that we don't block downloads on comet,
// socket and any kind of longstanding requests that don't need bandwidth.
// these methods track this time.
bool InThrottlingTimeWindow();
// Two hashtalbes keeping track of active transactions regarding window id and throttling. // Two hashtalbes keeping track of active transactions regarding window id and throttling.
// Used by the throttling algorithm to obtain number of transactions for the active tab // Used by the throttling algorithm to obtain number of transactions for the active tab
// and for inactive tabs according their throttle status. // and for inactive tabs according their throttle status.
@ -698,6 +714,8 @@ private:
// Whether we are inside the "stop reading" interval, altered by the throttle ticker // Whether we are inside the "stop reading" interval, altered by the throttle ticker
bool mThrottlingInhibitsReading; bool mThrottlingInhibitsReading;
TimeStamp mThrottlingWindowEndsAt;
// ticker for the 'stop reading'/'resume reading' signal // ticker for the 'stop reading'/'resume reading' signal
nsCOMPtr<nsITimer> mThrottleTicker; nsCOMPtr<nsITimer> mThrottleTicker;
// Checks if the combination of active transactions requires the ticker. // Checks if the combination of active transactions requires the ticker.

Просмотреть файл

@ -196,6 +196,7 @@ nsHttpHandler::nsHttpHandler()
, mThrottleSuspendFor(3000) , mThrottleSuspendFor(3000)
, mThrottleResumeFor(200) , mThrottleResumeFor(200)
, mThrottleResumeIn(400) , mThrottleResumeIn(400)
, mThrottleTimeWindow(3000)
, mUrgentStartEnabled(true) , mUrgentStartEnabled(true)
, mRedirectionLimit(10) , mRedirectionLimit(10)
, mPhishyUserPassLength(1) , mPhishyUserPassLength(1)
@ -590,7 +591,8 @@ nsHttpHandler::InitConnectionMgr()
mThrottleEnabled, mThrottleEnabled,
mThrottleSuspendFor, mThrottleSuspendFor,
mThrottleResumeFor, mThrottleResumeFor,
mThrottleResumeIn); mThrottleResumeIn,
mThrottleTimeWindow);
return rv; return rv;
} }
@ -1636,6 +1638,15 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
} }
} }
if (PREF_CHANGED(HTTP_PREF("throttle.time-window"))) {
rv = prefs->GetIntPref(HTTP_PREF("throttle.time-window"), &val);
mThrottleTimeWindow = (uint32_t)clamped(val, 0, 120000);
if (NS_SUCCEEDED(rv) && mConnMgr) {
Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_TIME_WINDOW,
mThrottleTimeWindow);
}
}
if (PREF_CHANGED(HTTP_PREF("on_click_priority"))) { if (PREF_CHANGED(HTTP_PREF("on_click_priority"))) {
Unused << prefs->GetBoolPref(HTTP_PREF("on_click_priority"), &mUrgentStartEnabled); Unused << prefs->GetBoolPref(HTTP_PREF("on_click_priority"), &mUrgentStartEnabled);
} }

Просмотреть файл

@ -460,6 +460,7 @@ private:
uint32_t mThrottleSuspendFor; uint32_t mThrottleSuspendFor;
uint32_t mThrottleResumeFor; uint32_t mThrottleResumeFor;
uint32_t mThrottleResumeIn; uint32_t mThrottleResumeIn;
uint32_t mThrottleTimeWindow;
bool mUrgentStartEnabled; bool mUrgentStartEnabled;

Просмотреть файл

@ -173,13 +173,13 @@ void nsHttpTransaction::ResumeReading()
} }
} }
bool nsHttpTransaction::EligibleForThrottling() bool nsHttpTransaction::EligibleForThrottling() const
{ {
return (mClassOfService & (nsIClassOfService::Throttleable | return (mClassOfService & (nsIClassOfService::Throttleable |
nsIClassOfService::DontThrottle | nsIClassOfService::DontThrottle |
nsIClassOfService::Leader | nsIClassOfService::Leader |
nsIClassOfService::Unblocked)) == nsIClassOfService::Unblocked)) ==
nsIClassOfService::Throttleable; nsIClassOfService::Throttleable;
} }
void nsHttpTransaction::SetClassOfService(uint32_t cos) void nsHttpTransaction::SetClassOfService(uint32_t cos)
@ -190,9 +190,9 @@ void nsHttpTransaction::SetClassOfService(uint32_t cos)
if (mConnection && wasThrottling != isThrottling) { if (mConnection && wasThrottling != isThrottling) {
// Do nothing until we are actually activated. For now // Do nothing until we are actually activated. For now
// only remember the throttle flag. Call to MoveActiveTransaction // only remember the throttle flag. Call to UpdateActiveTransaction
// would add this transaction to the list too early. // would add this transaction to the list too early.
gHttpHandler->ConnMgr()->MoveActiveTransaction(this, isThrottling); gHttpHandler->ConnMgr()->UpdateActiveTransaction(this);
if (mReadingStopped && !isThrottling) { if (mReadingStopped && !isThrottling) {
ResumeReading(); ResumeReading();
@ -526,8 +526,7 @@ nsHttpTransaction::OnActivated(bool h2)
} }
mActivated = true; mActivated = true;
gHttpHandler->ConnMgr()->AddActiveTransaction( gHttpHandler->ConnMgr()->AddActiveTransaction(this);
this, mClassOfService & nsIClassOfService::Throttleable);
} }
void void
@ -841,15 +840,25 @@ bool nsHttpTransaction::ShouldStopReading()
if (mActivatedAsH2) { if (mActivatedAsH2) {
// Throttling feature is now disabled for http/2 transactions // Throttling feature is now disabled for http/2 transactions
// because of bug 1367861. The logic around mActivatedAsH2 // because of bug 1367861. The logic around mActivatedAsH2
// will be removed when that is fixed // will be removed when that is fixed.
//
// Calling ShouldStopReading on the manager just to make sure
// the throttling time window is correctly updated by this transaction.
Unused << gHttpHandler->ConnMgr()->ShouldStopReading(this);
return false; return false;
} }
if (mClassOfService & nsIClassOfService::DontThrottle) { if (mClassOfService & nsIClassOfService::DontThrottle) {
// We deliberately don't touch the throttling window here since
// DontThrottle requests are expected to be long-standing media
// streams and would just unnecessarily block running downloads.
// If we want to ballance bandwidth for media responses against
// running downloads, we need to find something smarter like
// changing the suspend/resume throttling intervals at-runtime.
return false; return false;
} }
if (!gHttpHandler->ConnMgr()->ShouldStopReading(this, EligibleForThrottling())) { if (!gHttpHandler->ConnMgr()->ShouldStopReading(this)) {
// We are not obligated to throttle // We are not obligated to throttle
return false; return false;
} }
@ -943,8 +952,7 @@ nsHttpTransaction::Close(nsresult reason)
this, static_cast<uint32_t>(reason))); this, static_cast<uint32_t>(reason)));
if (!mClosed) { if (!mClosed) {
gHttpHandler->ConnMgr()->RemoveActiveTransaction( gHttpHandler->ConnMgr()->RemoveActiveTransaction(this);
this, mClassOfService & nsIClassOfService::Throttleable);
mActivated = false; mActivated = false;
} }

Просмотреть файл

@ -394,8 +394,8 @@ public:
void ResumeReading(); void ResumeReading();
// This examins classification of this transaction whether the Throttleable class // This examins classification of this transaction whether the Throttleable class
// has been set while Leader or Unblocked are not. // has been set while Leader, Unblocked, DontThrottle has not.
bool EligibleForThrottling(); bool EligibleForThrottling() const;
private: private:
bool mSubmittedRatePacing; bool mSubmittedRatePacing;

Просмотреть файл

@ -1,5 +1,4 @@
[parse-input-arguments-018.html] [parse-input-arguments-018.html]
type: reftest type: reftest
expected: expected:
if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL if (os == "mac"): FAIL
if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL

Просмотреть файл

@ -10,32 +10,35 @@ const DIALOG_URL = "chrome://payments/content/paymentRequest.xhtml";
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyServiceGetter(this,
"paymentSrv",
"@mozilla.org/dom/payments/payment-request-service;1",
"nsIPaymentRequestService");
function PaymentUIService() {} function PaymentUIService() {}
PaymentUIService.prototype = { PaymentUIService.prototype = {
classID: Components.ID("{01f8bd55-9017-438b-85ec-7c15d2b35cdc}"), classID: Components.ID("{01f8bd55-9017-438b-85ec-7c15d2b35cdc}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]), QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIService]),
canMakePayment(requestId) {
let canMakeResponse = Cc["@mozilla.org/dom/payments/payment-canmake-action-response;1"]
.createInstance(Ci.nsIPaymentCanMakeActionResponse);
canMakeResponse.init(requestId, false);
return canMakeResponse.QueryInterface(Ci.nsIPaymentActionResponse);
},
showPayment(requestId) { showPayment(requestId) {
return null;
}, },
abortPayment(requestId) { abortPayment(requestId) {
let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"] let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"]
.createInstance(Ci.nsIPaymentAbortActionResponse); .createInstance(Ci.nsIPaymentAbortActionResponse);
abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED); abortResponse.init(requestId, Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED);
return abortResponse.QueryInterface(Ci.nsIPaymentActionResponse); paymentSrv.respondPayment(abortResponse.QueryInterface(Ci.nsIPaymentActionResponse));
}, },
completePayment(requestId) { completePayment(requestId) {
return null; let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]
.createInstance(Ci.nsIPaymentCompleteActionResponse);
completeResponse.init(requestId, Ci.nsIPaymentActionResponse.COMPLTETE_SUCCEEDED);
paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
},
updatePayment(requestId) {
}, },
}; };

Просмотреть файл

@ -72,15 +72,13 @@ LogMessage(const nsAString &aMessage, nsIURI* aSourceURI, const nsAString &aSour
nsCOMPtr<nsIScriptError> error = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); nsCOMPtr<nsIScriptError> error = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
NS_ENSURE_TRUE(error, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(error, NS_ERROR_OUT_OF_MEMORY);
nsCString sourceName = aSourceURI->GetSpecOrDefault();
uint64_t windowID = 0; uint64_t windowID = 0;
GetWindowIDFromContext(aContext, &windowID); GetWindowIDFromContext(aContext, &windowID);
nsresult rv = nsresult rv =
error->InitWithWindowID(aMessage, NS_ConvertUTF8toUTF16(sourceName), error->InitWithSourceURI(aMessage, aSourceURI,
aSourceSample, 0, 0, nsIScriptError::errorFlag, aSourceSample, 0, 0, nsIScriptError::errorFlag,
"JavaScript", windowID); "JavaScript", windowID);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID); nsCOMPtr<nsIConsoleService> console = do_GetService(NS_CONSOLESERVICE_CONTRACTID);

Просмотреть файл

@ -720,46 +720,52 @@ AddPseudoEntry(uint32_t aFeatures, NotNull<RacyThreadInfo*> aRacyInfo,
MOZ_ASSERT(entry.kind() == js::ProfileEntry::Kind::CPP_NORMAL || MOZ_ASSERT(entry.kind() == js::ProfileEntry::Kind::CPP_NORMAL ||
entry.kind() == js::ProfileEntry::Kind::JS_NORMAL); entry.kind() == js::ProfileEntry::Kind::JS_NORMAL);
const char* label = entry.label();
const char* dynamicString = entry.dynamicString(); const char* dynamicString = entry.dynamicString();
bool isChromeJSEntry = false;
int lineno = -1; int lineno = -1;
// XXX: it's unclear why the computation of lineno should depend on if (entry.isJs()) {
// |dynamicString|. Perhaps it shouldn't? // There are two kinds of JS frames that get pushed onto the PseudoStack.
//
// - label = "", dynamic string = <something>
// - label = "js::RunScript", dynamic string = nullptr
//
// The line number is only interesting for the first case.
if (label[0] == '\0') {
MOZ_ASSERT(dynamicString);
if (dynamicString) {
bool isChromeJSEntry = false;
if (entry.isJs()) {
// We call entry.script() repeatedly -- rather than storing the result in // We call entry.script() repeatedly -- rather than storing the result in
// a local variable in order -- to avoid rooting hazards. // a local variable in order -- to avoid rooting hazards.
if (entry.script()) { if (entry.script()) {
isChromeJSEntry = IsChromeJSScript(entry.script()); isChromeJSEntry = IsChromeJSScript(entry.script());
if (!entry.pc()) { if (entry.pc()) {
lineno = JS_PCToLineNumber(entry.script(), entry.pc());
} else {
// The JIT only allows the top-most entry to have a nullptr pc. // The JIT only allows the top-most entry to have a nullptr pc.
MOZ_ASSERT(&entry == &aRacyInfo->entries[aRacyInfo->stackSize() - 1]); MOZ_ASSERT(&entry == &aRacyInfo->entries[aRacyInfo->stackSize() - 1]);
} else {
lineno = JS_PCToLineNumber(entry.script(), entry.pc());
} }
} }
} else { } else {
lineno = entry.line(); MOZ_ASSERT(strcmp(label, "js::RunScript") == 0 && !dynamicString);
} }
} else {
MOZ_ASSERT(entry.isCpp());
lineno = entry.line();
}
if (dynamicString) {
// Adjust the dynamic string as necessary. // Adjust the dynamic string as necessary.
if (ProfilerFeature::HasPrivacy(aFeatures) && !isChromeJSEntry) { if (ProfilerFeature::HasPrivacy(aFeatures) && !isChromeJSEntry) {
dynamicString = "(private)"; dynamicString = "(private)";
} else if (strlen(dynamicString) >= ProfileBuffer::kMaxFrameKeyLength) { } else if (strlen(dynamicString) >= ProfileBuffer::kMaxFrameKeyLength) {
dynamicString = "(too long)"; dynamicString = "(too long)";
} }
} else {
// XXX: Bug 1010578. Don't assume a CPP entry and try to get the line for
// js entries as well.
if (entry.isCpp()) {
lineno = entry.line();
}
} }
aCollector.CollectCodeLocation(entry.label(), dynamicString, lineno, aCollector.CollectCodeLocation(label, dynamicString, lineno,
Some(entry.category())); Some(entry.category()));
} }