diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index aae0044498..8dfafc926b 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -13535,6 +13535,11 @@ public: { nsAutoPopupStatePusher popupStatePusher(mPopupState); + // We need to set up an AutoJSAPI here for the following reason: When we do + // OnLinkClickSync we'll eventually end up in nsGlobalWindow::OpenInternal + // which only does popup blocking if !LegacyIsCallerChromeOrNativeCode(). + // So we need to fake things so that we don't look like native code as far + // as LegacyIsCallerNativeCode() is concerned. AutoJSAPI jsapi; if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) { mHandler->OnLinkClickSync(mContent, mURI, diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 881654e519..89e30d29a1 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -844,7 +844,7 @@ nsDOMWindowUtils::SendWheelEvent(float aX, wheelEvent.refPoint = nsContentUtils::ToWidgetPoint(CSSPoint(aX, aY), offset, presContext); - widget->DispatchAPZAwareEvent(&wheelEvent); + widget->DispatchInputEvent(&wheelEvent); if (widget->AsyncPanZoomEnabled()) { // Computing overflow deltas is not compatible with APZ, so if APZ is @@ -2596,6 +2596,8 @@ nsDOMWindowUtils::ZoomToFocusedInput() uint32_t flags = layers::DISABLE_ZOOM_OUT; if (!Preferences::GetBool("formhelper.autozoom")) { flags |= layers::PAN_INTO_VIEW_ONLY; + } else { + flags |= layers::ONLY_ZOOM_TO_DEFAULT_SCALE; } CSSRect bounds = nsLayoutUtils::GetBoundingContentRect(content, rootScrollFrame); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 70879fc0f3..8a18ac2cd1 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -1573,6 +1573,26 @@ nsDocument::~nsDocument() Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel); Accumulate(Telemetry::SCROLL_LINKED_EFFECT_FOUND, mHasScrollLinkedEffect); + + // record mixed object subrequest telemetry + if (mHasMixedContentObjectSubrequest) { + /* mixed object subrequest loaded on page*/ + Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 1); + } else { + /* no mixed object subrequests loaded on page*/ + Accumulate(Telemetry::MIXED_CONTENT_OBJECT_SUBREQUEST, 0); + } + + // record CSP telemetry on this document + if (mHasCSP) { + Accumulate(Telemetry::CSP_DOCUMENTS_COUNT, 1); + } + if (mHasUnsafeInlineCSP) { + Accumulate(Telemetry::CSP_UNSAFE_INLINE_DOCUMENTS_COUNT, 1); + } + if (mHasUnsafeEvalCSP) { + Accumulate(Telemetry::CSP_UNSAFE_EVAL_DOCUMENTS_COUNT, 1); + } } } @@ -2311,7 +2331,7 @@ nsDocument::RemoveDocStyleSheetsFromStyleSets() void nsDocument::RemoveStyleSheetsFromStyleSets( - nsTArray& aSheets, + const nsTArray& aSheets, SheetType aType) { // The stylesheets should forget us @@ -4151,7 +4171,7 @@ nsDocument::GetStyleSheetAt(int32_t aIndex) const } int32_t -nsDocument::GetIndexOfStyleSheet(StyleSheetHandle aSheet) const +nsDocument::GetIndexOfStyleSheet(const StyleSheetHandle aSheet) const { return mStyleSheets.IndexOf(aSheet); } diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 156b36d969..2d8d27e473 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -777,7 +777,8 @@ public: */ virtual int32_t GetNumberOfStyleSheets() const override; virtual mozilla::StyleSheetHandle GetStyleSheetAt(int32_t aIndex) const override; - virtual int32_t GetIndexOfStyleSheet(mozilla::StyleSheetHandle aSheet) const override; + virtual int32_t GetIndexOfStyleSheet( + const mozilla::StyleSheetHandle aSheet) const override; virtual void AddStyleSheet(mozilla::StyleSheetHandle aSheet) override; virtual void RemoveStyleSheet(mozilla::StyleSheetHandle aSheet) override; @@ -1490,7 +1491,7 @@ protected: void RemoveDocStyleSheetsFromStyleSets(); void RemoveStyleSheetsFromStyleSets( - nsTArray& aSheets, + const nsTArray& aSheets, mozilla::SheetType aType); void ResetStylesheetsToURI(nsIURI* aURI); void FillStyleSet(mozilla::StyleSetHandle aStyleSet); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 7afe07ea48..175b21ce92 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -12069,6 +12069,10 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName, } } + // XXXbz When this gets fixed to not use LegacyIsCallerNativeCode() + // (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run. + // But note that if you change this to GetEntryGlobal(), say, then + // OnLinkClickEvent::Run will need a full-blown AutoEntryScript. const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() && !isApp && !aDialog && !WindowExists(aName, !aCalledNoScript); diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 91ed89761d..e445d24036 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -633,6 +633,38 @@ public: mHasMixedDisplayContentBlocked = aHasMixedDisplayContentBlocked; } + /** + * Set the mixed content object subrequest flag for this document. + */ + void SetHasMixedContentObjectSubrequest(bool aHasMixedContentObjectSubrequest) + { + mHasMixedContentObjectSubrequest = aHasMixedContentObjectSubrequest; + } + + /** + * Set CSP flag for this document. + */ + void SetHasCSP(bool aHasCSP) + { + mHasCSP = aHasCSP; + } + + /** + * Set unsafe-inline CSP flag for this document. + */ + void SetHasUnsafeInlineCSP(bool aHasUnsafeInlineCSP) + { + mHasUnsafeInlineCSP = aHasUnsafeInlineCSP; + } + + /** + * Set unsafe-eval CSP flag for this document. + */ + void SetHasUnsafeEvalCSP(bool aHasUnsafeEvalCSP) + { + mHasUnsafeEvalCSP = aHasUnsafeEvalCSP; + } + /** * Get tracking content blocked flag for this document. */ @@ -979,7 +1011,8 @@ public: * @param aSheet the sheet to get the index of * @return aIndex the index of the sheet in the full list */ - virtual int32_t GetIndexOfStyleSheet(mozilla::StyleSheetHandle aSheet) const = 0; + virtual int32_t GetIndexOfStyleSheet( + const mozilla::StyleSheetHandle aSheet) const = 0; /** * Replace the stylesheets in aOldSheets with the stylesheets in @@ -2742,6 +2775,10 @@ public: bool InlineScriptAllowedByCSP(); void ReportHasScrollLinkedEffect(); + bool HasScrollLinkedEffect() const + { + return mHasScrollLinkedEffect; + } protected: bool GetUseCounter(mozilla::UseCounter aUseCounter) @@ -2907,11 +2944,15 @@ protected: // True iff we've ever fired a DOMTitleChanged event for this document bool mHaveFiredTitleChange : 1; - // True iff IsShowing() should be returning true + // State for IsShowing(). mIsShowing starts off false. It becomes true when + // OnPageShow happens and becomes false when OnPageHide happens. So it's false + // before the initial load completes and when we're in bfcache or unloaded, + // true otherwise. bool mIsShowing : 1; - // True iff the document "page" is not hidden (i.e. currently in the - // bfcache) + // State for IsVisible(). mVisible starts off true. It becomes false when + // OnPageHide happens, and becomes true again when OnPageShow happens. So + // it's false only when we're in bfcache or unloaded. bool mVisible : 1; // True if our content viewer has been removed from the docshell @@ -2969,6 +3010,18 @@ protected: // True if a document has blocked Mixed Display/Passive Content (see nsMixedContentBlocker.cpp) bool mHasMixedDisplayContentBlocked : 1; + // True if a document loads a plugin object that attempts to load mixed content subresources through necko(see nsMixedContentBlocker.cpp) + bool mHasMixedContentObjectSubrequest : 1; + + // True if a document load has a CSP attached. + bool mHasCSP : 1; + + // True if a document load has a CSP with unsafe-eval attached. + bool mHasUnsafeEvalCSP : 1; + + // True if a document load has a CSP with unsafe-inline attached. + bool mHasUnsafeInlineCSP : 1; + // True if a document has blocked Tracking Content bool mHasTrackingContentBlocked : 1; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 631c5d1b05..f66b69859a 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -1341,7 +1341,7 @@ bool TabParent::RecvDispatchWheelEvent(const mozilla::WidgetWheelEvent& aEvent) localEvent.widget = widget; localEvent.refPoint -= GetChildProcessOffset(); - widget->DispatchAPZAwareEvent(&localEvent); + widget->DispatchInputEvent(&localEvent); return true; } diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 868b3bc94c..e4f8decf97 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -86,6 +86,10 @@ MediaFormatReader::Shutdown() { MOZ_ASSERT(OnTaskQueue()); + if (HasVideo()) { + ReportDroppedFramesTelemetry(); + } + mDemuxerInitRequest.DisconnectIfExists(); mMetadataPromise.RejectIfExists(ReadMetadataFailureReason::METADATA_ERROR, __func__); mSeekPromise.RejectIfExists(NS_ERROR_FAILURE, __func__); @@ -667,6 +671,7 @@ MediaFormatReader::NotifyNewOutput(TrackType aTrack, MediaData* aSample) decoder.mOutput.AppendElement(aSample); decoder.mNumSamplesOutput++; decoder.mNumSamplesOutputTotal++; + decoder.mNumSamplesOutputTotalSinceTelemetry++; ScheduleUpdate(aTrack); } @@ -910,6 +915,9 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack, LOG("%s stream id has changed from:%d to:%d, draining decoder.", TrackTypeToStr(aTrack), decoder.mLastStreamSourceID, info->GetID()); + if (aTrack == TrackType::kVideoTrack) { + ReportDroppedFramesTelemetry(); + } decoder.mNeedDraining = true; decoder.mNextStreamSourceID = Some(info->GetID()); ScheduleUpdate(aTrack); @@ -1371,6 +1379,7 @@ MediaFormatReader::OnVideoSkipCompleted(uint32_t aSkipped) mDecoder->NotifyDecodedFrames(aSkipped, 0, aSkipped); } mVideo.mNumSamplesSkippedTotal += aSkipped; + mVideo.mNumSamplesSkippedTotalSinceTelemetry += aSkipped; MOZ_ASSERT(!mVideo.mError); // We have flushed the decoder, no frame could // have been decoded (and as such errored) NotifyDecodingRequested(TrackInfo::kVideoTrack); @@ -1700,4 +1709,51 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString) aString += NS_ConvertUTF8toUTF16(result); } +void +MediaFormatReader::ReportDroppedFramesTelemetry() +{ + MOZ_ASSERT(OnTaskQueue()); + + const VideoInfo* info = + mVideo.mInfo ? mVideo.mInfo->GetAsVideoInfo() : &mInfo.mVideo; + + if (!info || !mVideo.mDecoder) { + return; + } + + nsCString keyPhrase = nsCString("MimeType="); + keyPhrase.Append(info->mMimeType); + keyPhrase.Append("; "); + + keyPhrase.Append("Resolution="); + keyPhrase.AppendInt(info->mDisplay.width); + keyPhrase.Append('x'); + keyPhrase.AppendInt(info->mDisplay.height); + keyPhrase.Append("; "); + + keyPhrase.Append("HardwareAcceleration="); + if (VideoIsHardwareAccelerated()) { + keyPhrase.Append(mVideo.mDecoder->GetDescriptionName()); + keyPhrase.Append("enabled"); + } else { + keyPhrase.Append("disabled"); + } + + if (mVideo.mNumSamplesOutputTotalSinceTelemetry) { + uint32_t percentage = + 100 * mVideo.mNumSamplesSkippedTotalSinceTelemetry / + mVideo.mNumSamplesOutputTotalSinceTelemetry; + nsCOMPtr task = NS_NewRunnableFunction([=]() -> void { + LOG("Reporting telemetry DROPPED_FRAMES_IN_VIDEO_PLAYBACK"); + Telemetry::Accumulate(Telemetry::VIDEO_DETAILED_DROPPED_FRAMES_PROPORTION, + keyPhrase, + percentage); + }); + AbstractThread::MainThread()->Dispatch(task.forget()); + } + + mVideo.mNumSamplesSkippedTotalSinceTelemetry = 0; + mVideo.mNumSamplesOutputTotalSinceTelemetry = 0; +} + } // namespace mozilla diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index d817abaf59..c2d8b10689 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -234,6 +234,8 @@ private: , mNumSamplesOutput(0) , mNumSamplesOutputTotal(0) , mNumSamplesSkippedTotal(0) + , mNumSamplesOutputTotalSinceTelemetry(0) + , mNumSamplesSkippedTotalSinceTelemetry(0) , mSizeOfQueue(0) , mIsHardwareAccelerated(false) , mLastStreamSourceID(UINT32_MAX) @@ -312,6 +314,9 @@ private: uint64_t mNumSamplesOutputTotal; uint64_t mNumSamplesSkippedTotal; + uint64_t mNumSamplesOutputTotalSinceTelemetry; + uint64_t mNumSamplesSkippedTotalSinceTelemetry; + // These get overriden in the templated concrete class. // Indicate if we have a pending promise for decoded frame. // Rejecting the promise will stop the reader from decoding ahead. @@ -465,6 +470,9 @@ private: { OnSeekFailed(TrackType::kAudioTrack, aFailure); } + + void ReportDroppedFramesTelemetry(); + // Temporary seek information while we wait for the data Maybe mOriginalSeekTarget; Maybe mPendingSeekTime; diff --git a/dom/media/platforms/wmf/MFTDecoder.cpp b/dom/media/platforms/wmf/MFTDecoder.cpp index 5558d6d7b2..e5fd17da4a 100644 --- a/dom/media/platforms/wmf/MFTDecoder.cpp +++ b/dom/media/platforms/wmf/MFTDecoder.cpp @@ -236,7 +236,9 @@ MFTDecoder::Output(RefPtr* aOutput) // Treat other errors as unexpected, and warn. NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - MOZ_ASSERT(output.pSample); + if (!output.pSample) { + return S_OK; + } if (mDiscontinuity) { output.pSample->SetUINT32(MFSampleExtension_Discontinuity, TRUE); diff --git a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp index 5ca6a0ae89..c5b1c26e69 100644 --- a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp @@ -10,7 +10,7 @@ #include "WMFUtils.h" #include "nsTArray.h" #include "TimeUnits.h" - +#include "mozilla/Telemetry.h" #include "mozilla/Logging.h" extern mozilla::LogModule* GetPDMLog(); @@ -226,6 +226,16 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset, NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + if (!sample) { + LOG("Audio MFTDecoder returned success but null output."); + nsCOMPtr task = NS_NewRunnableFunction([]() -> void { + LOG("Reporting telemetry AUDIO_MFT_OUTPUT_NULL_SAMPLES"); + Telemetry::Accumulate(Telemetry::ID::AUDIO_MFT_OUTPUT_NULL_SAMPLES, 1); + }); + AbstractThread::MainThread()->Dispatch(task.forget()); + return E_FAIL; + } + RefPtr buffer; hr = sample->ConvertToContiguousBuffer(getter_AddRefs(buffer)); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); diff --git a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp index cdbbf31d45..7c49791068 100644 --- a/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp +++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.cpp @@ -198,4 +198,27 @@ WMFMediaDataDecoder::IsHardwareAccelerated(nsACString& aFailureReason) const { return mMFTManager && mMFTManager->IsHardwareAccelerated(aFailureReason); } +nsresult +WMFMediaDataDecoder::ConfigurationChanged(const TrackInfo& aConfig) +{ + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + + nsCOMPtr runnable = + NS_NewRunnableMethodWithArg&&>( + this, + &WMFMediaDataDecoder::ProcessConfigurationChanged, + aConfig.Clone()); + mTaskQueue->Dispatch(runnable.forget()); + return NS_OK; + +} + +void +WMFMediaDataDecoder::ProcessConfigurationChanged(UniquePtr&& aConfig) +{ + if (mMFTManager) { + mMFTManager->ConfigurationChanged(*aConfig); + } +} + } // namespace mozilla diff --git a/dom/media/platforms/wmf/WMFMediaDataDecoder.h b/dom/media/platforms/wmf/WMFMediaDataDecoder.h index 1059efdbcd..ce1e23b006 100644 --- a/dom/media/platforms/wmf/WMFMediaDataDecoder.h +++ b/dom/media/platforms/wmf/WMFMediaDataDecoder.h @@ -52,6 +52,8 @@ public: virtual TrackInfo::TrackType GetType() = 0; + virtual void ConfigurationChanged(const TrackInfo& aConfig) {} + virtual const char* GetDescriptionName() const = 0; protected: @@ -83,6 +85,8 @@ public: bool IsHardwareAccelerated(nsACString& aFailureReason) const override; + nsresult ConfigurationChanged(const TrackInfo& aConfig) override; + const char* GetDescriptionName() const override { return mMFTManager ? mMFTManager->GetDescriptionName() : ""; @@ -108,6 +112,10 @@ private: void ProcessShutdown(); + // Called on the task queue. Tell the MFT that the next Input will have a + // different configuration (typically resolution change). + void ProcessConfigurationChanged(UniquePtr&& aConfig); + RefPtr mTaskQueue; MediaDataDecoderCallback* mCallback; diff --git a/dom/media/platforms/wmf/WMFUtils.cpp b/dom/media/platforms/wmf/WMFUtils.cpp index a2abdbadb7..8255a96566 100644 --- a/dom/media/platforms/wmf/WMFUtils.cpp +++ b/dom/media/platforms/wmf/WMFUtils.cpp @@ -39,7 +39,7 @@ HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames) } HRESULT -GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride) +GetDefaultStride(IMFMediaType *aType, uint32_t aWidth, uint32_t* aOutStride) { // Try to get the default stride from the media type. HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, aOutStride); @@ -49,16 +49,11 @@ GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride) // Stride attribute not set, calculate it. GUID subtype = GUID_NULL; - uint32_t width = 0; - uint32_t height = 0; hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG*)(aOutStride)); + hr = wmf::MFGetStrideForBitmapInfoHeader(subtype.Data1, aWidth, (LONG*)(aOutStride)); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); return hr; @@ -188,7 +183,7 @@ LoadDLLs() #define ENSURE_FUNCTION_PTR_HELPER(FunctionType, FunctionName, DLL) \ static FunctionType FunctionName##Ptr = nullptr; \ if (!FunctionName##Ptr) { \ - FunctionName##Ptr = (FunctionType) GetProcAddress(GetModuleHandleW(L#DLL), #FunctionName); \ + FunctionName##Ptr = (FunctionType) GetProcAddress(GetModuleHandleW(L ## #DLL), #FunctionName); \ if (!FunctionName##Ptr) { \ NS_WARNING("Failed to get GetProcAddress of " #FunctionName " from " #DLL); \ return E_FAIL; \ @@ -282,7 +277,6 @@ MFCreateAlignedMemoryBuffer(DWORD cbMaxLength, HRESULT MFCreateDXGIDeviceManager(UINT *pResetToken, IMFDXGIDeviceManager **ppDXVAManager) { - DECL_FUNCTION_PTR(MFCreateDXGIDeviceManager, UINT*, IMFDXGIDeviceManager**); ENSURE_FUNCTION_PTR(MFCreateDXGIDeviceManager, mfplat.dll) return (MFCreateDXGIDeviceManagerPtr)(pResetToken, ppDXVAManager); } diff --git a/dom/media/platforms/wmf/WMFUtils.h b/dom/media/platforms/wmf/WMFUtils.h index af4dfc48b6..ac87797748 100644 --- a/dom/media/platforms/wmf/WMFUtils.h +++ b/dom/media/platforms/wmf/WMFUtils.h @@ -37,7 +37,7 @@ HRESULT HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames); HRESULT -GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride); +GetDefaultStride(IMFMediaType *aType, uint32_t aWidth, uint32_t* aOutStride); int32_t MFOffsetToInt32(const MFOffset& aOffset); diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp index d5db7f8012..0a60276d26 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp @@ -21,6 +21,7 @@ #include "IMFYCbCrImage.h" #include "mozilla/WindowsVersion.h" #include "mozilla/Preferences.h" +#include "mozilla/Telemetry.h" #include "nsPrintfCString.h" extern mozilla::LogModule* GetPDMLog(); @@ -70,9 +71,14 @@ WMFVideoMFTManager::WMFVideoMFTManager( mozilla::layers::LayersBackend aLayersBackend, mozilla::layers::ImageContainer* aImageContainer, bool aDXVAEnabled) - : mImageContainer(aImageContainer) + : mVideoInfo(aConfig) + , mVideoStride(0) + , mImageContainer(aImageContainer) , mDXVAEnabled(aDXVAEnabled) , mLayersBackend(aLayersBackend) + , mNullOutputCount(0) + , mGotValidOutputAfterNullOutput(false) + , mGotExcessiveNullOutput(false) // mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in // Init(). { @@ -98,6 +104,20 @@ WMFVideoMFTManager::~WMFVideoMFTManager() if (mDXVA2Manager) { DeleteOnMainThread(mDXVA2Manager); } + + // Record whether the video decoder successfully decoded, or output null + // samples but did/didn't recover. + uint32_t telemetry = (mNullOutputCount == 0) ? 0 : + (mGotValidOutputAfterNullOutput && mGotExcessiveNullOutput) ? 1 : + mGotExcessiveNullOutput ? 2 : + mGotValidOutputAfterNullOutput ? 3 : + 4; + + nsCOMPtr task = NS_NewRunnableFunction([=]() -> void { + LOG(nsPrintfCString("Reporting telemetry VIDEO_MFT_OUTPUT_NULL_SAMPLES=%d", telemetry).get()); + Telemetry::Accumulate(Telemetry::ID::VIDEO_MFT_OUTPUT_NULL_SAMPLES, telemetry); + }); + AbstractThread::MainThread()->Dispatch(task.forget()); } const GUID& @@ -150,8 +170,6 @@ public: bool WMFVideoMFTManager::InitializeDXVA(bool aForceD3D9) { - MOZ_ASSERT(!mDXVA2Manager); - // If we use DXVA but aren't running with a D3D layer manager then the // readback of decoded video frames from GPU to CPU memory grinds painting // to a halt, and makes playback performance *worse*. @@ -159,6 +177,7 @@ WMFVideoMFTManager::InitializeDXVA(bool aForceD3D9) mDXVAFailureReason.AssignLiteral("Hardware video decoding disabled or blacklisted"); return false; } + MOZ_ASSERT(!mDXVA2Manager); if (mLayersBackend != LayersBackend::LAYERS_D3D9 && mLayersBackend != LayersBackend::LAYERS_D3D11) { mDXVAFailureReason.AssignLiteral("Unsupported layers backend"); @@ -250,13 +269,6 @@ WMFVideoMFTManager::InitInternal(bool aForceD3D9) LOG("Video Decoder initialized, Using DXVA: %s", (mUseHwAccel ? "Yes" : "No")); - // Just in case ConfigureVideoFrameGeometry() does not set these - mVideoInfo = VideoInfo(); - mVideoStride = 0; - mVideoWidth = 0; - mVideoHeight = 0; - mPictureRegion.SetEmpty(); - return true; } @@ -323,36 +335,19 @@ WMFVideoMFTManager::Input(MediaRawData* aSample) // This code tests if the given resolution can be supported directly on the GPU, // and makes sure we only ask the MFT for DXVA if it can be supported properly. bool -WMFVideoMFTManager::MaybeToggleDXVA(IMFMediaType* aType) +WMFVideoMFTManager::CanUseDXVA(IMFMediaType* aType) { + MOZ_ASSERT(mDXVA2Manager); // SupportsConfig only checks for valid h264 decoders currently. - if (!mDXVA2Manager || mStreamType != H264) { - return false; + if (mStreamType != H264) { + return true; } // Assume the current samples duration is representative for the // entire video. float framerate = 1000000.0 / mLastDuration; - if (mDXVA2Manager->SupportsConfig(aType, framerate)) { - if (!mUseHwAccel) { - // DXVA disabled, but supported for this resolution - ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager()); - HRESULT hr = mDecoder->SendMFTMessage(MFT_MESSAGE_SET_D3D_MANAGER, manager); - if (SUCCEEDED(hr)) { - mUseHwAccel = true; - return true; - } - } - } else if (mUseHwAccel) { - // DXVA enabled, and not supported for this resolution - HRESULT hr = mDecoder->SendMFTMessage(MFT_MESSAGE_SET_D3D_MANAGER, 0); - MOZ_ASSERT(SUCCEEDED(hr), "Attempting to fall back to software failed?"); - mUseHwAccel = false; - return true; - } - - return false; + return mDXVA2Manager->SupportsConfig(aType, framerate); } HRESULT @@ -366,14 +361,14 @@ WMFVideoMFTManager::ConfigureVideoFrameGeometry() // change then we need to renegotiate our media types, // and resubmit our previous frame (since the MFT appears // to lose it otherwise). - if (MaybeToggleDXVA(mediaType)) { - hr = SetDecoderMediaTypes(); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - HRESULT hr = mDecoder->GetOutputMediaType(mediaType); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + if (mUseHwAccel && !CanUseDXVA(mediaType)) { + mDXVAEnabled = false; + if (!Init()) { + return E_FAIL; + } mDecoder->Input(mLastInput); + return S_OK; } // Verify that the video subtype is what we expect it to be. @@ -387,26 +382,17 @@ WMFVideoMFTManager::ConfigureVideoFrameGeometry() NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || !mUseHwAccel, E_FAIL); NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mUseHwAccel, E_FAIL); - nsIntRect pictureRegion; - hr = GetPictureRegion(mediaType, pictureRegion); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - UINT32 width = 0, height = 0; hr = MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - uint32_t aspectNum = 0, aspectDenom = 0; - hr = MFGetAttributeRatio(mediaType, - MF_MT_PIXEL_ASPECT_RATIO, - &aspectNum, - &aspectDenom); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - + mVideoInfo.mImage.width = width; + mVideoInfo.mImage.height = height; + nsIntRect pictureRegion = mVideoInfo.mImage; // Calculate and validate the picture region and frame dimensions after // scaling by the pixel aspect ratio. nsIntSize frameSize = nsIntSize(width, height); - nsIntSize displaySize = nsIntSize(pictureRegion.width, pictureRegion.height); - ScaleDisplayByAspectRatio(displaySize, float(aspectNum) / float(aspectDenom)); + nsIntSize displaySize = nsIntSize(mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height); if (!IsValidVideoRegion(frameSize, pictureRegion, displaySize)) { // Video track's frame sizes will overflow. Ignore the video track. return E_FAIL; @@ -418,18 +404,13 @@ WMFVideoMFTManager::ConfigureVideoFrameGeometry() } // Success! Save state. - mVideoInfo.mDisplay = displaySize; - GetDefaultStride(mediaType, &mVideoStride); - mVideoWidth = width; - mVideoHeight = height; - mPictureRegion = pictureRegion; + GetDefaultStride(mediaType, width, &mVideoStride); - LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d) PAR=%d:%d", + LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d)", width, height, mVideoStride, - mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height, - displaySize.width, displaySize.height, - aspectNum, aspectDenom); + pictureRegion.x, pictureRegion.y, pictureRegion.width, pictureRegion.height, + mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height); return S_OK; } @@ -471,25 +452,28 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample, // i.e., Y, then V, then U. VideoData::YCbCrBuffer b; + uint32_t videoWidth = mVideoInfo.mImage.width; + uint32_t videoHeight = mVideoInfo.mImage.height; + // Y (Y') plane b.mPlanes[0].mData = data; b.mPlanes[0].mStride = stride; - b.mPlanes[0].mHeight = mVideoHeight; - b.mPlanes[0].mWidth = mVideoWidth; + b.mPlanes[0].mHeight = videoHeight; + b.mPlanes[0].mWidth = videoWidth; b.mPlanes[0].mOffset = 0; b.mPlanes[0].mSkip = 0; // The V and U planes are stored 16-row-aligned, so we need to add padding // to the row heights to ensure the Y'CbCr planes are referenced properly. uint32_t padding = 0; - if (mVideoHeight % 16 != 0) { - padding = 16 - (mVideoHeight % 16); + if (videoHeight % 16 != 0) { + padding = 16 - (videoHeight % 16); } - uint32_t y_size = stride * (mVideoHeight + padding); - uint32_t v_size = stride * (mVideoHeight + padding) / 4; + uint32_t y_size = stride * (videoHeight + padding); + uint32_t v_size = stride * (videoHeight + padding) / 4; uint32_t halfStride = (stride + 1) / 2; - uint32_t halfHeight = (mVideoHeight + 1) / 2; - uint32_t halfWidth = (mVideoWidth + 1) / 2; + uint32_t halfHeight = (videoHeight + 1) / 2; + uint32_t halfWidth = (videoWidth + 1) / 2; // U plane (Cb) b.mPlanes[1].mData = data + y_size + v_size; @@ -518,7 +502,7 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample, VideoData::SetVideoDataToImage(image, mVideoInfo, b, - mPictureRegion, + mVideoInfo.mImage, false); RefPtr v = @@ -530,7 +514,7 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample, image.forget(), false, -1, - mPictureRegion); + mVideoInfo.mImage); v.forget(aOutVideoData); return S_OK; @@ -551,7 +535,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample, RefPtr image; hr = mDXVA2Manager->CopyToImage(aSample, - mPictureRegion, + mVideoInfo.mImage, mImageContainer, getter_AddRefs(image)); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); @@ -569,7 +553,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample, image.forget(), false, -1, - mPictureRegion); + mVideoInfo.mImage); NS_ENSURE_TRUE(v, E_FAIL); v.forget(aOutVideoData); @@ -610,6 +594,23 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset, continue; } if (SUCCEEDED(hr)) { + if (!sample) { + LOG("Video MFTDecoder returned success but no output!"); + // On some machines/input the MFT returns success but doesn't output + // a video frame. If we detect this, try again, but only up to a + // point; after 250 failures, give up. Note we count all failures + // over the life of the decoder, as we may end up exiting with a + // NEED_MORE_INPUT and coming back to hit the same error. So just + // counting with a local variable (like typeChangeCount does) may + // not work in this situation. + ++mNullOutputCount; + if (mNullOutputCount > 250) { + LOG("Excessive Video MFTDecoder returning success but no output; giving up"); + mGotExcessiveNullOutput = true; + return E_FAIL; + } + continue; + } break; } // Else unexpected error, assert, and bail. @@ -630,6 +631,10 @@ WMFVideoMFTManager::Output(int64_t aStreamOffset, aOutData = frame; + if (mNullOutputCount) { + mGotValidOutputAfterNullOutput = true; + } + return S_OK; } @@ -647,4 +652,22 @@ WMFVideoMFTManager::IsHardwareAccelerated(nsACString& aFailureReason) const return mDecoder && mUseHwAccel; } +const char* +WMFVideoMFTManager::GetDescriptionName() const +{ + if (mDecoder && mUseHwAccel && mDXVA2Manager) { + return (mDXVA2Manager->IsD3D11()) ? + "D3D11 Hardware Decoder" : "D3D9 Hardware Decoder"; + } else { + return "wmf software video decoder"; + } +} + +void +WMFVideoMFTManager::ConfigurationChanged(const TrackInfo& aConfig) +{ + MOZ_ASSERT(aConfig.GetAsVideoInfo()); + mVideoInfo = *aConfig.GetAsVideoInfo(); +} + } // namespace mozilla diff --git a/dom/media/platforms/wmf/WMFVideoMFTManager.h b/dom/media/platforms/wmf/WMFVideoMFTManager.h index aad6a28b38..186d209fa7 100644 --- a/dom/media/platforms/wmf/WMFVideoMFTManager.h +++ b/dom/media/platforms/wmf/WMFVideoMFTManager.h @@ -39,12 +39,9 @@ public: return TrackInfo::kVideoTrack; } - const char* GetDescriptionName() const override - { - nsCString failureReason; - return IsHardwareAccelerated(failureReason) - ? "wmf hardware video decoder" : "wmf software video decoder"; - } + void ConfigurationChanged(const TrackInfo& aConfig) override; + + const char* GetDescriptionName() const override; private: @@ -64,14 +61,11 @@ private: HRESULT SetDecoderMediaTypes(); - bool MaybeToggleDXVA(IMFMediaType* aType); + bool CanUseDXVA(IMFMediaType* aType); // Video frame geometry. VideoInfo mVideoInfo; uint32_t mVideoStride; - uint32_t mVideoWidth; - uint32_t mVideoHeight; - nsIntRect mPictureRegion; RefPtr mImageContainer; nsAutoPtr mDXVA2Manager; @@ -79,7 +73,7 @@ private: RefPtr mLastInput; float mLastDuration; - const bool mDXVAEnabled; + bool mDXVAEnabled; const layers::LayersBackend mLayersBackend; bool mUseHwAccel; @@ -96,6 +90,10 @@ private: const GUID& GetMFTGUID(); const GUID& GetMediaSubtypeGUID(); + + uint32_t mNullOutputCount; + bool mGotValidOutputAfterNullOutput; + bool mGotExcessiveNullOutput; }; } // namespace mozilla diff --git a/dom/network/TCPServerSocket.cpp b/dom/network/TCPServerSocket.cpp index caf03cf0e5..454696deb5 100644 --- a/dom/network/TCPServerSocket.cpp +++ b/dom/network/TCPServerSocket.cpp @@ -122,9 +122,6 @@ TCPServerSocket::Close() void TCPServerSocket::FireEvent(const nsAString& aType, TCPSocket* aSocket) { - AutoJSAPI api; - api.Init(GetOwnerGlobal()); - TCPServerSocketEventInit init; init.mBubbles = false; init.mCancelable = false; diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp index 0043048c47..5f160b9b51 100644 --- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -626,6 +626,9 @@ nsCSPContext::SetRequestContext(nsIDOMDocument* aDOMDocument, // console messages until it becomes available, see flushConsoleMessages mQueueUpMessages = !mInnerWindowID; mCallingChannelLoadGroup = doc->GetDocumentLoadGroup(); + + // set the flag on the document for CSP telemetry + doc->SetHasCSP(true); } else { NS_WARNING("No Document in SetRequestContext; can not query loadgroup; sending reports may fail."); diff --git a/dom/security/nsCSPContext.h b/dom/security/nsCSPContext.h index 1c1c848386..94286a11cc 100644 --- a/dom/security/nsCSPContext.h +++ b/dom/security/nsCSPContext.h @@ -81,6 +81,10 @@ class nsCSPContext : public nsIContentSecurityPolicy mLoadingPrincipal = nullptr; } + nsWeakPtr GetLoadingContext(){ + return mLoadingContext; + } + private: bool permitsInternal(CSPDirective aDir, nsIURI* aContentLocation, diff --git a/dom/security/nsCSPParser.cpp b/dom/security/nsCSPParser.cpp index 242ab9e632..16050726db 100644 --- a/dom/security/nsCSPParser.cpp +++ b/dom/security/nsCSPParser.cpp @@ -578,6 +578,10 @@ nsCSPParser::keywordSource() } if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_INLINE)) { + nsCOMPtr doc = do_QueryReferent(mCSPContext->GetLoadingContext()); + if (doc) { + doc->SetHasUnsafeInlineCSP(true); + } // make sure script-src only contains 'unsafe-inline' once; // ignore duplicates and log warning if (mUnsafeInlineKeywordSrc) { @@ -593,6 +597,10 @@ nsCSPParser::keywordSource() } if (CSP_IsKeyword(mCurToken, CSP_UNSAFE_EVAL)) { + nsCOMPtr doc = do_QueryReferent(mCSPContext->GetLoadingContext()); + if (doc) { + doc->SetHasUnsafeEvalCSP(true); + } return new nsCSPKeywordSrc(CSP_KeywordToEnum(mCurToken)); } return nullptr; diff --git a/dom/security/nsMixedContentBlocker.cpp b/dom/security/nsMixedContentBlocker.cpp index b25da54199..d9ffe29e93 100644 --- a/dom/security/nsMixedContentBlocker.cpp +++ b/dom/security/nsMixedContentBlocker.cpp @@ -799,6 +799,11 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, } } + // set hasMixedContentObjectSubrequest on this object if necessary + if (aContentType == TYPE_OBJECT_SUBREQUEST) { + rootDoc->SetHasMixedContentObjectSubrequest(true); + } + // If the content is display content, and the pref says display content should be blocked, block it. if (sBlockMixedDisplay && classification == eMixedDisplay) { if (allowMixedContent) { diff --git a/embedding/components/windowwatcher/moz.build b/embedding/components/windowwatcher/moz.build index 2d0766b591..617a56bde6 100644 --- a/embedding/components/windowwatcher/moz.build +++ b/embedding/components/windowwatcher/moz.build @@ -37,5 +37,6 @@ if CONFIG['MOZ_XUL']: FINAL_LIBRARY = 'xul' # For nsJSUtils LOCAL_INCLUDES += [ + '/docshell/base', '/dom/base', ] diff --git a/embedding/components/windowwatcher/nsWindowWatcher.cpp b/embedding/components/windowwatcher/nsWindowWatcher.cpp index 88b5f107fe..edb8e07fdb 100644 --- a/embedding/components/windowwatcher/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp @@ -18,6 +18,7 @@ #include "nsJSUtils.h" #include "plstr.h" +#include "nsDocShell.h" #include "nsIBaseWindow.h" #include "nsIBrowserDOMWindow.h" #include "nsIDocShell.h" @@ -81,6 +82,7 @@ struct nsWatcherWindowEntry { nsWatcherWindowEntry(nsIDOMWindow* aWindow, nsIWebBrowserChrome* aChrome) + : mChrome(nullptr) { #ifdef USEWEAKREFS mWindow = do_GetWeakReference(aWindow); @@ -451,6 +453,36 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow* aParent, aResult); } +// This static function checks if the aDocShell uses an UserContextId equal to +// nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID or equal to the +// userContextId of subjectPrincipal, if not null. +static bool +CheckUserContextCompatibility(nsIDocShell* aDocShell) +{ + MOZ_ASSERT(aDocShell); + + uint32_t userContextId = + static_cast(aDocShell)->GetOriginAttributes().mUserContextId; + + if (userContextId == nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) { + return true; + } + + nsCOMPtr subjectPrincipal = + nsContentUtils::GetCurrentJSContext() + ? nsContentUtils::SubjectPrincipal() : nullptr; + + if (!subjectPrincipal) { + return false; + } + + uint32_t principalUserContextId; + nsresult rv = subjectPrincipal->GetUserContextId(&principalUserContextId); + NS_ENSURE_SUCCESS(rv, false); + + return principalUserContextId == userContextId; +} + nsresult nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent, const char* aUrl, @@ -606,6 +638,9 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent, bool isCallerChrome = nsContentUtils::LegacyIsCallerChromeOrNativeCode() && !openedFromRemoteTab; + // XXXbz Why is an AutoJSAPI good enough here? Wouldn't AutoEntryScript (so + // we affect the entry global) make more sense? Or do we just want to affect + // GetSubjectPrincipal()? dom::AutoJSAPI jsapiChromeGuard; bool windowTypeIsChrome = @@ -692,6 +727,19 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent, do_QueryInterface(newDocShellItem); webNav->Stop(nsIWebNavigation::STOP_NETWORK); } + + // If this is a new window, but it's incompatible with the current + // userContextId, we ignore it and we pretend that nothing has been + // returned by ProvideWindow. + if (!windowIsNew && newDocShellItem) { + nsCOMPtr docShell = do_QueryInterface(newDocShellItem); + if (!CheckUserContextCompatibility(docShell)) { + newWindow = nullptr; + newDocShellItem = nullptr; + windowIsNew = false; + } + } + } else if (rv == NS_ERROR_ABORT) { // NS_ERROR_ABORT means the window provider has flat-out rejected // the open-window call and we should bail. Don't return an error @@ -983,6 +1031,18 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent, } } + // If this is a new window, we must set the userContextId from the + // subjectPrincipal. + if (windowIsNew && subjectPrincipal) { + uint32_t userContextId; + rv = subjectPrincipal->GetUserContextId(&userContextId); + NS_ENSURE_SUCCESS(rv, rv); + + auto* docShell = static_cast(newDocShell.get()); + + docShell->SetUserContextId(userContextId); + } + if (isNewToplevelWindow) { // Notify observers that the window is open and ready. // The window has not yet started to load a document. @@ -993,6 +1053,10 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent, } } + // Before loading the URI we want to be 100% sure that we use the correct + // userContextId. + MOZ_ASSERT(CheckUserContextCompatibility(newDocShell)); + if (uriToLoad && aNavigate) { newDocShell->LoadURI( uriToLoad, @@ -1628,7 +1692,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, } } - if (aDialog && !presenceFlag) { + if (aDialog && aFeaturesSpecified && !presenceFlag) { chromeFlags = nsIWebBrowserChrome::CHROME_DEFAULT; } @@ -2140,8 +2204,14 @@ nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem, int32_t winWidth = width + (sizeChromeWidth ? 0 : chromeWidth), winHeight = height + (sizeChromeHeight ? 0 : chromeHeight); - screen->GetAvailRectDisplayPix(&screenLeft, &screenTop, &screenWidth, - &screenHeight); + // Get screen dimensions (in device pixels) + screen->GetAvailRect(&screenLeft, &screenTop, &screenWidth, + &screenHeight); + // Convert them to CSS pixels + screenLeft = NSToIntRound(screenLeft / scale); + screenTop = NSToIntRound(screenTop / scale); + screenWidth = NSToIntRound(screenWidth / scale); + screenHeight = NSToIntRound(screenHeight / scale); if (aSizeSpec.SizeSpecified()) { /* Unlike position, force size out-of-bounds check only if diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c index 54b7363e05..91d1fe6583 100644 --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c @@ -2083,6 +2083,7 @@ _cairo_surface_paint (cairo_surface_t *surface, cairo_clip_t *clip) { cairo_status_t status; + cairo_rectangle_int_t extents; if (unlikely (surface->status)) return surface->status; @@ -2114,7 +2115,10 @@ _cairo_surface_paint (cairo_surface_t *surface, status = _cairo_surface_fallback_paint (surface, op, source, clip); FINISH: - surface->is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL; + surface->is_clear = op == CAIRO_OPERATOR_CLEAR && + (clip == NULL || + (_cairo_surface_get_extents (surface, &extents) && + _cairo_clip_contains_rectangle (clip, &extents))); return _cairo_surface_set_error (surface, status); } diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index f810ffc4ed..b2a333ff94 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -9,6 +9,7 @@ #include "Units.h" // for ScreenPoint #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted +#include "mozilla/gfx/2D.h" // for DrawTarget #include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4 #include "mozilla/gfx/Point.h" // for IntSize, Point #include "mozilla/gfx/Rect.h" // for Rect, IntRect @@ -363,10 +364,14 @@ public: * If aRenderBoundsOut is non-null, it will be set to the render bounds * actually used by the compositor in window space. If aRenderBoundsOut * is returned empty, composition should be aborted. + * + * If aOpaque is true, then all of aInvalidRegion will be drawn to with + * opaque content. */ virtual void BeginFrame(const nsIntRegion& aInvalidRegion, const gfx::Rect* aClipRectIn, const gfx::Rect& aRenderBounds, + bool aOpaque, gfx::Rect* aClipRectOut = nullptr, gfx::Rect* aRenderBoundsOut = nullptr) = 0; diff --git a/gfx/layers/CompositorTypes.h b/gfx/layers/CompositorTypes.h index 4096398791..f549386467 100644 --- a/gfx/layers/CompositorTypes.h +++ b/gfx/layers/CompositorTypes.h @@ -230,8 +230,7 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OpenMode) // We rely on the items in this enum being sequential enum class MaskType : uint8_t { MaskNone = 0, // no mask layer - Mask2d, // mask layer for layers with 2D transforms - Mask3d, // mask layer for layers with 3D transforms + Mask, // mask layer NumMaskTypes }; diff --git a/gfx/layers/CopyableCanvasLayer.cpp b/gfx/layers/CopyableCanvasLayer.cpp index 17cac7acd9..da6cacd268 100644 --- a/gfx/layers/CopyableCanvasLayer.cpp +++ b/gfx/layers/CopyableCanvasLayer.cpp @@ -18,6 +18,7 @@ #include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/Tools.h" #include "mozilla/gfx/Point.h" // for IntSize +#include "mozilla/layers/AsyncCanvasRenderer.h" #include "mozilla/layers/PersistentBufferProvider.h" #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc #include "nsISupportsImpl.h" // for gfxContext::AddRef, etc diff --git a/gfx/layers/Effects.cpp b/gfx/layers/Effects.cpp index cf768afe08..01fcd6ad5b 100644 --- a/gfx/layers/Effects.cpp +++ b/gfx/layers/Effects.cpp @@ -34,10 +34,6 @@ EffectMask::PrintInfo(std::stringstream& aStream, const char* aPrefix) aStream << nsPrintfCString("EffectMask (0x%p)", this).get(); AppendToString(aStream, mSize, " [size=", "]"); AppendToString(aStream, mMaskTransform, " [mask-transform=", "]"); - - if (mIs3D) { - aStream << " [is-3d]"; - } } void diff --git a/gfx/layers/Effects.h b/gfx/layers/Effects.h index 2bea06d8a3..e3ea48bfd3 100644 --- a/gfx/layers/Effects.h +++ b/gfx/layers/Effects.h @@ -85,7 +85,6 @@ struct EffectMask : public Effect const gfx::Matrix4x4 &aMaskTransform) : Effect(EffectTypes::MASK) , mMaskTexture(aMaskTexture) - , mIs3D(false) , mSize(aSize) , mMaskTransform(aMaskTransform) {} @@ -93,7 +92,6 @@ struct EffectMask : public Effect virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); TextureSource* mMaskTexture; - bool mIs3D; gfx::IntSize mSize; gfx::Matrix4x4 mMaskTransform; }; diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 95bf57d824..556d16572e 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -234,6 +234,12 @@ public: mDoSmoothScroll = aOther.mDoSmoothScroll; } + void UpdateScrollInfo(uint32_t aScrollGeneration, const CSSPoint& aScrollOffset) + { + mScrollOffset = aScrollOffset; + mScrollGeneration = aScrollGeneration; + } + // Make a copy of this FrameMetrics object which does not have any pointers // to heap-allocated memory (i.e. is Plain Old Data, or 'POD'), and is // therefore safe to be placed into shared memory. diff --git a/gfx/layers/ImageDataSerializer.h b/gfx/layers/ImageDataSerializer.h index 85afa41975..eccc9fb407 100644 --- a/gfx/layers/ImageDataSerializer.h +++ b/gfx/layers/ImageDataSerializer.h @@ -13,6 +13,7 @@ #include "mozilla/RefPtr.h" // for already_AddRefed #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Types.h" // for SurfaceFormat +#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor namespace mozilla { namespace gfx { diff --git a/gfx/layers/LayerScope.cpp b/gfx/layers/LayerScope.cpp index 1faedd0f58..5f8ba55704 100644 --- a/gfx/layers/LayerScope.cpp +++ b/gfx/layers/LayerScope.cpp @@ -1202,7 +1202,6 @@ SenderHelper::SendMaskEffect(GLContext* aGLContext, // Expose packet creation here, so we could dump secondary mask effect attributes. auto packet = MakeUnique(); TexturePacket::EffectMask* mask = packet->mutable_texture()->mutable_mask(); - mask->set_mis3d(aEffect->mIs3D); mask->mutable_msize()->set_w(aEffect->mSize.width); mask->mutable_msize()->set_h(aEffect->mSize.height); auto element = reinterpret_cast(&(aEffect->mMaskTransform)); diff --git a/gfx/layers/LayerScope.h b/gfx/layers/LayerScope.h index 0f258cdb68..24fde23973 100644 --- a/gfx/layers/LayerScope.h +++ b/gfx/layers/LayerScope.h @@ -9,6 +9,7 @@ #include #include +#include "gfxMatrix.h" namespace mozilla { @@ -16,10 +17,12 @@ namespace gl { class GLContext; } namespace layers { + namespace layerscope { class Packet; } struct EffectChain; class LayerComposite; +class TextureHost; class LayerScope { public: diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 60594d69c1..ef4a89f8dd 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -1466,11 +1466,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS ComputeEffectiveTransformsForChildren(idealTransform); } - if (idealTransform.CanDraw2D()) { - ComputeEffectiveTransformForMaskLayers(aTransformToSurface); - } else { - ComputeEffectiveTransformForMaskLayers(Matrix4x4()); - } + ComputeEffectiveTransformForMaskLayers(aTransformToSurface); } void diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index b5ab0c5ce5..65b208019b 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -7,6 +7,7 @@ #include "APZCTreeManager.h" #include "AsyncPanZoomController.h" #include "Compositor.h" // for Compositor +#include "DragTracker.h" // for DragTracker #include "gfxPrefs.h" // for gfxPrefs #include "HitTestingTreeNode.h" // for HitTestingTreeNode #include "InputBlockState.h" // for InputBlockState @@ -138,7 +139,7 @@ APZCTreeManager::UpdateHitTestingTree(CompositorBridgeParent* aCompositor, { APZThreadUtils::AssertOnCompositorThread(); - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // For testing purposes, we log some data to the APZTestData associated with // the layers id that originated this update. @@ -492,6 +493,10 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer, aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(), "parentScrollId", apzc->GetParent()->GetGuid().mScrollId); } + if (aMetrics.IsRootContent()) { + aState.mPaintLogger.LogTestData(aMetrics.GetScrollId(), + "isRootContent", true); + } } if (newApzc) { @@ -614,10 +619,6 @@ WillHandleWheelEvent(WidgetWheelEvent* aEvent) static bool WillHandleMouseEvent(const WidgetMouseEventBase& aEvent) { - if (!gfxPrefs::APZDragEnabled()) { - return false; - } - return aEvent.mMessage == eMouseMove || aEvent.mMessage == eMouseDown || aEvent.mMessage == eMouseUp; @@ -666,14 +667,22 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, switch (aEvent.mInputType) { case MULTITOUCH_INPUT: { MultiTouchInput& touchInput = aEvent.AsMultiTouchInput(); - touchInput.mHandledByAPZ = true; result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId); break; } case MOUSE_INPUT: { MouseInput& mouseInput = aEvent.AsMouseInput(); + if (DragTracker::StartsDrag(mouseInput)) { + // If this is the start of a drag we need to unambiguously know if it's + // going to land on a scrollbar or not. We can't apply an untransform + // here without knowing that, so we need to ensure the untransform is + // a no-op. + FlushRepaintsToClearScreenToGeckoTransform(); + } + + bool hitScrollbar = false; RefPtr apzc = GetTargetAPZC(mouseInput.mOrigin, - &hitResult); + &hitResult, &hitScrollbar); // When the mouse is outside the window we still want to handle dragging // but we won't find an APZC. Fallback to root APZC then. @@ -687,15 +696,36 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, /* aTargetConfirmed = */ false, mouseInput, aOutInputBlockId); + if (result == nsEventStatus_eConsumeDoDefault) { + // This input event is part of a drag block, so whether or not it is + // directed at a scrollbar depends on whether the drag block started + // on a scrollbar. + hitScrollbar = mInputQueue->IsDragOnScrollbar(hitScrollbar); + } + // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); - // TODO Dagging on a scrollbar probably behaves differently from - // the other input types in that the gecko coordinates are the same - // as the screen coordinates even though the async transform on the APZC - // is changing. I'm not really sure at this point and it'll take some - // though to figure out properly. - //mouseInput.mOrigin = untransformedOrigin; + if (!hitScrollbar) { + // The input was not targeted at a scrollbar, so we untransform it + // like we do for other content. Scrollbars are "special" because they + // have special handling in AsyncCompositionManager when resolution is + // applied. TODO: we should find a better way to deal with this. + ScreenToParentLayerMatrix4x4 transformToApzc = GetScreenToApzcTransform(apzc); + ParentLayerToScreenMatrix4x4 transformToGecko = GetApzcToGeckoTransform(apzc); + ScreenToScreenMatrix4x4 outTransform = transformToApzc * transformToGecko; + Maybe untransformedRefPoint = UntransformBy( + outTransform, mouseInput.mOrigin); + if (untransformedRefPoint) { + mouseInput.mOrigin = *untransformedRefPoint; + } + } else { + // Likewise, if the input was targeted at a scrollbar, we don't want to + // apply the callback transform in the main thread, so we remove the + // scrollid from the guid. We need to keep the layersId intact so + // that the response from the child process doesn't get discarded. + aOutTargetGuid->mScrollId = FrameMetrics::NULL_SCROLL_ID; + } } break; } case SCROLLWHEEL_INPUT: { @@ -865,6 +895,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutInputBlockId) { + aInput.mHandledByAPZ = true; if (aInput.mType == MultiTouchInput::MULTITOUCH_START) { // If we are panned into overscroll and a second finger goes down, // ignore that second touch point completely. The touch-start for it is @@ -1125,6 +1156,7 @@ APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent, for (size_t i = 0; i < touchInput.mTouches.Length(); i++) { *touchEvent.touches.AppendElement() = touchInput.mTouches[i].ToNewDOMTouch(); } + touchEvent.mFlags.mHandledByAPZ = touchInput.mHandledByAPZ; return result; } case eWheelEventClass: { @@ -1189,7 +1221,7 @@ void APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid, const Maybe& aConstraints) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr node = GetTargetNode(aGuid, nullptr); MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC @@ -1248,7 +1280,7 @@ APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform() // matched APZCs is the same. It is simplest to ensure that by flushing the // pending repaint requests, which makes all of the untransforms empty (and // therefore equal). - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); mTreeLock.AssertCurrentThreadOwns(); ForEachNode(mRootNode.get(), @@ -1273,7 +1305,7 @@ APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid) void APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr apzc = FindRootContentOrRootApzc(); if (apzc) { apzc->AdjustScrollForSurfaceShift(aShift); @@ -1289,7 +1321,7 @@ APZCTreeManager::ClearTree() APZThreadUtils::RunOnControllerThread(NewRunnableMethod( mInputQueue.get(), &InputQueue::Clear)); - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // Collect the nodes into a list, and then destroy each one. // We can't destroy them as we collect them, because ForEachNode() @@ -1311,7 +1343,7 @@ APZCTreeManager::ClearTree() RefPtr APZCTreeManager::GetRootNode() const { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); return mRootNode; } @@ -1503,7 +1535,7 @@ APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint) already_AddRefed APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr node = GetTargetNode(aGuid, nullptr); MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC RefPtr apzc = node ? node->GetApzc() : nullptr; @@ -1533,13 +1565,16 @@ APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid, } already_AddRefed -APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, HitTestResult* aOutHitResult) +APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, + HitTestResult* aOutHitResult, + bool* aOutHitScrollbar) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); HitTestResult hitResult = HitNothing; ParentLayerPoint point = ViewAs(aPoint, PixelCastJustification::ScreenIsParentLayerForRoot); - RefPtr target = GetAPZCAtPoint(mRootNode, point, &hitResult); + RefPtr target = GetAPZCAtPoint(mRootNode, point, + &hitResult, aOutHitScrollbar); if (aOutHitResult) { *aOutHitResult = hitResult; @@ -1568,7 +1603,7 @@ APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); return DepthFirstSearch(mRootNode.get(), [&aDragMetrics](HitTestingTreeNode* aNode) { @@ -1652,7 +1687,8 @@ APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics) AsyncPanZoomController* APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, const ParentLayerPoint& aHitTestPoint, - HitTestResult* aOutHitResult) + HitTestResult* aOutHitResult, + bool* aOutHitScrollbar) { mTreeLock.AssertCurrentThreadOwns(); @@ -1704,6 +1740,13 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode, if (*aOutHitResult != HitNothing) { MOZ_ASSERT(resultNode); + if (aOutHitScrollbar) { + for (HitTestingTreeNode* n = resultNode; n; n = n->GetParent()) { + if (n->IsScrollbarNode()) { + *aOutHitScrollbar = true; + } + } + } AsyncPanZoomController* result = resultNode->GetNearestContainingApzcWithSameLayersId(); if (!result) { result = FindRootApzcForLayersId(resultNode->GetLayersId()); @@ -1872,7 +1915,7 @@ ScreenToParentLayerMatrix4x4 APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const { Matrix4x4 result; - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // The comments below assume there is a chain of layers L..R with L and P having APZC instances as // explained in the comment above. This function is called with aApzc at L, and the loop @@ -1913,7 +1956,7 @@ ParentLayerToScreenMatrix4x4 APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const { Matrix4x4 result; - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // The comments below assume there is a chain of layers L..R with L and P having APZC instances as // explained in the comment above. This function is called with aApzc at L, and the loop @@ -1942,7 +1985,7 @@ APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) co already_AddRefed APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr apzc; // For now, we only ever want to do pinching on the root-content APZC for // a given layers id. diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index d0c470435d..7aaa361769 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -17,7 +17,7 @@ #include "mozilla/gfx/Matrix.h" // for Matrix4x4 #include "mozilla/layers/APZUtils.h" // for HitTestResult #include "mozilla/layers/TouchCounter.h"// for TouchCounter -#include "mozilla/Monitor.h" // for Monitor +#include "mozilla/Mutex.h" // for Mutex #include "mozilla/TimeStamp.h" // for mozilla::TimeStamp #include "mozilla/Vector.h" // for mozilla::Vector #include "nsAutoPtr.h" // for nsRefPtr @@ -44,7 +44,8 @@ enum AllowedTouchBehavior { enum ZoomToRectBehavior : uint32_t { DEFAULT_BEHAVIOR = 0, DISABLE_ZOOM_OUT = 1 << 0, - PAN_INTO_VIEW_ONLY = 1 << 1 + PAN_INTO_VIEW_ONLY = 1 << 1, + ONLY_ZOOM_TO_DEFAULT_SCALE = 1 << 2 }; class Layer; @@ -437,7 +438,8 @@ public: */ RefPtr GetRootNode() const; already_AddRefed GetTargetAPZC(const ScreenPoint& aPoint, - HitTestResult* aOutHitResult); + HitTestResult* aOutHitResult, + bool* aOutHitScrollbar = nullptr); ScreenToParentLayerMatrix4x4 GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const; ParentLayerToScreenMatrix4x4 GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const; private: @@ -455,7 +457,8 @@ private: GuidComparator aComparator); AsyncPanZoomController* GetAPZCAtPoint(HitTestingTreeNode* aNode, const ParentLayerPoint& aHitTestPoint, - HitTestResult* aOutHitResult); + HitTestResult* aOutHitResult, + bool* aOutHitScrollbar); AsyncPanZoomController* FindRootApzcForLayersId(uint64_t aLayersId) const; AsyncPanZoomController* FindRootContentApzcForLayersId(uint64_t aLayersId) const; AsyncPanZoomController* FindRootContentOrRootApzc() const; @@ -534,7 +537,7 @@ private: * is considered part of the APZC tree management state. * Finally, the lock needs to be held when accessing mZoomConstraints. * IMPORTANT: See the note about lock ordering at the top of this file. */ - mutable mozilla::Monitor mTreeLock; + mutable mozilla::Mutex mTreeLock; RefPtr mRootNode; /* Holds the zoom constraints for scrollable layers, as determined by the * the main-thread gecko code. */ diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 890a746f72..0795d0244d 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1032,6 +1032,10 @@ static float GetAxisScale(AsyncDragMetrics::DragDirection aDir, T aValue) { nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent, const AsyncDragMetrics& aDragMetrics) { + if (!gfxPrefs::APZDragEnabled()) { + return nsEventStatus_eIgnore; + } + if (!GetApzcTreeManager()) { return nsEventStatus_eConsumeNoDefault; } @@ -2035,7 +2039,13 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) if (controller) { CSSPoint geckoScreenPoint; if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { - if (CurrentTouchBlock()->IsDuringFastFling()) { + CancelableBlockState* block = CurrentInputBlock(); + MOZ_ASSERT(block); + if (!block->AsTouchBlock()) { + APZC_LOG("%p dropping long-press because some non-touch block interrupted it\n", this); + return nsEventStatus_eIgnore; + } + if (block->AsTouchBlock()->IsDuringFastFling()) { APZC_LOG("%p dropping long-press because of fast fling\n", this); return nsEventStatus_eIgnore; } @@ -2057,8 +2067,21 @@ nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aP if (controller) { CSSPoint geckoScreenPoint; if (ConvertToGecko(aPoint, &geckoScreenPoint)) { - if (!CurrentTouchBlock()->SetSingleTapOccurred()) { - return nsEventStatus_eIgnore; + CancelableBlockState* block = CurrentInputBlock(); + MOZ_ASSERT(block); + TouchBlockState* touch = block->AsTouchBlock(); + // |block| may be a non-touch block in the case where this function is + // invoked by GestureEventListener on a timeout. In that case we already + // verified that the single tap is allowed so we let it through. + // XXX there is a bug here that in such a case the touch block that + // generated this tap will not get its mSingleTapOccurred flag set. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1256344#c6 + if (touch) { + if (touch->IsDuringFastFling()) { + APZC_LOG("%p dropping single-tap because it was during a fast-fling\n", this); + return nsEventStatus_eIgnore; + } + touch->SetSingleTapOccurred(); } // Because this may be being running as part of APZCTreeManager::ReceiveInputEvent, // calling controller->HandleSingleTap directly might mean that content receives @@ -2326,7 +2349,18 @@ bool AsyncPanZoomController::AttemptScroll(ParentLayerPoint& aStartPoint, ParentLayerPoint displacement = aStartPoint - aEndPoint; ParentLayerPoint overscroll; // will be used outside monitor block - { + + // If the direction of panning is reversed within the same input block, + // a later event in the block could potentially scroll an APZC earlier + // in the handoff chain, than an earlier event in the block (because + // the earlier APZC was scrolled to its extent in the original direction). + // If immediate handoff is disallowed, we want to disallow this (to + // preserve the property that a single input block only scrolls one APZC), + // so we skip the earlier APZC. + bool scrollThisApzc = gfxPrefs::APZAllowImmediateHandoff() || + (CurrentInputBlock() && (!CurrentInputBlock()->GetScrolledApzc() || this == CurrentInputBlock()->GetScrolledApzc())); + + if (scrollThisApzc) { ReentrantMonitorAutoEnter lock(mMonitor); ParentLayerPoint adjustedDisplacement; @@ -2351,6 +2385,8 @@ bool AsyncPanZoomController::AttemptScroll(ParentLayerPoint& aStartPoint, ScheduleCompositeAndMaybeRepaint(); UpdateSharedCompositorFrameMetrics(); } + } else { + overscroll = displacement; } // Adjust the start point to reflect the consumed portion of the scroll. @@ -2683,7 +2719,10 @@ void AsyncPanZoomController::AdjustScrollForSurfaceShift(const ScreenPoint& aShi / mFrameMetrics.GetZoom(); APZC_LOG("%p adjusting scroll position by %s for surface shift\n", this, Stringify(adjustment).c_str()); - mFrameMetrics.ScrollBy(adjustment); + CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset(); + scrollOffset.y = mY.ClampOriginToScrollableRect(scrollOffset.y + adjustment.y); + scrollOffset.x = mX.ClampOriginToScrollableRect(scrollOffset.x + adjustment.x); + mFrameMetrics.SetScrollOffset(scrollOffset); ScheduleCompositeAndMaybeRepaint(); UpdateSharedCompositorFrameMetrics(); } @@ -2979,7 +3018,10 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, mAnimation = nullptr; SetState(NOTHING); } - if (wantsRepaints) { + // Request a repaint at the end of the animation in case something such as a + // call to NotifyLayersUpdated was invoked during the animation and Gecko's + // current state is some intermediate point of the animation. + if (!continueAnimation || wantsRepaints) { RequestContentRepaint(); } UpdateSharedCompositorFrameMetrics(); @@ -3247,6 +3289,15 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri ReentrantMonitorAutoEnter lock(mMonitor); bool isDefault = mFrameMetrics.IsDefault(); + if ((aLayerMetrics == mLastContentPaintMetrics) && !isDefault) { + // No new information here, skip it. Note that this is not just an + // optimization; it's correctness too. In the case where we get one of these + // stale aLayerMetrics *after* a call to NotifyScrollUpdated, processing the + // stale aLayerMetrics would clobber the more up-to-date information from + // NotifyScrollUpdated. + APZC_LOG("%p NotifyLayersUpdated short-circuit\n", this); + return; + } mLastContentPaintMetrics = aLayerMetrics; mFrameMetrics.SetScrollParentId(aLayerMetrics.GetScrollParentId()); @@ -3449,6 +3500,35 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri UpdateSharedCompositorFrameMetrics(); } +void +AsyncPanZoomController::NotifyScrollUpdated(uint32_t aScrollGeneration, + const CSSPoint& aScrollOffset) +{ + APZThreadUtils::AssertOnCompositorThread(); + ReentrantMonitorAutoEnter lock(mMonitor); + + APZC_LOG("%p NotifyScrollUpdated(%d, %s)\n", this, aScrollGeneration, + Stringify(aScrollOffset).c_str()); + + bool scrollOffsetUpdated = aScrollGeneration != mFrameMetrics.GetScrollGeneration(); + if (!scrollOffsetUpdated) { + return; + } + APZC_LOG("%p updating scroll offset from %s to %s\n", this, + Stringify(mFrameMetrics.GetScrollOffset()).c_str(), + Stringify(aScrollOffset).c_str()); + + mFrameMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset); + AcknowledgeScrollUpdate(); + mExpectedGeckoMetrics.UpdateScrollInfo(aScrollGeneration, aScrollOffset); + CancelAnimation(); + RequestContentRepaint(); + UpdateSharedCompositorFrameMetrics(); + // We don't call ScheduleComposite() here because that happens higher up + // in the call stack, when LayerTransactionParent handles this message. + // If we did it here it would incur an extra message posting unnecessarily. +} + void AsyncPanZoomController::AcknowledgeScrollUpdate() const { @@ -3550,12 +3630,31 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) { FrameMetrics endZoomToMetrics = mFrameMetrics; if (aFlags & PAN_INTO_VIEW_ONLY) { targetZoom = currentZoom; + } else if(aFlags & ONLY_ZOOM_TO_DEFAULT_SCALE) { + CSSToParentLayerScale zoomAtDefaultScale = + mFrameMetrics.GetDevPixelsPerCSSPixel() * LayoutDeviceToParentLayerScale(1.0); + if (targetZoom.scale > zoomAtDefaultScale.scale) { + // Only change the zoom if we are less than the default zoom + if (currentZoom.scale < zoomAtDefaultScale.scale) { + targetZoom = zoomAtDefaultScale; + } else { + targetZoom = currentZoom; + } + } } endZoomToMetrics.SetZoom(CSSToParentLayerScale2D(targetZoom)); // Adjust the zoomToRect to a sensible position to prevent overscrolling. CSSSize sizeAfterZoom = endZoomToMetrics.CalculateCompositedSizeInCssPixels(); + // Vertically center the zoomed element in the screen. + if (!zoomOut && (sizeAfterZoom.height > aRect.height)) { + aRect.y -= (sizeAfterZoom.height - aRect.height) * 0.5f; + if (aRect.y < 0.0f) { + aRect.y = 0.0f; + } + } + // If either of these conditions are met, the page will be // overscrolled after zoomed if (aRect.y + sizeAfterZoom.height > cssPageRect.height) { @@ -3567,14 +3666,6 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect, const uint32_t aFlags) { aRect.x = aRect.x > 0 ? aRect.x : 0; } - // Vertically center the zoomed element in the screen. - if (!zoomOut && (sizeAfterZoom.height > aRect.height)) { - aRect.y -= (sizeAfterZoom.height - aRect.height) * 0.5f; - if (aRect.y < 0.0f) { - aRect.y = 0.0f; - } - } - endZoomToMetrics.SetScrollOffset(aRect.TopLeft()); StartAnimation(new ZoomAnimation( diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index c7b2d36d99..aa86d188f5 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -187,6 +187,13 @@ public: void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint, bool aThisLayerTreeUpdated); + /** + * A lightweight version of NotifyLayersUpdated that allows just the scroll + * offset and scroll generation from the main thread to be propagated to APZ. + */ + void NotifyScrollUpdated(uint32_t aScrollGeneration, + const CSSPoint& aScrollOffset); + /** * The platform implementation must set the compositor parent so that we can * request composites. @@ -614,11 +621,6 @@ protected: */ APZCTreeManager* GetApzcTreeManager() const; - /** - * Gets a ref to the input queue that is shared across the entire tree manager. - */ - const RefPtr& GetInputQueue() const; - /** * Convert ScreenPoint relative to the screen to CSSPoint relative * to the parent document. This excludes the transient compositor transform. @@ -813,6 +815,11 @@ public: */ void ResetTouchInputState(); + /** + * Gets a ref to the input queue that is shared across the entire tree manager. + */ + const RefPtr& GetInputQueue() const; + private: void CancelAnimationAndGestureState(); diff --git a/gfx/layers/apz/src/CheckerboardEvent.h b/gfx/layers/apz/src/CheckerboardEvent.h index f82c5cf811..c71611d89c 100644 --- a/gfx/layers/apz/src/CheckerboardEvent.h +++ b/gfx/layers/apz/src/CheckerboardEvent.h @@ -10,6 +10,7 @@ #include "mozilla/TimeStamp.h" #include #include "Units.h" +#include namespace mozilla { namespace layers { diff --git a/gfx/layers/apz/src/DragTracker.cpp b/gfx/layers/apz/src/DragTracker.cpp new file mode 100644 index 0000000000..df52914590 --- /dev/null +++ b/gfx/layers/apz/src/DragTracker.cpp @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DragTracker.h" + +#include "InputData.h" + +#define DRAG_LOG(...) +// #define DRAG_LOG(...) printf_stderr("DRAG: " __VA_ARGS__) + +namespace mozilla { +namespace layers { + +DragTracker::DragTracker() + : mInDrag(false) +{ +} + +/*static*/ bool +DragTracker::StartsDrag(const MouseInput& aInput) +{ + return aInput.IsLeftButton() && aInput.mType == MouseInput::MOUSE_DOWN; +} + +/*static*/ bool +DragTracker::EndsDrag(const MouseInput& aInput) +{ + return aInput.IsLeftButton() && aInput.mType == MouseInput::MOUSE_UP; +} + +void +DragTracker::Update(const MouseInput& aInput) +{ + if (StartsDrag(aInput)) { + DRAG_LOG("Starting drag\n"); + mInDrag = true; + } else if (EndsDrag(aInput)) { + DRAG_LOG("Ending drag\n"); + mInDrag = false; + mOnScrollbar = Nothing(); + } +} + +bool +DragTracker::InDrag() const +{ + return mInDrag; +} + +bool +DragTracker::IsOnScrollbar(bool aOnScrollbar) +{ + if (!mOnScrollbar) { + DRAG_LOG("Setting hitscrollbar %d\n", aOnScrollbar); + mOnScrollbar = Some(aOnScrollbar); + } + return mOnScrollbar.value(); +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/apz/src/DragTracker.h b/gfx/layers/apz/src/DragTracker.h new file mode 100644 index 0000000000..9f7ff1222b --- /dev/null +++ b/gfx/layers/apz/src/DragTracker.h @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_layers_DragTracker_h +#define mozilla_layers_DragTracker_h + +#include "mozilla/EventForwards.h" +#include "mozilla/Maybe.h" + +namespace mozilla { + +class MouseInput; + +namespace layers { + +// DragTracker simply tracks a sequence of mouse inputs and allows us to tell +// if we are in a drag or not (i.e. the left mouse button went down and hasn't +// gone up yet). +class DragTracker +{ +public: + DragTracker(); + static bool StartsDrag(const MouseInput& aInput); + static bool EndsDrag(const MouseInput& aInput); + void Update(const MouseInput& aInput); + bool InDrag() const; + bool IsOnScrollbar(bool aOnScrollbar); + +private: + Maybe mOnScrollbar; + bool mInDrag; +}; + +} // namespace layers +} // namespace mozilla + +#endif /* mozilla_layers_DragTracker_h */ diff --git a/gfx/layers/apz/src/GestureEventListener.cpp b/gfx/layers/apz/src/GestureEventListener.cpp index c310168b2a..30766ba8fa 100644 --- a/gfx/layers/apz/src/GestureEventListener.cpp +++ b/gfx/layers/apz/src/GestureEventListener.cpp @@ -444,7 +444,7 @@ void GestureEventListener::HandleInputTimeoutLongTap() } } -void GestureEventListener::HandleInputTimeoutMaxTap() +void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling) { GEL_LOG("Running max-tap timeout task in state %d\n", mState); @@ -455,7 +455,9 @@ void GestureEventListener::HandleInputTimeoutMaxTap() } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP || mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) { SetState(GESTURE_NONE); - TriggerSingleTapConfirmedEvent(); + if (!aDuringFastFling) { + TriggerSingleTapConfirmedEvent(); + } } else { NS_WARNING("Unhandled state upon MAX_TAP timeout"); SetState(GESTURE_NONE); @@ -520,8 +522,10 @@ void GestureEventListener::CreateMaxTapTimeoutTask() { mLastTapInput = mLastTouchInput; + TouchBlockState* block = mAsyncPanZoomController->GetInputQueue()->CurrentTouchBlock(); mMaxTapTimeoutTask = - NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutMaxTap); + NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutMaxTap, + block->IsDuringFastFling()); mAsyncPanZoomController->PostDelayedTask( mMaxTapTimeoutTask, diff --git a/gfx/layers/apz/src/GestureEventListener.h b/gfx/layers/apz/src/GestureEventListener.h index e7ff8c0e85..5bd1a6e1e5 100644 --- a/gfx/layers/apz/src/GestureEventListener.h +++ b/gfx/layers/apz/src/GestureEventListener.h @@ -137,7 +137,7 @@ private: nsEventStatus HandleInputTouchMove(); nsEventStatus HandleInputTouchCancel(); void HandleInputTimeoutLongTap(); - void HandleInputTimeoutMaxTap(); + void HandleInputTimeoutMaxTap(bool aDuringFastFling); void TriggerSingleTapConfirmedEvent(); diff --git a/gfx/layers/apz/src/HitTestingTreeNode.cpp b/gfx/layers/apz/src/HitTestingTreeNode.cpp index 17f302aa5c..ce392a98c3 100644 --- a/gfx/layers/apz/src/HitTestingTreeNode.cpp +++ b/gfx/layers/apz/src/HitTestingTreeNode.cpp @@ -12,6 +12,7 @@ #include "mozilla/layers/APZThreadUtils.h" // for AssertOnCompositorThread #include "mozilla/layers/APZUtils.h" // for CompleteAsyncTransform #include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform::operator Matrix4x4() +#include "mozilla/layers/AsyncDragMetrics.h" // for AsyncDragMetrics #include "nsPrintfCString.h" // for nsPrintfCString #include "UnitTransforms.h" // for ViewAs @@ -114,6 +115,12 @@ HitTestingTreeNode::GetScrollSize() const return mScrollSize; } +bool +HitTestingTreeNode::IsScrollbarNode() const +{ + return (mScrollDir != Layer::NONE); +} + void HitTestingTreeNode::SetPrevSibling(HitTestingTreeNode* aSibling) { diff --git a/gfx/layers/apz/src/HitTestingTreeNode.h b/gfx/layers/apz/src/HitTestingTreeNode.h index 98c6ec11d7..f19562914a 100644 --- a/gfx/layers/apz/src/HitTestingTreeNode.h +++ b/gfx/layers/apz/src/HitTestingTreeNode.h @@ -95,6 +95,7 @@ public: void SetScrollbarData(FrameMetrics::ViewID aScrollViewId, Layer::ScrollDirection aDir, int32_t aScrollSize); bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const; int32_t GetScrollSize() const; + bool IsScrollbarNode() const; /* Convert aPoint into the LayerPixel space for the layer corresponding to * this node. */ diff --git a/gfx/layers/apz/src/InputBlockState.cpp b/gfx/layers/apz/src/InputBlockState.cpp index 72568d569c..b1552c7113 100644 --- a/gfx/layers/apz/src/InputBlockState.cpp +++ b/gfx/layers/apz/src/InputBlockState.cpp @@ -87,9 +87,33 @@ InputBlockState::IsTargetConfirmed() const return mTargetConfirmed; } +bool +InputBlockState::IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB) +{ + if (aA == aB) { + return true; + } + + bool seenA = false; + for (size_t i = 0; i < mOverscrollHandoffChain->Length(); ++i) { + AsyncPanZoomController* apzc = mOverscrollHandoffChain->GetApzcAtIndex(i); + if (apzc == aB) { + return seenA; + } + if (apzc == aA) { + seenA = true; + } + } + return false; +} + + void InputBlockState::SetScrolledApzc(AsyncPanZoomController* aApzc) { + // An input block should only have one scrolled APZC. + MOZ_ASSERT(!mScrolledApzc || mScrolledApzc == aApzc); + mScrolledApzc = aApzc; } @@ -716,16 +740,11 @@ TouchBlockState::IsDuringFastFling() const return mDuringFastFling; } -bool +void TouchBlockState::SetSingleTapOccurred() { - TBS_LOG("%p attempting to set single-tap occurred; disallowed=%d\n", - this, mDuringFastFling); - if (!mDuringFastFling) { - mSingleTapOccurred = true; - return true; - } - return false; + TBS_LOG("%p setting single-tap-occurred flag\n", this); + mSingleTapOccurred = true; } bool diff --git a/gfx/layers/apz/src/InputBlockState.h b/gfx/layers/apz/src/InputBlockState.h index 98a8bb9cb8..d962c1426f 100644 --- a/gfx/layers/apz/src/InputBlockState.h +++ b/gfx/layers/apz/src/InputBlockState.h @@ -9,9 +9,11 @@ #include "InputData.h" // for MultiTouchInput #include "mozilla/gfx/Matrix.h" // for Matrix4x4 +#include "mozilla/layers/APZUtils.h" // for TouchBehaviorFlags #include "mozilla/layers/AsyncDragMetrics.h" #include "nsAutoPtr.h" // for nsRefPtr #include "nsTArray.h" // for nsTArray +#include "TouchCounter.h" namespace mozilla { namespace layers { @@ -54,6 +56,11 @@ public: protected: virtual void UpdateTargetApzc(const RefPtr& aTargetApzc); +private: + // Checks whether |aA| is an ancestor of |aB| (or the same as |aB|) in + // |mOverscrollHandoffChain|. + bool IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB); + private: RefPtr mTargetApzc; bool mTargetConfirmed; @@ -409,10 +416,8 @@ public: /** * Set the single-tap-occurred flag that indicates that this touch block * triggered a single tap event. - * @return true if the flag was set. This may not happen if, for example, - * SetDuringFastFling was previously called. */ - bool SetSingleTapOccurred(); + void SetSingleTapOccurred(); /** * @return true iff the single-tap-occurred flag is set on this block. */ diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index b06ac33f6d..66f2b14f99 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -185,7 +185,7 @@ InputQueue::ReceiveMouseInput(const RefPtr& aTarget, // On a new mouse down we can have a new target so we must force a new block // with a new target. - bool newBlock = aEvent.mType == MouseInput::MOUSE_DOWN && aEvent.IsLeftButton(); + bool newBlock = DragTracker::StartsDrag(aEvent); DragBlockState* block = nullptr; if (!newBlock && !mInputBlockQueue.IsEmpty()) { @@ -196,8 +196,20 @@ InputQueue::ReceiveMouseInput(const RefPtr& aTarget, block = nullptr; } + if (!block && mDragTracker.InDrag()) { + // If there's no current drag block, but we're getting a move with a button + // down, we need to start a new drag block because we're obviously already + // in the middle of a drag (it probably got interrupted by something else). + INPQ_LOG("got a drag event outside a drag block, need to create a block to hold it\n"); + newBlock = true; + } + + mDragTracker.Update(aEvent); + if (!newBlock && !block) { - return nsEventStatus_eConsumeDoDefault; + // This input event is not in a drag block, so we're not doing anything + // with it, return eIgnore. + return nsEventStatus_eIgnore; } if (!block) { @@ -218,7 +230,7 @@ InputQueue::ReceiveMouseInput(const RefPtr& aTarget, block->AddEvent(aEvent.AsMouseInput()); - // The first event will confirm the block or not. + // This input event created a new drag block, so return DoDefault. return nsEventStatus_eConsumeDoDefault; } @@ -230,13 +242,12 @@ InputQueue::ReceiveMouseInput(const RefPtr& aTarget, block->AddEvent(aEvent.AsMouseInput()); } - bool mouseUp = aEvent.mType == MouseInput::MOUSE_UP && aEvent.IsLeftButton(); - if (mouseUp) { + if (DragTracker::EndsDrag(aEvent)) { block->MarkMouseUpReceived(); } - // If we're not the first event then we need to wait for the confirmation of - // the block. + // The event was added to the drag block and could potentially cause + // scrolling, so return DoDefault. return nsEventStatus_eConsumeDoDefault; } @@ -537,6 +548,19 @@ InputQueue::AllowScrollHandoff() const return true; } +bool +InputQueue::IsDragOnScrollbar(bool aHitScrollbar) +{ + if (!mDragTracker.InDrag()) { + return false; + } + // Now that we know we are in a drag, get the info from the drag tracker. + // We keep it in the tracker rather than the block because the block can get + // interrupted by something else (like a wheel event) and then a new block + // will get created without the info we want. The tracker will persist though. + return mDragTracker.IsOnScrollbar(aHitScrollbar); +} + void InputQueue::ScheduleMainThreadTimeout(const RefPtr& aTarget, uint64_t aInputBlockId) { INPQ_LOG("scheduling main thread timeout for target %p\n", aTarget.get()); diff --git a/gfx/layers/apz/src/InputQueue.h b/gfx/layers/apz/src/InputQueue.h index ffd4aad398..884290383b 100644 --- a/gfx/layers/apz/src/InputQueue.h +++ b/gfx/layers/apz/src/InputQueue.h @@ -7,11 +7,13 @@ #define mozilla_layers_InputQueue_h #include "APZUtils.h" +#include "DragTracker.h" #include "InputData.h" #include "mozilla/EventForwards.h" #include "mozilla/UniquePtr.h" #include "nsAutoPtr.h" #include "nsTArray.h" +#include "TouchCounter.h" namespace mozilla { @@ -118,6 +120,12 @@ public: * Whether the current pending block allows scroll handoff. */ bool AllowScrollHandoff() const; + /** + * If there is currently a drag in progress, return whether or not it was + * targeted at a scrollbar. If the drag was newly-created and doesn't know, + * use the provided |aOnScrollbar| to populate that information. + */ + bool IsDragOnScrollbar(bool aOnScrollbar); private: ~InputQueue(); @@ -182,6 +190,9 @@ private: // Track touches so we know when to clear mLastActiveApzc TouchCounter mTouchCounter; + + // Track mouse inputs so we know if we're in a drag or not + DragTracker mDragTracker; }; } // namespace layers diff --git a/gfx/layers/apz/src/OverscrollHandoffState.h b/gfx/layers/apz/src/OverscrollHandoffState.h index f0e78736ac..6ceb9e6f88 100644 --- a/gfx/layers/apz/src/OverscrollHandoffState.h +++ b/gfx/layers/apz/src/OverscrollHandoffState.h @@ -10,6 +10,7 @@ #include #include "nsAutoPtr.h" #include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING +#include "APZCTreeManager.h" #include "APZUtils.h" // for CancelAnimationFlags #include "Layers.h" // for Layer::ScrollDirection #include "Units.h" // for ScreenPoint diff --git a/gfx/layers/apz/test/mochitest/apz_test_utils.js b/gfx/layers/apz/test/mochitest/apz_test_utils.js index 834afd8970..06eb7984bd 100644 --- a/gfx/layers/apz/test/mochitest/apz_test_utils.js +++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js @@ -39,46 +39,6 @@ function convertTestData(testData) { return result; } -// ---------------------------------------------------------------- -// Utilities for reconstructing the structure of the APZC tree from -// 'parentScrollId' entries in the APZ test data. -// ---------------------------------------------------------------- - -// Create a node with scroll id 'id' in the APZC tree. -function makeNode(id) { - return {scrollId: id, children: []}; -} - -// Find a node with scroll id 'id' in the APZC tree rooted at 'root'. -function findNode(root, id) { - if (root.scrollId == id) { - return root; - } - for (var i = 0; i < root.children.length; ++i) { - var subtreeResult = findNode(root.children[i], id); - if (subtreeResult != null) { - return subtreeResult; - } - } - return null; -} - -// Add a child -> parent link to the APZC tree rooted at 'root'. -function addLink(root, child, parent) { - var parentNode = findNode(root, parent); - if (parentNode == null) { - parentNode = makeNode(parent); - root.children.push(parentNode); - } - parentNode.children.push(makeNode(child)); -} - -// Add a root node to the APZC tree. It will become a direct -// child of 'root'. -function addRoot(root, id) { - root.children.push(makeNode(id)); -} - // Given APZ test data for a single paint on the compositor side, // reconstruct the APZC tree structure from the 'parentScrollId' // entries that were logged. More specifically, the subset of the @@ -89,13 +49,51 @@ function buildApzcTree(paint) { // The APZC tree can potentially have multiple root nodes, // so we invent a node that is the parent of all roots. // This 'root' does not correspond to an APZC. - var root = makeNode(-1); + var root = {scrollId: -1, children: []}; for (var scrollId in paint) { + paint[scrollId].children = []; + paint[scrollId].scrollId = scrollId; + } + for (var scrollId in paint) { + var parentNode = null; if ("hasNoParentWithSameLayersId" in paint[scrollId]) { - addRoot(root, scrollId); + parentNode = root; } else if ("parentScrollId" in paint[scrollId]) { - addLink(root, scrollId, paint[scrollId]["parentScrollId"]); + parentNode = paint[paint[scrollId].parentScrollId]; } + parentNode.children.push(paint[scrollId]); } return root; } + +// Given an APZC tree produced by buildApzcTree, return the RCD node in +// the tree, or null if there was none. +function findRcdNode(apzcTree) { + if (!!apzcTree.isRootContent) { // isRootContent will be undefined or "1" + return apzcTree; + } + for (var i = 0; i < apzcTree.children.length; i++) { + var rcd = findRcdNode(apzcTree.children[i]); + if (rcd != null) { + return rcd; + } + } + return null; +} + +function flushApzRepaints(aCallback, aWindow = window) { + if (!aCallback) { + throw "A callback must be provided!"; + } + var repaintDone = function() { + SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed", false); + setTimeout(aCallback, 0); + }; + SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed", false); + if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) { + dump("Flushed APZ repaints, waiting for callback...\n"); + } else { + dump("Flushing APZ repaints was a no-op, triggering callback directly...\n"); + repaintDone(); + } +} diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index efeee7001f..a79e28c544 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -125,6 +125,10 @@ ScrollFrame(nsIContent* aContent, { // Scroll the window to the desired spot nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId()); + if (sf) { + sf->SetScrollableByAPZ(!aMetrics.IsScrollInfoLayer()); + } + bool scrollUpdated = false; CSSPoint apzScrollOffset = aMetrics.GetScrollOffset(); CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated); diff --git a/gfx/layers/apz/util/APZEventState.cpp b/gfx/layers/apz/util/APZEventState.cpp index 45629a2cea..ff02aee487 100644 --- a/gfx/layers/apz/util/APZEventState.cpp +++ b/gfx/layers/apz/util/APZEventState.cpp @@ -278,6 +278,7 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, // Since APZ doesn't know about it we don't want to send a response for // this block; we want to just skip over it from the point of view of // prevent-default notifications. + APZES_LOG("Got a synthetic touch-start!\n"); break; } if (isTouchPrevented) { diff --git a/gfx/layers/apz/util/CheckerboardReportService.cpp b/gfx/layers/apz/util/CheckerboardReportService.cpp index 19acd6c1b7..79b7c854d8 100644 --- a/gfx/layers/apz/util/CheckerboardReportService.cpp +++ b/gfx/layers/apz/util/CheckerboardReportService.cpp @@ -12,6 +12,7 @@ #include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown #include "mozilla/dom/CheckerboardReportServiceBinding.h" // for dom::CheckerboardReports #include "nsContentUtils.h" // for nsContentUtils +#include "nsXULAppAPI.h" namespace mozilla { namespace layers { diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 8fc744b563..12433ea332 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -166,26 +166,34 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect, } already_AddRefed -BasicCompositor::CreateRenderTargetForWindow(const IntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode) +BasicCompositor::CreateRenderTargetForWindow(const LayoutDeviceIntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode) { - if (aBufferMode != BufferMode::BUFFER_NONE) { - return CreateRenderTarget(aRect, aInit); - } - + MOZ_ASSERT(mDrawTarget); MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size"); if (aRect.width * aRect.height == 0) { return nullptr; } - MOZ_ASSERT(mDrawTarget); + RefPtr rt; + IntRect rect = aRect.ToUnknownRect(); - // Adjust bounds rect to account for new origin at (0, 0). - IntRect rect(0, 0, aRect.XMost(), aRect.YMost()); - RefPtr rt = new BasicCompositingRenderTarget(mDrawTarget, rect); - - if (aInit == INIT_MODE_CLEAR) { - mDrawTarget->ClearRect(gfx::Rect(aRect)); + if (aBufferMode != BufferMode::BUFFER_NONE) { + RefPtr target = mWidget->CreateBackBufferDrawTarget(mDrawTarget, aRect); + if (!target) { + return nullptr; + } + rt = new BasicCompositingRenderTarget(target, rect); + } else { + IntRect windowRect = rect; + // Adjust bounds rect to account for new origin at (0, 0). + if (windowRect.Size() != mDrawTarget->GetSize()) { + windowRect.ExpandToEnclose(IntPoint(0, 0)); + } + rt = new BasicCompositingRenderTarget(mDrawTarget, windowRect); + if (aInit == INIT_MODE_CLEAR) { + mDrawTarget->ClearRect(Rect(rect - rt->GetOrigin())); + } } return rt.forget(); @@ -389,6 +397,25 @@ RoundOut(Rect r) return IntRect(r.x, r.y, r.width, r.height); } +static void +SetupMask(const EffectChain& aEffectChain, + DrawTarget* aDest, + const IntPoint& aOffset, + RefPtr& aMaskSurface, + Matrix& aMaskTransform) +{ + if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) { + EffectMask *effectMask = static_cast(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get()); + aMaskSurface = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(aDest); + if (!aMaskSurface) { + gfxWarning() << "Invalid sourceMask effect"; + } + MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!"); + aMaskTransform = effectMask->mMaskTransform.As2D(); + aMaskTransform.PostTranslate(-aOffset.x, -aOffset.y); + } +} + void BasicCompositor::DrawQuad(const gfx::Rect& aRect, const gfx::Rect& aClipRect, @@ -434,7 +461,8 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, // When we apply the 3D transformation, we do it against a temporary // surface, so undo the coordinate offset. - new3DTransform = Matrix4x4::Translation(aRect.x, aRect.y, 0) * aTransform; + new3DTransform = aTransform; + new3DTransform.PreTranslate(aRect.x, aRect.y, 0); } buffer->PushClipRect(aClipRect); @@ -444,16 +472,8 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, RefPtr sourceMask; Matrix maskTransform; - if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) { - EffectMask *effectMask = static_cast(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get()); - sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(dest); - if (!sourceMask) { - gfxWarning() << "Invalid sourceMask effect"; - } - MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!"); - MOZ_ASSERT(!effectMask->mIs3D); - maskTransform = effectMask->mMaskTransform.As2D(); - maskTransform.PreTranslate(-offset.x, -offset.y); + if (aTransform.Is2D()) { + SetupMask(aEffectChain, dest, offset, sourceMask, maskTransform); } CompositionOp blendMode = CompositionOp::OP_OVER; @@ -560,8 +580,40 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, Transform(temp, source, new3DTransform, transformBounds.TopLeft()); + SetupMask(aEffectChain, buffer, offset, sourceMask, maskTransform); + + // Adjust for the fact that our content now start at 0,0 instead + // of the top left of transformBounds. transformBounds.MoveTo(0, 0); - buffer->DrawSurface(temp, transformBounds, transformBounds); + maskTransform.PostTranslate(-transformBounds.x, -transformBounds.y); + + if (sourceMask) { + // Transform the source by it's normal transform, and then the inverse + // of the mask transform so that it's in the mask's untransformed + // coordinate space. + Matrix old = buffer->GetTransform(); + Matrix sourceTransform = old; + + Matrix inverseMask = maskTransform; + inverseMask.Invert(); + + sourceTransform *= inverseMask; + + SurfacePattern source(temp, ExtendMode::CLAMP, sourceTransform); + + buffer->PushClipRect(transformBounds); + + // Mask in the untransformed coordinate space, and then transform + // by the mask transform to put the result back into destination + // coords. + buffer->SetTransform(maskTransform); + buffer->MaskSurface(source, sourceMask, Point(0, 0)); + buffer->SetTransform(old); + + buffer->PopClip(); + } else { + buffer->DrawSurface(temp, transformBounds, transformBounds); + } } buffer->PopClip(); @@ -577,6 +629,7 @@ void BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, const gfx::Rect *aClipRectIn, const gfx::Rect& aRenderBounds, + bool aOpaque, gfx::Rect *aClipRectOut /* = nullptr */, gfx::Rect *aRenderBoundsOut /* = nullptr */) { @@ -627,7 +680,9 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion, // Setup an intermediate render target to buffer all compositing. We will // copy this into mDrawTarget (the widget), and/or mTarget in EndFrame() RefPtr target = - CreateRenderTargetForWindow(mInvalidRect.ToUnknownRect(), INIT_MODE_CLEAR, bufferMode); + CreateRenderTargetForWindow(mInvalidRect, + aOpaque ? INIT_MODE_NONE : INIT_MODE_CLEAR, + bufferMode); if (!target) { if (!mTarget) { mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion); diff --git a/gfx/layers/basic/BasicCompositor.h b/gfx/layers/basic/BasicCompositor.h index 028fc0fd1b..e4696e1b3e 100644 --- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -63,7 +63,7 @@ public: const gfx::IntPoint &aSourcePoint) override; virtual already_AddRefed - CreateRenderTargetForWindow(const gfx::IntRect& aRect, + CreateRenderTargetForWindow(const LayoutDeviceIntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode); @@ -97,6 +97,7 @@ public: virtual void BeginFrame(const nsIntRegion& aInvalidRegion, const gfx::Rect *aClipRectIn, const gfx::Rect& aRenderBounds, + bool aOpaque, gfx::Rect *aClipRectOut = nullptr, gfx::Rect *aRenderBoundsOut = nullptr) override; virtual void EndFrame() override; diff --git a/gfx/layers/client/ClientTiledPaintedLayer.cpp b/gfx/layers/client/ClientTiledPaintedLayer.cpp index 000fa321af..55ae6e6656 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -32,6 +32,7 @@ ClientTiledPaintedLayer::ClientTiledPaintedLayer(ClientLayerManager* const aMana ClientLayerManager::PaintedLayerCreationHint aCreationHint) : PaintedLayer(aManager, static_cast(this), aCreationHint) , mContentClient() + , mHaveSingleTiledContentClient(false) { MOZ_COUNT_CTOR(ClientTiledPaintedLayer); mPaintData.mLastScrollOffset = ParentLayerPoint(0, 0); @@ -181,13 +182,15 @@ ClientTiledPaintedLayer::BeginPaint() + displayportMetrics.GetCompositionBounds().TopLeft(); Maybe criticalDisplayPortTransformed = ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort, layerBounds); - if (!criticalDisplayPortTransformed) { - mPaintData.ResetPaintData(); - return; + if (criticalDisplayPortTransformed) { + mPaintData.mCriticalDisplayPort = Some(RoundedToInt(*criticalDisplayPortTransformed)); + } else { + mPaintData.mCriticalDisplayPort = Some(LayerIntRect(0, 0, 0, 0)); } - mPaintData.mCriticalDisplayPort = RoundedToInt(*criticalDisplayPortTransformed); } - TILING_LOG("TILING %p: Critical displayport %s\n", this, Stringify(mPaintData.mCriticalDisplayPort).c_str()); + TILING_LOG("TILING %p: Critical displayport %s\n", this, + mPaintData.mCriticalDisplayPort ? + Stringify(*mPaintData.mCriticalDisplayPort).c_str() : "not set"); // Store the resolution from the displayport ancestor layer. Because this is Gecko-side, // before any async transforms have occurred, we can use the zoom for this. @@ -200,11 +203,11 @@ ClientTiledPaintedLayer::BeginPaint() ParentLayerToLayerMatrix4x4 transformToBounds = mPaintData.mTransformToCompBounds.Inverse(); Maybe compositionBoundsTransformed = ApplyParentLayerToLayerTransform( transformToBounds, scrollMetrics.GetCompositionBounds(), layerBounds); - if (!compositionBoundsTransformed) { - mPaintData.ResetPaintData(); - return; + if (compositionBoundsTransformed) { + mPaintData.mCompositionBounds = *compositionBoundsTransformed; + } else { + mPaintData.mCompositionBounds.SetEmpty(); } - mPaintData.mCompositionBounds = *compositionBoundsTransformed; TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str()); // Calculate the scroll offset since the last transaction @@ -260,7 +263,7 @@ ClientTiledPaintedLayer::UseProgressiveDraw() { return false; } - if (mPaintData.mCriticalDisplayPort.IsEmpty()) { + if (!mPaintData.mCriticalDisplayPort) { // This catches three scenarios: // 1) This layer doesn't have a scrolling ancestor // 2) This layer is subject to OMTA transforms @@ -279,7 +282,7 @@ ClientTiledPaintedLayer::UseProgressiveDraw() { if (ClientManager()->AsyncPanZoomEnabled()) { LayerMetricsWrapper scrollAncestor; GetAncestorLayers(&scrollAncestor, nullptr, nullptr); - MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is non-empty + MOZ_ASSERT(scrollAncestor); // because mPaintData.mCriticalDisplayPort is set const FrameMetrics& parentMetrics = scrollAncestor.Metrics(); if (!IsScrollingOnCompositor(parentMetrics)) { return false; @@ -295,22 +298,24 @@ ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion, LayerManager::DrawPaintedLayerCallback aCallback, void* aCallbackData) { - // If we have no high-precision stuff to draw, or we have started drawing low-precision - // already, then we shouldn't do anything there. - if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) { + // If we have started drawing low-precision already, then we + // shouldn't do anything there. + if (mPaintData.mLowPrecisionPaintCount != 0) { return false; } - // Only draw progressively when the resolution is unchanged - if (UseProgressiveDraw() && + // Only draw progressively when there is something to paint and the + // resolution is unchanged + if (!aInvalidRegion.IsEmpty() && + UseProgressiveDraw() && mContentClient->GetTiledBuffer()->GetFrameResolution() == mPaintData.mResolution) { // Store the old valid region, then clear it before painting. // We clip the old valid region to the visible region, as it only gets // used to decide stale content (currently valid and previously visible) nsIntRegion oldValidRegion = mContentClient->GetTiledBuffer()->GetValidRegion(); oldValidRegion.And(oldValidRegion, aVisibleRegion); - if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { - oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect()); + if (mPaintData.mCriticalDisplayPort) { + oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect()); } TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str()); @@ -319,11 +324,12 @@ ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion, oldValidRegion, &mPaintData, aCallback, aCallbackData); } - // Otherwise do a non-progressive paint + // Otherwise do a non-progressive paint. We must do this even when + // the region to paint is empty as the valid region may have shrunk. mValidRegion = aVisibleRegion; - if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { - mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect()); + if (mPaintData.mCriticalDisplayPort) { + mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect()); } TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str()); @@ -344,7 +350,8 @@ ClientTiledPaintedLayer::RenderLowPrecision(nsIntRegion& aInvalidRegion, { // Render the low precision buffer, if the visible region is larger than the // critical display port. - if (!nsIntRegion(mPaintData.mCriticalDisplayPort.ToUnknownRect()).Contains(aVisibleRegion)) { + if (!mPaintData.mCriticalDisplayPort || + !nsIntRegion(mPaintData.mCriticalDisplayPort->ToUnknownRect()).Contains(aVisibleRegion)) { nsIntRegion oldValidRegion = mContentClient->GetLowPrecisionTiledBuffer()->GetValidRegion(); oldValidRegion.And(oldValidRegion, aVisibleRegion); @@ -415,18 +422,26 @@ ClientTiledPaintedLayer::RenderLayer() void *data = ClientManager()->GetPaintedLayerCallbackData(); IntSize layerSize = mVisibleRegion.ToUnknownRegion().GetBounds().Size(); - if (mContentClient && !mContentClient->SupportsLayerSize(layerSize, ClientManager())) { + IntSize tileSize(gfxPlatform::GetPlatform()->GetTileWidth(), + gfxPlatform::GetPlatform()->GetTileHeight()); + + bool wantSingleTiledContentClient = + (mCreationHint == LayerManager::NONE || layerSize <= tileSize) && + SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) && + gfxPrefs::LayersSingleTileEnabled(); + + if (mContentClient && mHaveSingleTiledContentClient && !wantSingleTiledContentClient) { mContentClient = nullptr; mValidRegion.SetEmpty(); } if (!mContentClient) { - if (mCreationHint == LayerManager::NONE && - SingleTiledContentClient::ClientSupportsLayerSize(layerSize, ClientManager()) && - gfxPrefs::LayersSingleTileEnabled()) { + if (wantSingleTiledContentClient) { mContentClient = new SingleTiledContentClient(this, ClientManager()); + mHaveSingleTiledContentClient = true; } else { mContentClient = new MultiTiledContentClient(this, ClientManager()); + mHaveSingleTiledContentClient = false; } mContentClient->Connect(); @@ -490,16 +505,16 @@ ClientTiledPaintedLayer::RenderLayer() // critical displayport are discarded on the first update. Also make sure that we // only draw stuff inside the critical displayport on the first update. mValidRegion.And(mValidRegion, neededRegion); - if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { - mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect()); - invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect()); + if (mPaintData.mCriticalDisplayPort) { + mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect()); + invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect()); } TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(mValidRegion).c_str()); TILING_LOG("TILING %p: First-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str()); } else { - if (!mPaintData.mCriticalDisplayPort.IsEmpty()) { - invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort.ToUnknownRect()); + if (mPaintData.mCriticalDisplayPort) { + invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort->ToUnknownRect()); } TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str()); } diff --git a/gfx/layers/client/ClientTiledPaintedLayer.h b/gfx/layers/client/ClientTiledPaintedLayer.h index cda3867a3e..f4c3f2a8a9 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.h +++ b/gfx/layers/client/ClientTiledPaintedLayer.h @@ -133,6 +133,9 @@ private: void EndPaint(); RefPtr mContentClient; + // Flag to indicate if mContentClient is a SingleTiledContentClient. This is + // only valid when mContentClient is non-null. + bool mHaveSingleTiledContentClient; nsIntRegion mLowPrecisionValidRegion; BasicTiledLayerPaintData mPaintData; }; diff --git a/gfx/layers/client/SingleTiledContentClient.cpp b/gfx/layers/client/SingleTiledContentClient.cpp index 16488e08c2..4f22726aca 100644 --- a/gfx/layers/client/SingleTiledContentClient.cpp +++ b/gfx/layers/client/SingleTiledContentClient.cpp @@ -46,12 +46,6 @@ SingleTiledContentClient::ClientSupportsLayerSize(const gfx::IntSize& aSize, Cli return aSize.width <= maxTextureSize && aSize.height <= maxTextureSize; } -bool -SingleTiledContentClient::SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const -{ - return ClientSupportsLayerSize(aSize, aManager); -} - ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer* aPaintedLayer, CompositableClient* aCompositableClient, ClientLayerManager* aManager) diff --git a/gfx/layers/client/SingleTiledContentClient.h b/gfx/layers/client/SingleTiledContentClient.h index e2869976af..2486f83cea 100644 --- a/gfx/layers/client/SingleTiledContentClient.h +++ b/gfx/layers/client/SingleTiledContentClient.h @@ -127,8 +127,6 @@ public: virtual ClientTiledLayerBuffer* GetTiledBuffer() override { return mTiledBuffer; } virtual ClientTiledLayerBuffer* GetLowPrecisionTiledBuffer() override { return nullptr; } - virtual bool SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const override; - private: RefPtr mTiledBuffer; }; diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 14de995660..8dcda1f08c 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -916,47 +916,47 @@ ClientMultiTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, long start = PR_IntervalNow(); #endif - // If this region is empty XMost() - 1 will give us a negative value. - NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n"); - if (!gfxPrefs::TiledDrawTargetEnabled()) { - RefPtr ctxt; + if (!aPaintRegion.IsEmpty()) { - const IntRect bounds = aPaintRegion.GetBounds(); - { - PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferAlloc", + RefPtr ctxt; + + const IntRect bounds = aPaintRegion.GetBounds(); + { + PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferAlloc", + js::ProfileEntry::Category::GRAPHICS); + + mSinglePaintDrawTarget = + gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( + gfx::IntSize(ceilf(bounds.width * mResolution), + ceilf(bounds.height * mResolution)), + gfxPlatform::GetPlatform()->Optimal2DFormatForContent( + GetContentType())); + + if (!mSinglePaintDrawTarget) { + return; + } + + ctxt = new gfxContext(mSinglePaintDrawTarget); + + mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y); + } + ctxt->NewPath(); + ctxt->SetMatrix( + ctxt->CurrentMatrix().Scale(mResolution, mResolution). + Translate(-bounds.x, -bounds.y)); +#ifdef GFX_TILEDLAYER_PREF_WARNINGS + if (PR_IntervalNow() - start > 3) { + printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start); + } + start = PR_IntervalNow(); +#endif + PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw", js::ProfileEntry::Category::GRAPHICS); - mSinglePaintDrawTarget = - gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( - gfx::IntSize(ceilf(bounds.width * mResolution), - ceilf(bounds.height * mResolution)), - gfxPlatform::GetPlatform()->Optimal2DFormatForContent( - GetContentType())); - - if (!mSinglePaintDrawTarget) { - return; - } - - ctxt = new gfxContext(mSinglePaintDrawTarget); - - mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y); + mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion, + DrawRegionClip::NONE, nsIntRegion(), mCallbackData); } - ctxt->NewPath(); - ctxt->SetMatrix( - ctxt->CurrentMatrix().Scale(mResolution, mResolution). - Translate(-bounds.x, -bounds.y)); -#ifdef GFX_TILEDLAYER_PREF_WARNINGS - if (PR_IntervalNow() - start > 3) { - printf_stderr("Slow alloc %i\n", PR_IntervalNow() - start); - } - start = PR_IntervalNow(); -#endif - PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw", - js::ProfileEntry::Category::GRAPHICS); - - mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion, - DrawRegionClip::NONE, nsIntRegion(), mCallbackData); } #ifdef GFX_TILEDLAYER_PREF_WARNINGS @@ -1132,79 +1132,81 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion, oldRetainedTiles.Clear(); - for (size_t i = 0; i < newTileCount; ++i) { - const TileIntPoint tilePosition = newTiles.TilePosition(i); - - IntPoint tileOffset = GetTileOffset(tilePosition); - nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize); - tileDrawRegion.AndWith(aPaintRegion); - - if (tileDrawRegion.IsEmpty()) { - continue; - } - - TileClient& tile = mRetainedTiles[i]; - if (!ValidateTile(tile, GetTileOffset(tilePosition), tileDrawRegion)) { - gfxCriticalError() << "ValidateTile failed"; - } - } - - if (gfxPrefs::TiledDrawTargetEnabled() && mMoz2DTiles.size() > 0) { - gfx::TileSet tileset; - for (size_t i = 0; i < mMoz2DTiles.size(); ++i) { - mMoz2DTiles[i].mTileOrigin -= mTilingOrigin; - } - tileset.mTiles = &mMoz2DTiles[0]; - tileset.mTileCount = mMoz2DTiles.size(); - RefPtr drawTarget = gfx::Factory::CreateTiledDrawTarget(tileset); - drawTarget->SetTransform(Matrix()); - - RefPtr ctx = new gfxContext(drawTarget); - ctx->SetMatrix( - ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin))); - - mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion, - DrawRegionClip::DRAW, nsIntRegion(), mCallbackData); - mMoz2DTiles.clear(); - // Reset: - mTilingOrigin = IntPoint(std::numeric_limits::max(), - std::numeric_limits::max()); - } - - bool edgePaddingEnabled = gfxPrefs::TileEdgePaddingEnabled(); - - for (uint32_t i = 0; i < mRetainedTiles.Length(); ++i) { - TileClient& tile = mRetainedTiles[i]; - - // Only worry about padding when not doing low-res because it simplifies - // the math and the artifacts won't be noticable - // Edge padding prevents sampling artifacts when compositing. - if (edgePaddingEnabled && mResolution == 1 && - tile.mFrontBuffer && tile.mFrontBuffer->IsLocked()) { - + if (!aPaintRegion.IsEmpty()) { + for (size_t i = 0; i < newTileCount; ++i) { const TileIntPoint tilePosition = newTiles.TilePosition(i); - IntPoint tileOffset = GetTileOffset(tilePosition); - // Strictly speakig we want the unscaled rect here, but it doesn't matter - // because we only run this code when the resolution is equal to 1. - IntRect tileRect = IntRect(tileOffset.x, tileOffset.y, - GetTileSize().width, GetTileSize().height); + IntPoint tileOffset = GetTileOffset(tilePosition); nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize); tileDrawRegion.AndWith(aPaintRegion); - nsIntRegion tileValidRegion = mValidRegion; - tileValidRegion.OrWith(tileDrawRegion); + if (tileDrawRegion.IsEmpty()) { + continue; + } - // We only need to pad out if the tile has area that's not valid - if (!tileValidRegion.Contains(tileRect)) { - tileValidRegion = tileValidRegion.Intersect(tileRect); - // translate the region into tile space and pad - tileValidRegion.MoveBy(-IntPoint(tileOffset.x, tileOffset.y)); - RefPtr drawTarget = tile.mFrontBuffer->BorrowDrawTarget(); - PadDrawTargetOutFromRegion(drawTarget, tileValidRegion); + TileClient& tile = mRetainedTiles[i]; + if (!ValidateTile(tile, GetTileOffset(tilePosition), tileDrawRegion)) { + gfxCriticalError() << "ValidateTile failed"; } } - UnlockTile(tile); + + if (gfxPrefs::TiledDrawTargetEnabled() && mMoz2DTiles.size() > 0) { + gfx::TileSet tileset; + for (size_t i = 0; i < mMoz2DTiles.size(); ++i) { + mMoz2DTiles[i].mTileOrigin -= mTilingOrigin; + } + tileset.mTiles = &mMoz2DTiles[0]; + tileset.mTileCount = mMoz2DTiles.size(); + RefPtr drawTarget = gfx::Factory::CreateTiledDrawTarget(tileset); + drawTarget->SetTransform(Matrix()); + + RefPtr ctx = new gfxContext(drawTarget); + ctx->SetMatrix( + ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin))); + + mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion, + DrawRegionClip::DRAW, nsIntRegion(), mCallbackData); + mMoz2DTiles.clear(); + // Reset: + mTilingOrigin = IntPoint(std::numeric_limits::max(), + std::numeric_limits::max()); + } + + bool edgePaddingEnabled = gfxPrefs::TileEdgePaddingEnabled(); + + for (uint32_t i = 0; i < mRetainedTiles.Length(); ++i) { + TileClient& tile = mRetainedTiles[i]; + + // Only worry about padding when not doing low-res because it simplifies + // the math and the artifacts won't be noticable + // Edge padding prevents sampling artifacts when compositing. + if (edgePaddingEnabled && mResolution == 1 && + tile.mFrontBuffer && tile.mFrontBuffer->IsLocked()) { + + const TileIntPoint tilePosition = newTiles.TilePosition(i); + IntPoint tileOffset = GetTileOffset(tilePosition); + // Strictly speakig we want the unscaled rect here, but it doesn't matter + // because we only run this code when the resolution is equal to 1. + IntRect tileRect = IntRect(tileOffset.x, tileOffset.y, + GetTileSize().width, GetTileSize().height); + + nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize); + tileDrawRegion.AndWith(aPaintRegion); + + nsIntRegion tileValidRegion = mValidRegion; + tileValidRegion.OrWith(tileDrawRegion); + + // We only need to pad out if the tile has area that's not valid + if (!tileValidRegion.Contains(tileRect)) { + tileValidRegion = tileValidRegion.Intersect(tileRect); + // translate the region into tile space and pad + tileValidRegion.MoveBy(-IntPoint(tileOffset.x, tileOffset.y)); + RefPtr drawTarget = tile.mFrontBuffer->BorrowDrawTarget(); + PadDrawTargetOutFromRegion(drawTarget, tileValidRegion); + } + } + UnlockTile(tile); + } } mTiles = newTiles; @@ -1685,7 +1687,7 @@ BasicTiledLayerPaintData::ResetPaintData() mLowPrecisionPaintCount = 0; mPaintFinished = false; mCompositionBounds.SetEmpty(); - mCriticalDisplayPort.SetEmpty(); + mCriticalDisplayPort = Nothing(); } } // namespace layers diff --git a/gfx/layers/client/TiledContentClient.h b/gfx/layers/client/TiledContentClient.h index ee80c21726..3d2311040b 100644 --- a/gfx/layers/client/TiledContentClient.h +++ b/gfx/layers/client/TiledContentClient.h @@ -318,10 +318,10 @@ struct BasicTiledLayerPaintData { /* * The critical displayport of the content from the nearest ancestor layer - * that represents scrollable content with a display port set. Empty if a - * critical displayport is not set. + * that represents scrollable content with a display port set. isNothing() + * if a critical displayport is not set. */ - LayerIntRect mCriticalDisplayPort; + Maybe mCriticalDisplayPort; /* * The render resolution of the document that the content this layer @@ -628,9 +628,6 @@ public: }; virtual void UpdatedBuffer(TiledBufferType aType) = 0; - virtual bool SupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager) const - { return true; } - private: const char* mName; }; diff --git a/gfx/layers/composite/CompositableHost.cpp b/gfx/layers/composite/CompositableHost.cpp index 1c9a5f2bf4..5ed3d3fe9d 100644 --- a/gfx/layers/composite/CompositableHost.cpp +++ b/gfx/layers/composite/CompositableHost.cpp @@ -148,8 +148,7 @@ CompositableHost::SetCompositor(Compositor* aCompositor) bool CompositableHost::AddMaskEffect(EffectChain& aEffects, - const gfx::Matrix4x4& aTransform, - bool aIs3D) + const gfx::Matrix4x4& aTransform) { CompositableTextureSourceRef source; RefPtr host = GetAsTextureHost(); @@ -174,7 +173,6 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects, RefPtr effect = new EffectMask(source, source->GetSize(), aTransform); - effect->mIs3D = aIs3D; aEffects.mSecondaryEffects[EffectTypes::MASK] = effect; return true; } diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index bbf95b65c9..26ebe590f3 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -121,8 +121,7 @@ public: * @return true if the effect was added, false otherwise. */ bool AddMaskEffect(EffectChain& aEffects, - const gfx::Matrix4x4& aTransform, - bool aIs3D = false); + const gfx::Matrix4x4& aTransform); void RemoveMaskEffect(); diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index bbbce528a0..8924a347c2 100755 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -8,6 +8,7 @@ #include "apz/src/AsyncPanZoomController.h" // for AsyncPanZoomController #include "FrameMetrics.h" // for FrameMetrics #include "Units.h" // for LayerRect, LayerPixel, etc +#include "CompositableHost.h" // for CompositableHost #include "gfxEnv.h" // for gfxEnv #include "gfxPrefs.h" // for gfxPrefs #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc @@ -30,6 +31,7 @@ #include "nsISupportsUtils.h" // for NS_ADDREF, NS_RELEASE #include "nsRegion.h" // for nsIntRegion #include "nsTArray.h" // for AutoTArray +#include #include "TextRenderer.h" // for TextRenderer #include #include "VRManager.h" // for VRManager diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 8ead236e9f..357659f2d6 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -899,13 +899,15 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion) CompositorBench(mCompositor, bounds); + MOZ_ASSERT(mRoot->GetOpacity() == 1); + bool opaqueContent = (mRoot->GetContentFlags() & Layer::CONTENT_OPAQUE) != 0; if (mRoot->GetClipRect()) { clipRect = *mRoot->GetClipRect(); Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height); - mCompositor->BeginFrame(aInvalidRegion, &rect, bounds, nullptr, &actualBounds); + mCompositor->BeginFrame(aInvalidRegion, &rect, bounds, opaqueContent, nullptr, &actualBounds); } else { gfx::Rect rect; - mCompositor->BeginFrame(aInvalidRegion, nullptr, bounds, &rect, &actualBounds); + mCompositor->BeginFrame(aInvalidRegion, nullptr, bounds, opaqueContent, &rect, &actualBounds); clipRect = ParentLayerIntRect(rect.x, rect.y, rect.width, rect.height); } @@ -1158,8 +1160,10 @@ LayerManagerComposite::RenderToPresentationSurface() nsIntRegion invalid; Rect bounds(0.0f, 0.0f, scale * pageWidth, (float)actualHeight); Rect rect, actualBounds; + MOZ_ASSERT(mRoot->GetOpacity() == 1); + bool opaqueContent = (mRoot->GetContentFlags() & Layer::CONTENT_OPAQUE) != 0; - mCompositor->BeginFrame(invalid, nullptr, bounds, &rect, &actualBounds); + mCompositor->BeginFrame(invalid, nullptr, bounds, opaqueContent, &rect, &actualBounds); // The Java side of Fennec sets a scissor rect that accounts for // chrome such as the URL bar. Override that so that the entire frame buffer @@ -1462,8 +1466,7 @@ LayerManagerComposite::CreateRefLayerComposite() } LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer, - EffectChain& aEffects, - bool aIs3D) + EffectChain& aEffects) : mCompositable(nullptr), mFailed(false) { if (!aMaskLayer) { @@ -1477,7 +1480,7 @@ LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer, return; } - if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform(), aIs3D)) { + if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform())) { mCompositable = nullptr; mFailed = true; } diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h index 03029dca7d..4e01e3eccb 100644 --- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -188,8 +188,7 @@ public: { public: AutoAddMaskEffect(Layer* aMaskLayer, - EffectChain& aEffect, - bool aIs3D = false); + EffectChain& aEffect); ~AutoAddMaskEffect(); bool Failed() const { return mFailed; } @@ -582,16 +581,11 @@ RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor, // no mask layers at all } - bool firstMaskIs3D = false; - if (ContainerLayer* container = aLayer->AsContainerLayer()) { - firstMaskIs3D = !container->GetTransform().CanDraw2D(); - } - if (maskLayerCount <= 1) { // This is the common case. Render in one pass and return. EffectChain effectChain(aLayer); LayerManagerComposite::AutoAddMaskEffect - autoMaskEffect(firstMask, effectChain, firstMaskIs3D); + autoMaskEffect(firstMask, effectChain); aLayer->AsLayerComposite()->AddBlendModeEffect(effectChain); aRenderCallback(effectChain, gfx::Rect(aClipRect)); return; @@ -630,7 +624,7 @@ RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor, { EffectChain firstEffectChain(aLayer); LayerManagerComposite::AutoAddMaskEffect - firstMaskEffect(firstMask, firstEffectChain, firstMaskIs3D); + firstMaskEffect(firstMask, firstEffectChain); aRenderCallback(firstEffectChain, gfx::Rect(aClipRect - surfaceRect.TopLeft())); // firstTarget now contains the transformed source with the first mask and // opacity already applied. diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 392e888ccf..ff43084203 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -565,6 +565,10 @@ public: virtual void WaitAcquireFenceHandleSyncComplete() {}; + virtual bool NeedsFenceHandle() { return false; } + + virtual FenceHandle GetCompositorReleaseFence() { return FenceHandle(); } + protected: FenceHandle mReleaseFenceHandle; diff --git a/gfx/layers/d3d11/BlendShaderConstants.h b/gfx/layers/d3d11/BlendShaderConstants.h index b548e6e7ef..d89240c184 100644 --- a/gfx/layers/d3d11/BlendShaderConstants.h +++ b/gfx/layers/d3d11/BlendShaderConstants.h @@ -14,8 +14,7 @@ // These must be in the same order as the Mask enum. #define PS_MASK_NONE 0 -#define PS_MASK_2D 1 -#define PS_MASK_3D 2 +#define PS_MASK 1 // These must be in the same order as CompositionOp. #define PS_BLEND_MULTIPLY 0 @@ -50,8 +49,7 @@ BlendOpToShaderConstant(gfx::CompositionOp aOp) { namespace { static inline void BlendShaderConstantAsserts() { static_assert(PS_MASK_NONE == int(mozilla::layers::MaskType::MaskNone), "shader constant is out of sync"); - static_assert(PS_MASK_2D == int(mozilla::layers::MaskType::Mask2d), "shader constant is out of sync"); - static_assert(PS_MASK_3D == int(mozilla::layers::MaskType::Mask3d), "shader constant is out of sync"); + static_assert(PS_MASK == int(mozilla::layers::MaskType::Mask), "shader constant is out of sync"); static_assert(int(mozilla::gfx::CompositionOp::OP_LUMINOSITY) - int(mozilla::gfx::CompositionOp::OP_MULTIPLY) == 14, "shader constants are out of sync"); } diff --git a/gfx/layers/d3d11/CompositorD3D11.cpp b/gfx/layers/d3d11/CompositorD3D11.cpp index 995c1d417e..5bf230cf98 100644 --- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -907,12 +907,7 @@ CompositorD3D11::DrawQuad(const gfx::Rect& aRect, MaskType maskType = MaskType::MaskNone; if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) { - if (aTransform.Is2D()) { - maskType = MaskType::Mask2d; - } else { - MOZ_ASSERT(aEffectChain.mPrimaryEffect->mType == EffectTypes::RGB); - maskType = MaskType::Mask3d; - } + maskType = MaskType::Mask; EffectMask* maskEffect = static_cast(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get()); @@ -1129,6 +1124,7 @@ void CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion, const Rect* aClipRectIn, const Rect& aRenderBounds, + bool aOpaque, Rect* aClipRectOut, Rect* aRenderBoundsOut) { @@ -1493,8 +1489,7 @@ DeviceAttachmentsD3D11::InitBlendShaders() { if (!mVSQuadBlendShader[MaskType::MaskNone]) { InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone); - InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask2d); - InitVertexShader(sLayerQuadBlendMask3DVS, mVSQuadBlendShader, MaskType::Mask3d); + InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask); } if (!mBlendShader[MaskType::MaskNone]) { InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone); @@ -1506,21 +1501,19 @@ bool DeviceAttachmentsD3D11::CreateShaders() { InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone); - InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask2d); - InitVertexShader(sLayerQuadMask3DVS, mVSQuadShader, MaskType::Mask3d); + InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask); InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone); - InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask2d); + InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask); InitPixelShader(sRGBShader, mRGBShader, MaskType::MaskNone); - InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask2d); + InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask); InitPixelShader(sRGBAShader, mRGBAShader, MaskType::MaskNone); - InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask2d); - InitPixelShader(sRGBAShaderMask3D, mRGBAShader, MaskType::Mask3d); + InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask); InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone); - InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask2d); + InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask); if (gfxPrefs::ComponentAlphaEnabled()) { InitPixelShader(sComponentAlphaShader, mComponentAlphaShader, MaskType::MaskNone); - InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask2d); + InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask); } InitVertexShader(sOculus050VRDistortionVS, getter_AddRefs(mVRDistortionVS[VRHMDType::Oculus050])); diff --git a/gfx/layers/d3d11/CompositorD3D11.h b/gfx/layers/d3d11/CompositorD3D11.h index a285844293..4f363828b2 100644 --- a/gfx/layers/d3d11/CompositorD3D11.h +++ b/gfx/layers/d3d11/CompositorD3D11.h @@ -111,6 +111,7 @@ public: virtual void BeginFrame(const nsIntRegion& aInvalidRegion, const gfx::Rect *aClipRectIn, const gfx::Rect& aRenderBounds, + bool aOpaque, gfx::Rect *aClipRectOut = nullptr, gfx::Rect *aRenderBoundsOut = nullptr) override; diff --git a/gfx/layers/d3d11/CompositorD3D11.hlsl b/gfx/layers/d3d11/CompositorD3D11.hlsl index 953c090c15..535c562d0e 100644 --- a/gfx/layers/d3d11/CompositorD3D11.hlsl +++ b/gfx/layers/d3d11/CompositorD3D11.hlsl @@ -47,12 +47,6 @@ struct VS_OUTPUT { }; struct VS_MASK_OUTPUT { - float4 vPosition : SV_Position; - float2 vTexCoords : TEXCOORD0; - float2 vMaskCoords : TEXCOORD1; -}; - -struct VS_MASK_3D_OUTPUT { float4 vPosition : SV_Position; float2 vTexCoords : TEXCOORD0; float3 vMaskCoords : TEXCOORD1; @@ -153,23 +147,6 @@ VS_MASK_OUTPUT LayerQuadMaskVS(const VS_INPUT aVertex) // calculate the position on the mask texture outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z; outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w; - - outp.vTexCoords = TexCoords(aVertex.vPosition.xy); - - return outp; -} - -VS_MASK_3D_OUTPUT LayerQuadMask3DVS(const VS_INPUT aVertex) -{ - VS_MASK_3D_OUTPUT outp; - float4 position = TransformedPosition(aVertex.vPosition); - - outp.vPosition = VertexPosition(position); - - // calculate the position on the mask texture - position.xyz /= position.w; - outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z; - outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w; // We use the w coord to do non-perspective correct interpolation: // the quad might be transformed in 3D, in which case it will have some // perspective. The graphics card will do perspective-correct interpolation @@ -187,16 +164,9 @@ VS_MASK_3D_OUTPUT LayerQuadMask3DVS(const VS_INPUT aVertex) } float4 RGBAShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target -{ - float2 maskCoords = aVertex.vMaskCoords; - float mask = tMask.Sample(sSampler, maskCoords).r; - return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask; -} - -float4 RGBAShaderMask3D(const VS_MASK_3D_OUTPUT aVertex) : SV_Target { float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; - float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).r; + float mask = tMask.Sample(sSampler, maskCoords).r; return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask; } @@ -206,7 +176,7 @@ float4 RGBShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target result = tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity; result.a = fLayerOpacity; - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tMask.Sample(sSampler, maskCoords).r; return result * mask; } @@ -240,7 +210,7 @@ float4 CalculateYCbCrColor(const float2 aTexCoords) float4 YCbCrShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target { - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tMask.Sample(sSampler, maskCoords).r; return CalculateYCbCrColor(aVertex.vTexCoords) * fLayerOpacity * mask; @@ -254,7 +224,7 @@ PS_OUTPUT ComponentAlphaShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target result.vAlpha = 1.0 - tRGBWhite.Sample(sSampler, aVertex.vTexCoords) + result.vSrc; result.vSrc.a = result.vAlpha.g; - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tMask.Sample(sSampler, maskCoords).r; result.vSrc *= fLayerOpacity * mask; result.vAlpha *= fLayerOpacity * mask; @@ -264,7 +234,7 @@ PS_OUTPUT ComponentAlphaShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target float4 SolidColorShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target { - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tMask.Sample(sSampler, maskCoords).r; return fLayerColor * mask; } @@ -325,18 +295,6 @@ VS_BLEND_OUTPUT LayerQuadBlendMaskVS(const VS_INPUT aVertex) { VS_MASK_OUTPUT v = LayerQuadMaskVS(aVertex); - VS_BLEND_OUTPUT o; - o.vPosition = v.vPosition; - o.vTexCoords = v.vTexCoords; - o.vMaskCoords = float3(v.vMaskCoords, 0); - o.vBackdropCoords = BackdropPosition(v.vPosition); - return o; -} - -VS_BLEND_OUTPUT LayerQuadBlendMask3DVS(const VS_INPUT aVertex) -{ - VS_MASK_3D_OUTPUT v = LayerQuadMask3DVS(aVertex); - VS_BLEND_OUTPUT o; o.vPosition = v.vPosition; o.vTexCoords = v.vTexCoords; @@ -367,7 +325,7 @@ float4 ComputeBlendSourceColor(const VS_BLEND_OUTPUT aVertex) VS_MASK_OUTPUT tmp; tmp.vPosition = aVertex.vPosition; tmp.vTexCoords = aVertex.vTexCoords; - tmp.vMaskCoords = aVertex.vMaskCoords.xy; + tmp.vMaskCoords = aVertex.vMaskCoords; if (iBlendConfig.x == PS_LAYER_RGB) { return RGBShaderMask(tmp); @@ -377,13 +335,6 @@ float4 ComputeBlendSourceColor(const VS_BLEND_OUTPUT aVertex) return YCbCrShaderMask(tmp); } return SolidColorShaderMask(tmp); - } else if (iBlendConfig.y == PS_MASK_3D) { - // The only Mask 3D shader is RGBA. - VS_MASK_3D_OUTPUT tmp; - tmp.vPosition = aVertex.vPosition; - tmp.vTexCoords = aVertex.vTexCoords; - tmp.vMaskCoords = aVertex.vMaskCoords; - return RGBAShaderMask3D(tmp); } return float4(0.0, 0.0, 0.0, 1.0); diff --git a/gfx/layers/d3d11/CompositorD3D11Shaders.h b/gfx/layers/d3d11/CompositorD3D11Shaders.h index 8788130325..73cccf7d17 100644 --- a/gfx/layers/d3d11/CompositorD3D11Shaders.h +++ b/gfx/layers/d3d11/CompositorD3D11Shaders.h @@ -1,7 +1,7 @@ struct ShaderBytes { const void* mData; size_t mLength; }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -25,9 +25,9 @@ struct ShaderBytes { const void* mData; size_t mLength; }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// $Globals cbuffer NA NA cb0 1 // // // @@ -83,7 +83,7 @@ struct ShaderBytes { const void* mData; size_t mLength; }; // approximately 15 instruction slots used vs_4_0 -dcl_constantbuffer cb0[11], immediateIndexed +dcl_constantbuffer CB0[11], immediateIndexed dcl_input v0.xy dcl_output_siv o0.xyzw, position dcl_output o1.xy @@ -106,10 +106,10 @@ ret const BYTE LayerQuadVS[] = { - 68, 88, 66, 67, 141, 229, - 88, 115, 31, 138, 49, 78, - 16, 5, 63, 222, 239, 137, - 213, 18, 1, 0, 0, 0, + 68, 88, 66, 67, 112, 85, + 167, 74, 15, 232, 29, 85, + 162, 39, 212, 215, 65, 102, + 169, 150, 1, 0, 0, 0, 24, 7, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 152, 1, 0, 0, 160, 3, @@ -382,10 +382,10 @@ const BYTE LayerQuadVS[] = 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, - 101, 114, 32, 54, 46, 51, - 46, 57, 54, 48, 48, 46, - 49, 54, 51, 56, 52, 0, - 171, 171, 73, 83, 71, 78, + 101, 114, 32, 49, 48, 46, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 73, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, @@ -413,7 +413,7 @@ const BYTE LayerQuadVS[] = ShaderBytes sLayerQuadVS = { LayerQuadVS, sizeof(LayerQuadVS) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -437,9 +437,9 @@ ShaderBytes sLayerQuadVS = { LayerQuadVS, sizeof(LayerQuadVS) }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// $Globals cbuffer NA NA cb0 1 // // // @@ -472,7 +472,7 @@ ShaderBytes sLayerQuadVS = { LayerQuadVS, sizeof(LayerQuadVS) }; // approximately 1 instruction slot used ps_4_0 -dcl_constantbuffer cb0[1], immediateIndexed +dcl_constantbuffer CB0[1], immediateIndexed dcl_output o0.xyzw mov o0.xyzw, cb0[0].xyzw ret @@ -481,10 +481,10 @@ ret const BYTE SolidColorShader[] = { - 68, 88, 66, 67, 46, 104, - 157, 133, 222, 110, 60, 127, - 132, 226, 126, 208, 247, 164, - 42, 238, 1, 0, 0, 0, + 68, 88, 66, 67, 232, 227, + 42, 205, 188, 244, 239, 58, + 34, 67, 23, 11, 8, 108, + 224, 50, 1, 0, 0, 0, 68, 4, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 132, 0, 0, 0, 204, 0, @@ -636,10 +636,10 @@ const BYTE SolidColorShader[] = 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, @@ -667,7 +667,7 @@ const BYTE SolidColorShader[] = ShaderBytes sSolidColorShader = { SolidColorShader, sizeof(SolidColorShader) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -691,11 +691,11 @@ ShaderBytes sSolidColorShader = { SolidColorShader, sizeof(SolidColorShader) }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tRGB texture float4 2d 0 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tRGB texture float4 2d t0 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -740,7 +740,7 @@ ShaderBytes sSolidColorShader = { SolidColorShader, sizeof(SolidColorShader) }; // approximately 4 instruction slots used (1 texture, 3 arithmetic) ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed +dcl_constantbuffer CB0[2], immediateIndexed dcl_sampler s0, mode_default dcl_resource_texture2d (float,float,float,float) t0 dcl_input_ps linear v1.xy @@ -755,10 +755,10 @@ ret const BYTE RGBShader[] = { - 68, 88, 66, 67, 65, 119, - 74, 180, 122, 23, 76, 16, - 140, 81, 225, 186, 127, 137, - 70, 249, 1, 0, 0, 0, + 68, 88, 66, 67, 125, 240, + 204, 179, 182, 100, 41, 5, + 9, 193, 104, 239, 180, 186, + 251, 1, 1, 0, 0, 0, 76, 5, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 204, 0, 0, 0, 136, 1, @@ -954,10 +954,10 @@ const BYTE RGBShader[] = 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, @@ -985,7 +985,7 @@ const BYTE RGBShader[] = ShaderBytes sRGBShader = { RGBShader, sizeof(RGBShader) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -1009,11 +1009,11 @@ ShaderBytes sRGBShader = { RGBShader, sizeof(RGBShader) }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tRGB texture float4 2d 0 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tRGB texture float4 2d t0 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -1057,7 +1057,7 @@ ShaderBytes sRGBShader = { RGBShader, sizeof(RGBShader) }; // approximately 3 instruction slots used (1 texture, 2 arithmetic) ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed +dcl_constantbuffer CB0[2], immediateIndexed dcl_sampler s0, mode_default dcl_resource_texture2d (float,float,float,float) t0 dcl_input_ps linear v1.xy @@ -1071,10 +1071,10 @@ ret const BYTE RGBAShader[] = { - 68, 88, 66, 67, 134, 186, - 102, 217, 28, 249, 237, 84, - 31, 38, 2, 143, 235, 216, - 237, 103, 1, 0, 0, 0, + 68, 88, 66, 67, 199, 240, + 113, 171, 34, 194, 134, 123, + 243, 63, 156, 246, 8, 157, + 15, 85, 1, 0, 0, 0, 40, 5, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 192, 0, 0, 0, 100, 1, @@ -1264,10 +1264,10 @@ const BYTE RGBAShader[] = 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, @@ -1295,7 +1295,7 @@ const BYTE RGBAShader[] = ShaderBytes sRGBAShader = { RGBAShader, sizeof(RGBAShader) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -1319,12 +1319,12 @@ ShaderBytes sRGBAShader = { RGBAShader, sizeof(RGBAShader) }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tRGB texture float4 2d 0 1 -// tRGBWhite texture float4 2d 4 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tRGB texture float4 2d t0 1 +// tRGBWhite texture float4 2d t4 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -1378,7 +1378,7 @@ ShaderBytes sRGBAShader = { RGBAShader, sizeof(RGBAShader) }; // approximately 9 instruction slots used (2 texture, 7 arithmetic) ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed +dcl_constantbuffer CB0[2], immediateIndexed dcl_sampler s0, mode_default dcl_resource_texture2d (float,float,float,float) t0 dcl_resource_texture2d (float,float,float,float) t4 @@ -1399,10 +1399,10 @@ ret const BYTE ComponentAlphaShader[] = { - 68, 88, 66, 67, 70, 65, - 219, 11, 235, 82, 64, 151, - 37, 101, 86, 144, 19, 4, - 125, 155, 1, 0, 0, 0, + 68, 88, 66, 67, 207, 79, + 99, 143, 94, 253, 50, 234, + 183, 114, 100, 130, 114, 218, + 230, 139, 1, 0, 0, 0, 168, 6, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 64, 1, 0, 0, 160, 2, @@ -1652,10 +1652,10 @@ const BYTE ComponentAlphaShader[] = 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, @@ -1687,7 +1687,7 @@ const BYTE ComponentAlphaShader[] = ShaderBytes sComponentAlphaShader = { ComponentAlphaShader, sizeof(ComponentAlphaShader) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -1711,13 +1711,13 @@ ShaderBytes sComponentAlphaShader = { ComponentAlphaShader, sizeof(ComponentAlph // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tY texture float4 2d 1 1 -// tCb texture float4 2d 2 1 -// tCr texture float4 2d 3 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tY texture float4 2d t1 1 +// tCb texture float4 2d t2 1 +// tCr texture float4 2d t3 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -1779,7 +1779,7 @@ ShaderBytes sComponentAlphaShader = { ComponentAlphaShader, sizeof(ComponentAlph // approximately 15 instruction slots used (3 texture, 12 arithmetic) ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed +dcl_constantbuffer CB0[2], immediateIndexed dcl_sampler s0, mode_default dcl_resource_texture2d (float,float,float,float) t1 dcl_resource_texture2d (float,float,float,float) t2 @@ -1807,10 +1807,10 @@ ret const BYTE YCbCrShader[] = { - 68, 88, 66, 67, 17, 182, - 131, 145, 148, 37, 135, 136, - 214, 75, 157, 57, 87, 83, - 119, 226, 1, 0, 0, 0, + 68, 88, 66, 67, 38, 102, + 184, 10, 33, 16, 211, 116, + 233, 219, 255, 155, 108, 20, + 81, 243, 1, 0, 0, 0, 56, 8, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 220, 1, 0, 0, 44, 4, @@ -2131,10 +2131,10 @@ const BYTE YCbCrShader[] = 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, - 101, 114, 32, 54, 46, 51, - 46, 57, 54, 48, 48, 46, - 49, 54, 51, 56, 52, 0, - 171, 171, 73, 83, 71, 78, + 101, 114, 32, 49, 48, 46, + 48, 46, 49, 48, 48, 49, + 49, 46, 49, 54, 51, 56, + 52, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, @@ -2162,7 +2162,7 @@ const BYTE YCbCrShader[] = ShaderBytes sYCbCrShader = { YCbCrShader, sizeof(YCbCrShader) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -2186,464 +2186,9 @@ ShaderBytes sYCbCrShader = { YCbCrShader, sizeof(YCbCrShader) }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// POSITION 0 xy 0 NONE float xy -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Position 0 xyzw 0 POS float xyzw -// TEXCOORD 0 xy 1 NONE float xy -// TEXCOORD 1 zw 1 NONE float zw -// -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c1 cb0 0 2 ( FLT, FLT, FLT, FLT) -// c3 cb0 3 9 ( FLT, FLT, FLT, FLT) -// -// -// Runtime generated constant mappings: -// -// Target Reg Constant Description -// ---------- -------------------------------------------------- -// c0 Vertex Shader position offset -// -// -// Level9 shader bytecode: -// - vs_2_x - dcl_texcoord v0 - rcp r0.x, c11.z - mad r0.yz, v0.xxyw, c10.xzww, c10.xxyw - mul r1, r0.z, c2 - mad r1, c1, r0.y, r1 - add r1, r1, c3 - add r0.yz, r1.xxyw, -c11.xxyw - mul oT0.w, r0.x, r0.y - rcp r0.x, c11.w - mul oT0.z, r0.x, r0.z - mad oT0.xy, v0, c9.zwzw, c9 - rcp r0.x, r1.w - mul r1.xyz, r0.x, r1 - add r0, r1, -c8 - mul r0.xyz, r0.w, r0 - mul r1, r0.y, c5 - mad r1, c4, r0.x, r1 - mad r1, c6, r0.z, r1 - mad r0, c7, r0.w, r1 - mad oPos.xy, r0.w, c0, r0 - mov oPos.zw, r0 - -// approximately 20 instruction slots used -vs_4_0 -dcl_constantbuffer cb0[12], immediateIndexed -dcl_input v0.xy -dcl_output_siv o0.xyzw, position -dcl_output o1.xy -dcl_output o1.zw -dcl_temps 2 -mad r0.xy, v0.xyxx, cb0[10].zwzz, cb0[10].xyxx -mul r1.xyzw, r0.yyyy, cb0[1].xyzw -mad r0.xyzw, cb0[0].xyzw, r0.xxxx, r1.xyzw -add r0.xyzw, r0.xyzw, cb0[3].xyzw -div r1.xyz, r0.xyzx, r0.wwww -mov r1.w, r0.w -add r0.xy, r0.xyxx, -cb0[11].xyxx -div o1.zw, r0.xxxy, cb0[11].zzzw -add r0.xyzw, r1.xyzw, -cb0[8].xyzw -mul r0.xyz, r0.wwww, r0.xyzx -mul r1.xyzw, r0.yyyy, cb0[5].xyzw -mad r1.xyzw, cb0[4].xyzw, r0.xxxx, r1.xyzw -mad r1.xyzw, cb0[6].xyzw, r0.zzzz, r1.xyzw -mad o0.xyzw, cb0[7].xyzw, r0.wwww, r1.xyzw -mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx -ret -// Approximately 16 instruction slots used -#endif - -const BYTE LayerQuadMaskVS[] = -{ - 68, 88, 66, 67, 117, 253, - 188, 162, 139, 208, 50, 178, - 49, 2, 251, 153, 144, 237, - 178, 212, 1, 0, 0, 0, - 220, 7, 0, 0, 6, 0, - 0, 0, 56, 0, 0, 0, - 224, 1, 0, 0, 76, 4, - 0, 0, 200, 4, 0, 0, - 56, 7, 0, 0, 108, 7, - 0, 0, 65, 111, 110, 57, - 160, 1, 0, 0, 160, 1, - 0, 0, 0, 2, 254, 255, - 96, 1, 0, 0, 64, 0, - 0, 0, 2, 0, 36, 0, - 0, 0, 60, 0, 0, 0, - 60, 0, 0, 0, 36, 0, - 1, 0, 60, 0, 0, 0, - 0, 0, 2, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 9, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 254, 255, - 31, 0, 0, 2, 5, 0, - 0, 128, 0, 0, 15, 144, - 6, 0, 0, 2, 0, 0, - 1, 128, 11, 0, 170, 160, - 4, 0, 0, 4, 0, 0, - 6, 128, 0, 0, 208, 144, - 10, 0, 248, 160, 10, 0, - 208, 160, 5, 0, 0, 3, - 1, 0, 15, 128, 0, 0, - 170, 128, 2, 0, 228, 160, - 4, 0, 0, 4, 1, 0, - 15, 128, 1, 0, 228, 160, - 0, 0, 85, 128, 1, 0, - 228, 128, 2, 0, 0, 3, - 1, 0, 15, 128, 1, 0, - 228, 128, 3, 0, 228, 160, - 2, 0, 0, 3, 0, 0, - 6, 128, 1, 0, 208, 128, - 11, 0, 208, 161, 5, 0, - 0, 3, 0, 0, 8, 224, - 0, 0, 0, 128, 0, 0, - 85, 128, 6, 0, 0, 2, - 0, 0, 1, 128, 11, 0, - 255, 160, 5, 0, 0, 3, - 0, 0, 4, 224, 0, 0, - 0, 128, 0, 0, 170, 128, - 4, 0, 0, 4, 0, 0, - 3, 224, 0, 0, 228, 144, - 9, 0, 238, 160, 9, 0, - 228, 160, 6, 0, 0, 2, - 0, 0, 1, 128, 1, 0, - 255, 128, 5, 0, 0, 3, - 1, 0, 7, 128, 0, 0, - 0, 128, 1, 0, 228, 128, - 2, 0, 0, 3, 0, 0, - 15, 128, 1, 0, 228, 128, - 8, 0, 228, 161, 5, 0, - 0, 3, 0, 0, 7, 128, - 0, 0, 255, 128, 0, 0, - 228, 128, 5, 0, 0, 3, - 1, 0, 15, 128, 0, 0, - 85, 128, 5, 0, 228, 160, - 4, 0, 0, 4, 1, 0, - 15, 128, 4, 0, 228, 160, - 0, 0, 0, 128, 1, 0, - 228, 128, 4, 0, 0, 4, - 1, 0, 15, 128, 6, 0, - 228, 160, 0, 0, 170, 128, - 1, 0, 228, 128, 4, 0, - 0, 4, 0, 0, 15, 128, - 7, 0, 228, 160, 0, 0, - 255, 128, 1, 0, 228, 128, - 4, 0, 0, 4, 0, 0, - 3, 192, 0, 0, 255, 128, - 0, 0, 228, 160, 0, 0, - 228, 128, 1, 0, 0, 2, - 0, 0, 12, 192, 0, 0, - 228, 128, 255, 255, 0, 0, - 83, 72, 68, 82, 100, 2, - 0, 0, 64, 0, 1, 0, - 153, 0, 0, 0, 89, 0, - 0, 4, 70, 142, 32, 0, - 0, 0, 0, 0, 12, 0, - 0, 0, 95, 0, 0, 3, - 50, 16, 16, 0, 0, 0, - 0, 0, 103, 0, 0, 4, - 242, 32, 16, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 101, 0, 0, 3, 50, 32, - 16, 0, 1, 0, 0, 0, - 101, 0, 0, 3, 194, 32, - 16, 0, 1, 0, 0, 0, - 104, 0, 0, 2, 2, 0, - 0, 0, 50, 0, 0, 11, - 50, 0, 16, 0, 0, 0, - 0, 0, 70, 16, 16, 0, - 0, 0, 0, 0, 230, 138, - 32, 0, 0, 0, 0, 0, - 10, 0, 0, 0, 70, 128, - 32, 0, 0, 0, 0, 0, - 10, 0, 0, 0, 56, 0, - 0, 8, 242, 0, 16, 0, - 1, 0, 0, 0, 86, 5, - 16, 0, 0, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 50, 0, 0, 10, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 6, 0, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 1, 0, 0, 0, 0, 0, - 0, 8, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 0, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 14, 0, 0, 7, 114, 0, - 16, 0, 1, 0, 0, 0, - 70, 2, 16, 0, 0, 0, - 0, 0, 246, 15, 16, 0, - 0, 0, 0, 0, 54, 0, - 0, 5, 130, 0, 16, 0, - 1, 0, 0, 0, 58, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 50, 0, - 16, 0, 0, 0, 0, 0, - 70, 0, 16, 0, 0, 0, - 0, 0, 70, 128, 32, 128, - 65, 0, 0, 0, 0, 0, - 0, 0, 11, 0, 0, 0, - 14, 0, 0, 8, 194, 32, - 16, 0, 1, 0, 0, 0, - 6, 4, 16, 0, 0, 0, - 0, 0, 166, 142, 32, 0, - 0, 0, 0, 0, 11, 0, - 0, 0, 0, 0, 0, 9, - 242, 0, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 1, 0, 0, 0, 70, 142, - 32, 128, 65, 0, 0, 0, - 0, 0, 0, 0, 8, 0, - 0, 0, 56, 0, 0, 7, - 114, 0, 16, 0, 0, 0, - 0, 0, 246, 15, 16, 0, - 0, 0, 0, 0, 70, 2, - 16, 0, 0, 0, 0, 0, - 56, 0, 0, 8, 242, 0, - 16, 0, 1, 0, 0, 0, - 86, 5, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 5, 0, - 0, 0, 50, 0, 0, 10, - 242, 0, 16, 0, 1, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 4, 0, - 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 1, 0, 0, 0, - 50, 0, 0, 10, 242, 0, - 16, 0, 1, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 6, 0, 0, 0, - 166, 10, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 1, 0, 0, 0, 50, 0, - 0, 10, 242, 32, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 7, 0, 0, 0, 246, 15, - 16, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 1, 0, - 0, 0, 50, 0, 0, 11, - 50, 32, 16, 0, 1, 0, - 0, 0, 70, 16, 16, 0, - 0, 0, 0, 0, 230, 138, - 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 70, 128, - 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 116, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 4, 0, - 0, 0, 14, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 82, 68, 69, 70, 104, 2, - 0, 0, 1, 0, 0, 0, - 72, 0, 0, 0, 1, 0, - 0, 0, 28, 0, 0, 0, - 0, 4, 254, 255, 0, 1, - 0, 0, 52, 2, 0, 0, - 60, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 36, 71, 108, 111, - 98, 97, 108, 115, 0, 171, - 171, 171, 60, 0, 0, 0, - 10, 0, 0, 0, 96, 0, - 0, 0, 48, 1, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 80, 1, 0, 0, - 0, 0, 0, 0, 64, 0, - 0, 0, 2, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 112, 1, 0, 0, - 64, 0, 0, 0, 64, 0, - 0, 0, 2, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 124, 1, 0, 0, - 128, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 144, 1, 0, 0, 0, 0, - 0, 0, 160, 1, 0, 0, - 144, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 192, 1, 0, 0, - 160, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 203, 1, 0, 0, - 176, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 213, 1, 0, 0, - 192, 0, 0, 0, 64, 0, - 0, 0, 0, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 232, 1, 0, 0, - 0, 1, 0, 0, 16, 0, - 0, 0, 0, 0, 0, 0, - 144, 1, 0, 0, 0, 0, - 0, 0, 244, 1, 0, 0, - 16, 1, 0, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 4, 2, 0, 0, 0, 0, - 0, 0, 20, 2, 0, 0, - 32, 1, 0, 0, 16, 0, - 0, 0, 0, 0, 0, 0, - 36, 2, 0, 0, 0, 0, - 0, 0, 109, 76, 97, 121, - 101, 114, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 3, 0, 3, 0, 4, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 80, - 114, 111, 106, 101, 99, 116, - 105, 111, 110, 0, 118, 82, - 101, 110, 100, 101, 114, 84, - 97, 114, 103, 101, 116, 79, - 102, 102, 115, 101, 116, 0, - 1, 0, 3, 0, 1, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 118, 84, - 101, 120, 116, 117, 114, 101, - 67, 111, 111, 114, 100, 115, - 0, 171, 1, 0, 3, 0, - 1, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 118, 76, 97, 121, 101, 114, - 81, 117, 97, 100, 0, 118, - 77, 97, 115, 107, 81, 117, - 97, 100, 0, 109, 66, 97, - 99, 107, 100, 114, 111, 112, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 102, 76, - 97, 121, 101, 114, 67, 111, - 108, 111, 114, 0, 102, 76, - 97, 121, 101, 114, 79, 112, - 97, 99, 105, 116, 121, 0, - 171, 171, 0, 0, 3, 0, - 1, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 105, 66, 108, 101, 110, 100, - 67, 111, 110, 102, 105, 103, - 0, 171, 171, 171, 1, 0, - 19, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 77, 105, 99, 114, - 111, 115, 111, 102, 116, 32, - 40, 82, 41, 32, 72, 76, - 83, 76, 32, 83, 104, 97, - 100, 101, 114, 32, 67, 111, - 109, 112, 105, 108, 101, 114, - 32, 54, 46, 51, 46, 57, - 54, 48, 48, 46, 49, 54, - 51, 56, 52, 0, 171, 171, - 73, 83, 71, 78, 44, 0, - 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 32, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 3, 3, 0, 0, 80, 79, - 83, 73, 84, 73, 79, 78, - 0, 171, 171, 171, 79, 83, - 71, 78, 104, 0, 0, 0, - 3, 0, 0, 0, 8, 0, - 0, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 92, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 3, 12, - 0, 0, 92, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 12, 3, - 0, 0, 83, 86, 95, 80, - 111, 115, 105, 116, 105, 111, - 110, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171 -}; -ShaderBytes sLayerQuadMaskVS = { LayerQuadMaskVS, sizeof(LayerQuadMaskVS) }; -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 -// -// -// Buffer Definitions: -// -// cbuffer $Globals -// { -// -// float4x4 mLayerTransform; // Offset: 0 Size: 64 -// float4x4 mProjection; // Offset: 64 Size: 64 -// float4 vRenderTargetOffset; // Offset: 128 Size: 16 -// float4 vTextureCoords; // Offset: 144 Size: 16 -// float4 vLayerQuad; // Offset: 160 Size: 16 -// float4 vMaskQuad; // Offset: 176 Size: 16 -// float4x4 mBackdropTransform; // Offset: 192 Size: 64 [unused] -// float4 fLayerColor; // Offset: 256 Size: 16 [unused] -// float fLayerOpacity; // Offset: 272 Size: 4 [unused] -// uint4 iBlendConfig; // Offset: 288 Size: 16 [unused] -// -// } -// -// -// Resource Bindings: -// -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// $Globals cbuffer NA NA cb0 1 // // // @@ -2689,15 +2234,15 @@ ShaderBytes sLayerQuadMaskVS = { LayerQuadMaskVS, sizeof(LayerQuadMaskVS) }; mul r2, r1.y, c2 mad r1, c1, r1.x, r2 add r1, r1, c3 - rcp r2.x, r1.w - mad r2.yz, r1.xxyw, r2.x, -c11.xxyw - mul r1.xyz, r1, r2.x - mul r0.x, r0.w, r2.y + add r2.xy, r1, -c11 + mul r0.x, r0.w, r2.x rcp r0.w, c11.w - mul r0.y, r0.w, r2.z + mul r0.y, r0.w, r2.y mul oT1.xyz, r0, r1.w - add r0, r1, -c8 mad oT0.xy, v0, c9.zwzw, c9 + rcp r0.x, r1.w + mul r1.xyz, r0.x, r1 + add r0, r1, -c8 mul r0.xyz, r0.w, r0 mul r1, r0.y, c5 mad r1, c4, r0.x, r1 @@ -2708,47 +2253,48 @@ ShaderBytes sLayerQuadMaskVS = { LayerQuadMaskVS, sizeof(LayerQuadMaskVS) }; // approximately 22 instruction slots used vs_4_0 -dcl_constantbuffer cb0[12], immediateIndexed +dcl_constantbuffer CB0[12], immediateIndexed dcl_input v0.xy dcl_output_siv o0.xyzw, position dcl_output o1.xy dcl_output o2.xyz -dcl_temps 3 +dcl_temps 4 mad r0.xy, v0.xyxx, cb0[10].zwzz, cb0[10].xyxx mul r1.xyzw, r0.yyyy, cb0[1].xyzw mad r0.xyzw, cb0[0].xyzw, r0.xxxx, r1.xyzw add r0.xyzw, r0.xyzw, cb0[3].xyzw -div r0.xyz, r0.xyzx, r0.wwww -add r1.xyzw, r0.xyzw, -cb0[8].xyzw +div r1.xyz, r0.xyzx, r0.wwww +mov r1.w, r0.w +add r2.xyzw, r1.xyzw, -cb0[8].xyzw +mul r1.xyz, r2.wwww, r2.xyzx +mul r3.xyzw, r1.yyyy, cb0[5].xyzw +mad r3.xyzw, cb0[4].xyzw, r1.xxxx, r3.xyzw +mad r3.xyzw, cb0[6].xyzw, r1.zzzz, r3.xyzw +mad o0.xyzw, cb0[7].xyzw, r2.wwww, r3.xyzw +mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx add r0.xy, r0.xyxx, -cb0[11].xyxx div r0.xy, r0.xyxx, cb0[11].zwzz -mul r1.xyz, r1.wwww, r1.xyzx -mul r2.xyzw, r1.yyyy, cb0[5].xyzw -mad r2.xyzw, cb0[4].xyzw, r1.xxxx, r2.xyzw -mad r2.xyzw, cb0[6].xyzw, r1.zzzz, r2.xyzw -mad o0.xyzw, cb0[7].xyzw, r1.wwww, r2.xyzw -mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx mov r0.z, l(1.000000) -mul o2.xyz, r0.wwww, r0.xyzx +mul o2.xyz, r1.wwww, r0.xyzx ret -// Approximately 17 instruction slots used +// Approximately 18 instruction slots used #endif -const BYTE LayerQuadMask3DVS[] = +const BYTE LayerQuadMaskVS[] = { - 68, 88, 66, 67, 124, 99, - 104, 27, 0, 223, 159, 8, - 231, 86, 180, 224, 50, 178, - 27, 163, 1, 0, 0, 0, - 48, 8, 0, 0, 6, 0, + 68, 88, 66, 67, 170, 122, + 113, 58, 123, 23, 243, 241, + 143, 157, 226, 223, 154, 53, + 167, 168, 1, 0, 0, 0, + 64, 8, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, - 24, 2, 0, 0, 160, 4, - 0, 0, 28, 5, 0, 0, - 140, 7, 0, 0, 192, 7, + 20, 2, 0, 0, 176, 4, + 0, 0, 44, 5, 0, 0, + 156, 7, 0, 0, 208, 7, 0, 0, 65, 111, 110, 57, - 216, 1, 0, 0, 216, 1, + 212, 1, 0, 0, 212, 1, 0, 0, 0, 2, 254, 255, - 152, 1, 0, 0, 64, 0, + 148, 1, 0, 0, 64, 0, 0, 0, 2, 0, 36, 0, 0, 0, 60, 0, 0, 0, 60, 0, 0, 0, 36, 0, @@ -2780,102 +2326,142 @@ const BYTE LayerQuadMask3DVS[] = 228, 128, 2, 0, 0, 3, 1, 0, 15, 128, 1, 0, 228, 128, 3, 0, 228, 160, - 6, 0, 0, 2, 2, 0, - 1, 128, 1, 0, 255, 128, - 4, 0, 0, 4, 2, 0, - 6, 128, 1, 0, 208, 128, - 2, 0, 0, 128, 11, 0, - 208, 161, 5, 0, 0, 3, - 1, 0, 7, 128, 1, 0, - 228, 128, 2, 0, 0, 128, - 5, 0, 0, 3, 0, 0, - 1, 128, 0, 0, 255, 128, - 2, 0, 85, 128, 6, 0, - 0, 2, 0, 0, 8, 128, - 11, 0, 255, 160, 5, 0, - 0, 3, 0, 0, 2, 128, + 2, 0, 0, 3, 2, 0, + 3, 128, 1, 0, 228, 128, + 11, 0, 228, 161, 5, 0, + 0, 3, 0, 0, 1, 128, 0, 0, 255, 128, 2, 0, - 170, 128, 5, 0, 0, 3, - 1, 0, 7, 224, 0, 0, - 228, 128, 1, 0, 255, 128, - 2, 0, 0, 3, 0, 0, - 15, 128, 1, 0, 228, 128, - 8, 0, 228, 161, 4, 0, + 0, 128, 6, 0, 0, 2, + 0, 0, 8, 128, 11, 0, + 255, 160, 5, 0, 0, 3, + 0, 0, 2, 128, 0, 0, + 255, 128, 2, 0, 85, 128, + 5, 0, 0, 3, 1, 0, + 7, 224, 0, 0, 228, 128, + 1, 0, 255, 128, 4, 0, 0, 4, 0, 0, 3, 224, 0, 0, 228, 144, 9, 0, 238, 160, 9, 0, 228, 160, - 5, 0, 0, 3, 0, 0, - 7, 128, 0, 0, 255, 128, - 0, 0, 228, 128, 5, 0, - 0, 3, 1, 0, 15, 128, - 0, 0, 85, 128, 5, 0, - 228, 160, 4, 0, 0, 4, - 1, 0, 15, 128, 4, 0, - 228, 160, 0, 0, 0, 128, - 1, 0, 228, 128, 4, 0, + 6, 0, 0, 2, 0, 0, + 1, 128, 1, 0, 255, 128, + 5, 0, 0, 3, 1, 0, + 7, 128, 0, 0, 0, 128, + 1, 0, 228, 128, 2, 0, + 0, 3, 0, 0, 15, 128, + 1, 0, 228, 128, 8, 0, + 228, 161, 5, 0, 0, 3, + 0, 0, 7, 128, 0, 0, + 255, 128, 0, 0, 228, 128, + 5, 0, 0, 3, 1, 0, + 15, 128, 0, 0, 85, 128, + 5, 0, 228, 160, 4, 0, 0, 4, 1, 0, 15, 128, - 6, 0, 228, 160, 0, 0, - 170, 128, 1, 0, 228, 128, - 4, 0, 0, 4, 0, 0, - 15, 128, 7, 0, 228, 160, - 0, 0, 255, 128, 1, 0, + 4, 0, 228, 160, 0, 0, + 0, 128, 1, 0, 228, 128, + 4, 0, 0, 4, 1, 0, + 15, 128, 6, 0, 228, 160, + 0, 0, 170, 128, 1, 0, 228, 128, 4, 0, 0, 4, - 0, 0, 3, 192, 0, 0, - 255, 128, 0, 0, 228, 160, - 0, 0, 228, 128, 1, 0, - 0, 2, 0, 0, 12, 192, - 0, 0, 228, 128, 255, 255, - 0, 0, 83, 72, 68, 82, - 128, 2, 0, 0, 64, 0, - 1, 0, 160, 0, 0, 0, - 89, 0, 0, 4, 70, 142, + 0, 0, 15, 128, 7, 0, + 228, 160, 0, 0, 255, 128, + 1, 0, 228, 128, 4, 0, + 0, 4, 0, 0, 3, 192, + 0, 0, 255, 128, 0, 0, + 228, 160, 0, 0, 228, 128, + 1, 0, 0, 2, 0, 0, + 12, 192, 0, 0, 228, 128, + 255, 255, 0, 0, 83, 72, + 68, 82, 148, 2, 0, 0, + 64, 0, 1, 0, 165, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 12, 0, 0, 0, + 95, 0, 0, 3, 50, 16, + 16, 0, 0, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 50, 32, 16, 0, + 1, 0, 0, 0, 101, 0, + 0, 3, 114, 32, 16, 0, + 2, 0, 0, 0, 104, 0, + 0, 2, 4, 0, 0, 0, + 50, 0, 0, 11, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 0, 0, + 0, 0, 230, 138, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 70, 128, 32, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 56, 0, 0, 8, + 242, 0, 16, 0, 1, 0, + 0, 0, 86, 5, 16, 0, + 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, - 12, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 0, 0, 0, 0, 103, 0, - 0, 4, 242, 32, 16, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 101, 0, 0, 3, - 50, 32, 16, 0, 1, 0, - 0, 0, 101, 0, 0, 3, - 114, 32, 16, 0, 2, 0, - 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 50, 0, + 0, 10, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 0, 0, 0, 8, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 14, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 246, 15, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 130, 0, 16, 0, 1, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 9, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 7, 114, 0, 16, 0, + 1, 0, 0, 0, 246, 15, + 16, 0, 2, 0, 0, 0, + 70, 2, 16, 0, 2, 0, + 0, 0, 56, 0, 0, 8, + 242, 0, 16, 0, 3, 0, + 0, 0, 86, 5, 16, 0, + 1, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 50, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 6, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 10, + 242, 0, 16, 0, 3, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 166, 10, 16, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 50, 0, 0, 10, 242, 32, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 7, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 14, 16, 0, 3, 0, 0, 0, 50, 0, - 0, 11, 50, 0, 16, 0, - 0, 0, 0, 0, 70, 16, + 0, 11, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, 16, 0, 0, 0, 0, 0, 230, 138, 32, 0, 0, 0, - 0, 0, 10, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 70, 128, 32, 0, 0, 0, - 0, 0, 10, 0, 0, 0, - 56, 0, 0, 8, 242, 0, - 16, 0, 1, 0, 0, 0, - 86, 5, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 50, 0, 0, 10, - 242, 0, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 1, 0, 0, 0, - 0, 0, 0, 8, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 14, 0, 0, 7, - 114, 0, 16, 0, 0, 0, - 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 246, 15, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 242, 0, - 16, 0, 1, 0, 0, 0, - 70, 14, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 128, - 65, 0, 0, 0, 0, 0, - 0, 0, 8, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 9, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, @@ -2887,210 +2473,172 @@ const BYTE LayerQuadMask3DVS[] = 70, 0, 16, 0, 0, 0, 0, 0, 230, 138, 32, 0, 0, 0, 0, 0, 11, 0, - 0, 0, 56, 0, 0, 7, - 114, 0, 16, 0, 1, 0, - 0, 0, 246, 15, 16, 0, - 1, 0, 0, 0, 70, 2, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 114, 32, 16, 0, + 2, 0, 0, 0, 246, 15, 16, 0, 1, 0, 0, 0, - 56, 0, 0, 8, 242, 0, - 16, 0, 2, 0, 0, 0, - 86, 5, 16, 0, 1, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 5, 0, - 0, 0, 50, 0, 0, 10, - 242, 0, 16, 0, 2, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 4, 0, - 0, 0, 6, 0, 16, 0, - 1, 0, 0, 0, 70, 14, - 16, 0, 2, 0, 0, 0, - 50, 0, 0, 10, 242, 0, - 16, 0, 2, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 6, 0, 0, 0, - 166, 10, 16, 0, 1, 0, - 0, 0, 70, 14, 16, 0, - 2, 0, 0, 0, 50, 0, - 0, 10, 242, 32, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 7, 0, 0, 0, 246, 15, - 16, 0, 1, 0, 0, 0, - 70, 14, 16, 0, 2, 0, - 0, 0, 50, 0, 0, 11, - 50, 32, 16, 0, 1, 0, - 0, 0, 70, 16, 16, 0, - 0, 0, 0, 0, 230, 138, - 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 70, 128, - 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 54, 0, - 0, 5, 66, 0, 16, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 128, 63, - 56, 0, 0, 7, 114, 32, - 16, 0, 2, 0, 0, 0, - 246, 15, 16, 0, 0, 0, - 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 116, 0, 0, 0, 17, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 4, 0, - 0, 0, 15, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 82, 68, 69, 70, 104, 2, - 0, 0, 1, 0, 0, 0, - 72, 0, 0, 0, 1, 0, - 0, 0, 28, 0, 0, 0, - 0, 4, 254, 255, 0, 1, - 0, 0, 52, 2, 0, 0, - 60, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 18, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 36, 71, 108, 111, - 98, 97, 108, 115, 0, 171, - 171, 171, 60, 0, 0, 0, - 10, 0, 0, 0, 96, 0, - 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 80, 1, 0, 0, - 0, 0, 0, 0, 64, 0, - 0, 0, 2, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 112, 1, 0, 0, - 64, 0, 0, 0, 64, 0, - 0, 0, 2, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 124, 1, 0, 0, - 128, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 144, 1, 0, 0, 0, 0, - 0, 0, 160, 1, 0, 0, - 144, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 192, 1, 0, 0, - 160, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 203, 1, 0, 0, - 176, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 213, 1, 0, 0, - 192, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 232, 1, 0, 0, - 0, 1, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 144, 1, 0, 0, 0, 0, - 0, 0, 244, 1, 0, 0, - 16, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, - 4, 2, 0, 0, 0, 0, - 0, 0, 20, 2, 0, 0, - 32, 1, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 36, 2, 0, 0, 0, 0, - 0, 0, 109, 76, 97, 121, - 101, 114, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 3, 0, 3, 0, 4, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 80, - 114, 111, 106, 101, 99, 116, - 105, 111, 110, 0, 118, 82, - 101, 110, 100, 101, 114, 84, - 97, 114, 103, 101, 116, 79, - 102, 102, 115, 101, 116, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 68, + 69, 70, 104, 2, 0, 0, + 1, 0, 0, 0, 72, 0, + 0, 0, 1, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 254, 255, 0, 1, 0, 0, + 52, 2, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 36, 71, 108, 111, 98, 97, + 108, 115, 0, 171, 171, 171, + 60, 0, 0, 0, 10, 0, + 0, 0, 96, 0, 0, 0, + 48, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 80, 1, 0, 0, 0, 0, + 0, 0, 64, 0, 0, 0, + 2, 0, 0, 0, 96, 1, + 0, 0, 0, 0, 0, 0, + 112, 1, 0, 0, 64, 0, + 0, 0, 64, 0, 0, 0, + 2, 0, 0, 0, 96, 1, + 0, 0, 0, 0, 0, 0, + 124, 1, 0, 0, 128, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 160, 1, 0, 0, 144, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 1, + 0, 0, 0, 0, 0, 0, + 192, 1, 0, 0, 160, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 1, + 0, 0, 0, 0, 0, 0, + 203, 1, 0, 0, 176, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 1, + 0, 0, 0, 0, 0, 0, + 213, 1, 0, 0, 192, 0, + 0, 0, 64, 0, 0, 0, + 0, 0, 0, 0, 96, 1, + 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 0, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 244, 1, 0, 0, 16, 1, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 4, 2, + 0, 0, 0, 0, 0, 0, + 20, 2, 0, 0, 32, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 36, 2, + 0, 0, 0, 0, 0, 0, + 109, 76, 97, 121, 101, 114, + 84, 114, 97, 110, 115, 102, + 111, 114, 109, 0, 3, 0, + 3, 0, 4, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 80, 114, 111, + 106, 101, 99, 116, 105, 111, + 110, 0, 118, 82, 101, 110, + 100, 101, 114, 84, 97, 114, + 103, 101, 116, 79, 102, 102, + 115, 101, 116, 0, 1, 0, + 3, 0, 1, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 118, 84, 101, 120, + 116, 117, 114, 101, 67, 111, + 111, 114, 100, 115, 0, 171, 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 118, 84, - 101, 120, 116, 117, 114, 101, - 67, 111, 111, 114, 100, 115, - 0, 171, 1, 0, 3, 0, + 0, 0, 0, 0, 118, 76, + 97, 121, 101, 114, 81, 117, + 97, 100, 0, 118, 77, 97, + 115, 107, 81, 117, 97, 100, + 0, 109, 66, 97, 99, 107, + 100, 114, 111, 112, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 102, 76, 97, 121, + 101, 114, 67, 111, 108, 111, + 114, 0, 102, 76, 97, 121, + 101, 114, 79, 112, 97, 99, + 105, 116, 121, 0, 171, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 105, 66, + 108, 101, 110, 100, 67, 111, + 110, 102, 105, 103, 0, 171, + 171, 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 76, 97, 121, 101, 114, - 81, 117, 97, 100, 0, 118, - 77, 97, 115, 107, 81, 117, - 97, 100, 0, 109, 66, 97, - 99, 107, 100, 114, 111, 112, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 102, 76, - 97, 121, 101, 114, 67, 111, - 108, 111, 114, 0, 102, 76, - 97, 121, 101, 114, 79, 112, - 97, 99, 105, 116, 121, 0, - 171, 171, 0, 0, 3, 0, - 1, 0, 1, 0, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 105, 66, 108, 101, 110, 100, - 67, 111, 110, 102, 105, 103, - 0, 171, 171, 171, 1, 0, - 19, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 77, 105, 99, 114, - 111, 115, 111, 102, 116, 32, - 40, 82, 41, 32, 72, 76, - 83, 76, 32, 83, 104, 97, - 100, 101, 114, 32, 67, 111, - 109, 112, 105, 108, 101, 114, - 32, 54, 46, 51, 46, 57, - 54, 48, 48, 46, 49, 54, - 51, 56, 52, 0, 171, 171, - 73, 83, 71, 78, 44, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 3, + 0, 0, 80, 79, 83, 73, + 84, 73, 79, 78, 0, 171, + 171, 171, 79, 83, 71, 78, + 104, 0, 0, 0, 3, 0, + 0, 0, 8, 0, 0, 0, + 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 32, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 92, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 0, 0, 80, 79, - 83, 73, 84, 73, 79, 78, - 0, 171, 171, 171, 79, 83, - 71, 78, 104, 0, 0, 0, - 3, 0, 0, 0, 8, 0, - 0, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 92, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 3, 12, - 0, 0, 92, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 2, 0, 0, 0, 7, 8, - 0, 0, 83, 86, 95, 80, - 111, 115, 105, 116, 105, 111, - 110, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171 + 3, 0, 0, 0, 2, 0, + 0, 0, 7, 8, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 171, 171, 171 }; -ShaderBytes sLayerQuadMask3DVS = { LayerQuadMask3DVS, sizeof(LayerQuadMask3DVS) }; +ShaderBytes sLayerQuadMaskVS = { LayerQuadMaskVS, sizeof(LayerQuadMaskVS) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -3114,11 +2662,11 @@ ShaderBytes sLayerQuadMask3DVS = { LayerQuadMask3DVS, sizeof(LayerQuadMask3DVS) // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tMask texture float4 2d 5 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tMask texture float4 2d t5 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -3128,7 +2676,7 @@ ShaderBytes sLayerQuadMask3DVS = { LayerQuadMask3DVS, sizeof(LayerQuadMask3DVS) // -------------------- ----- ------ -------- -------- ------- ------ // SV_Position 0 xyzw 0 POS float // TEXCOORD 0 xy 1 NONE float -// TEXCOORD 1 zw 1 NONE float zw +// TEXCOORD 1 xyz 2 NONE float xyz // // // Output signature: @@ -3155,42 +2703,44 @@ ShaderBytes sLayerQuadMask3DVS = { LayerQuadMask3DVS, sizeof(LayerQuadMask3DVS) // Level9 shader bytecode: // ps_2_x - dcl t0 + dcl t1.xyz dcl_2d s0 - mov r0.xy, t0.wzzw + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 texld r0, r0, s0 mul r0, r0.x, c0 mov oC0, r0 -// approximately 4 instruction slots used (1 texture, 3 arithmetic) +// approximately 5 instruction slots used (1 texture, 4 arithmetic) ps_4_0 -dcl_constantbuffer cb0[1], immediateIndexed +dcl_constantbuffer CB0[1], immediateIndexed dcl_sampler s0, mode_default dcl_resource_texture2d (float,float,float,float) t5 -dcl_input_ps linear v1.zw +dcl_input_ps linear v2.xyz dcl_output o0.xyzw dcl_temps 1 -sample r0.xyzw, v1.zwzz, t5.xyzw, s0 +div r0.xy, v2.xyxx, v2.zzzz +sample r0.xyzw, r0.xyxx, t5.xyzw, s0 mul o0.xyzw, r0.xxxx, cb0[0].xyzw ret -// Approximately 3 instruction slots used +// Approximately 4 instruction slots used #endif const BYTE SolidColorShaderMask[] = { - 68, 88, 66, 67, 179, 163, - 177, 178, 96, 7, 246, 20, - 94, 198, 166, 18, 116, 245, - 163, 94, 1, 0, 0, 0, - 76, 5, 0, 0, 6, 0, + 68, 88, 66, 67, 136, 34, + 160, 50, 38, 225, 198, 78, + 252, 58, 191, 192, 204, 38, + 60, 224, 1, 0, 0, 0, + 120, 5, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, - 204, 0, 0, 0, 112, 1, - 0, 0, 236, 1, 0, 0, - 168, 4, 0, 0, 24, 5, + 220, 0, 0, 0, 156, 1, + 0, 0, 24, 2, 0, 0, + 212, 4, 0, 0, 68, 5, 0, 0, 65, 111, 110, 57, - 140, 0, 0, 0, 140, 0, + 156, 0, 0, 0, 156, 0, 0, 0, 0, 2, 255, 255, - 88, 0, 0, 0, 52, 0, + 104, 0, 0, 0, 52, 0, 0, 0, 1, 0, 40, 0, 0, 0, 52, 0, 0, 0, 52, 0, 1, 0, 36, 0, @@ -3199,216 +2749,224 @@ const BYTE SolidColorShaderMask[] = 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, 0, 2, 0, 0, - 0, 128, 0, 0, 15, 176, + 0, 128, 1, 0, 7, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, - 1, 0, 0, 2, 0, 0, - 3, 128, 0, 0, 235, 176, - 66, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 228, 128, - 0, 8, 228, 160, 5, 0, + 6, 0, 0, 2, 0, 0, + 8, 128, 1, 0, 170, 176, + 5, 0, 0, 3, 0, 0, + 3, 128, 0, 0, 255, 128, + 1, 0, 228, 176, 66, 0, 0, 3, 0, 0, 15, 128, - 0, 0, 0, 128, 0, 0, - 228, 160, 1, 0, 0, 2, - 0, 8, 15, 128, 0, 0, - 228, 128, 255, 255, 0, 0, - 83, 72, 68, 82, 156, 0, - 0, 0, 64, 0, 0, 0, - 39, 0, 0, 0, 89, 0, - 0, 4, 70, 142, 32, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 90, 0, 0, 3, - 0, 96, 16, 0, 0, 0, - 0, 0, 88, 24, 0, 4, - 0, 112, 16, 0, 5, 0, - 0, 0, 85, 85, 0, 0, - 98, 16, 0, 3, 194, 16, - 16, 0, 1, 0, 0, 0, - 101, 0, 0, 3, 242, 32, + 0, 0, 228, 128, 0, 8, + 228, 160, 5, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 0, 128, 0, 0, 228, 160, + 1, 0, 0, 2, 0, 8, + 15, 128, 0, 0, 228, 128, + 255, 255, 0, 0, 83, 72, + 68, 82, 184, 0, 0, 0, + 64, 0, 0, 0, 46, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, - 104, 0, 0, 2, 1, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 0, 0, - 0, 0, 230, 26, 16, 0, - 1, 0, 0, 0, 70, 126, + 88, 24, 0, 4, 0, 112, 16, 0, 5, 0, 0, 0, - 0, 96, 16, 0, 0, 0, - 0, 0, 56, 0, 0, 8, - 242, 32, 16, 0, 0, 0, - 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 116, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 2, 0, - 0, 0, 1, 0, 0, 0, + 85, 85, 0, 0, 98, 16, + 0, 3, 114, 16, 16, 0, + 2, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 14, 0, 0, 7, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 2, 0, + 0, 0, 166, 26, 16, 0, + 2, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 70, 126, 16, 0, 5, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 242, 32, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 116, 0, 0, 0, + 4, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 82, 68, 69, 70, + 180, 2, 0, 0, 1, 0, + 0, 0, 148, 0, 0, 0, + 3, 0, 0, 0, 28, 0, + 0, 0, 0, 4, 255, 255, + 0, 1, 0, 0, 128, 2, + 0, 0, 124, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 133, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 5, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 115, 83, 97, 109, + 112, 108, 101, 114, 0, 116, + 77, 97, 115, 107, 0, 36, + 71, 108, 111, 98, 97, 108, + 115, 0, 139, 0, 0, 0, + 10, 0, 0, 0, 172, 0, + 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 156, 1, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 2, 0, 0, 0, + 168, 1, 0, 0, 0, 0, + 0, 0, 184, 1, 0, 0, + 16, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 200, 1, 0, 0, 0, 0, + 0, 0, 216, 1, 0, 0, + 32, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 0, 0, + 0, 0, 248, 1, 0, 0, + 48, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 0, 0, 0, 0, + 0, 0, 24, 2, 0, 0, + 112, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 8, 2, 0, 0, 0, 0, + 0, 0, 36, 2, 0, 0, + 176, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 168, 1, 0, 0, 0, 0, + 0, 0, 56, 2, 0, 0, + 192, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 72, 2, 0, 0, 0, 0, + 0, 0, 88, 2, 0, 0, + 208, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 72, 2, 0, 0, 0, 0, + 0, 0, 99, 2, 0, 0, + 224, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 82, 68, 69, 70, 180, 2, - 0, 0, 1, 0, 0, 0, - 148, 0, 0, 0, 3, 0, - 0, 0, 28, 0, 0, 0, - 0, 4, 255, 255, 0, 1, - 0, 0, 128, 2, 0, 0, - 124, 0, 0, 0, 3, 0, + 72, 2, 0, 0, 0, 0, + 0, 0, 109, 2, 0, 0, + 240, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 133, 0, 0, 0, - 2, 0, 0, 0, 5, 0, - 0, 0, 4, 0, 0, 0, - 255, 255, 255, 255, 5, 0, - 0, 0, 1, 0, 0, 0, - 13, 0, 0, 0, 139, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 115, 83, 97, 109, 112, 108, - 101, 114, 0, 116, 77, 97, - 115, 107, 0, 36, 71, 108, - 111, 98, 97, 108, 115, 0, - 139, 0, 0, 0, 10, 0, - 0, 0, 172, 0, 0, 0, - 48, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 156, 1, 0, 0, 0, 0, - 0, 0, 16, 0, 0, 0, - 2, 0, 0, 0, 168, 1, - 0, 0, 0, 0, 0, 0, - 184, 1, 0, 0, 16, 0, - 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 200, 1, - 0, 0, 0, 0, 0, 0, - 216, 1, 0, 0, 32, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 232, 1, - 0, 0, 0, 0, 0, 0, - 248, 1, 0, 0, 48, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 8, 2, - 0, 0, 0, 0, 0, 0, - 24, 2, 0, 0, 112, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 8, 2, - 0, 0, 0, 0, 0, 0, - 36, 2, 0, 0, 176, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 168, 1, - 0, 0, 0, 0, 0, 0, - 56, 2, 0, 0, 192, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 72, 2, - 0, 0, 0, 0, 0, 0, - 88, 2, 0, 0, 208, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 72, 2, - 0, 0, 0, 0, 0, 0, - 99, 2, 0, 0, 224, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 72, 2, - 0, 0, 0, 0, 0, 0, - 109, 2, 0, 0, 240, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 8, 2, + 8, 2, 0, 0, 0, 0, + 0, 0, 102, 76, 97, 121, + 101, 114, 67, 111, 108, 111, + 114, 0, 1, 0, 3, 0, + 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 76, 97, 121, 101, 114, - 67, 111, 108, 111, 114, 0, + 79, 112, 97, 99, 105, 116, + 121, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 105, 66, 108, 101, + 110, 100, 67, 111, 110, 102, + 105, 103, 0, 171, 171, 171, + 1, 0, 19, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 76, + 97, 121, 101, 114, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 3, 0, 3, 0, + 4, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 80, 114, 111, 106, 101, + 99, 116, 105, 111, 110, 0, + 118, 82, 101, 110, 100, 101, + 114, 84, 97, 114, 103, 101, + 116, 79, 102, 102, 115, 101, + 116, 0, 118, 84, 101, 120, + 116, 117, 114, 101, 67, 111, + 111, 114, 100, 115, 0, 171, 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 102, 76, - 97, 121, 101, 114, 79, 112, - 97, 99, 105, 116, 121, 0, - 171, 171, 0, 0, 3, 0, - 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 118, 76, + 97, 121, 101, 114, 81, 117, + 97, 100, 0, 118, 77, 97, + 115, 107, 81, 117, 97, 100, + 0, 109, 66, 97, 99, 107, + 100, 114, 111, 112, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, + 73, 83, 71, 78, 104, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, - 105, 66, 108, 101, 110, 100, - 67, 111, 110, 102, 105, 103, - 0, 171, 171, 171, 1, 0, - 19, 0, 1, 0, 4, 0, + 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 109, 76, 97, 121, - 101, 114, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 3, 0, 3, 0, 4, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 80, - 114, 111, 106, 101, 99, 116, - 105, 111, 110, 0, 118, 82, - 101, 110, 100, 101, 114, 84, - 97, 114, 103, 101, 116, 79, - 102, 102, 115, 101, 116, 0, - 118, 84, 101, 120, 116, 117, - 114, 101, 67, 111, 111, 114, - 100, 115, 0, 171, 1, 0, - 3, 0, 1, 0, 4, 0, + 15, 0, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 92, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 118, 76, 97, 121, - 101, 114, 81, 117, 97, 100, - 0, 118, 77, 97, 115, 107, - 81, 117, 97, 100, 0, 109, - 66, 97, 99, 107, 100, 114, - 111, 112, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 77, 105, 99, 114, 111, 115, - 111, 102, 116, 32, 40, 82, - 41, 32, 72, 76, 83, 76, - 32, 83, 104, 97, 100, 101, - 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, - 71, 78, 104, 0, 0, 0, - 3, 0, 0, 0, 8, 0, - 0, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, - 0, 0, 92, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 3, 0, - 0, 0, 92, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 12, 12, - 0, 0, 83, 86, 95, 80, - 111, 115, 105, 116, 105, 111, - 110, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171, 79, 83, 71, 78, - 44, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 83, 86, 95, 84, 97, 114, - 103, 101, 116, 0, 171, 171 + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171 }; ShaderBytes sSolidColorShaderMask = { SolidColorShaderMask, sizeof(SolidColorShaderMask) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -3432,735 +2990,12 @@ ShaderBytes sSolidColorShaderMask = { SolidColorShaderMask, sizeof(SolidColorSha // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tRGB texture float4 2d 0 1 -// tMask texture float4 2d 5 1 -// $Globals cbuffer NA NA 0 1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Position 0 xyzw 0 POS float -// TEXCOORD 0 xy 1 NONE float xy -// TEXCOORD 1 zw 1 NONE float zw -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Target 0 xyzw 0 TARGET float xyzw -// -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c0 cb0 1 1 ( FLT, FLT, FLT, FLT) -// -// -// Sampler/Resource to DX9 shader sampler mappings: -// -// Target Sampler Source Sampler Source Resource -// -------------- --------------- ---------------- -// s0 s0 t0 -// s1 s0 t5 -// -// -// Level9 shader bytecode: -// - ps_2_x - dcl t0 - dcl_2d s0 - dcl_2d s1 - mov r0.xy, t0.wzzw - texld r1, t0, s0 - texld r0, r0, s1 - mul r1.xyz, r1, c0.x - mov r1.w, c0.x - mul r0, r0.x, r1 - mov oC0, r0 - -// approximately 7 instruction slots used (2 texture, 5 arithmetic) -ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed -dcl_sampler s0, mode_default -dcl_resource_texture2d (float,float,float,float) t0 -dcl_resource_texture2d (float,float,float,float) t5 -dcl_input_ps linear v1.xy -dcl_input_ps linear v1.zw -dcl_output o0.xyzw -dcl_temps 2 -sample r0.xyzw, v1.xyxx, t0.xyzw, s0 -mul r0.xyz, r0.xyzx, cb0[1].xxxx -sample r1.xyzw, v1.zwzz, t5.xyzw, s0 -mov r0.w, cb0[1].x -mul o0.xyzw, r0.xyzw, r1.xxxx -ret -// Approximately 6 instruction slots used -#endif - -const BYTE RGBShaderMask[] = -{ - 68, 88, 66, 67, 194, 201, - 10, 158, 40, 223, 107, 77, - 239, 65, 209, 32, 8, 192, - 127, 244, 1, 0, 0, 0, - 36, 6, 0, 0, 6, 0, - 0, 0, 56, 0, 0, 0, - 8, 1, 0, 0, 32, 2, - 0, 0, 156, 2, 0, 0, - 128, 5, 0, 0, 240, 5, - 0, 0, 65, 111, 110, 57, - 200, 0, 0, 0, 200, 0, - 0, 0, 0, 2, 255, 255, - 144, 0, 0, 0, 56, 0, - 0, 0, 1, 0, 44, 0, - 0, 0, 56, 0, 0, 0, - 56, 0, 2, 0, 36, 0, - 0, 0, 56, 0, 0, 0, - 0, 0, 5, 0, 1, 0, - 0, 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 1, 2, 255, 255, 31, 0, - 0, 2, 0, 0, 0, 128, - 0, 0, 15, 176, 31, 0, - 0, 2, 0, 0, 0, 144, - 0, 8, 15, 160, 31, 0, - 0, 2, 0, 0, 0, 144, - 1, 8, 15, 160, 1, 0, - 0, 2, 0, 0, 3, 128, - 0, 0, 235, 176, 66, 0, - 0, 3, 1, 0, 15, 128, - 0, 0, 228, 176, 0, 8, - 228, 160, 66, 0, 0, 3, - 0, 0, 15, 128, 0, 0, - 228, 128, 1, 8, 228, 160, - 5, 0, 0, 3, 1, 0, - 7, 128, 1, 0, 228, 128, - 0, 0, 0, 160, 1, 0, - 0, 2, 1, 0, 8, 128, - 0, 0, 0, 160, 5, 0, - 0, 3, 0, 0, 15, 128, - 0, 0, 0, 128, 1, 0, - 228, 128, 1, 0, 0, 2, - 0, 8, 15, 128, 0, 0, - 228, 128, 255, 255, 0, 0, - 83, 72, 68, 82, 16, 1, - 0, 0, 64, 0, 0, 0, - 68, 0, 0, 0, 89, 0, - 0, 4, 70, 142, 32, 0, - 0, 0, 0, 0, 2, 0, - 0, 0, 90, 0, 0, 3, - 0, 96, 16, 0, 0, 0, - 0, 0, 88, 24, 0, 4, - 0, 112, 16, 0, 0, 0, - 0, 0, 85, 85, 0, 0, - 88, 24, 0, 4, 0, 112, - 16, 0, 5, 0, 0, 0, - 85, 85, 0, 0, 98, 16, - 0, 3, 50, 16, 16, 0, - 1, 0, 0, 0, 98, 16, - 0, 3, 194, 16, 16, 0, - 1, 0, 0, 0, 101, 0, - 0, 3, 242, 32, 16, 0, - 0, 0, 0, 0, 104, 0, - 0, 2, 2, 0, 0, 0, - 69, 0, 0, 9, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 16, 16, 0, 1, 0, - 0, 0, 70, 126, 16, 0, - 0, 0, 0, 0, 0, 96, - 16, 0, 0, 0, 0, 0, - 56, 0, 0, 8, 114, 0, - 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, - 0, 0, 6, 128, 32, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 1, 0, - 0, 0, 230, 26, 16, 0, - 1, 0, 0, 0, 70, 126, - 16, 0, 5, 0, 0, 0, - 0, 96, 16, 0, 0, 0, - 0, 0, 54, 0, 0, 6, - 130, 0, 16, 0, 0, 0, - 0, 0, 10, 128, 32, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 56, 0, 0, 7, - 242, 32, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 0, 0, 0, 0, 6, 0, - 16, 0, 1, 0, 0, 0, - 62, 0, 0, 1, 83, 84, - 65, 84, 116, 0, 0, 0, - 6, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 82, 68, 69, 70, - 220, 2, 0, 0, 1, 0, - 0, 0, 188, 0, 0, 0, - 4, 0, 0, 0, 28, 0, - 0, 0, 0, 4, 255, 255, - 0, 1, 0, 0, 168, 2, - 0, 0, 156, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 165, 0, - 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 0, 0, 0, 0, 1, 0, - 0, 0, 13, 0, 0, 0, - 170, 0, 0, 0, 2, 0, - 0, 0, 5, 0, 0, 0, - 4, 0, 0, 0, 255, 255, - 255, 255, 5, 0, 0, 0, - 1, 0, 0, 0, 13, 0, - 0, 0, 176, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 115, 83, - 97, 109, 112, 108, 101, 114, - 0, 116, 82, 71, 66, 0, - 116, 77, 97, 115, 107, 0, - 36, 71, 108, 111, 98, 97, - 108, 115, 0, 171, 171, 171, - 176, 0, 0, 0, 10, 0, - 0, 0, 212, 0, 0, 0, - 48, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 196, 1, 0, 0, 0, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 208, 1, - 0, 0, 0, 0, 0, 0, - 224, 1, 0, 0, 16, 0, - 0, 0, 4, 0, 0, 0, - 2, 0, 0, 0, 240, 1, - 0, 0, 0, 0, 0, 0, - 0, 2, 0, 0, 32, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 16, 2, - 0, 0, 0, 0, 0, 0, - 32, 2, 0, 0, 48, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 48, 2, - 0, 0, 0, 0, 0, 0, - 64, 2, 0, 0, 112, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 48, 2, - 0, 0, 0, 0, 0, 0, - 76, 2, 0, 0, 176, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 208, 1, - 0, 0, 0, 0, 0, 0, - 96, 2, 0, 0, 192, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 112, 2, - 0, 0, 0, 0, 0, 0, - 128, 2, 0, 0, 208, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 112, 2, - 0, 0, 0, 0, 0, 0, - 139, 2, 0, 0, 224, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 112, 2, - 0, 0, 0, 0, 0, 0, - 149, 2, 0, 0, 240, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 48, 2, - 0, 0, 0, 0, 0, 0, - 102, 76, 97, 121, 101, 114, - 67, 111, 108, 111, 114, 0, - 1, 0, 3, 0, 1, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 102, 76, - 97, 121, 101, 114, 79, 112, - 97, 99, 105, 116, 121, 0, - 171, 171, 0, 0, 3, 0, - 1, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 105, 66, 108, 101, 110, 100, - 67, 111, 110, 102, 105, 103, - 0, 171, 171, 171, 1, 0, - 19, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 109, 76, 97, 121, - 101, 114, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 3, 0, 3, 0, 4, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 80, - 114, 111, 106, 101, 99, 116, - 105, 111, 110, 0, 118, 82, - 101, 110, 100, 101, 114, 84, - 97, 114, 103, 101, 116, 79, - 102, 102, 115, 101, 116, 0, - 118, 84, 101, 120, 116, 117, - 114, 101, 67, 111, 111, 114, - 100, 115, 0, 171, 1, 0, - 3, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 118, 76, 97, 121, - 101, 114, 81, 117, 97, 100, - 0, 118, 77, 97, 115, 107, - 81, 117, 97, 100, 0, 109, - 66, 97, 99, 107, 100, 114, - 111, 112, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 77, 105, 99, 114, 111, 115, - 111, 102, 116, 32, 40, 82, - 41, 32, 72, 76, 83, 76, - 32, 83, 104, 97, 100, 101, - 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, - 71, 78, 104, 0, 0, 0, - 3, 0, 0, 0, 8, 0, - 0, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 92, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 3, 3, - 0, 0, 92, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 12, 12, - 0, 0, 83, 86, 95, 80, - 111, 115, 105, 116, 105, 111, - 110, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171, 79, 83, 71, 78, - 44, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 83, 86, 95, 84, 97, 114, - 103, 101, 116, 0, 171, 171 -}; -ShaderBytes sRGBShaderMask = { RGBShaderMask, sizeof(RGBShaderMask) }; -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 -// -// -// Buffer Definitions: -// -// cbuffer $Globals -// { -// -// float4 fLayerColor; // Offset: 0 Size: 16 [unused] -// float fLayerOpacity; // Offset: 16 Size: 4 -// uint4 iBlendConfig; // Offset: 32 Size: 16 [unused] -// float4x4 mLayerTransform; // Offset: 48 Size: 64 [unused] -// float4x4 mProjection; // Offset: 112 Size: 64 [unused] -// float4 vRenderTargetOffset; // Offset: 176 Size: 16 [unused] -// float4 vTextureCoords; // Offset: 192 Size: 16 [unused] -// float4 vLayerQuad; // Offset: 208 Size: 16 [unused] -// float4 vMaskQuad; // Offset: 224 Size: 16 [unused] -// float4x4 mBackdropTransform; // Offset: 240 Size: 64 [unused] -// -// } -// -// -// Resource Bindings: -// -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tRGB texture float4 2d 0 1 -// tMask texture float4 2d 5 1 -// $Globals cbuffer NA NA 0 1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Position 0 xyzw 0 POS float -// TEXCOORD 0 xy 1 NONE float xy -// TEXCOORD 1 zw 1 NONE float zw -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Target 0 xyzw 0 TARGET float xyzw -// -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c0 cb0 1 1 ( FLT, FLT, FLT, FLT) -// -// -// Sampler/Resource to DX9 shader sampler mappings: -// -// Target Sampler Source Sampler Source Resource -// -------------- --------------- ---------------- -// s0 s0 t0 -// s1 s0 t5 -// -// -// Level9 shader bytecode: -// - ps_2_x - dcl t0 - dcl_2d s0 - dcl_2d s1 - mov r0.xy, t0.wzzw - texld r1, t0, s0 - texld r0, r0, s1 - mul r1, r1, c0.x - mul r0, r0.x, r1 - mov oC0, r0 - -// approximately 6 instruction slots used (2 texture, 4 arithmetic) -ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed -dcl_sampler s0, mode_default -dcl_resource_texture2d (float,float,float,float) t0 -dcl_resource_texture2d (float,float,float,float) t5 -dcl_input_ps linear v1.xy -dcl_input_ps linear v1.zw -dcl_output o0.xyzw -dcl_temps 2 -sample r0.xyzw, v1.xyxx, t0.xyzw, s0 -mul r0.xyzw, r0.xyzw, cb0[1].xxxx -sample r1.xyzw, v1.zwzz, t5.xyzw, s0 -mul o0.xyzw, r0.xyzw, r1.xxxx -ret -// Approximately 5 instruction slots used -#endif - -const BYTE RGBAShaderMask[] = -{ - 68, 88, 66, 67, 4, 189, - 159, 243, 83, 63, 56, 82, - 222, 120, 117, 50, 17, 240, - 195, 36, 1, 0, 0, 0, - 0, 6, 0, 0, 6, 0, - 0, 0, 56, 0, 0, 0, - 252, 0, 0, 0, 252, 1, - 0, 0, 120, 2, 0, 0, - 92, 5, 0, 0, 204, 5, - 0, 0, 65, 111, 110, 57, - 188, 0, 0, 0, 188, 0, - 0, 0, 0, 2, 255, 255, - 132, 0, 0, 0, 56, 0, - 0, 0, 1, 0, 44, 0, - 0, 0, 56, 0, 0, 0, - 56, 0, 2, 0, 36, 0, - 0, 0, 56, 0, 0, 0, - 0, 0, 5, 0, 1, 0, - 0, 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 1, 2, 255, 255, 31, 0, - 0, 2, 0, 0, 0, 128, - 0, 0, 15, 176, 31, 0, - 0, 2, 0, 0, 0, 144, - 0, 8, 15, 160, 31, 0, - 0, 2, 0, 0, 0, 144, - 1, 8, 15, 160, 1, 0, - 0, 2, 0, 0, 3, 128, - 0, 0, 235, 176, 66, 0, - 0, 3, 1, 0, 15, 128, - 0, 0, 228, 176, 0, 8, - 228, 160, 66, 0, 0, 3, - 0, 0, 15, 128, 0, 0, - 228, 128, 1, 8, 228, 160, - 5, 0, 0, 3, 1, 0, - 15, 128, 1, 0, 228, 128, - 0, 0, 0, 160, 5, 0, - 0, 3, 0, 0, 15, 128, - 0, 0, 0, 128, 1, 0, - 228, 128, 1, 0, 0, 2, - 0, 8, 15, 128, 0, 0, - 228, 128, 255, 255, 0, 0, - 83, 72, 68, 82, 248, 0, - 0, 0, 64, 0, 0, 0, - 62, 0, 0, 0, 89, 0, - 0, 4, 70, 142, 32, 0, - 0, 0, 0, 0, 2, 0, - 0, 0, 90, 0, 0, 3, - 0, 96, 16, 0, 0, 0, - 0, 0, 88, 24, 0, 4, - 0, 112, 16, 0, 0, 0, - 0, 0, 85, 85, 0, 0, - 88, 24, 0, 4, 0, 112, - 16, 0, 5, 0, 0, 0, - 85, 85, 0, 0, 98, 16, - 0, 3, 50, 16, 16, 0, - 1, 0, 0, 0, 98, 16, - 0, 3, 194, 16, 16, 0, - 1, 0, 0, 0, 101, 0, - 0, 3, 242, 32, 16, 0, - 0, 0, 0, 0, 104, 0, - 0, 2, 2, 0, 0, 0, - 69, 0, 0, 9, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 16, 16, 0, 1, 0, - 0, 0, 70, 126, 16, 0, - 0, 0, 0, 0, 0, 96, - 16, 0, 0, 0, 0, 0, - 56, 0, 0, 8, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 0, 0, - 0, 0, 6, 128, 32, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 1, 0, - 0, 0, 230, 26, 16, 0, - 1, 0, 0, 0, 70, 126, - 16, 0, 5, 0, 0, 0, - 0, 96, 16, 0, 0, 0, - 0, 0, 56, 0, 0, 7, - 242, 32, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 0, 0, 0, 0, 6, 0, - 16, 0, 1, 0, 0, 0, - 62, 0, 0, 1, 83, 84, - 65, 84, 116, 0, 0, 0, - 5, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 82, 68, 69, 70, - 220, 2, 0, 0, 1, 0, - 0, 0, 188, 0, 0, 0, - 4, 0, 0, 0, 28, 0, - 0, 0, 0, 4, 255, 255, - 0, 1, 0, 0, 168, 2, - 0, 0, 156, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 165, 0, - 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 0, 0, 0, 0, 1, 0, - 0, 0, 13, 0, 0, 0, - 170, 0, 0, 0, 2, 0, - 0, 0, 5, 0, 0, 0, - 4, 0, 0, 0, 255, 255, - 255, 255, 5, 0, 0, 0, - 1, 0, 0, 0, 13, 0, - 0, 0, 176, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 115, 83, - 97, 109, 112, 108, 101, 114, - 0, 116, 82, 71, 66, 0, - 116, 77, 97, 115, 107, 0, - 36, 71, 108, 111, 98, 97, - 108, 115, 0, 171, 171, 171, - 176, 0, 0, 0, 10, 0, - 0, 0, 212, 0, 0, 0, - 48, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 196, 1, 0, 0, 0, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 208, 1, - 0, 0, 0, 0, 0, 0, - 224, 1, 0, 0, 16, 0, - 0, 0, 4, 0, 0, 0, - 2, 0, 0, 0, 240, 1, - 0, 0, 0, 0, 0, 0, - 0, 2, 0, 0, 32, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 16, 2, - 0, 0, 0, 0, 0, 0, - 32, 2, 0, 0, 48, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 48, 2, - 0, 0, 0, 0, 0, 0, - 64, 2, 0, 0, 112, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 48, 2, - 0, 0, 0, 0, 0, 0, - 76, 2, 0, 0, 176, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 208, 1, - 0, 0, 0, 0, 0, 0, - 96, 2, 0, 0, 192, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 112, 2, - 0, 0, 0, 0, 0, 0, - 128, 2, 0, 0, 208, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 112, 2, - 0, 0, 0, 0, 0, 0, - 139, 2, 0, 0, 224, 0, - 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 112, 2, - 0, 0, 0, 0, 0, 0, - 149, 2, 0, 0, 240, 0, - 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 48, 2, - 0, 0, 0, 0, 0, 0, - 102, 76, 97, 121, 101, 114, - 67, 111, 108, 111, 114, 0, - 1, 0, 3, 0, 1, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 102, 76, - 97, 121, 101, 114, 79, 112, - 97, 99, 105, 116, 121, 0, - 171, 171, 0, 0, 3, 0, - 1, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 105, 66, 108, 101, 110, 100, - 67, 111, 110, 102, 105, 103, - 0, 171, 171, 171, 1, 0, - 19, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 109, 76, 97, 121, - 101, 114, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 3, 0, 3, 0, 4, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 80, - 114, 111, 106, 101, 99, 116, - 105, 111, 110, 0, 118, 82, - 101, 110, 100, 101, 114, 84, - 97, 114, 103, 101, 116, 79, - 102, 102, 115, 101, 116, 0, - 118, 84, 101, 120, 116, 117, - 114, 101, 67, 111, 111, 114, - 100, 115, 0, 171, 1, 0, - 3, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 118, 76, 97, 121, - 101, 114, 81, 117, 97, 100, - 0, 118, 77, 97, 115, 107, - 81, 117, 97, 100, 0, 109, - 66, 97, 99, 107, 100, 114, - 111, 112, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 77, 105, 99, 114, 111, 115, - 111, 102, 116, 32, 40, 82, - 41, 32, 72, 76, 83, 76, - 32, 83, 104, 97, 100, 101, - 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, - 71, 78, 104, 0, 0, 0, - 3, 0, 0, 0, 8, 0, - 0, 0, 80, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 92, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 3, 3, - 0, 0, 92, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 12, 12, - 0, 0, 83, 86, 95, 80, - 111, 115, 105, 116, 105, 111, - 110, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171, 79, 83, 71, 78, - 44, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 83, 86, 95, 84, 97, 114, - 103, 101, 116, 0, 171, 171 -}; -ShaderBytes sRGBAShaderMask = { RGBAShaderMask, sizeof(RGBAShaderMask) }; -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 -// -// -// Buffer Definitions: -// -// cbuffer $Globals -// { -// -// float4 fLayerColor; // Offset: 0 Size: 16 [unused] -// float fLayerOpacity; // Offset: 16 Size: 4 -// uint4 iBlendConfig; // Offset: 32 Size: 16 [unused] -// float4x4 mLayerTransform; // Offset: 48 Size: 64 [unused] -// float4x4 mProjection; // Offset: 112 Size: 64 [unused] -// float4 vRenderTargetOffset; // Offset: 176 Size: 16 [unused] -// float4 vTextureCoords; // Offset: 192 Size: 16 [unused] -// float4 vLayerQuad; // Offset: 208 Size: 16 [unused] -// float4 vMaskQuad; // Offset: 224 Size: 16 [unused] -// float4x4 mBackdropTransform; // Offset: 240 Size: 64 [unused] -// -// } -// -// -// Resource Bindings: -// -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// LayerTextureSamplerLinear sampler NA NA 1 1 -// tRGB texture float4 2d 0 1 -// tMask texture float4 2d 5 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tRGB texture float4 2d t0 1 +// tMask texture float4 2d t5 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -4192,7 +3027,385 @@ ShaderBytes sRGBAShaderMask = { RGBAShaderMask, sizeof(RGBAShaderMask) }; // Target Sampler Source Sampler Source Resource // -------------- --------------- ---------------- // s0 s0 t0 -// s1 s1 t5 +// s1 s0 t5 +// +// +// Level9 shader bytecode: +// + ps_2_x + dcl t0.xy + dcl t1.xyz + dcl_2d s0 + dcl_2d s1 + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r1, t0, s0 + texld r0, r0, s1 + mul r1.xyz, r1, c0.x + mov r1.w, c0.x + mul r0, r0.x, r1 + mov oC0, r0 + +// approximately 8 instruction slots used (2 texture, 6 arithmetic) +ps_4_0 +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texture2d (float,float,float,float) t5 +dcl_input_ps linear v1.xy +dcl_input_ps linear v2.xyz +dcl_output o0.xyzw +dcl_temps 2 +sample r0.xyzw, v1.xyxx, t0.xyzw, s0 +mul r0.xyz, r0.xyzx, cb0[1].xxxx +div r1.xy, v2.xyxx, v2.zzzz +sample r1.xyzw, r1.xyxx, t5.xyzw, s0 +mov r0.w, cb0[1].x +mul o0.xyzw, r0.xyzw, r1.xxxx +ret +// Approximately 7 instruction slots used +#endif + +const BYTE RGBShaderMask[] = +{ + 68, 88, 66, 67, 79, 247, + 118, 147, 119, 222, 85, 19, + 212, 225, 110, 66, 228, 229, + 204, 201, 1, 0, 0, 0, + 92, 6, 0, 0, 6, 0, + 0, 0, 56, 0, 0, 0, + 36, 1, 0, 0, 88, 2, + 0, 0, 212, 2, 0, 0, + 184, 5, 0, 0, 40, 6, + 0, 0, 65, 111, 110, 57, + 228, 0, 0, 0, 228, 0, + 0, 0, 0, 2, 255, 255, + 172, 0, 0, 0, 56, 0, + 0, 0, 1, 0, 44, 0, + 0, 0, 56, 0, 0, 0, + 56, 0, 2, 0, 36, 0, + 0, 0, 56, 0, 0, 0, + 0, 0, 5, 0, 1, 0, + 0, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 1, 2, 255, 255, 31, 0, + 0, 2, 0, 0, 0, 128, + 0, 0, 3, 176, 31, 0, + 0, 2, 0, 0, 0, 128, + 1, 0, 7, 176, 31, 0, + 0, 2, 0, 0, 0, 144, + 0, 8, 15, 160, 31, 0, + 0, 2, 0, 0, 0, 144, + 1, 8, 15, 160, 6, 0, + 0, 2, 0, 0, 8, 128, + 1, 0, 170, 176, 5, 0, + 0, 3, 0, 0, 3, 128, + 0, 0, 255, 128, 1, 0, + 228, 176, 66, 0, 0, 3, + 1, 0, 15, 128, 0, 0, + 228, 176, 0, 8, 228, 160, + 66, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 128, + 1, 8, 228, 160, 5, 0, + 0, 3, 1, 0, 7, 128, + 1, 0, 228, 128, 0, 0, + 0, 160, 1, 0, 0, 2, + 1, 0, 8, 128, 0, 0, + 0, 160, 5, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 0, 128, 1, 0, 228, 128, + 1, 0, 0, 2, 0, 8, + 15, 128, 0, 0, 228, 128, + 255, 255, 0, 0, 83, 72, + 68, 82, 44, 1, 0, 0, + 64, 0, 0, 0, 75, 0, + 0, 0, 89, 0, 0, 4, + 70, 142, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 90, 0, 0, 3, 0, 96, + 16, 0, 0, 0, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 0, 0, 0, 0, + 85, 85, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 5, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 1, 0, + 0, 0, 98, 16, 0, 3, + 114, 16, 16, 0, 2, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 114, 0, 16, 0, + 0, 0, 0, 0, 70, 2, + 16, 0, 0, 0, 0, 0, + 6, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 14, 0, 0, 7, 50, 0, + 16, 0, 1, 0, 0, 0, + 70, 16, 16, 0, 2, 0, + 0, 0, 166, 26, 16, 0, + 2, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 5, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 130, 0, 16, 0, + 0, 0, 0, 0, 10, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 7, 0, 0, 0, + 2, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 68, + 69, 70, 220, 2, 0, 0, + 1, 0, 0, 0, 188, 0, + 0, 0, 4, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 168, 2, 0, 0, 156, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 165, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 170, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 5, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 176, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 115, 83, 97, 109, 112, 108, + 101, 114, 0, 116, 82, 71, + 66, 0, 116, 77, 97, 115, + 107, 0, 36, 71, 108, 111, + 98, 97, 108, 115, 0, 171, + 171, 171, 176, 0, 0, 0, + 10, 0, 0, 0, 212, 0, + 0, 0, 48, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 196, 1, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 208, 1, 0, 0, 0, 0, + 0, 0, 224, 1, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 240, 1, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, + 32, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 16, 2, 0, 0, 0, 0, + 0, 0, 32, 2, 0, 0, + 48, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 48, 2, 0, 0, 0, 0, + 0, 0, 64, 2, 0, 0, + 112, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 48, 2, 0, 0, 0, 0, + 0, 0, 76, 2, 0, 0, + 176, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 208, 1, 0, 0, 0, 0, + 0, 0, 96, 2, 0, 0, + 192, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 112, 2, 0, 0, 0, 0, + 0, 0, 128, 2, 0, 0, + 208, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 112, 2, 0, 0, 0, 0, + 0, 0, 139, 2, 0, 0, + 224, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 112, 2, 0, 0, 0, 0, + 0, 0, 149, 2, 0, 0, + 240, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 48, 2, 0, 0, 0, 0, + 0, 0, 102, 76, 97, 121, + 101, 114, 67, 111, 108, 111, + 114, 0, 1, 0, 3, 0, + 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 102, 76, 97, 121, 101, 114, + 79, 112, 97, 99, 105, 116, + 121, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 105, 66, 108, 101, + 110, 100, 67, 111, 110, 102, + 105, 103, 0, 171, 171, 171, + 1, 0, 19, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 76, + 97, 121, 101, 114, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 3, 0, 3, 0, + 4, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 80, 114, 111, 106, 101, + 99, 116, 105, 111, 110, 0, + 118, 82, 101, 110, 100, 101, + 114, 84, 97, 114, 103, 101, + 116, 79, 102, 102, 115, 101, + 116, 0, 118, 84, 101, 120, + 116, 117, 114, 101, 67, 111, + 111, 114, 100, 115, 0, 171, + 1, 0, 3, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 76, + 97, 121, 101, 114, 81, 117, + 97, 100, 0, 118, 77, 97, + 115, 107, 81, 117, 97, 100, + 0, 109, 66, 97, 99, 107, + 100, 114, 111, 112, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, + 73, 83, 71, 78, 104, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 92, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171 +}; +ShaderBytes sRGBShaderMask = { RGBShaderMask, sizeof(RGBShaderMask) }; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 +// +// +// Buffer Definitions: +// +// cbuffer $Globals +// { +// +// float4 fLayerColor; // Offset: 0 Size: 16 [unused] +// float fLayerOpacity; // Offset: 16 Size: 4 +// uint4 iBlendConfig; // Offset: 32 Size: 16 [unused] +// float4x4 mLayerTransform; // Offset: 48 Size: 64 [unused] +// float4x4 mProjection; // Offset: 112 Size: 64 [unused] +// float4 vRenderTargetOffset; // Offset: 176 Size: 16 [unused] +// float4 vTextureCoords; // Offset: 192 Size: 16 [unused] +// float4 vLayerQuad; // Offset: 208 Size: 16 [unused] +// float4 vMaskQuad; // Offset: 224 Size: 16 [unused] +// float4x4 mBackdropTransform; // Offset: 240 Size: 64 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tRGB texture float4 2d t0 1 +// tMask texture float4 2d t5 1 +// $Globals cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 xyz 2 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +// +// Constant buffer to DX9 shader constant mappings: +// +// Target Reg Buffer Start Reg # of Regs Data Conversion +// ---------- ------- --------- --------- ---------------------- +// c0 cb0 1 1 ( FLT, FLT, FLT, FLT) +// +// +// Sampler/Resource to DX9 shader sampler mappings: +// +// Target Sampler Source Sampler Source Resource +// -------------- --------------- ---------------- +// s0 s0 t0 +// s1 s0 t5 // // // Level9 shader bytecode: @@ -4212,9 +3425,8 @@ ShaderBytes sRGBAShaderMask = { RGBAShaderMask, sizeof(RGBAShaderMask) }; // approximately 7 instruction slots used (2 texture, 5 arithmetic) ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed +dcl_constantbuffer CB0[2], immediateIndexed dcl_sampler s0, mode_default -dcl_sampler s1, mode_default dcl_resource_texture2d (float,float,float,float) t0 dcl_resource_texture2d (float,float,float,float) t5 dcl_input_ps linear v1.xy @@ -4222,7 +3434,7 @@ dcl_input_ps linear v2.xyz dcl_output o0.xyzw dcl_temps 2 div r0.xy, v2.xyxx, v2.zzzz -sample r0.xyzw, r0.xyxx, t5.xyzw, s1 +sample r0.xyzw, r0.xyxx, t5.xyzw, s0 sample r1.xyzw, v1.xyxx, t0.xyzw, s0 mul r1.xyzw, r1.xyzw, cb0[1].xxxx mul o0.xyzw, r0.xxxx, r1.xyzw @@ -4230,17 +3442,17 @@ ret // Approximately 6 instruction slots used #endif -const BYTE RGBAShaderMask3D[] = +const BYTE RGBAShaderMask[] = { - 68, 88, 66, 67, 3, 204, - 183, 228, 12, 40, 73, 204, - 169, 156, 99, 236, 238, 160, - 185, 204, 1, 0, 0, 0, - 124, 6, 0, 0, 6, 0, + 68, 88, 66, 67, 100, 50, + 112, 237, 158, 118, 201, 119, + 153, 231, 223, 176, 232, 201, + 145, 152, 1, 0, 0, 0, + 56, 6, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, - 24, 1, 0, 0, 64, 2, - 0, 0, 188, 2, 0, 0, - 216, 5, 0, 0, 72, 6, + 24, 1, 0, 0, 52, 2, + 0, 0, 176, 2, 0, 0, + 148, 5, 0, 0, 4, 6, 0, 0, 65, 111, 110, 57, 216, 0, 0, 0, 216, 0, 0, 0, 0, 2, 255, 255, @@ -4249,7 +3461,7 @@ const BYTE RGBAShaderMask3D[] = 0, 0, 56, 0, 0, 0, 56, 0, 2, 0, 36, 0, 0, 0, 56, 0, 0, 0, - 0, 0, 5, 1, 1, 0, + 0, 0, 5, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, @@ -4279,15 +3491,13 @@ const BYTE RGBAShaderMask3D[] = 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83, 72, - 68, 82, 32, 1, 0, 0, - 64, 0, 0, 0, 72, 0, + 68, 82, 20, 1, 0, 0, + 64, 0, 0, 0, 69, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, - 90, 0, 0, 3, 0, 96, - 16, 0, 1, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 88, 24, @@ -4310,7 +3520,7 @@ const BYTE RGBAShaderMask3D[] = 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 5, 0, 0, 0, - 0, 96, 16, 0, 1, 0, + 0, 96, 16, 0, 0, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 1, 0, 0, 0, 70, 16, 16, 0, @@ -4349,171 +3559,162 @@ const BYTE RGBAShaderMask3D[] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, - 69, 70, 20, 3, 0, 0, - 1, 0, 0, 0, 244, 0, - 0, 0, 5, 0, 0, 0, + 69, 70, 220, 2, 0, 0, + 1, 0, 0, 0, 188, 0, + 0, 0, 4, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, - 224, 2, 0, 0, 188, 0, + 168, 2, 0, 0, 156, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, - 197, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 223, 0, 0, 0, + 165, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 170, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, - 255, 255, 255, 255, 0, 0, + 255, 255, 255, 255, 5, 0, 0, 0, 1, 0, 0, 0, - 13, 0, 0, 0, 228, 0, + 13, 0, 0, 0, 176, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 115, 83, 97, 109, 112, 108, + 101, 114, 0, 116, 82, 71, + 66, 0, 116, 77, 97, 115, + 107, 0, 36, 71, 108, 111, + 98, 97, 108, 115, 0, 171, + 171, 171, 176, 0, 0, 0, + 10, 0, 0, 0, 212, 0, + 0, 0, 48, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 196, 1, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 208, 1, 0, 0, 0, 0, + 0, 0, 224, 1, 0, 0, + 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 5, 0, 0, 0, 1, 0, - 0, 0, 13, 0, 0, 0, - 234, 0, 0, 0, 0, 0, + 240, 1, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, + 32, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 16, 2, 0, 0, 0, 0, + 0, 0, 32, 2, 0, 0, + 48, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 48, 2, 0, 0, 0, 0, + 0, 0, 64, 2, 0, 0, + 112, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 115, 83, 97, 109, - 112, 108, 101, 114, 0, 76, - 97, 121, 101, 114, 84, 101, - 120, 116, 117, 114, 101, 83, - 97, 109, 112, 108, 101, 114, - 76, 105, 110, 101, 97, 114, - 0, 116, 82, 71, 66, 0, - 116, 77, 97, 115, 107, 0, - 36, 71, 108, 111, 98, 97, - 108, 115, 0, 171, 234, 0, - 0, 0, 10, 0, 0, 0, - 12, 1, 0, 0, 48, 1, + 48, 2, 0, 0, 0, 0, + 0, 0, 76, 2, 0, 0, + 176, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 252, 1, + 208, 1, 0, 0, 0, 0, + 0, 0, 96, 2, 0, 0, + 192, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 8, 2, 0, 0, - 0, 0, 0, 0, 24, 2, - 0, 0, 16, 0, 0, 0, - 4, 0, 0, 0, 2, 0, - 0, 0, 40, 2, 0, 0, - 0, 0, 0, 0, 56, 2, - 0, 0, 32, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 72, 2, 0, 0, - 0, 0, 0, 0, 88, 2, - 0, 0, 48, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 104, 2, 0, 0, - 0, 0, 0, 0, 120, 2, - 0, 0, 112, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 104, 2, 0, 0, - 0, 0, 0, 0, 132, 2, - 0, 0, 176, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 8, 2, 0, 0, - 0, 0, 0, 0, 152, 2, - 0, 0, 192, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 168, 2, 0, 0, - 0, 0, 0, 0, 184, 2, - 0, 0, 208, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 168, 2, 0, 0, - 0, 0, 0, 0, 195, 2, - 0, 0, 224, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 168, 2, 0, 0, - 0, 0, 0, 0, 205, 2, - 0, 0, 240, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 104, 2, 0, 0, - 0, 0, 0, 0, 102, 76, - 97, 121, 101, 114, 67, 111, - 108, 111, 114, 0, 1, 0, - 3, 0, 1, 0, 4, 0, + 112, 2, 0, 0, 0, 0, + 0, 0, 128, 2, 0, 0, + 208, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 112, 2, 0, 0, 0, 0, + 0, 0, 139, 2, 0, 0, + 224, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 112, 2, 0, 0, 0, 0, + 0, 0, 149, 2, 0, 0, + 240, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 48, 2, 0, 0, 0, 0, 0, 0, 102, 76, 97, 121, - 101, 114, 79, 112, 97, 99, - 105, 116, 121, 0, 171, 171, - 0, 0, 3, 0, 1, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 105, 66, - 108, 101, 110, 100, 67, 111, - 110, 102, 105, 103, 0, 171, - 171, 171, 1, 0, 19, 0, + 101, 114, 67, 111, 108, 111, + 114, 0, 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 109, 76, 97, 121, 101, 114, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 3, 0, - 3, 0, 4, 0, 4, 0, + 102, 76, 97, 121, 101, 114, + 79, 112, 97, 99, 105, 116, + 121, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 109, 80, 114, 111, - 106, 101, 99, 116, 105, 111, - 110, 0, 118, 82, 101, 110, - 100, 101, 114, 84, 97, 114, - 103, 101, 116, 79, 102, 102, - 115, 101, 116, 0, 118, 84, - 101, 120, 116, 117, 114, 101, - 67, 111, 111, 114, 100, 115, - 0, 171, 1, 0, 3, 0, - 1, 0, 4, 0, 0, 0, + 0, 0, 105, 66, 108, 101, + 110, 100, 67, 111, 110, 102, + 105, 103, 0, 171, 171, 171, + 1, 0, 19, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 76, + 97, 121, 101, 114, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 3, 0, 3, 0, + 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 76, 97, 121, 101, 114, - 81, 117, 97, 100, 0, 118, - 77, 97, 115, 107, 81, 117, - 97, 100, 0, 109, 66, 97, - 99, 107, 100, 114, 111, 112, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 77, 105, - 99, 114, 111, 115, 111, 102, - 116, 32, 40, 82, 41, 32, - 72, 76, 83, 76, 32, 83, - 104, 97, 100, 101, 114, 32, - 67, 111, 109, 112, 105, 108, - 101, 114, 32, 54, 46, 51, - 46, 57, 54, 48, 48, 46, + 109, 80, 114, 111, 106, 101, + 99, 116, 105, 111, 110, 0, + 118, 82, 101, 110, 100, 101, + 114, 84, 97, 114, 103, 101, + 116, 79, 102, 102, 115, 101, + 116, 0, 118, 84, 101, 120, + 116, 117, 114, 101, 67, 111, + 111, 114, 100, 115, 0, 171, + 1, 0, 3, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 76, + 97, 121, 101, 114, 81, 117, + 97, 100, 0, 118, 77, 97, + 115, 107, 81, 117, 97, 100, + 0, 109, 66, 97, 99, 107, + 100, 114, 111, 112, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, 49, 54, 51, 56, 52, 0, - 171, 171, 73, 83, 71, 78, - 104, 0, 0, 0, 3, 0, - 0, 0, 8, 0, 0, 0, - 80, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 92, 0, 0, 0, 0, 0, + 73, 83, 71, 78, 104, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 3, 3, 0, 0, - 92, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 2, 0, - 0, 0, 7, 7, 0, 0, - 83, 86, 95, 80, 111, 115, - 105, 116, 105, 111, 110, 0, - 84, 69, 88, 67, 79, 79, - 82, 68, 0, 171, 171, 171, - 79, 83, 71, 78, 44, 0, - 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 32, 0, + 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 92, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 15, 0, 0, 0, 83, 86, - 95, 84, 97, 114, 103, 101, - 116, 0, 171, 171 + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171 }; -ShaderBytes sRGBAShaderMask3D = { RGBAShaderMask3D, sizeof(RGBAShaderMask3D) }; +ShaderBytes sRGBAShaderMask = { RGBAShaderMask, sizeof(RGBAShaderMask) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -4537,14 +3738,14 @@ ShaderBytes sRGBAShaderMask3D = { RGBAShaderMask3D, sizeof(RGBAShaderMask3D) }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tY texture float4 2d 1 1 -// tCb texture float4 2d 2 1 -// tCr texture float4 2d 3 1 -// tMask texture float4 2d 5 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tY texture float4 2d t1 1 +// tCb texture float4 2d t2 1 +// tCr texture float4 2d t3 1 +// tMask texture float4 2d t5 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -4554,7 +3755,7 @@ ShaderBytes sRGBAShaderMask3D = { RGBAShaderMask3D, sizeof(RGBAShaderMask3D) }; // -------------------- ----- ------ -------- -------- ------- ------ // SV_Position 0 xyzw 0 POS float // TEXCOORD 0 xy 1 NONE float xy -// TEXCOORD 1 zw 1 NONE float zw +// TEXCOORD 1 xyz 2 NONE float xyz // // // Output signature: @@ -4586,7 +3787,8 @@ ShaderBytes sRGBAShaderMask3D = { RGBAShaderMask3D, sizeof(RGBAShaderMask3D) }; ps_2_x def c1, -0.50195998, -0.0627499968, 1.59603, 0.812969983 def c2, 1.16437995, 2.01723003, 0.391759992, 1 - dcl t0 + dcl t0.xy + dcl t1.xyz dcl_2d s0 dcl_2d s1 dcl_2d s2 @@ -4598,7 +3800,8 @@ ShaderBytes sRGBAShaderMask3D = { RGBAShaderMask3D, sizeof(RGBAShaderMask3D) }; add r0.x, r0.x, c1.y mad r0.z, r0.x, c2.x, -r0.z mad r1.x, r0.x, c2.x, r0.y - mov r2.xy, t0.wzzw + rcp r0.y, t1.z + mul r2.xy, r0.y, t1 texld r3, t0, s1 texld r2, r2, s3 add r0.y, r3.x, c1.x @@ -4610,16 +3813,16 @@ ShaderBytes sRGBAShaderMask3D = { RGBAShaderMask3D, sizeof(RGBAShaderMask3D) }; mul r0, r2.x, r0 mov oC0, r0 -// approximately 18 instruction slots used (4 texture, 14 arithmetic) +// approximately 19 instruction slots used (4 texture, 15 arithmetic) ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed +dcl_constantbuffer CB0[2], immediateIndexed dcl_sampler s0, mode_default dcl_resource_texture2d (float,float,float,float) t1 dcl_resource_texture2d (float,float,float,float) t2 dcl_resource_texture2d (float,float,float,float) t3 dcl_resource_texture2d (float,float,float,float) t5 dcl_input_ps linear v1.xy -dcl_input_ps linear v1.zw +dcl_input_ps linear v2.xyz dcl_output o0.xyzw dcl_temps 3 sample r0.xyzw, v1.xyxx, t3.xyzw, s0 @@ -4636,27 +3839,28 @@ mul r0.x, r0.x, l(2.017230) mad r1.z, r0.z, l(1.164380), r0.x mov r1.w, l(1.000000) mul r0.xyzw, r1.xyzw, cb0[1].xxxx -sample r1.xyzw, v1.zwzz, t5.xyzw, s0 +div r1.xy, v2.xyxx, v2.zzzz +sample r1.xyzw, r1.xyxx, t5.xyzw, s0 mul o0.xyzw, r0.xyzw, r1.xxxx ret -// Approximately 17 instruction slots used +// Approximately 18 instruction slots used #endif const BYTE YCbCrShaderMask[] = { - 68, 88, 66, 67, 221, 32, - 127, 20, 214, 189, 35, 93, - 175, 146, 75, 225, 8, 148, - 130, 206, 1, 0, 0, 0, - 12, 9, 0, 0, 6, 0, + 68, 88, 66, 67, 204, 171, + 122, 254, 247, 109, 96, 89, + 237, 176, 206, 43, 154, 27, + 195, 203, 1, 0, 0, 0, + 68, 9, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, - 24, 2, 0, 0, 196, 4, - 0, 0, 64, 5, 0, 0, - 104, 8, 0, 0, 216, 8, + 52, 2, 0, 0, 252, 4, + 0, 0, 120, 5, 0, 0, + 160, 8, 0, 0, 16, 9, 0, 0, 65, 111, 110, 57, - 216, 1, 0, 0, 216, 1, + 244, 1, 0, 0, 244, 1, 0, 0, 0, 2, 255, 255, - 152, 1, 0, 0, 64, 0, + 180, 1, 0, 0, 64, 0, 0, 0, 1, 0, 52, 0, 0, 0, 64, 0, 0, 0, 64, 0, 4, 0, 36, 0, @@ -4675,7 +3879,9 @@ const BYTE YCbCrShaderMask[] = 76, 26, 1, 64, 196, 148, 200, 62, 0, 0, 128, 63, 31, 0, 0, 2, 0, 0, - 0, 128, 0, 0, 15, 176, + 0, 128, 0, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 128, 1, 0, 7, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 31, 0, 0, 2, 0, 0, @@ -4704,257 +3910,711 @@ const BYTE YCbCrShaderMask[] = 0, 4, 1, 0, 1, 128, 0, 0, 0, 128, 2, 0, 0, 160, 0, 0, 85, 128, - 1, 0, 0, 2, 2, 0, - 3, 128, 0, 0, 235, 176, - 66, 0, 0, 3, 3, 0, - 15, 128, 0, 0, 228, 176, - 1, 8, 228, 160, 66, 0, - 0, 3, 2, 0, 15, 128, - 2, 0, 228, 128, 3, 8, - 228, 160, 2, 0, 0, 3, - 0, 0, 2, 128, 3, 0, - 0, 128, 1, 0, 0, 160, - 4, 0, 0, 4, 1, 0, - 2, 128, 0, 0, 85, 128, - 2, 0, 170, 161, 0, 0, - 170, 128, 5, 0, 0, 3, - 0, 0, 2, 128, 0, 0, - 85, 128, 2, 0, 85, 160, - 4, 0, 0, 4, 1, 0, - 4, 128, 0, 0, 0, 128, - 2, 0, 0, 160, 0, 0, - 85, 128, 1, 0, 0, 2, - 1, 0, 8, 128, 2, 0, - 255, 160, 5, 0, 0, 3, - 0, 0, 15, 128, 1, 0, - 228, 128, 0, 0, 0, 160, + 6, 0, 0, 2, 0, 0, + 2, 128, 1, 0, 170, 176, + 5, 0, 0, 3, 2, 0, + 3, 128, 0, 0, 85, 128, + 1, 0, 228, 176, 66, 0, + 0, 3, 3, 0, 15, 128, + 0, 0, 228, 176, 1, 8, + 228, 160, 66, 0, 0, 3, + 2, 0, 15, 128, 2, 0, + 228, 128, 3, 8, 228, 160, + 2, 0, 0, 3, 0, 0, + 2, 128, 3, 0, 0, 128, + 1, 0, 0, 160, 4, 0, + 0, 4, 1, 0, 2, 128, + 0, 0, 85, 128, 2, 0, + 170, 161, 0, 0, 170, 128, 5, 0, 0, 3, 0, 0, - 15, 128, 2, 0, 0, 128, - 0, 0, 228, 128, 1, 0, - 0, 2, 0, 8, 15, 128, - 0, 0, 228, 128, 255, 255, - 0, 0, 83, 72, 68, 82, - 164, 2, 0, 0, 64, 0, - 0, 0, 169, 0, 0, 0, - 89, 0, 0, 4, 70, 142, - 32, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 90, 0, - 0, 3, 0, 96, 16, 0, - 0, 0, 0, 0, 88, 24, - 0, 4, 0, 112, 16, 0, - 1, 0, 0, 0, 85, 85, + 2, 128, 0, 0, 85, 128, + 2, 0, 85, 160, 4, 0, + 0, 4, 1, 0, 4, 128, + 0, 0, 0, 128, 2, 0, + 0, 160, 0, 0, 85, 128, + 1, 0, 0, 2, 1, 0, + 8, 128, 2, 0, 255, 160, + 5, 0, 0, 3, 0, 0, + 15, 128, 1, 0, 228, 128, + 0, 0, 0, 160, 5, 0, + 0, 3, 0, 0, 15, 128, + 2, 0, 0, 128, 0, 0, + 228, 128, 1, 0, 0, 2, + 0, 8, 15, 128, 0, 0, + 228, 128, 255, 255, 0, 0, + 83, 72, 68, 82, 192, 2, + 0, 0, 64, 0, 0, 0, + 176, 0, 0, 0, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, - 0, 112, 16, 0, 2, 0, + 0, 112, 16, 0, 1, 0, 0, 0, 85, 85, 0, 0, 88, 24, 0, 4, 0, 112, + 16, 0, 2, 0, 0, 0, + 85, 85, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 3, 0, 0, 0, 85, 85, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 5, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 98, 16, 0, 3, 114, 16, + 16, 0, 2, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 3, 0, + 0, 0, 69, 0, 0, 9, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 1, 0, 0, 0, 70, 126, 16, 0, 3, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 115, 128, 0, 191, + 56, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 182, 74, 204, 63, 205, 30, + 80, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 1, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 0, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 18, 131, + 128, 189, 50, 0, 0, 10, + 34, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 103, 10, 149, 63, + 26, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 9, 18, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 103, 10, 149, 63, 10, 0, + 16, 0, 0, 0, 0, 0, + 69, 0, 0, 9, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 70, 126, 16, 0, + 2, 0, 0, 0, 0, 96, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 18, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 2, 0, + 0, 0, 1, 64, 0, 0, + 115, 128, 0, 191, 50, 0, + 0, 10, 34, 0, 16, 0, + 1, 0, 0, 0, 10, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 196, 148, 200, 62, + 26, 0, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 18, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 76, 26, 1, 64, + 50, 0, 0, 9, 66, 0, + 16, 0, 1, 0, 0, 0, + 42, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 103, 10, 149, 63, 10, 0, + 16, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 130, 0, + 16, 0, 1, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 56, 0, 0, 8, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 6, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 14, 0, + 0, 7, 50, 0, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 2, 0, 0, 0, + 166, 26, 16, 0, 2, 0, + 0, 0, 69, 0, 0, 9, + 242, 0, 16, 0, 1, 0, + 0, 0, 70, 0, 16, 0, + 1, 0, 0, 0, 70, 126, + 16, 0, 5, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 7, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 0, 0, 0, 0, 6, 0, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 116, 0, 0, 0, + 18, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 82, 68, 69, 70, + 32, 3, 0, 0, 1, 0, + 0, 0, 0, 1, 0, 0, + 6, 0, 0, 0, 28, 0, + 0, 0, 0, 4, 255, 255, + 0, 1, 0, 0, 236, 2, + 0, 0, 220, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 229, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 232, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 2, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 236, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 3, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 240, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 5, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 246, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 115, 83, 97, 109, + 112, 108, 101, 114, 0, 116, + 89, 0, 116, 67, 98, 0, + 116, 67, 114, 0, 116, 77, + 97, 115, 107, 0, 36, 71, + 108, 111, 98, 97, 108, 115, + 0, 171, 246, 0, 0, 0, + 10, 0, 0, 0, 24, 1, + 0, 0, 48, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 2, 0, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 20, 2, 0, 0, 0, 0, + 0, 0, 36, 2, 0, 0, + 16, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 52, 2, 0, 0, 0, 0, + 0, 0, 68, 2, 0, 0, + 32, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 84, 2, 0, 0, 0, 0, + 0, 0, 100, 2, 0, 0, + 48, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 116, 2, 0, 0, 0, 0, + 0, 0, 132, 2, 0, 0, + 112, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 116, 2, 0, 0, 0, 0, + 0, 0, 144, 2, 0, 0, + 176, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 20, 2, 0, 0, 0, 0, + 0, 0, 164, 2, 0, 0, + 192, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 180, 2, 0, 0, 0, 0, + 0, 0, 196, 2, 0, 0, + 208, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 180, 2, 0, 0, 0, 0, + 0, 0, 207, 2, 0, 0, + 224, 0, 0, 0, 16, 0, + 0, 0, 0, 0, 0, 0, + 180, 2, 0, 0, 0, 0, + 0, 0, 217, 2, 0, 0, + 240, 0, 0, 0, 64, 0, + 0, 0, 0, 0, 0, 0, + 116, 2, 0, 0, 0, 0, + 0, 0, 102, 76, 97, 121, + 101, 114, 67, 111, 108, 111, + 114, 0, 1, 0, 3, 0, + 1, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 102, 76, 97, 121, 101, 114, + 79, 112, 97, 99, 105, 116, + 121, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 105, 66, 108, 101, + 110, 100, 67, 111, 110, 102, + 105, 103, 0, 171, 171, 171, + 1, 0, 19, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 76, + 97, 121, 101, 114, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 3, 0, 3, 0, + 4, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 109, 80, 114, 111, 106, 101, + 99, 116, 105, 111, 110, 0, + 118, 82, 101, 110, 100, 101, + 114, 84, 97, 114, 103, 101, + 116, 79, 102, 102, 115, 101, + 116, 0, 118, 84, 101, 120, + 116, 117, 114, 101, 67, 111, + 111, 114, 100, 115, 0, 171, + 1, 0, 3, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 76, + 97, 121, 101, 114, 81, 117, + 97, 100, 0, 118, 77, 97, + 115, 107, 81, 117, 97, 100, + 0, 109, 66, 97, 99, 107, + 100, 114, 111, 112, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, + 73, 83, 71, 78, 104, 0, + 0, 0, 3, 0, 0, 0, + 8, 0, 0, 0, 80, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 92, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 92, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171 +}; +ShaderBytes sYCbCrShaderMask = { YCbCrShaderMask, sizeof(YCbCrShaderMask) }; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 +// +// +// Buffer Definitions: +// +// cbuffer $Globals +// { +// +// float4 fLayerColor; // Offset: 0 Size: 16 [unused] +// float fLayerOpacity; // Offset: 16 Size: 4 +// uint4 iBlendConfig; // Offset: 32 Size: 16 [unused] +// float4x4 mLayerTransform; // Offset: 48 Size: 64 [unused] +// float4x4 mProjection; // Offset: 112 Size: 64 [unused] +// float4 vRenderTargetOffset; // Offset: 176 Size: 16 [unused] +// float4 vTextureCoords; // Offset: 192 Size: 16 [unused] +// float4 vLayerQuad; // Offset: 208 Size: 16 [unused] +// float4 vMaskQuad; // Offset: 224 Size: 16 [unused] +// float4x4 mBackdropTransform; // Offset: 240 Size: 64 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tRGB texture float4 2d t0 1 +// tRGBWhite texture float4 2d t4 1 +// tMask texture float4 2d t5 1 +// $Globals cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Position 0 xyzw 0 POS float +// TEXCOORD 0 xy 1 NONE float xy +// TEXCOORD 1 xyz 2 NONE float xyz +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// SV_Target 1 xyzw 1 TARGET float xyzw +// +// +// Constant buffer to DX9 shader constant mappings: +// +// Target Reg Buffer Start Reg # of Regs Data Conversion +// ---------- ------- --------- --------- ---------------------- +// c0 cb0 1 1 ( FLT, FLT, FLT, FLT) +// +// +// Sampler/Resource to DX9 shader sampler mappings: +// +// Target Sampler Source Sampler Source Resource +// -------------- --------------- ---------------- +// s0 s0 t0 +// s1 s0 t4 +// s2 s0 t5 +// +// +// Level9 shader bytecode: +// + ps_2_x + def c1, 1, 0, 0, 0 + dcl t0.xy + dcl t1.xyz + dcl_2d s0 + dcl_2d s1 + dcl_2d s2 + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r0, r0, s2 + mul r0.x, r0.x, c0.x + texld r1, t0, s0 + texld r2, t0, s1 + add r2, r1, -r2 + add r2, r2, c1.x + mov r1.w, r2.y + mul r2, r0.x, r2 + mul r0, r0.x, r1 + mov oC0, r0 + mov oC1, r2 + +// approximately 13 instruction slots used (3 texture, 10 arithmetic) +ps_4_0 +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_resource_texture2d (float,float,float,float) t4 +dcl_resource_texture2d (float,float,float,float) t5 +dcl_input_ps linear v1.xy +dcl_input_ps linear v2.xyz +dcl_output o0.xyzw +dcl_output o1.xyzw +dcl_temps 3 +div r0.xy, v2.xyxx, v2.zzzz +sample r0.xyzw, r0.xyxx, t5.xyzw, s0 +mul r0.x, r0.x, cb0[1].x +sample r1.xyzw, v1.xyxx, t4.xyzw, s0 +sample r2.xyzw, v1.xyxx, t0.xyzw, s0 +add r1.xyzw, -r1.xyzw, r2.xyzw +add r1.xyzw, r1.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000) +mov r2.w, r1.y +mul o1.xyzw, r0.xxxx, r1.xyzw +mul o0.xyzw, r0.xxxx, r2.xyzw +ret +// Approximately 11 instruction slots used +#endif + +const BYTE ComponentAlphaShaderMask[] = +{ + 68, 88, 66, 67, 15, 154, + 37, 42, 228, 90, 173, 36, + 200, 249, 246, 236, 145, 93, + 169, 30, 1, 0, 0, 0, + 176, 7, 0, 0, 6, 0, + 0, 0, 56, 0, 0, 0, + 152, 1, 0, 0, 108, 3, + 0, 0, 232, 3, 0, 0, + 244, 6, 0, 0, 100, 7, + 0, 0, 65, 111, 110, 57, + 88, 1, 0, 0, 88, 1, + 0, 0, 0, 2, 255, 255, + 28, 1, 0, 0, 60, 0, + 0, 0, 1, 0, 48, 0, + 0, 0, 60, 0, 0, 0, + 60, 0, 3, 0, 36, 0, + 0, 0, 60, 0, 0, 0, + 0, 0, 4, 0, 1, 0, + 5, 0, 2, 0, 0, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 2, + 255, 255, 81, 0, 0, 5, + 1, 0, 15, 160, 0, 0, + 128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 2, + 0, 0, 0, 128, 0, 0, + 3, 176, 31, 0, 0, 2, + 0, 0, 0, 128, 1, 0, + 7, 176, 31, 0, 0, 2, + 0, 0, 0, 144, 0, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 1, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 2, 8, + 15, 160, 6, 0, 0, 2, + 0, 0, 8, 128, 1, 0, + 170, 176, 5, 0, 0, 3, + 0, 0, 3, 128, 0, 0, + 255, 128, 1, 0, 228, 176, + 66, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 128, + 2, 8, 228, 160, 5, 0, + 0, 3, 0, 0, 1, 128, + 0, 0, 0, 128, 0, 0, + 0, 160, 66, 0, 0, 3, + 1, 0, 15, 128, 0, 0, + 228, 176, 0, 8, 228, 160, + 66, 0, 0, 3, 2, 0, + 15, 128, 0, 0, 228, 176, + 1, 8, 228, 160, 2, 0, + 0, 3, 2, 0, 15, 128, + 1, 0, 228, 128, 2, 0, + 228, 129, 2, 0, 0, 3, + 2, 0, 15, 128, 2, 0, + 228, 128, 1, 0, 0, 160, + 1, 0, 0, 2, 1, 0, + 8, 128, 2, 0, 85, 128, + 5, 0, 0, 3, 2, 0, + 15, 128, 0, 0, 0, 128, + 2, 0, 228, 128, 5, 0, + 0, 3, 0, 0, 15, 128, + 0, 0, 0, 128, 1, 0, + 228, 128, 1, 0, 0, 2, + 0, 8, 15, 128, 0, 0, + 228, 128, 1, 0, 0, 2, + 1, 8, 15, 128, 2, 0, + 228, 128, 255, 255, 0, 0, + 83, 72, 68, 82, 204, 1, + 0, 0, 64, 0, 0, 0, + 115, 0, 0, 0, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 24, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 88, 24, 0, 4, 0, 112, + 16, 0, 4, 0, 0, 0, 85, 85, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 5, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 98, 16, 0, 3, - 194, 16, 16, 0, 1, 0, + 114, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 1, 0, 0, 0, 104, 0, 0, 2, - 3, 0, 0, 0, 69, 0, - 0, 9, 242, 0, 16, 0, + 3, 0, 0, 0, 14, 0, + 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, - 16, 0, 1, 0, 0, 0, - 70, 126, 16, 0, 3, 0, - 0, 0, 0, 96, 16, 0, - 0, 0, 0, 0, 0, 0, - 0, 7, 18, 0, 16, 0, - 0, 0, 0, 0, 10, 0, - 16, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 115, 128, - 0, 191, 56, 0, 0, 10, - 50, 0, 16, 0, 0, 0, - 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 2, 64, - 0, 0, 182, 74, 204, 63, - 205, 30, 80, 63, 0, 0, - 0, 0, 0, 0, 0, 0, - 69, 0, 0, 9, 242, 0, - 16, 0, 1, 0, 0, 0, - 70, 16, 16, 0, 1, 0, - 0, 0, 70, 126, 16, 0, - 1, 0, 0, 0, 0, 96, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 7, 66, 0, - 16, 0, 0, 0, 0, 0, - 10, 0, 16, 0, 1, 0, - 0, 0, 1, 64, 0, 0, - 18, 131, 128, 189, 50, 0, - 0, 10, 34, 0, 16, 0, - 0, 0, 0, 0, 42, 0, - 16, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 103, 10, - 149, 63, 26, 0, 16, 128, - 65, 0, 0, 0, 0, 0, - 0, 0, 50, 0, 0, 9, - 18, 0, 16, 0, 1, 0, - 0, 0, 42, 0, 16, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 103, 10, 149, 63, - 10, 0, 16, 0, 0, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 2, 0, - 0, 0, 70, 16, 16, 0, - 1, 0, 0, 0, 70, 126, 16, 0, 2, 0, 0, 0, + 166, 26, 16, 0, 2, 0, + 0, 0, 69, 0, 0, 9, + 242, 0, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 5, 0, 0, 0, 0, 96, 16, 0, 0, 0, - 0, 0, 0, 0, 0, 7, + 0, 0, 56, 0, 0, 8, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, - 2, 0, 0, 0, 1, 64, - 0, 0, 115, 128, 0, 191, - 50, 0, 0, 10, 34, 0, + 0, 0, 0, 0, 10, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 1, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, - 10, 0, 16, 128, 65, 0, + 70, 126, 16, 0, 4, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 2, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 196, 148, - 200, 62, 26, 0, 16, 0, - 0, 0, 0, 0, 56, 0, - 0, 7, 18, 0, 16, 0, - 0, 0, 0, 0, 10, 0, - 16, 0, 0, 0, 0, 0, - 1, 64, 0, 0, 76, 26, - 1, 64, 50, 0, 0, 9, - 66, 0, 16, 0, 1, 0, - 0, 0, 42, 0, 16, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 103, 10, 149, 63, - 10, 0, 16, 0, 0, 0, - 0, 0, 54, 0, 0, 5, - 130, 0, 16, 0, 1, 0, - 0, 0, 1, 64, 0, 0, - 0, 0, 128, 63, 56, 0, 0, 8, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 14, + 1, 0, 0, 0, 70, 14, + 16, 128, 65, 0, 0, 0, + 1, 0, 0, 0, 70, 14, + 16, 0, 2, 0, 0, 0, + 0, 0, 0, 10, 242, 0, 16, 0, 1, 0, 0, 0, - 6, 128, 32, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 69, 0, 0, 9, 242, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 63, 0, 0, 128, 63, + 0, 0, 128, 63, 54, 0, + 0, 5, 130, 0, 16, 0, + 2, 0, 0, 0, 26, 0, 16, 0, 1, 0, 0, 0, - 230, 26, 16, 0, 1, 0, - 0, 0, 70, 126, 16, 0, - 5, 0, 0, 0, 0, 96, - 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 242, 32, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 56, 0, + 0, 7, 242, 32, 16, 0, + 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 0, 0, - 0, 0, 6, 0, 16, 0, - 1, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 116, 0, 0, 0, 17, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 3, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, 0, 0, 11, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 82, 68, 69, 70, 32, 3, - 0, 0, 1, 0, 0, 0, - 0, 1, 0, 0, 6, 0, - 0, 0, 28, 0, 0, 0, - 0, 4, 255, 255, 0, 1, - 0, 0, 236, 2, 0, 0, - 220, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 1, 0, - 0, 0, 229, 0, 0, 0, - 2, 0, 0, 0, 5, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, - 255, 255, 255, 255, 1, 0, - 0, 0, 1, 0, 0, 0, - 13, 0, 0, 0, 232, 0, - 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 2, 0, 0, 0, 1, 0, - 0, 0, 13, 0, 0, 0, - 236, 0, 0, 0, 2, 0, + 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 68, + 69, 70, 4, 3, 0, 0, + 1, 0, 0, 0, 228, 0, 0, 0, 5, 0, 0, 0, - 4, 0, 0, 0, 255, 255, - 255, 255, 3, 0, 0, 0, - 1, 0, 0, 0, 13, 0, - 0, 0, 240, 0, 0, 0, - 2, 0, 0, 0, 5, 0, - 0, 0, 4, 0, 0, 0, - 255, 255, 255, 255, 5, 0, - 0, 0, 1, 0, 0, 0, - 13, 0, 0, 0, 246, 0, - 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 255, 255, 0, 1, 0, 0, + 208, 2, 0, 0, 188, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 197, 0, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 202, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 4, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 212, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 5, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 115, 83, 97, 109, 112, 108, - 101, 114, 0, 116, 89, 0, - 116, 67, 98, 0, 116, 67, - 114, 0, 116, 77, 97, 115, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 115, 83, 97, 109, + 112, 108, 101, 114, 0, 116, + 82, 71, 66, 0, 116, 82, + 71, 66, 87, 104, 105, 116, + 101, 0, 116, 77, 97, 115, 107, 0, 36, 71, 108, 111, 98, 97, 108, 115, 0, 171, - 246, 0, 0, 0, 10, 0, - 0, 0, 24, 1, 0, 0, + 218, 0, 0, 0, 10, 0, + 0, 0, 252, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 2, 0, 0, 0, 0, + 236, 1, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 20, 2, + 0, 0, 0, 0, 248, 1, 0, 0, 0, 0, 0, 0, - 36, 2, 0, 0, 16, 0, + 8, 2, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, - 2, 0, 0, 0, 52, 2, + 2, 0, 0, 0, 24, 2, 0, 0, 0, 0, 0, 0, - 68, 2, 0, 0, 32, 0, + 40, 2, 0, 0, 32, 0, 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 84, 2, + 0, 0, 0, 0, 56, 2, 0, 0, 0, 0, 0, 0, - 100, 2, 0, 0, 48, 0, + 72, 2, 0, 0, 48, 0, 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 116, 2, + 0, 0, 0, 0, 88, 2, 0, 0, 0, 0, 0, 0, - 132, 2, 0, 0, 112, 0, + 104, 2, 0, 0, 112, 0, 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 116, 2, + 0, 0, 0, 0, 88, 2, 0, 0, 0, 0, 0, 0, - 144, 2, 0, 0, 176, 0, + 116, 2, 0, 0, 176, 0, 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 20, 2, + 0, 0, 0, 0, 248, 1, 0, 0, 0, 0, 0, 0, - 164, 2, 0, 0, 192, 0, + 136, 2, 0, 0, 192, 0, 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 180, 2, + 0, 0, 0, 0, 152, 2, 0, 0, 0, 0, 0, 0, - 196, 2, 0, 0, 208, 0, + 168, 2, 0, 0, 208, 0, 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 180, 2, + 0, 0, 0, 0, 152, 2, 0, 0, 0, 0, 0, 0, - 207, 2, 0, 0, 224, 0, + 179, 2, 0, 0, 224, 0, 0, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 180, 2, + 0, 0, 0, 0, 152, 2, 0, 0, 0, 0, 0, 0, - 217, 2, 0, 0, 240, 0, + 189, 2, 0, 0, 240, 0, 0, 0, 64, 0, 0, 0, - 0, 0, 0, 0, 116, 2, + 0, 0, 0, 0, 88, 2, 0, 0, 0, 0, 0, 0, 102, 76, 97, 121, 101, 114, 67, 111, 108, 111, 114, 0, @@ -4999,10 +4659,10 @@ const BYTE YCbCrShaderMask[] = 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, 71, 78, 104, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, @@ -5016,463 +4676,29 @@ const BYTE YCbCrShaderMask[] = 0, 0, 92, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 12, 12, + 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, - 44, 0, 0, 0, 1, 0, + 68, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, - 32, 0, 0, 0, 0, 0, + 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, + 56, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 97, 114, 103, 101, 116, 0, 171, 171 }; -ShaderBytes sYCbCrShaderMask = { YCbCrShaderMask, sizeof(YCbCrShaderMask) }; -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 -// -// -// Buffer Definitions: -// -// cbuffer $Globals -// { -// -// float4 fLayerColor; // Offset: 0 Size: 16 [unused] -// float fLayerOpacity; // Offset: 16 Size: 4 -// uint4 iBlendConfig; // Offset: 32 Size: 16 [unused] -// float4x4 mLayerTransform; // Offset: 48 Size: 64 [unused] -// float4x4 mProjection; // Offset: 112 Size: 64 [unused] -// float4 vRenderTargetOffset; // Offset: 176 Size: 16 [unused] -// float4 vTextureCoords; // Offset: 192 Size: 16 [unused] -// float4 vLayerQuad; // Offset: 208 Size: 16 [unused] -// float4 vMaskQuad; // Offset: 224 Size: 16 [unused] -// float4x4 mBackdropTransform; // Offset: 240 Size: 64 [unused] -// -// } -// -// -// Resource Bindings: -// -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// tRGB texture float4 2d 0 1 -// tRGBWhite texture float4 2d 4 1 -// tMask texture float4 2d 5 1 -// $Globals cbuffer NA NA 0 1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Position 0 xyzw 0 POS float -// TEXCOORD 0 xy 1 NONE float xy -// TEXCOORD 1 zw 1 NONE float zw -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Target 0 xyzw 0 TARGET float xyzw -// SV_Target 1 xyzw 1 TARGET float xyzw -// -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c0 cb0 1 1 ( FLT, FLT, FLT, FLT) -// -// -// Sampler/Resource to DX9 shader sampler mappings: -// -// Target Sampler Source Sampler Source Resource -// -------------- --------------- ---------------- -// s0 s0 t0 -// s1 s0 t4 -// s2 s0 t5 -// -// -// Level9 shader bytecode: -// - ps_2_x - def c1, 1, 0, 0, 0 - dcl t0 - dcl_2d s0 - dcl_2d s1 - dcl_2d s2 - mov r0.xy, t0.wzzw - texld r0, r0, s2 - mul r0.x, r0.x, c0.x - texld r1, t0, s0 - texld r2, t0, s1 - add r2, r1, -r2 - add r2, r2, c1.x - mov r1.w, r2.y - mul r2, r0.x, r2 - mul r0, r0.x, r1 - mov oC0, r0 - mov oC1, r2 - -// approximately 12 instruction slots used (3 texture, 9 arithmetic) -ps_4_0 -dcl_constantbuffer cb0[2], immediateIndexed -dcl_sampler s0, mode_default -dcl_resource_texture2d (float,float,float,float) t0 -dcl_resource_texture2d (float,float,float,float) t4 -dcl_resource_texture2d (float,float,float,float) t5 -dcl_input_ps linear v1.xy -dcl_input_ps linear v1.zw -dcl_output o0.xyzw -dcl_output o1.xyzw -dcl_temps 3 -sample r0.xyzw, v1.xyxx, t4.xyzw, s0 -sample r1.xyzw, v1.xyxx, t0.xyzw, s0 -add r0.xyzw, -r0.xyzw, r1.xyzw -add r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000) -mov r1.w, r0.y -sample r2.xyzw, v1.zwzz, t5.xyzw, s0 -mul r2.x, r2.x, cb0[1].x -mul o0.xyzw, r1.xyzw, r2.xxxx -mul o1.xyzw, r0.xyzw, r2.xxxx -ret -// Approximately 10 instruction slots used -#endif - -const BYTE ComponentAlphaShaderMask[] = -{ - 68, 88, 66, 67, 231, 247, - 98, 196, 91, 244, 200, 52, - 117, 97, 164, 190, 237, 87, - 108, 62, 1, 0, 0, 0, - 120, 7, 0, 0, 6, 0, - 0, 0, 56, 0, 0, 0, - 124, 1, 0, 0, 52, 3, - 0, 0, 176, 3, 0, 0, - 188, 6, 0, 0, 44, 7, - 0, 0, 65, 111, 110, 57, - 60, 1, 0, 0, 60, 1, - 0, 0, 0, 2, 255, 255, - 0, 1, 0, 0, 60, 0, - 0, 0, 1, 0, 48, 0, - 0, 0, 60, 0, 0, 0, - 60, 0, 3, 0, 36, 0, - 0, 0, 60, 0, 0, 0, - 0, 0, 4, 0, 1, 0, - 5, 0, 2, 0, 0, 0, - 1, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 1, 2, - 255, 255, 81, 0, 0, 5, - 1, 0, 15, 160, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 31, 0, 0, 2, - 0, 0, 0, 128, 0, 0, - 15, 176, 31, 0, 0, 2, - 0, 0, 0, 144, 0, 8, - 15, 160, 31, 0, 0, 2, - 0, 0, 0, 144, 1, 8, - 15, 160, 31, 0, 0, 2, - 0, 0, 0, 144, 2, 8, - 15, 160, 1, 0, 0, 2, - 0, 0, 3, 128, 0, 0, - 235, 176, 66, 0, 0, 3, - 0, 0, 15, 128, 0, 0, - 228, 128, 2, 8, 228, 160, - 5, 0, 0, 3, 0, 0, - 1, 128, 0, 0, 0, 128, - 0, 0, 0, 160, 66, 0, - 0, 3, 1, 0, 15, 128, - 0, 0, 228, 176, 0, 8, - 228, 160, 66, 0, 0, 3, - 2, 0, 15, 128, 0, 0, - 228, 176, 1, 8, 228, 160, - 2, 0, 0, 3, 2, 0, - 15, 128, 1, 0, 228, 128, - 2, 0, 228, 129, 2, 0, - 0, 3, 2, 0, 15, 128, - 2, 0, 228, 128, 1, 0, - 0, 160, 1, 0, 0, 2, - 1, 0, 8, 128, 2, 0, - 85, 128, 5, 0, 0, 3, - 2, 0, 15, 128, 0, 0, - 0, 128, 2, 0, 228, 128, - 5, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 0, 128, - 1, 0, 228, 128, 1, 0, - 0, 2, 0, 8, 15, 128, - 0, 0, 228, 128, 1, 0, - 0, 2, 1, 8, 15, 128, - 2, 0, 228, 128, 255, 255, - 0, 0, 83, 72, 68, 82, - 176, 1, 0, 0, 64, 0, - 0, 0, 108, 0, 0, 0, - 89, 0, 0, 4, 70, 142, - 32, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 90, 0, - 0, 3, 0, 96, 16, 0, - 0, 0, 0, 0, 88, 24, - 0, 4, 0, 112, 16, 0, - 0, 0, 0, 0, 85, 85, - 0, 0, 88, 24, 0, 4, - 0, 112, 16, 0, 4, 0, - 0, 0, 85, 85, 0, 0, - 88, 24, 0, 4, 0, 112, - 16, 0, 5, 0, 0, 0, - 85, 85, 0, 0, 98, 16, - 0, 3, 50, 16, 16, 0, - 1, 0, 0, 0, 98, 16, - 0, 3, 194, 16, 16, 0, - 1, 0, 0, 0, 101, 0, - 0, 3, 242, 32, 16, 0, - 0, 0, 0, 0, 101, 0, - 0, 3, 242, 32, 16, 0, - 1, 0, 0, 0, 104, 0, - 0, 2, 3, 0, 0, 0, - 69, 0, 0, 9, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 16, 16, 0, 1, 0, - 0, 0, 70, 126, 16, 0, - 4, 0, 0, 0, 0, 96, - 16, 0, 0, 0, 0, 0, - 69, 0, 0, 9, 242, 0, - 16, 0, 1, 0, 0, 0, - 70, 16, 16, 0, 1, 0, - 0, 0, 70, 126, 16, 0, - 0, 0, 0, 0, 0, 96, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 8, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 14, 16, 128, 65, 0, - 0, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 1, 0, - 0, 0, 0, 0, 0, 10, - 242, 0, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 0, 0, 0, 0, 2, 64, - 0, 0, 0, 0, 128, 63, - 0, 0, 128, 63, 0, 0, - 128, 63, 0, 0, 128, 63, - 54, 0, 0, 5, 130, 0, - 16, 0, 1, 0, 0, 0, - 26, 0, 16, 0, 0, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 2, 0, - 0, 0, 230, 26, 16, 0, - 1, 0, 0, 0, 70, 126, - 16, 0, 5, 0, 0, 0, - 0, 96, 16, 0, 0, 0, - 0, 0, 56, 0, 0, 8, - 18, 0, 16, 0, 2, 0, - 0, 0, 10, 0, 16, 0, - 2, 0, 0, 0, 10, 128, - 32, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 56, 0, - 0, 7, 242, 32, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 1, 0, 0, 0, - 6, 0, 16, 0, 2, 0, - 0, 0, 56, 0, 0, 7, - 242, 32, 16, 0, 1, 0, - 0, 0, 70, 14, 16, 0, - 0, 0, 0, 0, 6, 0, - 16, 0, 2, 0, 0, 0, - 62, 0, 0, 1, 83, 84, - 65, 84, 116, 0, 0, 0, - 10, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 5, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 82, 68, 69, 70, - 4, 3, 0, 0, 1, 0, - 0, 0, 228, 0, 0, 0, - 5, 0, 0, 0, 28, 0, - 0, 0, 0, 4, 255, 255, - 0, 1, 0, 0, 208, 2, - 0, 0, 188, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 1, 0, 0, 0, 197, 0, - 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 0, 0, 0, 0, 1, 0, - 0, 0, 13, 0, 0, 0, - 202, 0, 0, 0, 2, 0, - 0, 0, 5, 0, 0, 0, - 4, 0, 0, 0, 255, 255, - 255, 255, 4, 0, 0, 0, - 1, 0, 0, 0, 13, 0, - 0, 0, 212, 0, 0, 0, - 2, 0, 0, 0, 5, 0, - 0, 0, 4, 0, 0, 0, - 255, 255, 255, 255, 5, 0, - 0, 0, 1, 0, 0, 0, - 13, 0, 0, 0, 218, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 115, 83, 97, 109, 112, 108, - 101, 114, 0, 116, 82, 71, - 66, 0, 116, 82, 71, 66, - 87, 104, 105, 116, 101, 0, - 116, 77, 97, 115, 107, 0, - 36, 71, 108, 111, 98, 97, - 108, 115, 0, 171, 218, 0, - 0, 0, 10, 0, 0, 0, - 252, 0, 0, 0, 48, 1, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 236, 1, - 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 248, 1, 0, 0, - 0, 0, 0, 0, 8, 2, - 0, 0, 16, 0, 0, 0, - 4, 0, 0, 0, 2, 0, - 0, 0, 24, 2, 0, 0, - 0, 0, 0, 0, 40, 2, - 0, 0, 32, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 56, 2, 0, 0, - 0, 0, 0, 0, 72, 2, - 0, 0, 48, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 88, 2, 0, 0, - 0, 0, 0, 0, 104, 2, - 0, 0, 112, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 88, 2, 0, 0, - 0, 0, 0, 0, 116, 2, - 0, 0, 176, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 248, 1, 0, 0, - 0, 0, 0, 0, 136, 2, - 0, 0, 192, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 152, 2, 0, 0, - 0, 0, 0, 0, 168, 2, - 0, 0, 208, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 152, 2, 0, 0, - 0, 0, 0, 0, 179, 2, - 0, 0, 224, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 152, 2, 0, 0, - 0, 0, 0, 0, 189, 2, - 0, 0, 240, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 88, 2, 0, 0, - 0, 0, 0, 0, 102, 76, - 97, 121, 101, 114, 67, 111, - 108, 111, 114, 0, 1, 0, - 3, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 102, 76, 97, 121, - 101, 114, 79, 112, 97, 99, - 105, 116, 121, 0, 171, 171, - 0, 0, 3, 0, 1, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 105, 66, - 108, 101, 110, 100, 67, 111, - 110, 102, 105, 103, 0, 171, - 171, 171, 1, 0, 19, 0, - 1, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 109, 76, 97, 121, 101, 114, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 3, 0, - 3, 0, 4, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 109, 80, 114, 111, - 106, 101, 99, 116, 105, 111, - 110, 0, 118, 82, 101, 110, - 100, 101, 114, 84, 97, 114, - 103, 101, 116, 79, 102, 102, - 115, 101, 116, 0, 118, 84, - 101, 120, 116, 117, 114, 101, - 67, 111, 111, 114, 100, 115, - 0, 171, 1, 0, 3, 0, - 1, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 118, 76, 97, 121, 101, 114, - 81, 117, 97, 100, 0, 118, - 77, 97, 115, 107, 81, 117, - 97, 100, 0, 109, 66, 97, - 99, 107, 100, 114, 111, 112, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 77, 105, - 99, 114, 111, 115, 111, 102, - 116, 32, 40, 82, 41, 32, - 72, 76, 83, 76, 32, 83, - 104, 97, 100, 101, 114, 32, - 67, 111, 109, 112, 105, 108, - 101, 114, 32, 54, 46, 51, - 46, 57, 54, 48, 48, 46, - 49, 54, 51, 56, 52, 0, - 171, 171, 73, 83, 71, 78, - 104, 0, 0, 0, 3, 0, - 0, 0, 8, 0, 0, 0, - 80, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 92, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 3, 3, 0, 0, - 92, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 12, 12, 0, 0, - 83, 86, 95, 80, 111, 115, - 105, 116, 105, 111, 110, 0, - 84, 69, 88, 67, 79, 79, - 82, 68, 0, 171, 171, 171, - 79, 83, 71, 78, 68, 0, - 0, 0, 2, 0, 0, 0, - 8, 0, 0, 0, 56, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 15, 0, 0, 0, 56, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 15, 0, 0, 0, 83, 86, - 95, 84, 97, 114, 103, 101, - 116, 0, 171, 171 -}; ShaderBytes sComponentAlphaShaderMask = { ComponentAlphaShaderMask, sizeof(ComponentAlphaShaderMask) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -5496,9 +4722,9 @@ ShaderBytes sComponentAlphaShaderMask = { ComponentAlphaShaderMask, sizeof(Compo // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// $Globals cbuffer NA NA cb0 1 // // // @@ -5566,7 +4792,7 @@ ShaderBytes sComponentAlphaShaderMask = { ComponentAlphaShaderMask, sizeof(Compo // approximately 22 instruction slots used vs_4_0 -dcl_constantbuffer cb0[16], immediateIndexed +dcl_constantbuffer CB0[16], immediateIndexed dcl_input v0.xy dcl_output_siv o0.xyzw, position dcl_output o1.xy @@ -5599,10 +4825,10 @@ ret const BYTE LayerQuadBlendVS[] = { - 68, 88, 66, 67, 238, 0, - 14, 218, 242, 150, 72, 155, - 68, 134, 76, 43, 160, 82, - 75, 24, 1, 0, 0, 0, + 68, 88, 66, 67, 76, 129, + 194, 215, 223, 117, 197, 26, + 131, 244, 213, 174, 68, 116, + 23, 183, 1, 0, 0, 0, 12, 9, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 60, 2, 0, 0, 100, 5, @@ -5950,10 +5176,10 @@ const BYTE LayerQuadBlendVS[] = 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 171, 171, 73, 83, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, @@ -5989,7 +5215,7 @@ const BYTE LayerQuadBlendVS[] = ShaderBytes sLayerQuadBlendVS = { LayerQuadBlendVS, sizeof(LayerQuadBlendVS) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -6013,556 +5239,9 @@ ShaderBytes sLayerQuadBlendVS = { LayerQuadBlendVS, sizeof(LayerQuadBlendVS) }; // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 -// -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// POSITION 0 xy 0 NONE float xy -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Position 0 xyzw 0 POS float xyzw -// TEXCOORD 0 xy 1 NONE float xy -// TEXCOORD 2 zw 1 NONE float zw -// TEXCOORD 1 xyz 2 NONE float xyz -// -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c1 cb0 0 2 ( FLT, FLT, FLT, FLT) -// c3 cb0 3 11 ( FLT, FLT, FLT, FLT) -// c14 cb0 15 1 ( FLT, FLT, FLT, FLT) -// -// -// Runtime generated constant mappings: -// -// Target Reg Constant Description -// ---------- -------------------------------------------------- -// c0 Vertex Shader position offset -// -// -// Level9 shader bytecode: -// - vs_2_x - def c15, 1, 0.5, 0, 0 - dcl_texcoord v0 - rcp r0.x, c11.z - mad r0.yz, v0.xxyw, c10.xzww, c10.xxyw - mul r1, r0.z, c2 - mad r1, c1, r0.y, r1 - add r1, r1, c3 - add r0.yz, r1.xxyw, -c11.xxyw - mul oT1.x, r0.x, r0.y - rcp r0.x, c11.w - mul oT1.y, r0.x, r0.z - mad oT0.xy, v0, c9.zwzw, c9 - rcp r0.x, r1.w - mul r1.xyz, r0.x, r1 - add r0, r1, -c8 - mul r0.xyz, r0.w, r0 - mul r1, r0.y, c5 - mad r1, c4, r0.x, r1 - mad r1, c6, r0.z, r1 - mad r0, c7, r0.w, r1 - add r1.xy, r0, c15.x - mad r1.y, r1.y, -c15.y, c15.x - mul r1.x, r1.x, c15.y - mul r1.yz, r1.y, c13.xyxw - mad r1.xy, c12.yxzw, r1.x, r1.yzzw - add oT0.zw, r1.xyxy, c14.xyyx - mad oPos.xy, r0.w, c0, r0 - mov oPos.zw, r0 - mov oT1.z, c15.z - -// approximately 27 instruction slots used -vs_4_0 -dcl_constantbuffer cb0[16], immediateIndexed -dcl_input v0.xy -dcl_output_siv o0.xyzw, position -dcl_output o1.xy -dcl_output o1.zw -dcl_output o2.xyz -dcl_temps 2 -mad r0.xy, v0.xyxx, cb0[10].zwzz, cb0[10].xyxx -mul r1.xyzw, r0.yyyy, cb0[1].xyzw -mad r0.xyzw, cb0[0].xyzw, r0.xxxx, r1.xyzw -add r0.xyzw, r0.xyzw, cb0[3].xyzw -div r1.xyz, r0.xyzx, r0.wwww -mov r1.w, r0.w -add r0.xy, r0.xyxx, -cb0[11].xyxx -div o2.xy, r0.xyxx, cb0[11].zwzz -add r0.xyzw, r1.xyzw, -cb0[8].xyzw -mul r0.xyz, r0.wwww, r0.xyzx -mul r1.xyzw, r0.yyyy, cb0[5].xyzw -mad r1.xyzw, cb0[4].xyzw, r0.xxxx, r1.xyzw -mad r1.xyzw, cb0[6].xyzw, r0.zzzz, r1.xyzw -mad r0.xyzw, cb0[7].xyzw, r0.wwww, r1.xyzw -mov o0.xyzw, r0.xyzw -add r0.xy, r0.xyxx, l(1.000000, 1.000000, 0.000000, 0.000000) -mad r0.y, -r0.y, l(0.500000), l(1.000000) -mul r0.x, r0.x, l(0.500000) -mul r0.yz, r0.yyyy, cb0[13].xxyx -mad r0.xy, cb0[12].xyxx, r0.xxxx, r0.yzyy -add o1.zw, r0.xxxy, cb0[15].xxxy -mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx -mov o2.z, l(0) -ret -// Approximately 24 instruction slots used -#endif - -const BYTE LayerQuadBlendMaskVS[] = -{ - 68, 88, 66, 67, 120, 167, - 168, 154, 138, 114, 232, 254, - 144, 109, 183, 6, 132, 16, - 244, 173, 1, 0, 0, 0, - 148, 9, 0, 0, 6, 0, - 0, 0, 56, 0, 0, 0, - 120, 2, 0, 0, 236, 5, - 0, 0, 104, 6, 0, 0, - 216, 8, 0, 0, 12, 9, - 0, 0, 65, 111, 110, 57, - 56, 2, 0, 0, 56, 2, - 0, 0, 0, 2, 254, 255, - 236, 1, 0, 0, 76, 0, - 0, 0, 3, 0, 36, 0, - 0, 0, 72, 0, 0, 0, - 72, 0, 0, 0, 36, 0, - 1, 0, 72, 0, 0, 0, - 0, 0, 2, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 11, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 15, 0, 1, 0, 14, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 254, 255, - 81, 0, 0, 5, 15, 0, - 15, 160, 0, 0, 128, 63, - 0, 0, 0, 63, 0, 0, - 0, 0, 0, 0, 0, 0, - 31, 0, 0, 2, 5, 0, - 0, 128, 0, 0, 15, 144, - 6, 0, 0, 2, 0, 0, - 1, 128, 11, 0, 170, 160, - 4, 0, 0, 4, 0, 0, - 6, 128, 0, 0, 208, 144, - 10, 0, 248, 160, 10, 0, - 208, 160, 5, 0, 0, 3, - 1, 0, 15, 128, 0, 0, - 170, 128, 2, 0, 228, 160, - 4, 0, 0, 4, 1, 0, - 15, 128, 1, 0, 228, 160, - 0, 0, 85, 128, 1, 0, - 228, 128, 2, 0, 0, 3, - 1, 0, 15, 128, 1, 0, - 228, 128, 3, 0, 228, 160, - 2, 0, 0, 3, 0, 0, - 6, 128, 1, 0, 208, 128, - 11, 0, 208, 161, 5, 0, - 0, 3, 1, 0, 1, 224, - 0, 0, 0, 128, 0, 0, - 85, 128, 6, 0, 0, 2, - 0, 0, 1, 128, 11, 0, - 255, 160, 5, 0, 0, 3, - 1, 0, 2, 224, 0, 0, - 0, 128, 0, 0, 170, 128, - 4, 0, 0, 4, 0, 0, - 3, 224, 0, 0, 228, 144, - 9, 0, 238, 160, 9, 0, - 228, 160, 6, 0, 0, 2, - 0, 0, 1, 128, 1, 0, - 255, 128, 5, 0, 0, 3, - 1, 0, 7, 128, 0, 0, - 0, 128, 1, 0, 228, 128, - 2, 0, 0, 3, 0, 0, - 15, 128, 1, 0, 228, 128, - 8, 0, 228, 161, 5, 0, - 0, 3, 0, 0, 7, 128, - 0, 0, 255, 128, 0, 0, - 228, 128, 5, 0, 0, 3, - 1, 0, 15, 128, 0, 0, - 85, 128, 5, 0, 228, 160, - 4, 0, 0, 4, 1, 0, - 15, 128, 4, 0, 228, 160, - 0, 0, 0, 128, 1, 0, - 228, 128, 4, 0, 0, 4, - 1, 0, 15, 128, 6, 0, - 228, 160, 0, 0, 170, 128, - 1, 0, 228, 128, 4, 0, - 0, 4, 0, 0, 15, 128, - 7, 0, 228, 160, 0, 0, - 255, 128, 1, 0, 228, 128, - 2, 0, 0, 3, 1, 0, - 3, 128, 0, 0, 228, 128, - 15, 0, 0, 160, 4, 0, - 0, 4, 1, 0, 2, 128, - 1, 0, 85, 128, 15, 0, - 85, 161, 15, 0, 0, 160, - 5, 0, 0, 3, 1, 0, - 1, 128, 1, 0, 0, 128, - 15, 0, 85, 160, 5, 0, - 0, 3, 1, 0, 6, 128, - 1, 0, 85, 128, 13, 0, - 196, 160, 4, 0, 0, 4, - 1, 0, 3, 128, 12, 0, - 225, 160, 1, 0, 0, 128, - 1, 0, 233, 128, 2, 0, - 0, 3, 0, 0, 12, 224, - 1, 0, 68, 128, 14, 0, - 20, 160, 4, 0, 0, 4, - 0, 0, 3, 192, 0, 0, - 255, 128, 0, 0, 228, 160, - 0, 0, 228, 128, 1, 0, - 0, 2, 0, 0, 12, 192, - 0, 0, 228, 128, 1, 0, - 0, 2, 1, 0, 4, 224, - 15, 0, 170, 160, 255, 255, - 0, 0, 83, 72, 68, 82, - 108, 3, 0, 0, 64, 0, - 1, 0, 219, 0, 0, 0, - 89, 0, 0, 4, 70, 142, - 32, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 0, 0, 0, 0, 103, 0, - 0, 4, 242, 32, 16, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 101, 0, 0, 3, - 50, 32, 16, 0, 1, 0, - 0, 0, 101, 0, 0, 3, - 194, 32, 16, 0, 1, 0, - 0, 0, 101, 0, 0, 3, - 114, 32, 16, 0, 2, 0, - 0, 0, 104, 0, 0, 2, - 2, 0, 0, 0, 50, 0, - 0, 11, 50, 0, 16, 0, - 0, 0, 0, 0, 70, 16, - 16, 0, 0, 0, 0, 0, - 230, 138, 32, 0, 0, 0, - 0, 0, 10, 0, 0, 0, - 70, 128, 32, 0, 0, 0, - 0, 0, 10, 0, 0, 0, - 56, 0, 0, 8, 242, 0, - 16, 0, 1, 0, 0, 0, - 86, 5, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 50, 0, 0, 10, - 242, 0, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 1, 0, 0, 0, - 0, 0, 0, 8, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 14, 0, 0, 7, - 114, 0, 16, 0, 1, 0, - 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 246, 15, - 16, 0, 0, 0, 0, 0, - 54, 0, 0, 5, 130, 0, - 16, 0, 1, 0, 0, 0, - 58, 0, 16, 0, 0, 0, - 0, 0, 0, 0, 0, 9, - 50, 0, 16, 0, 0, 0, - 0, 0, 70, 0, 16, 0, - 0, 0, 0, 0, 70, 128, - 32, 128, 65, 0, 0, 0, - 0, 0, 0, 0, 11, 0, - 0, 0, 14, 0, 0, 8, - 50, 32, 16, 0, 2, 0, - 0, 0, 70, 0, 16, 0, - 0, 0, 0, 0, 230, 138, - 32, 0, 0, 0, 0, 0, - 11, 0, 0, 0, 0, 0, - 0, 9, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 1, 0, 0, 0, - 70, 142, 32, 128, 65, 0, - 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 56, 0, - 0, 7, 114, 0, 16, 0, - 0, 0, 0, 0, 246, 15, - 16, 0, 0, 0, 0, 0, - 70, 2, 16, 0, 0, 0, - 0, 0, 56, 0, 0, 8, - 242, 0, 16, 0, 1, 0, - 0, 0, 86, 5, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 50, 0, - 0, 10, 242, 0, 16, 0, - 1, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 6, 0, - 16, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 1, 0, - 0, 0, 50, 0, 0, 10, - 242, 0, 16, 0, 1, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 6, 0, - 0, 0, 166, 10, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 1, 0, 0, 0, - 50, 0, 0, 10, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 7, 0, 0, 0, - 246, 15, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 1, 0, 0, 0, 54, 0, - 0, 5, 242, 32, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 50, 0, - 16, 0, 0, 0, 0, 0, - 70, 0, 16, 0, 0, 0, - 0, 0, 2, 64, 0, 0, - 0, 0, 128, 63, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 0, - 0, 10, 34, 0, 16, 0, - 0, 0, 0, 0, 26, 0, - 16, 128, 65, 0, 0, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 0, 63, - 1, 64, 0, 0, 0, 0, - 128, 63, 56, 0, 0, 7, - 18, 0, 16, 0, 0, 0, - 0, 0, 10, 0, 16, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 0, 63, - 56, 0, 0, 8, 98, 0, - 16, 0, 0, 0, 0, 0, - 86, 5, 16, 0, 0, 0, - 0, 0, 6, 129, 32, 0, - 0, 0, 0, 0, 13, 0, - 0, 0, 50, 0, 0, 10, - 50, 0, 16, 0, 0, 0, - 0, 0, 70, 128, 32, 0, - 0, 0, 0, 0, 12, 0, - 0, 0, 6, 0, 16, 0, - 0, 0, 0, 0, 150, 5, - 16, 0, 0, 0, 0, 0, - 0, 0, 0, 8, 194, 32, - 16, 0, 1, 0, 0, 0, - 6, 4, 16, 0, 0, 0, - 0, 0, 6, 132, 32, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 50, 0, 0, 11, - 50, 32, 16, 0, 1, 0, - 0, 0, 70, 16, 16, 0, - 0, 0, 0, 0, 230, 138, - 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 70, 128, - 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 54, 0, - 0, 5, 66, 32, 16, 0, - 2, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 0, 0, - 62, 0, 0, 1, 83, 84, - 65, 84, 116, 0, 0, 0, - 24, 0, 0, 0, 2, 0, - 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 20, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 82, 68, 69, 70, - 104, 2, 0, 0, 1, 0, - 0, 0, 72, 0, 0, 0, - 1, 0, 0, 0, 28, 0, - 0, 0, 0, 4, 254, 255, - 0, 1, 0, 0, 52, 2, - 0, 0, 60, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 36, 71, - 108, 111, 98, 97, 108, 115, - 0, 171, 171, 171, 60, 0, - 0, 0, 10, 0, 0, 0, - 96, 0, 0, 0, 48, 1, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 80, 1, - 0, 0, 0, 0, 0, 0, - 64, 0, 0, 0, 2, 0, - 0, 0, 96, 1, 0, 0, - 0, 0, 0, 0, 112, 1, - 0, 0, 64, 0, 0, 0, - 64, 0, 0, 0, 2, 0, - 0, 0, 96, 1, 0, 0, - 0, 0, 0, 0, 124, 1, - 0, 0, 128, 0, 0, 0, - 16, 0, 0, 0, 2, 0, - 0, 0, 144, 1, 0, 0, - 0, 0, 0, 0, 160, 1, - 0, 0, 144, 0, 0, 0, - 16, 0, 0, 0, 2, 0, - 0, 0, 176, 1, 0, 0, - 0, 0, 0, 0, 192, 1, - 0, 0, 160, 0, 0, 0, - 16, 0, 0, 0, 2, 0, - 0, 0, 176, 1, 0, 0, - 0, 0, 0, 0, 203, 1, - 0, 0, 176, 0, 0, 0, - 16, 0, 0, 0, 2, 0, - 0, 0, 176, 1, 0, 0, - 0, 0, 0, 0, 213, 1, - 0, 0, 192, 0, 0, 0, - 64, 0, 0, 0, 2, 0, - 0, 0, 96, 1, 0, 0, - 0, 0, 0, 0, 232, 1, - 0, 0, 0, 1, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 144, 1, 0, 0, - 0, 0, 0, 0, 244, 1, - 0, 0, 16, 1, 0, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 4, 2, 0, 0, - 0, 0, 0, 0, 20, 2, - 0, 0, 32, 1, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 36, 2, 0, 0, - 0, 0, 0, 0, 109, 76, - 97, 121, 101, 114, 84, 114, - 97, 110, 115, 102, 111, 114, - 109, 0, 3, 0, 3, 0, - 4, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 109, 80, 114, 111, 106, 101, - 99, 116, 105, 111, 110, 0, - 118, 82, 101, 110, 100, 101, - 114, 84, 97, 114, 103, 101, - 116, 79, 102, 102, 115, 101, - 116, 0, 1, 0, 3, 0, - 1, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 118, 84, 101, 120, 116, 117, - 114, 101, 67, 111, 111, 114, - 100, 115, 0, 171, 1, 0, - 3, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 118, 76, 97, 121, - 101, 114, 81, 117, 97, 100, - 0, 118, 77, 97, 115, 107, - 81, 117, 97, 100, 0, 109, - 66, 97, 99, 107, 100, 114, - 111, 112, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 102, 76, 97, 121, 101, 114, - 67, 111, 108, 111, 114, 0, - 102, 76, 97, 121, 101, 114, - 79, 112, 97, 99, 105, 116, - 121, 0, 171, 171, 0, 0, - 3, 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 105, 66, 108, 101, - 110, 100, 67, 111, 110, 102, - 105, 103, 0, 171, 171, 171, - 1, 0, 19, 0, 1, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 77, 105, - 99, 114, 111, 115, 111, 102, - 116, 32, 40, 82, 41, 32, - 72, 76, 83, 76, 32, 83, - 104, 97, 100, 101, 114, 32, - 67, 111, 109, 112, 105, 108, - 101, 114, 32, 54, 46, 51, - 46, 57, 54, 48, 48, 46, - 49, 54, 51, 56, 52, 0, - 171, 171, 73, 83, 71, 78, - 44, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 3, 3, 0, 0, - 80, 79, 83, 73, 84, 73, - 79, 78, 0, 171, 171, 171, - 79, 83, 71, 78, 128, 0, - 0, 0, 4, 0, 0, 0, - 8, 0, 0, 0, 104, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 15, 0, 0, 0, 116, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 3, 12, 0, 0, 116, 0, - 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 12, 3, 0, 0, 116, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 2, 0, 0, 0, - 7, 8, 0, 0, 83, 86, - 95, 80, 111, 115, 105, 116, - 105, 111, 110, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 171, 171, 171 -}; -ShaderBytes sLayerQuadBlendMaskVS = { LayerQuadBlendMaskVS, sizeof(LayerQuadBlendMaskVS) }; -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 -// -// -// Buffer Definitions: -// -// cbuffer $Globals -// { -// -// float4x4 mLayerTransform; // Offset: 0 Size: 64 -// float4x4 mProjection; // Offset: 64 Size: 64 -// float4 vRenderTargetOffset; // Offset: 128 Size: 16 -// float4 vTextureCoords; // Offset: 144 Size: 16 -// float4 vLayerQuad; // Offset: 160 Size: 16 -// float4 vMaskQuad; // Offset: 176 Size: 16 -// float4x4 mBackdropTransform; // Offset: 192 Size: 64 -// float4 fLayerColor; // Offset: 256 Size: 16 [unused] -// float fLayerOpacity; // Offset: 272 Size: 4 [unused] -// uint4 iBlendConfig; // Offset: 288 Size: 16 [unused] -// -// } -// -// -// Resource Bindings: -// -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// $Globals cbuffer NA NA cb0 1 // // // @@ -6610,15 +5289,15 @@ ShaderBytes sLayerQuadBlendMaskVS = { LayerQuadBlendMaskVS, sizeof(LayerQuadBlen mul r2, r1.y, c2 mad r1, c1, r1.x, r2 add r1, r1, c3 - rcp r2.x, r1.w - mad r2.yz, r1.xxyw, r2.x, -c11.xxyw - mul r1.xyz, r1, r2.x - mul r0.x, r0.w, r2.y + add r2.xy, r1, -c11 + mul r0.x, r0.w, r2.x rcp r0.w, c11.w - mul r0.y, r0.w, r2.z + mul r0.y, r0.w, r2.y mul oT1.xyz, r0, r1.w - add r0, r1, -c8 mad oT0.xy, v0, c9.zwzw, c9 + rcp r0.x, r1.w + mul r1.xyz, r0.x, r1 + add r0, r1, -c8 mul r0.xyz, r0.w, r0 mul r1, r0.y, c5 mad r1, c4, r0.x, r1 @@ -6635,55 +5314,56 @@ ShaderBytes sLayerQuadBlendMaskVS = { LayerQuadBlendMaskVS, sizeof(LayerQuadBlen // approximately 28 instruction slots used vs_4_0 -dcl_constantbuffer cb0[16], immediateIndexed +dcl_constantbuffer CB0[16], immediateIndexed dcl_input v0.xy dcl_output_siv o0.xyzw, position dcl_output o1.xy dcl_output o1.zw dcl_output o2.xyz -dcl_temps 3 +dcl_temps 4 mad r0.xy, v0.xyxx, cb0[10].zwzz, cb0[10].xyxx mul r1.xyzw, r0.yyyy, cb0[1].xyzw mad r0.xyzw, cb0[0].xyzw, r0.xxxx, r1.xyzw add r0.xyzw, r0.xyzw, cb0[3].xyzw -div r0.xyz, r0.xyzx, r0.wwww -add r1.xyzw, r0.xyzw, -cb0[8].xyzw +div r1.xyz, r0.xyzx, r0.wwww +mov r1.w, r0.w +add r2.xyzw, r1.xyzw, -cb0[8].xyzw +mul r1.xyz, r2.wwww, r2.xyzx +mul r3.xyzw, r1.yyyy, cb0[5].xyzw +mad r3.xyzw, cb0[4].xyzw, r1.xxxx, r3.xyzw +mad r3.xyzw, cb0[6].xyzw, r1.zzzz, r3.xyzw +mad r2.xyzw, cb0[7].xyzw, r2.wwww, r3.xyzw +mov o0.xyzw, r2.xyzw +add r0.zw, r2.xxxy, l(0.000000, 0.000000, 1.000000, 1.000000) +mad r0.w, -r0.w, l(0.500000), l(1.000000) +mul r0.z, r0.z, l(0.500000) +mul r1.xy, r0.wwww, cb0[13].xyxx +mad r0.zw, cb0[12].xxxy, r0.zzzz, r1.xxxy +add o1.zw, r0.zzzw, cb0[15].xxxy +mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx add r0.xy, r0.xyxx, -cb0[11].xyxx div r0.xy, r0.xyxx, cb0[11].zwzz -mul r1.xyz, r1.wwww, r1.xyzx -mul r2.xyzw, r1.yyyy, cb0[5].xyzw -mad r2.xyzw, cb0[4].xyzw, r1.xxxx, r2.xyzw -mad r2.xyzw, cb0[6].xyzw, r1.zzzz, r2.xyzw -mad r1.xyzw, cb0[7].xyzw, r1.wwww, r2.xyzw -mov o0.xyzw, r1.xyzw -add r1.xy, r1.xyxx, l(1.000000, 1.000000, 0.000000, 0.000000) -mad r1.y, -r1.y, l(0.500000), l(1.000000) -mul r1.x, r1.x, l(0.500000) -mul r1.yz, r1.yyyy, cb0[13].xxyx -mad r1.xy, cb0[12].xyxx, r1.xxxx, r1.yzyy -add o1.zw, r1.xxxy, cb0[15].xxxy -mad o1.xy, v0.xyxx, cb0[9].zwzz, cb0[9].xyxx mov r0.z, l(1.000000) -mul o2.xyz, r0.wwww, r0.xyzx +mul o2.xyz, r1.wwww, r0.xyzx ret -// Approximately 24 instruction slots used +// Approximately 25 instruction slots used #endif -const BYTE LayerQuadBlendMask3DVS[] = +const BYTE LayerQuadBlendMaskVS[] = { - 68, 88, 66, 67, 114, 33, - 168, 234, 171, 245, 21, 91, - 164, 147, 216, 15, 58, 222, - 28, 166, 1, 0, 0, 0, - 176, 9, 0, 0, 6, 0, + 68, 88, 66, 67, 215, 232, + 211, 207, 91, 59, 72, 19, + 182, 146, 63, 212, 224, 141, + 136, 84, 1, 0, 0, 0, + 192, 9, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, - 140, 2, 0, 0, 8, 6, - 0, 0, 132, 6, 0, 0, - 244, 8, 0, 0, 40, 9, + 136, 2, 0, 0, 24, 6, + 0, 0, 148, 6, 0, 0, + 4, 9, 0, 0, 56, 9, 0, 0, 65, 111, 110, 57, - 76, 2, 0, 0, 76, 2, + 72, 2, 0, 0, 72, 2, 0, 0, 0, 2, 254, 255, - 0, 2, 0, 0, 76, 0, + 252, 1, 0, 0, 76, 0, 0, 0, 3, 0, 36, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 36, 0, @@ -6717,379 +5397,381 @@ const BYTE LayerQuadBlendMask3DVS[] = 228, 128, 2, 0, 0, 3, 1, 0, 15, 128, 1, 0, 228, 128, 3, 0, 228, 160, - 6, 0, 0, 2, 2, 0, - 1, 128, 1, 0, 255, 128, - 4, 0, 0, 4, 2, 0, - 6, 128, 1, 0, 208, 128, - 2, 0, 0, 128, 11, 0, - 208, 161, 5, 0, 0, 3, - 1, 0, 7, 128, 1, 0, - 228, 128, 2, 0, 0, 128, - 5, 0, 0, 3, 0, 0, - 1, 128, 0, 0, 255, 128, - 2, 0, 85, 128, 6, 0, - 0, 2, 0, 0, 8, 128, - 11, 0, 255, 160, 5, 0, - 0, 3, 0, 0, 2, 128, + 2, 0, 0, 3, 2, 0, + 3, 128, 1, 0, 228, 128, + 11, 0, 228, 161, 5, 0, + 0, 3, 0, 0, 1, 128, 0, 0, 255, 128, 2, 0, - 170, 128, 5, 0, 0, 3, - 1, 0, 7, 224, 0, 0, - 228, 128, 1, 0, 255, 128, - 2, 0, 0, 3, 0, 0, - 15, 128, 1, 0, 228, 128, - 8, 0, 228, 161, 4, 0, + 0, 128, 6, 0, 0, 2, + 0, 0, 8, 128, 11, 0, + 255, 160, 5, 0, 0, 3, + 0, 0, 2, 128, 0, 0, + 255, 128, 2, 0, 85, 128, + 5, 0, 0, 3, 1, 0, + 7, 224, 0, 0, 228, 128, + 1, 0, 255, 128, 4, 0, 0, 4, 0, 0, 3, 224, 0, 0, 228, 144, 9, 0, 238, 160, 9, 0, 228, 160, - 5, 0, 0, 3, 0, 0, - 7, 128, 0, 0, 255, 128, - 0, 0, 228, 128, 5, 0, - 0, 3, 1, 0, 15, 128, - 0, 0, 85, 128, 5, 0, - 228, 160, 4, 0, 0, 4, - 1, 0, 15, 128, 4, 0, - 228, 160, 0, 0, 0, 128, - 1, 0, 228, 128, 4, 0, - 0, 4, 1, 0, 15, 128, - 6, 0, 228, 160, 0, 0, - 170, 128, 1, 0, 228, 128, - 4, 0, 0, 4, 0, 0, - 15, 128, 7, 0, 228, 160, - 0, 0, 255, 128, 1, 0, - 228, 128, 2, 0, 0, 3, - 1, 0, 3, 128, 0, 0, - 228, 128, 15, 0, 0, 160, - 4, 0, 0, 4, 1, 0, - 2, 128, 1, 0, 85, 128, - 15, 0, 85, 161, 15, 0, - 0, 160, 5, 0, 0, 3, - 1, 0, 1, 128, 1, 0, - 0, 128, 15, 0, 85, 160, + 6, 0, 0, 2, 0, 0, + 1, 128, 1, 0, 255, 128, 5, 0, 0, 3, 1, 0, - 6, 128, 1, 0, 85, 128, - 13, 0, 196, 160, 4, 0, - 0, 4, 1, 0, 3, 128, - 12, 0, 225, 160, 1, 0, - 0, 128, 1, 0, 233, 128, - 2, 0, 0, 3, 0, 0, - 12, 224, 1, 0, 68, 128, - 14, 0, 20, 160, 4, 0, - 0, 4, 0, 0, 3, 192, - 0, 0, 255, 128, 0, 0, - 228, 160, 0, 0, 228, 128, - 1, 0, 0, 2, 0, 0, - 12, 192, 0, 0, 228, 128, - 255, 255, 0, 0, 83, 72, - 68, 82, 116, 3, 0, 0, - 64, 0, 1, 0, 221, 0, - 0, 0, 89, 0, 0, 4, - 70, 142, 32, 0, 0, 0, - 0, 0, 16, 0, 0, 0, - 95, 0, 0, 3, 50, 16, - 16, 0, 0, 0, 0, 0, - 103, 0, 0, 4, 242, 32, - 16, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 101, 0, - 0, 3, 50, 32, 16, 0, - 1, 0, 0, 0, 101, 0, - 0, 3, 194, 32, 16, 0, - 1, 0, 0, 0, 101, 0, - 0, 3, 114, 32, 16, 0, - 2, 0, 0, 0, 104, 0, - 0, 2, 3, 0, 0, 0, - 50, 0, 0, 11, 50, 0, - 16, 0, 0, 0, 0, 0, - 70, 16, 16, 0, 0, 0, - 0, 0, 230, 138, 32, 0, - 0, 0, 0, 0, 10, 0, - 0, 0, 70, 128, 32, 0, - 0, 0, 0, 0, 10, 0, - 0, 0, 56, 0, 0, 8, - 242, 0, 16, 0, 1, 0, - 0, 0, 86, 5, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 50, 0, - 0, 10, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, 0, - 16, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 1, 0, - 0, 0, 0, 0, 0, 8, - 242, 0, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 14, 0, - 0, 7, 114, 0, 16, 0, - 0, 0, 0, 0, 70, 2, - 16, 0, 0, 0, 0, 0, - 246, 15, 16, 0, 0, 0, - 0, 0, 0, 0, 0, 9, - 242, 0, 16, 0, 1, 0, - 0, 0, 70, 14, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 128, 65, 0, 0, 0, - 0, 0, 0, 0, 8, 0, - 0, 0, 0, 0, 0, 9, - 50, 0, 16, 0, 0, 0, - 0, 0, 70, 0, 16, 0, - 0, 0, 0, 0, 70, 128, - 32, 128, 65, 0, 0, 0, - 0, 0, 0, 0, 11, 0, - 0, 0, 14, 0, 0, 8, - 50, 0, 16, 0, 0, 0, - 0, 0, 70, 0, 16, 0, - 0, 0, 0, 0, 230, 138, - 32, 0, 0, 0, 0, 0, - 11, 0, 0, 0, 56, 0, - 0, 7, 114, 0, 16, 0, - 1, 0, 0, 0, 246, 15, + 7, 128, 0, 0, 0, 128, + 1, 0, 228, 128, 2, 0, + 0, 3, 0, 0, 15, 128, + 1, 0, 228, 128, 8, 0, + 228, 161, 5, 0, 0, 3, + 0, 0, 7, 128, 0, 0, + 255, 128, 0, 0, 228, 128, + 5, 0, 0, 3, 1, 0, + 15, 128, 0, 0, 85, 128, + 5, 0, 228, 160, 4, 0, + 0, 4, 1, 0, 15, 128, + 4, 0, 228, 160, 0, 0, + 0, 128, 1, 0, 228, 128, + 4, 0, 0, 4, 1, 0, + 15, 128, 6, 0, 228, 160, + 0, 0, 170, 128, 1, 0, + 228, 128, 4, 0, 0, 4, + 0, 0, 15, 128, 7, 0, + 228, 160, 0, 0, 255, 128, + 1, 0, 228, 128, 2, 0, + 0, 3, 1, 0, 3, 128, + 0, 0, 228, 128, 15, 0, + 0, 160, 4, 0, 0, 4, + 1, 0, 2, 128, 1, 0, + 85, 128, 15, 0, 85, 161, + 15, 0, 0, 160, 5, 0, + 0, 3, 1, 0, 1, 128, + 1, 0, 0, 128, 15, 0, + 85, 160, 5, 0, 0, 3, + 1, 0, 6, 128, 1, 0, + 85, 128, 13, 0, 196, 160, + 4, 0, 0, 4, 1, 0, + 3, 128, 12, 0, 225, 160, + 1, 0, 0, 128, 1, 0, + 233, 128, 2, 0, 0, 3, + 0, 0, 12, 224, 1, 0, + 68, 128, 14, 0, 20, 160, + 4, 0, 0, 4, 0, 0, + 3, 192, 0, 0, 255, 128, + 0, 0, 228, 160, 0, 0, + 228, 128, 1, 0, 0, 2, + 0, 0, 12, 192, 0, 0, + 228, 128, 255, 255, 0, 0, + 83, 72, 68, 82, 136, 3, + 0, 0, 64, 0, 1, 0, + 226, 0, 0, 0, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 16, 0, + 0, 0, 95, 0, 0, 3, + 50, 16, 16, 0, 0, 0, + 0, 0, 103, 0, 0, 4, + 242, 32, 16, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 101, 0, 0, 3, 50, 32, 16, 0, 1, 0, 0, 0, - 70, 2, 16, 0, 1, 0, - 0, 0, 56, 0, 0, 8, - 242, 0, 16, 0, 2, 0, - 0, 0, 86, 5, 16, 0, - 1, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 50, 0, - 0, 10, 242, 0, 16, 0, - 2, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 6, 0, + 101, 0, 0, 3, 194, 32, 16, 0, 1, 0, 0, 0, - 70, 14, 16, 0, 2, 0, - 0, 0, 50, 0, 0, 10, - 242, 0, 16, 0, 2, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 6, 0, - 0, 0, 166, 10, 16, 0, - 1, 0, 0, 0, 70, 14, + 101, 0, 0, 3, 114, 32, 16, 0, 2, 0, 0, 0, - 50, 0, 0, 10, 242, 0, - 16, 0, 1, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 7, 0, 0, 0, - 246, 15, 16, 0, 1, 0, - 0, 0, 70, 14, 16, 0, - 2, 0, 0, 0, 54, 0, - 0, 5, 242, 32, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 1, 0, 0, 0, - 0, 0, 0, 10, 50, 0, - 16, 0, 1, 0, 0, 0, - 70, 0, 16, 0, 1, 0, - 0, 0, 2, 64, 0, 0, - 0, 0, 128, 63, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 50, 0, - 0, 10, 34, 0, 16, 0, - 1, 0, 0, 0, 26, 0, - 16, 128, 65, 0, 0, 0, - 1, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 0, 63, - 1, 64, 0, 0, 0, 0, - 128, 63, 56, 0, 0, 7, - 18, 0, 16, 0, 1, 0, - 0, 0, 10, 0, 16, 0, - 1, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 0, 63, - 56, 0, 0, 8, 98, 0, - 16, 0, 1, 0, 0, 0, - 86, 5, 16, 0, 1, 0, - 0, 0, 6, 129, 32, 0, - 0, 0, 0, 0, 13, 0, - 0, 0, 50, 0, 0, 10, - 50, 0, 16, 0, 1, 0, - 0, 0, 70, 128, 32, 0, - 0, 0, 0, 0, 12, 0, - 0, 0, 6, 0, 16, 0, - 1, 0, 0, 0, 150, 5, - 16, 0, 1, 0, 0, 0, - 0, 0, 0, 8, 194, 32, - 16, 0, 1, 0, 0, 0, - 6, 4, 16, 0, 1, 0, - 0, 0, 6, 132, 32, 0, - 0, 0, 0, 0, 15, 0, + 104, 0, 0, 2, 4, 0, 0, 0, 50, 0, 0, 11, - 50, 32, 16, 0, 1, 0, + 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 0, 0, 0, 0, 230, 138, 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 70, 128, + 10, 0, 0, 0, 70, 128, 32, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 54, 0, - 0, 5, 66, 0, 16, 0, - 0, 0, 0, 0, 1, 64, - 0, 0, 0, 0, 128, 63, - 56, 0, 0, 7, 114, 32, - 16, 0, 2, 0, 0, 0, - 246, 15, 16, 0, 0, 0, - 0, 0, 70, 2, 16, 0, - 0, 0, 0, 0, 62, 0, - 0, 1, 83, 84, 65, 84, - 116, 0, 0, 0, 24, 0, + 10, 0, 0, 0, 56, 0, + 0, 8, 242, 0, 16, 0, + 1, 0, 0, 0, 86, 5, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 50, 0, 0, 10, 242, 0, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 6, 0, 16, 0, 0, 0, + 0, 0, 70, 14, 16, 0, + 1, 0, 0, 0, 0, 0, + 0, 8, 242, 0, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 142, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 5, 0, - 0, 0, 21, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, + 14, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 130, 0, 16, 0, + 1, 0, 0, 0, 58, 0, + 16, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 242, 0, + 16, 0, 2, 0, 0, 0, + 70, 14, 16, 0, 1, 0, + 0, 0, 70, 142, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 7, 114, 0, + 16, 0, 1, 0, 0, 0, + 246, 15, 16, 0, 2, 0, + 0, 0, 70, 2, 16, 0, + 2, 0, 0, 0, 56, 0, + 0, 8, 242, 0, 16, 0, + 3, 0, 0, 0, 86, 5, + 16, 0, 1, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 50, 0, 0, 10, 242, 0, + 16, 0, 3, 0, 0, 0, + 70, 142, 32, 0, 0, 0, + 0, 0, 4, 0, 0, 0, + 6, 0, 16, 0, 1, 0, + 0, 0, 70, 14, 16, 0, + 3, 0, 0, 0, 50, 0, + 0, 10, 242, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 166, 10, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 50, 0, 0, 10, + 242, 0, 16, 0, 2, 0, + 0, 0, 70, 142, 32, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 246, 15, 16, 0, + 2, 0, 0, 0, 70, 14, + 16, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 242, 32, + 16, 0, 0, 0, 0, 0, + 70, 14, 16, 0, 2, 0, + 0, 0, 0, 0, 0, 10, + 194, 0, 16, 0, 0, 0, + 0, 0, 6, 4, 16, 0, + 2, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 63, + 50, 0, 0, 10, 130, 0, + 16, 0, 0, 0, 0, 0, + 58, 0, 16, 128, 65, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 82, 68, 69, 70, 104, 2, - 0, 0, 1, 0, 0, 0, - 72, 0, 0, 0, 1, 0, - 0, 0, 28, 0, 0, 0, - 0, 4, 254, 255, 0, 1, - 0, 0, 52, 2, 0, 0, - 60, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 66, 0, 16, 0, + 0, 0, 0, 0, 42, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 63, 56, 0, 0, 8, + 50, 0, 16, 0, 1, 0, + 0, 0, 246, 15, 16, 0, + 0, 0, 0, 0, 70, 128, + 32, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 50, 0, + 0, 10, 194, 0, 16, 0, + 0, 0, 0, 0, 6, 132, + 32, 0, 0, 0, 0, 0, + 12, 0, 0, 0, 166, 10, + 16, 0, 0, 0, 0, 0, + 6, 4, 16, 0, 1, 0, + 0, 0, 0, 0, 0, 8, + 194, 32, 16, 0, 1, 0, + 0, 0, 166, 14, 16, 0, + 0, 0, 0, 0, 6, 132, + 32, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 50, 0, + 0, 11, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 230, 138, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 70, 128, 32, 0, 0, 0, + 0, 0, 9, 0, 0, 0, + 0, 0, 0, 9, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 70, 128, 32, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, + 14, 0, 0, 8, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 0, 16, 0, 0, 0, + 0, 0, 230, 138, 32, 0, + 0, 0, 0, 0, 11, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 56, 0, + 0, 7, 114, 32, 16, 0, + 2, 0, 0, 0, 246, 15, + 16, 0, 1, 0, 0, 0, + 70, 2, 16, 0, 0, 0, + 0, 0, 62, 0, 0, 1, + 83, 84, 65, 84, 116, 0, + 0, 0, 25, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, + 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 36, 71, 108, 111, - 98, 97, 108, 115, 0, 171, - 171, 171, 60, 0, 0, 0, - 10, 0, 0, 0, 96, 0, - 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 80, 1, 0, 0, - 0, 0, 0, 0, 64, 0, - 0, 0, 2, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 112, 1, 0, 0, - 64, 0, 0, 0, 64, 0, - 0, 0, 2, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 124, 1, 0, 0, - 128, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 144, 1, 0, 0, 0, 0, - 0, 0, 160, 1, 0, 0, - 144, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 192, 1, 0, 0, - 160, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 203, 1, 0, 0, - 176, 0, 0, 0, 16, 0, - 0, 0, 2, 0, 0, 0, - 176, 1, 0, 0, 0, 0, - 0, 0, 213, 1, 0, 0, - 192, 0, 0, 0, 64, 0, - 0, 0, 2, 0, 0, 0, - 96, 1, 0, 0, 0, 0, - 0, 0, 232, 1, 0, 0, - 0, 1, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 144, 1, 0, 0, 0, 0, - 0, 0, 244, 1, 0, 0, - 16, 1, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, - 4, 2, 0, 0, 0, 0, - 0, 0, 20, 2, 0, 0, - 32, 1, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 36, 2, 0, 0, 0, 0, - 0, 0, 109, 76, 97, 121, - 101, 114, 84, 114, 97, 110, - 115, 102, 111, 114, 109, 0, - 3, 0, 3, 0, 4, 0, - 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 109, 80, - 114, 111, 106, 101, 99, 116, - 105, 111, 110, 0, 118, 82, - 101, 110, 100, 101, 114, 84, - 97, 114, 103, 101, 116, 79, - 102, 102, 115, 101, 116, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 82, 68, + 69, 70, 104, 2, 0, 0, + 1, 0, 0, 0, 72, 0, + 0, 0, 1, 0, 0, 0, + 28, 0, 0, 0, 0, 4, + 254, 255, 0, 1, 0, 0, + 52, 2, 0, 0, 60, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 36, 71, 108, 111, 98, 97, + 108, 115, 0, 171, 171, 171, + 60, 0, 0, 0, 10, 0, + 0, 0, 96, 0, 0, 0, + 48, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 80, 1, 0, 0, 0, 0, + 0, 0, 64, 0, 0, 0, + 2, 0, 0, 0, 96, 1, + 0, 0, 0, 0, 0, 0, + 112, 1, 0, 0, 64, 0, + 0, 0, 64, 0, 0, 0, + 2, 0, 0, 0, 96, 1, + 0, 0, 0, 0, 0, 0, + 124, 1, 0, 0, 128, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 160, 1, 0, 0, 144, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 1, + 0, 0, 0, 0, 0, 0, + 192, 1, 0, 0, 160, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 1, + 0, 0, 0, 0, 0, 0, + 203, 1, 0, 0, 176, 0, + 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 176, 1, + 0, 0, 0, 0, 0, 0, + 213, 1, 0, 0, 192, 0, + 0, 0, 64, 0, 0, 0, + 2, 0, 0, 0, 96, 1, + 0, 0, 0, 0, 0, 0, + 232, 1, 0, 0, 0, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 144, 1, + 0, 0, 0, 0, 0, 0, + 244, 1, 0, 0, 16, 1, + 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 4, 2, + 0, 0, 0, 0, 0, 0, + 20, 2, 0, 0, 32, 1, + 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 36, 2, + 0, 0, 0, 0, 0, 0, + 109, 76, 97, 121, 101, 114, + 84, 114, 97, 110, 115, 102, + 111, 114, 109, 0, 3, 0, + 3, 0, 4, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 109, 80, 114, 111, + 106, 101, 99, 116, 105, 111, + 110, 0, 118, 82, 101, 110, + 100, 101, 114, 84, 97, 114, + 103, 101, 116, 79, 102, 102, + 115, 101, 116, 0, 1, 0, + 3, 0, 1, 0, 4, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 118, 84, 101, 120, + 116, 117, 114, 101, 67, 111, + 111, 114, 100, 115, 0, 171, 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 118, 84, - 101, 120, 116, 117, 114, 101, - 67, 111, 111, 114, 100, 115, - 0, 171, 1, 0, 3, 0, + 0, 0, 0, 0, 118, 76, + 97, 121, 101, 114, 81, 117, + 97, 100, 0, 118, 77, 97, + 115, 107, 81, 117, 97, 100, + 0, 109, 66, 97, 99, 107, + 100, 114, 111, 112, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 102, 76, 97, 121, + 101, 114, 67, 111, 108, 111, + 114, 0, 102, 76, 97, 121, + 101, 114, 79, 112, 97, 99, + 105, 116, 121, 0, 171, 171, + 0, 0, 3, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 105, 66, + 108, 101, 110, 100, 67, 111, + 110, 102, 105, 103, 0, 171, + 171, 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 76, 97, 121, 101, 114, - 81, 117, 97, 100, 0, 118, - 77, 97, 115, 107, 81, 117, - 97, 100, 0, 109, 66, 97, - 99, 107, 100, 114, 111, 112, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 102, 76, - 97, 121, 101, 114, 67, 111, - 108, 111, 114, 0, 102, 76, - 97, 121, 101, 114, 79, 112, - 97, 99, 105, 116, 121, 0, - 171, 171, 0, 0, 3, 0, - 1, 0, 1, 0, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 105, 66, 108, 101, 110, 100, - 67, 111, 110, 102, 105, 103, - 0, 171, 171, 171, 1, 0, - 19, 0, 1, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 77, 105, 99, 114, - 111, 115, 111, 102, 116, 32, - 40, 82, 41, 32, 72, 76, - 83, 76, 32, 83, 104, 97, - 100, 101, 114, 32, 67, 111, - 109, 112, 105, 108, 101, 114, - 32, 54, 46, 51, 46, 57, - 54, 48, 48, 46, 49, 54, - 51, 56, 52, 0, 171, 171, - 73, 83, 71, 78, 44, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 3, + 0, 0, 80, 79, 83, 73, + 84, 73, 79, 78, 0, 171, + 171, 171, 79, 83, 71, 78, + 128, 0, 0, 0, 4, 0, + 0, 0, 8, 0, 0, 0, + 104, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 32, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 3, 12, 0, 0, + 116, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 0, 0, 80, 79, - 83, 73, 84, 73, 79, 78, - 0, 171, 171, 171, 79, 83, - 71, 78, 128, 0, 0, 0, - 4, 0, 0, 0, 8, 0, - 0, 0, 104, 0, 0, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 3, 0, 0, 0, - 0, 0, 0, 0, 15, 0, - 0, 0, 116, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 12, 3, 0, 0, + 116, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 3, 12, - 0, 0, 116, 0, 0, 0, - 2, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 1, 0, 0, 0, 12, 3, - 0, 0, 116, 0, 0, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, - 2, 0, 0, 0, 7, 8, - 0, 0, 83, 86, 95, 80, - 111, 115, 105, 116, 105, 111, - 110, 0, 84, 69, 88, 67, - 79, 79, 82, 68, 0, 171, - 171, 171 + 3, 0, 0, 0, 2, 0, + 0, 0, 7, 8, 0, 0, + 83, 86, 95, 80, 111, 115, + 105, 116, 105, 111, 110, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 171, 171, 171 }; -ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuadBlendMask3DVS) }; +ShaderBytes sLayerQuadBlendMaskVS = { LayerQuadBlendMaskVS, sizeof(LayerQuadBlendMaskVS) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -7113,17 +5795,16 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// sSampler sampler NA NA 0 1 -// LayerTextureSamplerLinear sampler NA NA 1 1 -// tRGB texture float4 2d 0 1 -// tY texture float4 2d 1 1 -// tCb texture float4 2d 2 1 -// tCr texture float4 2d 3 1 -// tMask texture float4 2d 5 1 -// tBackdrop texture float4 2d 6 1 -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// sSampler sampler NA NA s0 1 +// tRGB texture float4 2d t0 1 +// tY texture float4 2d t1 1 +// tCb texture float4 2d t2 1 +// tCr texture float4 2d t3 1 +// tMask texture float4 2d t5 1 +// tBackdrop texture float4 2d t6 1 +// $Globals cbuffer NA NA cb0 1 // // // @@ -7162,7 +5843,6 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad // s3 s0 t3 // s4 s0 t5 // s5 s0 t6 -// s6 s1 t5 // // // Level9 shader bytecode: @@ -7170,11 +5850,11 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad ps_2_x def c3, -1, -2, -0.50195998, -0.0627499968 def c4, 1.59603, 0.812969983, 1.16437995, 2.01723003 - def c5, -1, -2, -3, -4 - def c6, -5, -6, -7, -8 + def c5, -2, -3, -4, -5 + def c6, -6, -7, -8, -9 def c7, 1, 0.25, 2, -1 - def c8, 16, -12, -13, -14 - def c9, -9, -10, -11, -12 + def c8, 16, -12, -14, 0 + def c9, -10, -11, -12, -13 def c10, 0.300000012, 0.589999974, 0.109999999, 0 def c11, 0.391759992, -1, -0, -0.5 dcl t0 @@ -7185,7 +5865,6 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad dcl_2d s3 dcl_2d s4 dcl_2d s5 - dcl_2d s6 mov r0.x, -c11.z mov r1.x, -c11.z mov r2.z, -c11.z @@ -7196,8 +5875,10 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad add r0.w, r3.x, c3.w mad r1.w, r0.w, c4.z, -r3.z mad r3.x, r0.w, c4.z, r3.y - texld r4, t1, s4 + rcp r2.w, t1.z + mul r4.xy, r2.w, t1 texld r5, t0, s2 + texld r4, r4, s4 add r2.w, r5.x, c3.z mad r3.y, r2.w, -c11.x, r1.w mul r1.w, r2.w, c4.w @@ -7205,32 +5886,29 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad mov r3.w, -c3.x mul r3, r3, c1.x mul r5, r4.x, r3 - rcp r0.w, t1.z - mul r6.xy, r0.w, t1 + mov r6.xy, t0.wzzw texld r7, t0, s0 - texld r6, r6, s6 + texld r6, r6, s5 mul r7, r7, c1.x mul r8, r4.x, r7 mov r9.xy, c3 - add r10, r9.xyxy, c2.xxyy + add r10, r9.xyxx, c2.xxyz mul r10, r10, r10 cmp r5, -r10.x, r8, r5 - mov r8.xyz, r7 - mov r8.w, c1.x - mul r11, r4.x, r8 - mul r4, r4.x, c0 - cmp r5, -c2.x, r11, r5 - cmp r6.yz, -r10.xyww, c11.y, c11.z - cmp r6.yz, -r10.xxzw, c3.x, r6 - cmp r6.yz, -c2.xxyw, r9.x, r6 - cmp r4, r6.y, r4, r5 - mul r5, r6.x, r7 cmp r3, -r10.x, r7, r3 - cmp r4, -r10.z, r4, r5 - cmp r3, -c2.x, r8, r3 - cmp r3, r6.y, c0, r3 + mov r7.w, c1.x + mul r8, r4.x, r7 + cmp r3, -c2.x, r7, r3 + mul r4, r4.x, c0 + cmp r5, -c2.x, r8, r5 + cmp r7.xy, -r10.yzzw, c11.y, c11.z + cmp r0.w, -r10.x, c3.x, r7.x + cmp r1.w, -c2.y, r9.x, r7.y + cmp r0.w, -c2.x, r9.x, r0.w + cmp r4, r0.w, r4, r5 + cmp r3, r0.w, c0, r3 cmp r3, -c2.y, r3, r4 - cmp r3, r6.z, -c11.zzzy, r3 + cmp r3, r1.w, -c11.zzzy, r3 rcp r0.w, r3.w mul r4.xyz, r0.w, r3 cmp r4.xyz, -c2.w, r3, r4 @@ -7238,42 +5916,40 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad cmp r5.zw, r5.x, r4.xyxy, r4.xyyx max r0.w, r5.z, r4.z min r1.w, r4.z, r5.w - add r6.w, r0.w, -r1.w - mov r7.xy, t0.wzzw - texld r7, r7, s5 - rcp r0.w, r7.w - mul r8.xyz, r0.w, r7 - mad r5.zw, r7.xyzy, r0.w, -r8.xyxz - mul r9.xy, r6.w, r5.zwzw - mad r10, r7.yxxz, r0.w, -r8.xzyy - rcp r1.w, r10.x - mul r6.y, r1.w, r9.x - cmp r1.yz, r10.z, -c11.z, r6.xwyw - mul r11, r6.w, r10 + add r7.w, r0.w, -r1.w + rcp r0.w, r6.w + mul r8.xyz, r0.w, r6 + mad r5.zw, r6.xyzy, r0.w, -r8.xyxz + mul r9.xy, r7.w, r5.zwzw + mad r11, r6.yxxz, r0.w, -r8.xzyy + rcp r1.w, r11.x + mul r7.y, r1.w, r9.x + cmp r1.yz, r11.z, -c11.z, r7.xwyw + mul r12, r7.w, r11 rcp r1.w, r5.w - mul r6.x, r1.w, r11.y - cmp r2.xy, r10.w, -c11.z, r6.xwzw + mul r7.x, r1.w, r12.y + cmp r2.xy, r11.w, -c11.z, r7.xwzw cmp r1.xyz, r5.z, r1, r2 rcp r1.w, r5.z - mul r6.z, r1.w, r11.x - cmp r0.yz, r10.y, -c11.z, r6.xzww - cmp r0.xyz, r10.w, r0, r1 + mul r7.z, r1.w, r12.x + cmp r0.yz, r11.y, -c11.z, r7.xzww + cmp r0.xyz, r11.w, r0, r1 mov r1.y, -c11.z mov r2.y, -c11.z - mov r12.z, -c11.z - rcp r1.w, r10.z - mul r6.y, r1.w, r11.w - cmp r2.xz, r10.x, -c11.z, r6.wyyw - rcp r1.w, r10.y - mul r6.x, r1.w, r9.y - cmp r12.xy, r5.z, -c11.z, r6.wxzw - cmp r2.xyz, r10.w, r2, r12 - rcp r1.w, r10.w - mul r6.z, r1.w, r11.z - cmp r1.xz, r5.w, -c11.z, r6.zyww + mov r10.z, -c11.z + rcp r1.w, r11.z + mul r7.y, r1.w, r12.w + cmp r2.xz, r11.x, -c11.z, r7.wyyw + rcp r1.w, r11.y + mul r7.x, r1.w, r9.y + cmp r10.xy, r5.z, -c11.z, r7.wxzw + cmp r2.xyz, r11.w, r2, r10 + rcp r1.w, r11.w + mul r7.z, r1.w, r12.z + cmp r1.xz, r5.w, -c11.z, r7.zyww cmp r1.xyz, r5.z, r1, r2 - cmp r0.xyz, r10.x, r0, r1 - cmp r1.xy, r10.z, r8, r8.yxzw + cmp r0.xyz, r11.x, r0, r1 + cmp r1.xy, r11.z, r8, r8.yxzw dp3 r4.w, c10, r0 dp3 r8.w, c10, r8 add r4.w, -r4.w, r8.w @@ -7298,66 +5974,66 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad mad r2.xyz, r2.yzww, r1.w, r1.z cmp r0.xyz, r4.w, r0, r2 mov r4.w, c2.z - add r1.zw, r4.w, c8 - mul r1.zw, r1, r1 - dp3 r2.x, c10, r4 - add r2.y, -r8.w, r2.x - add r2.x, -r2.x, r8.w - add r2.xzw, r2.x, r4.xyyz - mad r6.xyz, r7, r0.w, r2.y - add r6.w, -r6.y, r6.x - cmp r5.zw, r6.w, r6.xyyx, r6.xyxy - min r2.y, r6.z, r5.z - max r9.x, r5.w, r6.z - dp3 r6.w, c10, r6 - add r5.z, -r2.y, r6.w + add r1.z, r4.w, c8.z + mul r1.z, r1.z, r1.z + dp3 r1.w, c10, r4 + add r2.x, -r8.w, r1.w + add r1.w, -r1.w, r8.w + add r2.yzw, r1.w, r4.xxyz + mad r7.xyz, r6, r0.w, r2.x + add r1.w, -r7.y, r7.x + cmp r5.zw, r1.w, r7.xyyx, r7.xyxy + min r1.w, r7.z, r5.z + max r2.x, r5.w, r7.z + dp3 r7.w, c10, r7 + add r5.z, -r1.w, r7.w rcp r5.z, r5.z - add r9.yzw, -r6.w, r6.xxyz - mul r9.yzw, r6.w, r9 - mad r9.yzw, r9, r5.z, r6.w - cmp r6.xyz, r2.y, r6, r9.yzww - add r9.yzw, -r6.w, r6.xxyz - add r2.y, -r6.w, -c3.x - mul r9.yzw, r2.y, r9 - add r2.y, -r6.w, r9.x - add r5.z, -r9.x, -c3.x - rcp r5.w, r2.y - mad r9.xyz, r9.yzww, r5.w, r6.w - cmp r6.xyz, r5.z, r6, r9 - cmp r6.xyz, -r1.w, r6, -c11.z - add r1.w, -r2.z, r2.x - cmp r5.zw, r1.w, r2.xyzx, r2.xyxz - min r1.w, r2.w, r5.z - max r6.w, r5.w, r2.w - dp3 r2.y, c10, r2.xzww - add r5.z, -r1.w, r2.y - rcp r5.z, r5.z - add r9.xyz, -r2.y, r2.xzww - mul r9.xyz, r2.y, r9 - mad r9.xyz, r9, r5.z, r2.y - cmp r2.xzw, r1.w, r2, r9.xyyz - add r9.xyz, -r2.y, r2.xzww - add r1.w, -r2.y, -c3.x + add r9.xyz, -r7.w, r7 + mul r9.xyz, r7.w, r9 + mad r9.xyz, r9, r5.z, r7.w + cmp r7.xyz, r1.w, r7, r9 + add r9.xyz, -r7.w, r7 + add r1.w, -r7.w, -c3.x mul r9.xyz, r1.w, r9 - add r1.w, -r2.y, r6.w - add r6.w, -r6.w, -c3.x + add r1.w, r2.x, -r7.w + add r9.w, -r2.x, -c3.x rcp r1.w, r1.w - mad r9.xyz, r9, r1.w, r2.y - cmp r2.xyz, r6.w, r2.xzww, r9 - cmp r2.xyz, -r1.z, r2, r6 - add r6, r4.w, c9 - mul r6, r6, r6 - cmp r0.xyz, -r6.w, r0, r2 + mad r9.xyz, r9, r1.w, r7.w + cmp r7.xyz, r9.w, r7, r9 + cmp r7.xyz, -r1.z, r7, -c11.z + add r7.w, -r2.z, r2.y + cmp r1.zw, r7.w, r2.xyzy, r2.xyyz + min r7.w, r2.w, r1.z + max r5.z, r1.w, r2.w + dp3 r5.w, c10, r2.yzww + add r1.z, -r7.w, r5.w + rcp r1.z, r1.z + add r9.xyz, r2.yzww, -r5.w + mul r9.xyz, r5.w, r9 + mad r9.xyz, r9, r1.z, r5.w + cmp r2.xyz, r7.w, r2.yzww, r9 + add r9.xyz, -r5.w, r2 + add r2.w, -r5.w, -c3.x + mul r9.xyz, r2.w, r9 + add r2.w, -r5.w, r5.z + add r7.w, -r5.z, -c3.x + rcp r2.w, r2.w + mad r9.xyz, r9, r2.w, r5.w + cmp r2.xyz, r7.w, r2, r9 + add r9, r4.w, c9 + mul r9, r9, r9 + cmp r2.xyz, -r9.w, r2, r7 + cmp r0.xyz, -r9.z, r0, r2 add r2, -r4.xxzy, r4.yzxz - mov r9.y, -c11.z + mov r7.y, -c11.z mov r10.y, -c11.z mov r11.z, -c11.z - rcp r6.w, r2.z - max r9.w, r1.x, r8.z - min r10.w, r8.z, r1.y - add r1.w, r9.w, -r10.w + rcp r7.w, r2.z + max r11.w, r1.x, r8.z + min r5.z, r8.z, r1.y + add r1.w, -r5.z, r11.w mul r5.zw, r1.w, r5.xyxy - mul r1.x, r6.w, r5.w + mul r1.x, r7.w, r5.w cmp r11.xy, r2.y, -c11.z, r1.wxzw rcp r5.w, r5.x mul r12, r1.w, r2 @@ -7366,161 +6042,160 @@ ShaderBytes sLayerQuadBlendMask3DVS = { LayerQuadBlendMask3DVS, sizeof(LayerQuad cmp r10.xyz, r2.w, r10, r11 rcp r5.w, r2.w mul r1.z, r5.w, r5.z - cmp r9.xz, r5.y, -c11.z, r1.zyww - cmp r9.xyz, r2.y, r9, r10 + cmp r7.xz, r5.y, -c11.z, r1.zyww + cmp r7.xyz, r2.y, r7, r10 mov r10.x, -c11.z mov r11.x, -c11.z mov r13.z, -c11.z - rcp r6.w, r2.x - mul r1.y, r6.w, r12.y + rcp r7.w, r2.x + mul r1.y, r7.w, r12.y cmp r11.yz, r5.x, -c11.z, r1.xwyw - rcp r6.w, r5.y - mul r1.x, r6.w, r12.z + rcp r7.w, r5.y + mul r1.x, r7.w, r12.z cmp r13.xy, r2.w, -c11.z, r1.xwzw cmp r5.xyz, r2.y, r11, r13 rcp r5.w, r2.y mul r1.z, r5.w, r12.x cmp r10.yz, r2.z, -c11.z, r1.xzww cmp r1.xyz, r2.w, r10, r5 - cmp r1.xyz, r2.x, r1, r9 + cmp r1.xyz, r2.x, r1, r7 dp3 r1.w, c10, r1 add r1.w, -r1.w, r8.w add r1.xyz, r1.w, r1 add r1.w, -r1.y, r1.x cmp r2.xy, r1.w, r1.yxzw, r1 - min r6.w, r1.z, r2.x - max r8.w, r2.y, r1.z + min r8.w, r1.z, r2.x + max r5.x, r2.y, r1.z dp3 r1.w, c10, r1 - add r2.x, -r6.w, r1.w + add r2.x, -r8.w, r1.w rcp r2.x, r2.x add r2.yzw, -r1.w, r1.xxyz mul r2.yzw, r1.w, r2 mad r2.xyz, r2.yzww, r2.x, r1.w - cmp r1.xyz, r6.w, r1, r2 + cmp r1.xyz, r8.w, r1, r2 add r2.xyz, -r1.w, r1 add r2.w, -r1.w, -c3.x mul r2.xyz, r2.w, r2 - add r2.w, -r1.w, r8.w - add r6.w, -r8.w, -c3.x + add r2.w, -r1.w, r5.x + add r8.w, -r5.x, -c3.x rcp r2.w, r2.w mad r2.xyz, r2, r2.w, r1.w - cmp r1.xyz, r6.w, r1, r2 - cmp r0.xyz, -r6.z, r1, r0 - mad r1.xyz, r7, r0.w, r4 + cmp r1.xyz, r8.w, r1, r2 + cmp r0.xyz, -r9.y, r1, r0 + mad r1.xyz, r6, r0.w, r4 mul r2.xyz, r4, r8 mad r5.xyz, r2, c3.y, r1 mad r1.xyz, r8, -r4, r1 - cmp r0.xyz, -r6.y, r5, r0 - mad r5.xyz, r7, r0.w, -r4 + cmp r0.xyz, -r9.x, r5, r0 + mad r5.xyz, r6, r0.w, -r4 abs r5.xyz, r5 - cmp r0.xyz, -r6.x, r5, r0 + add r7, r4.w, c6 + mul r7, r7, r7 + cmp r0.xyz, -r7.w, r5, r0 add r5.xy, -r4.yzzw, -c11.w - mad r6.xyz, r4, c7.z, c7.w - mad r1.w, r7.z, -r0.w, c7.y - mad r9.xyz, r8, c8.x, c8.y - mad r9.xyz, r9, r8, -c5.w - mul r9.xyz, r8, r9 + mad r9.xyz, r4, c7.z, c7.w + mad r1.w, r6.z, -r0.w, c7.y + mad r10.xyz, r8, c8.x, c8.y + mad r10.xyz, r10, r8, -c5.z + mul r10.xyz, r8, r10 rsq r2.w, r8.z rcp r2.w, r2.w - cmp r1.w, r1.w, r9.z, r2.w - mad r1.w, r7.z, -r0.w, r1.w - mad r1.w, r6.z, r1.w, r8.z - mad r10.xyz, r4, c3.y, -c3.x - mul r10.xyz, r8, r10 - mad r11, r7.yzxy, -r0.w, c7.xxyy - mad r5.zw, r10.xyyz, -r11.xyxy, r8.xyyz - cmp r12.z, r5.y, r5.w, r1.w + cmp r1.w, r1.w, r10.z, r2.w + mad r1.w, r6.z, -r0.w, r1.w + mad r1.w, r9.z, r1.w, r8.z + mad r11.xyz, r4, c3.y, -c3.x + mul r11.xyz, r8, r11 + mad r12, r6.yzxy, -r0.w, c7.xxyy + mad r5.zw, r11.xyyz, -r12.xyxy, r8.xyyz + cmp r13.z, r5.y, r5.w, r1.w rsq r1.w, r8.y rcp r1.w, r1.w - cmp r1.w, r11.w, r9.y, r1.w - mad r1.w, r7.y, -r0.w, r1.w - mad r1.w, r6.y, r1.w, r8.y - cmp r12.y, r5.x, r5.z, r1.w - add r13, r4.w, c6 - mul r13, r13, r13 + cmp r1.w, r12.w, r10.y, r1.w + mad r1.w, r6.y, -r0.w, r1.w + mad r1.w, r9.y, r1.w, r8.y + cmp r13.y, r5.x, r5.z, r1.w add r14, -r4.xyzx, -c11.yyyw rsq r1.w, r8.x rcp r1.w, r1.w - cmp r1.w, r11.z, r9.x, r1.w - mad r1.w, r7.x, -r0.w, r1.w - mad r1.w, r6.x, r1.w, r8.x - mad r6, r7.xyzx, -r0.w, -c11.wwwy - mad r9.xyz, r7, r0.w, c3.x - mul r9.xyz, r9, r9 - mad r0.w, r10.x, -r6.w, r8.x - cmp r12.x, r14.w, r0.w, r1.w - cmp r0.xyz, -r13.w, r12, r0 - add r10.xyz, r8, r8 - mad r12.xyz, r4, -c3.y, r10 - add r12.xyz, r12, c3.x - mad r15.xyz, r4, -r10, r12 - mul r10.xyz, r4, r10 + cmp r1.w, r12.z, r10.x, r1.w + mad r1.w, r6.x, -r0.w, r1.w + mad r1.w, r9.x, r1.w, r8.x + mad r9, r6.xyzx, -r0.w, -c11.wwwy + mad r10.xyz, r6, r0.w, c3.x + mul r10.xyz, r10, r10 + mad r0.w, r11.x, -r9.w, r8.x + cmp r13.x, r14.w, r0.w, r1.w + cmp r0.xyz, -r7.z, r13, r0 + add r11.xyz, r8, r8 + mad r13.xyz, r4, -c3.y, r11 + add r13.xyz, r13, c3.x + mad r15.xyz, r4, -r11, r13 + mul r11.xyz, r4, r11 add r16.xyz, r4, r4 mul r17.xyz, r8, r16 - mad r12.xyz, r16, -r8, r12 - cmp r6.xyz, r6, r10, r12 + mad r13.xyz, r16, -r8, r13 + cmp r9.xyz, r9, r11, r13 cmp r5.yz, r5.xxyw, r17, r15 cmp r5.x, r14.w, r17.x, r15.x - cmp r0.xyz, -r13.z, r5, r0 + cmp r0.xyz, -r7.y, r5, r0 rcp r0.w, r4.x - mad r0.w, r6.w, -r0.w, -c3.x + mad r0.w, r9.w, -r0.w, -c3.x max r1.w, r0.w, -c11.z mul r5.xyz, r4, r4 cmp r0.w, -r5.x, -c11.z, r1.w - cmp r10.x, -r9.x, -c3.x, r0.w + cmp r11.x, -r10.x, -c3.x, r0.w rcp r0.w, r4.y - mad r0.w, r11.x, -r0.w, -c3.x + mad r0.w, r12.x, -r0.w, -c3.x max r1.w, r0.w, -c11.z cmp r0.w, -r5.y, -c11.z, r1.w - cmp r10.y, -r9.y, -c3.x, r0.w + cmp r11.y, -r10.y, -c3.x, r0.w rcp r0.w, r4.z - mad r0.w, r11.y, -r0.w, -c3.x + mad r0.w, r12.y, -r0.w, -c3.x max r1.w, r0.w, -c11.z cmp r0.w, -r5.z, -c11.z, r1.w - cmp r10.z, -r9.z, -c3.x, r0.w - cmp r0.xyz, -r13.y, r10, r0 - add r5.xyz, r4, c3.x - mul r5.xyz, r5, r5 + cmp r11.z, -r10.z, -c3.x, r0.w + cmp r0.xyz, -r7.x, r11, r0 + add r5, r4.w, c5 + mul r5, r5, r5 + add r7.xyz, r4, c3.x + mul r7.xyz, r7, r7 rcp r0.w, r14.x mul r0.w, r0.w, r8.x min r1.w, r0.w, -c3.x - cmp r0.w, -r5.x, -c3.x, r1.w - mul r9.xyz, r8, r8 - cmp r10.x, -r9.x, -c11.z, r0.w + cmp r0.w, -r7.x, -c3.x, r1.w + mul r10.xyz, r8, r8 + cmp r11.x, -r10.x, -c11.z, r0.w rcp r0.w, r14.y rcp r1.w, r14.z mul r1.w, r1.w, r8.z min r2.w, r1.w, -c3.x - cmp r1.w, -r5.z, -c3.x, r2.w - cmp r10.z, -r9.z, -c11.z, r1.w + cmp r1.w, -r7.z, -c3.x, r2.w + cmp r11.z, -r10.z, -c11.z, r1.w mul r0.w, r0.w, r8.y min r1.w, r0.w, -c3.x - cmp r0.w, -r5.y, -c3.x, r1.w - cmp r10.y, -r9.y, -c11.z, r0.w - cmp r0.xyz, -r13.x, r10, r0 - add r5, r4.w, c5 - mul r5, r5, r5 - max r9.xyz, r8, r4 + cmp r0.w, -r7.y, -c3.x, r1.w + cmp r11.y, -r10.y, -c11.z, r0.w + cmp r0.xyz, -r5.w, r11, r0 + max r7.xyz, r8, r4 min r10.xyz, r4, r8 - cmp r0.xyz, -r5.w, r9, r0 - cmp r0.xyz, -r5.z, r10, r0 - cmp r0.xyz, -r5.y, r6, r0 - cmp r0.xyz, -r5.x, r1, r0 + cmp r0.xyz, -r5.z, r7, r0 + cmp r0.xyz, -r5.y, r10, r0 + cmp r0.xyz, -r5.x, r9, r0 + cmp r0.xyz, -r10.w, r1, r0 cmp r0.xyz, -c2.z, r2, r0 - lrp r1.xyz, r7.w, r0, r4 + lrp r1.xyz, r6.w, r0, r4 mul r0.xyz, r3.w, r1 mul r1.x, r3.w, r3.w mov r0.w, r3.w - cmp r0, -r1.x, r7, r0 - mul r1.x, r7.w, r7.w + cmp r0, -r1.x, r6, r0 + mul r1.x, r6.w, r6.w cmp r0, -r1.x, r3, r0 mov oC0, r0 -// approximately 329 instruction slots used (7 texture, 322 arithmetic) +// approximately 326 instruction slots used (6 texture, 320 arithmetic) ps_4_0 -dcl_constantbuffer cb0[3], immediateIndexed +dcl_constantbuffer CB0[3], immediateIndexed dcl_sampler s0, mode_default -dcl_sampler s1, mode_default dcl_resource_texture2d (float,float,float,float) t0 dcl_resource_texture2d (float,float,float,float) t1 dcl_resource_texture2d (float,float,float,float) t2 @@ -7568,19 +6243,21 @@ if_z cb0[2].y movc r1.xyzw, r2.xxxx, r1.xyzw, cb0[0].xyzw mov r2.x, l(-1) else - ieq r2.y, l(1), cb0[2].y - if_nz r2.y + ieq r2.x, l(1), cb0[2].y + if_nz r2.x if_z cb0[2].x sample r3.xyzw, v1.xyxx, t0.xyzw, s0 mul r3.xyz, r3.xyzx, cb0[1].xxxx - sample r4.xyzw, v2.xyxx, t5.xyzw, s0 + div r2.yz, v2.xxyx, v2.zzzz + sample r4.xyzw, r2.yzyy, t5.xyzw, s0 mov r3.w, cb0[1].x mul r1.xyzw, r3.xyzw, r4.xxxx mov r2.y, l(-1) else ieq r2.z, l(1), cb0[2].x if_nz r2.z - sample r3.xyzw, v2.xyxx, t5.xyzw, s0 + div r2.zw, v2.xxxy, v2.zzzz + sample r3.xyzw, r2.zwzz, t5.xyzw, s0 sample r4.xyzw, v1.xyxx, t0.xyzw, s0 mul r4.xyzw, r4.xyzw, cb0[1].xxxx mul r1.xyzw, r3.xxxx, r4.xyzw @@ -7588,7 +6265,8 @@ else else ieq r2.y, l(2), cb0[2].x if_nz r2.y - sample r3.xyzw, v2.xyxx, t5.xyzw, s0 + div r2.zw, v2.xxxy, v2.zzzz + sample r3.xyzw, r2.zwzz, t5.xyzw, s0 sample r4.xyzw, v1.xyxx, t3.xyzw, s0 add r2.z, r4.x, l(-0.501960) sample r4.xyzw, v1.xyxx, t1.xyzw, s0 @@ -7608,18 +6286,9 @@ else endif endif if_z r2.y - sample r3.xyzw, v2.xyxx, t5.xyzw, s0 - mul r1.xyzw, r3.xxxx, cb0[0].xyzw - endif - mov r2.x, l(-1) - else - ieq r2.x, l(2), cb0[2].y - if_nz r2.x div r2.yz, v2.xxyx, v2.zzzz - sample r3.xyzw, r2.yzyy, t5.xyzw, s1 - sample r4.xyzw, v1.xyxx, t0.xyzw, s0 - mul r4.xyzw, r4.xyzw, cb0[1].xxxx - mul r1.xyzw, r3.xxxx, r4.xyzw + sample r3.xyzw, r2.yzyy, t5.xyzw, s0 + mul r1.xyzw, r3.xxxx, cb0[0].xyzw endif endif endif @@ -7877,122 +6546,124 @@ mad r0.xyz, r2.xxxx, r1.xyzx, r0.xyzx mul o0.xyz, r1.wwww, r0.xyzx mov o0.w, r1.w ret -// Approximately 345 instruction slots used +// Approximately 339 instruction slots used #endif const BYTE BlendShader[] = { - 68, 88, 66, 67, 121, 58, - 99, 114, 236, 21, 118, 177, - 57, 125, 153, 182, 56, 164, - 101, 220, 1, 0, 0, 0, - 176, 68, 0, 0, 6, 0, + 68, 88, 66, 67, 122, 174, + 220, 58, 170, 47, 87, 82, + 85, 5, 178, 49, 217, 101, + 104, 140, 1, 0, 0, 0, + 184, 67, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, - 152, 23, 0, 0, 200, 63, - 0, 0, 68, 64, 0, 0, - 244, 67, 0, 0, 124, 68, + 92, 23, 0, 0, 8, 63, + 0, 0, 132, 63, 0, 0, + 252, 66, 0, 0, 132, 67, 0, 0, 65, 111, 110, 57, - 88, 23, 0, 0, 88, 23, + 28, 23, 0, 0, 28, 23, 0, 0, 0, 2, 255, 255, - 0, 23, 0, 0, 88, 0, - 0, 0, 2, 0, 64, 0, - 0, 0, 88, 0, 0, 0, - 88, 0, 7, 0, 36, 0, - 0, 0, 88, 0, 0, 0, + 200, 22, 0, 0, 84, 0, + 0, 0, 2, 0, 60, 0, + 0, 0, 84, 0, 0, 0, + 84, 0, 6, 0, 36, 0, + 0, 0, 84, 0, 0, 0, 0, 0, 1, 0, 1, 0, 2, 0, 2, 0, 3, 0, 3, 0, 5, 0, 4, 0, - 6, 0, 5, 0, 5, 1, - 6, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, - 1, 0, 2, 0, 3, 3, - 3, 3, 1, 2, 255, 255, - 81, 0, 0, 5, 3, 0, - 15, 160, 0, 0, 128, 191, - 0, 0, 0, 192, 115, 128, - 0, 191, 18, 131, 128, 189, - 81, 0, 0, 5, 4, 0, - 15, 160, 182, 74, 204, 63, - 205, 30, 80, 63, 103, 10, - 149, 63, 76, 26, 1, 64, - 81, 0, 0, 5, 5, 0, - 15, 160, 0, 0, 128, 191, - 0, 0, 0, 192, 0, 0, - 64, 192, 0, 0, 128, 192, - 81, 0, 0, 5, 6, 0, - 15, 160, 0, 0, 160, 192, - 0, 0, 192, 192, 0, 0, - 224, 192, 0, 0, 0, 193, - 81, 0, 0, 5, 7, 0, - 15, 160, 0, 0, 128, 63, - 0, 0, 128, 62, 0, 0, - 0, 64, 0, 0, 128, 191, - 81, 0, 0, 5, 8, 0, - 15, 160, 0, 0, 128, 65, + 6, 0, 5, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 1, 0, 2, 0, + 3, 3, 3, 3, 1, 2, + 255, 255, 81, 0, 0, 5, + 3, 0, 15, 160, 0, 0, + 128, 191, 0, 0, 0, 192, + 115, 128, 0, 191, 18, 131, + 128, 189, 81, 0, 0, 5, + 4, 0, 15, 160, 182, 74, + 204, 63, 205, 30, 80, 63, + 103, 10, 149, 63, 76, 26, + 1, 64, 81, 0, 0, 5, + 5, 0, 15, 160, 0, 0, + 0, 192, 0, 0, 64, 192, + 0, 0, 128, 192, 0, 0, + 160, 192, 81, 0, 0, 5, + 6, 0, 15, 160, 0, 0, + 192, 192, 0, 0, 224, 192, + 0, 0, 0, 193, 0, 0, + 16, 193, 81, 0, 0, 5, + 7, 0, 15, 160, 0, 0, + 128, 63, 0, 0, 128, 62, + 0, 0, 0, 64, 0, 0, + 128, 191, 81, 0, 0, 5, + 8, 0, 15, 160, 0, 0, + 128, 65, 0, 0, 64, 193, + 0, 0, 96, 193, 0, 0, + 0, 0, 81, 0, 0, 5, + 9, 0, 15, 160, 0, 0, + 32, 193, 0, 0, 48, 193, 0, 0, 64, 193, 0, 0, - 80, 193, 0, 0, 96, 193, - 81, 0, 0, 5, 9, 0, - 15, 160, 0, 0, 16, 193, - 0, 0, 32, 193, 0, 0, - 48, 193, 0, 0, 64, 193, - 81, 0, 0, 5, 10, 0, - 15, 160, 154, 153, 153, 62, - 61, 10, 23, 63, 174, 71, - 225, 61, 0, 0, 0, 0, - 81, 0, 0, 5, 11, 0, - 15, 160, 196, 148, 200, 62, - 0, 0, 128, 191, 0, 0, - 0, 128, 0, 0, 0, 191, - 31, 0, 0, 2, 0, 0, - 0, 128, 0, 0, 15, 176, - 31, 0, 0, 2, 0, 0, - 0, 128, 1, 0, 7, 176, - 31, 0, 0, 2, 0, 0, - 0, 144, 0, 8, 15, 160, - 31, 0, 0, 2, 0, 0, - 0, 144, 1, 8, 15, 160, - 31, 0, 0, 2, 0, 0, - 0, 144, 2, 8, 15, 160, - 31, 0, 0, 2, 0, 0, - 0, 144, 3, 8, 15, 160, - 31, 0, 0, 2, 0, 0, - 0, 144, 4, 8, 15, 160, - 31, 0, 0, 2, 0, 0, - 0, 144, 5, 8, 15, 160, - 31, 0, 0, 2, 0, 0, - 0, 144, 6, 8, 15, 160, - 1, 0, 0, 2, 0, 0, - 1, 128, 11, 0, 170, 161, - 1, 0, 0, 2, 1, 0, - 1, 128, 11, 0, 170, 161, - 1, 0, 0, 2, 2, 0, - 4, 128, 11, 0, 170, 161, - 66, 0, 0, 3, 3, 0, - 15, 128, 0, 0, 228, 176, - 1, 8, 228, 160, 66, 0, - 0, 3, 4, 0, 15, 128, - 0, 0, 228, 176, 3, 8, - 228, 160, 2, 0, 0, 3, - 0, 0, 8, 128, 4, 0, - 0, 128, 3, 0, 170, 160, - 5, 0, 0, 3, 3, 0, - 6, 128, 0, 0, 255, 128, - 4, 0, 208, 160, 2, 0, - 0, 3, 0, 0, 8, 128, - 3, 0, 0, 128, 3, 0, - 255, 160, 4, 0, 0, 4, - 1, 0, 8, 128, 0, 0, - 255, 128, 4, 0, 170, 160, - 3, 0, 170, 129, 4, 0, - 0, 4, 3, 0, 1, 128, - 0, 0, 255, 128, 4, 0, - 170, 160, 3, 0, 85, 128, + 80, 193, 81, 0, 0, 5, + 10, 0, 15, 160, 154, 153, + 153, 62, 61, 10, 23, 63, + 174, 71, 225, 61, 0, 0, + 0, 0, 81, 0, 0, 5, + 11, 0, 15, 160, 196, 148, + 200, 62, 0, 0, 128, 191, + 0, 0, 0, 128, 0, 0, + 0, 191, 31, 0, 0, 2, + 0, 0, 0, 128, 0, 0, + 15, 176, 31, 0, 0, 2, + 0, 0, 0, 128, 1, 0, + 7, 176, 31, 0, 0, 2, + 0, 0, 0, 144, 0, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 1, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 2, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 3, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 4, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 5, 8, + 15, 160, 1, 0, 0, 2, + 0, 0, 1, 128, 11, 0, + 170, 161, 1, 0, 0, 2, + 1, 0, 1, 128, 11, 0, + 170, 161, 1, 0, 0, 2, + 2, 0, 4, 128, 11, 0, + 170, 161, 66, 0, 0, 3, + 3, 0, 15, 128, 0, 0, + 228, 176, 1, 8, 228, 160, 66, 0, 0, 3, 4, 0, - 15, 128, 1, 0, 228, 176, - 4, 8, 228, 160, 66, 0, - 0, 3, 5, 0, 15, 128, - 0, 0, 228, 176, 2, 8, + 15, 128, 0, 0, 228, 176, + 3, 8, 228, 160, 2, 0, + 0, 3, 0, 0, 8, 128, + 4, 0, 0, 128, 3, 0, + 170, 160, 5, 0, 0, 3, + 3, 0, 6, 128, 0, 0, + 255, 128, 4, 0, 208, 160, + 2, 0, 0, 3, 0, 0, + 8, 128, 3, 0, 0, 128, + 3, 0, 255, 160, 4, 0, + 0, 4, 1, 0, 8, 128, + 0, 0, 255, 128, 4, 0, + 170, 160, 3, 0, 170, 129, + 4, 0, 0, 4, 3, 0, + 1, 128, 0, 0, 255, 128, + 4, 0, 170, 160, 3, 0, + 85, 128, 6, 0, 0, 2, + 2, 0, 8, 128, 1, 0, + 170, 176, 5, 0, 0, 3, + 4, 0, 3, 128, 2, 0, + 255, 128, 1, 0, 228, 176, + 66, 0, 0, 3, 5, 0, + 15, 128, 0, 0, 228, 176, + 2, 8, 228, 160, 66, 0, + 0, 3, 4, 0, 15, 128, + 4, 0, 228, 128, 4, 8, 228, 160, 2, 0, 0, 3, 2, 0, 8, 128, 5, 0, 0, 128, 3, 0, 170, 160, @@ -8012,197 +6683,185 @@ const BYTE BlendShader[] = 228, 128, 1, 0, 0, 160, 5, 0, 0, 3, 5, 0, 15, 128, 4, 0, 0, 128, - 3, 0, 228, 128, 6, 0, - 0, 2, 0, 0, 8, 128, - 1, 0, 170, 176, 5, 0, - 0, 3, 6, 0, 3, 128, - 0, 0, 255, 128, 1, 0, - 228, 176, 66, 0, 0, 3, - 7, 0, 15, 128, 0, 0, - 228, 176, 0, 8, 228, 160, - 66, 0, 0, 3, 6, 0, - 15, 128, 6, 0, 228, 128, - 6, 8, 228, 160, 5, 0, + 3, 0, 228, 128, 1, 0, + 0, 2, 6, 0, 3, 128, + 0, 0, 235, 176, 66, 0, 0, 3, 7, 0, 15, 128, - 7, 0, 228, 128, 1, 0, + 0, 0, 228, 176, 0, 8, + 228, 160, 66, 0, 0, 3, + 6, 0, 15, 128, 6, 0, + 228, 128, 5, 8, 228, 160, + 5, 0, 0, 3, 7, 0, + 15, 128, 7, 0, 228, 128, + 1, 0, 0, 160, 5, 0, + 0, 3, 8, 0, 15, 128, + 4, 0, 0, 128, 7, 0, + 228, 128, 1, 0, 0, 2, + 9, 0, 3, 128, 3, 0, + 228, 160, 2, 0, 0, 3, + 10, 0, 15, 128, 9, 0, + 4, 128, 2, 0, 144, 160, + 5, 0, 0, 3, 10, 0, + 15, 128, 10, 0, 228, 128, + 10, 0, 228, 128, 88, 0, + 0, 4, 5, 0, 15, 128, + 10, 0, 0, 129, 8, 0, + 228, 128, 5, 0, 228, 128, + 88, 0, 0, 4, 3, 0, + 15, 128, 10, 0, 0, 129, + 7, 0, 228, 128, 3, 0, + 228, 128, 1, 0, 0, 2, + 7, 0, 8, 128, 1, 0, 0, 160, 5, 0, 0, 3, 8, 0, 15, 128, 4, 0, 0, 128, 7, 0, 228, 128, - 1, 0, 0, 2, 9, 0, - 3, 128, 3, 0, 228, 160, - 2, 0, 0, 3, 10, 0, - 15, 128, 9, 0, 68, 128, - 2, 0, 80, 160, 5, 0, - 0, 3, 10, 0, 15, 128, - 10, 0, 228, 128, 10, 0, - 228, 128, 88, 0, 0, 4, - 5, 0, 15, 128, 10, 0, - 0, 129, 8, 0, 228, 128, - 5, 0, 228, 128, 1, 0, - 0, 2, 8, 0, 7, 128, - 7, 0, 228, 128, 1, 0, - 0, 2, 8, 0, 8, 128, - 1, 0, 0, 160, 5, 0, - 0, 3, 11, 0, 15, 128, - 4, 0, 0, 128, 8, 0, + 88, 0, 0, 4, 3, 0, + 15, 128, 2, 0, 0, 161, + 7, 0, 228, 128, 3, 0, 228, 128, 5, 0, 0, 3, 4, 0, 15, 128, 4, 0, 0, 128, 0, 0, 228, 160, 88, 0, 0, 4, 5, 0, 15, 128, 2, 0, 0, 161, - 11, 0, 228, 128, 5, 0, + 8, 0, 228, 128, 5, 0, 228, 128, 88, 0, 0, 4, - 6, 0, 6, 128, 10, 0, - 244, 129, 11, 0, 85, 160, + 7, 0, 3, 128, 10, 0, + 233, 129, 11, 0, 85, 160, 11, 0, 170, 160, 88, 0, - 0, 4, 6, 0, 6, 128, - 10, 0, 224, 129, 3, 0, - 0, 160, 6, 0, 228, 128, - 88, 0, 0, 4, 6, 0, - 6, 128, 2, 0, 208, 161, - 9, 0, 0, 128, 6, 0, - 228, 128, 88, 0, 0, 4, - 4, 0, 15, 128, 6, 0, - 85, 128, 4, 0, 228, 128, - 5, 0, 228, 128, 5, 0, - 0, 3, 5, 0, 15, 128, - 6, 0, 0, 128, 7, 0, - 228, 128, 88, 0, 0, 4, - 3, 0, 15, 128, 10, 0, - 0, 129, 7, 0, 228, 128, - 3, 0, 228, 128, 88, 0, + 0, 4, 0, 0, 8, 128, + 10, 0, 0, 129, 3, 0, + 0, 160, 7, 0, 0, 128, + 88, 0, 0, 4, 1, 0, + 8, 128, 2, 0, 85, 161, + 9, 0, 0, 128, 7, 0, + 85, 128, 88, 0, 0, 4, + 0, 0, 8, 128, 2, 0, + 0, 161, 9, 0, 0, 128, + 0, 0, 255, 128, 88, 0, 0, 4, 4, 0, 15, 128, - 10, 0, 170, 129, 4, 0, + 0, 0, 255, 128, 4, 0, 228, 128, 5, 0, 228, 128, 88, 0, 0, 4, 3, 0, - 15, 128, 2, 0, 0, 161, - 8, 0, 228, 128, 3, 0, + 15, 128, 0, 0, 255, 128, + 0, 0, 228, 160, 3, 0, 228, 128, 88, 0, 0, 4, - 3, 0, 15, 128, 6, 0, - 85, 128, 0, 0, 228, 160, - 3, 0, 228, 128, 88, 0, + 3, 0, 15, 128, 2, 0, + 85, 161, 3, 0, 228, 128, + 4, 0, 228, 128, 88, 0, 0, 4, 3, 0, 15, 128, - 2, 0, 85, 161, 3, 0, - 228, 128, 4, 0, 228, 128, - 88, 0, 0, 4, 3, 0, - 15, 128, 6, 0, 170, 128, - 11, 0, 106, 161, 3, 0, - 228, 128, 6, 0, 0, 2, - 0, 0, 8, 128, 3, 0, - 255, 128, 5, 0, 0, 3, - 4, 0, 7, 128, 0, 0, - 255, 128, 3, 0, 228, 128, - 88, 0, 0, 4, 4, 0, - 7, 128, 2, 0, 255, 161, - 3, 0, 228, 128, 4, 0, - 228, 128, 2, 0, 0, 3, - 5, 0, 3, 128, 4, 0, - 233, 129, 4, 0, 228, 128, - 88, 0, 0, 4, 5, 0, - 12, 128, 5, 0, 0, 128, - 4, 0, 68, 128, 4, 0, - 20, 128, 11, 0, 0, 3, - 0, 0, 8, 128, 5, 0, - 170, 128, 4, 0, 170, 128, - 10, 0, 0, 3, 1, 0, - 8, 128, 4, 0, 170, 128, - 5, 0, 255, 128, 2, 0, - 0, 3, 6, 0, 8, 128, - 0, 0, 255, 128, 1, 0, - 255, 129, 1, 0, 0, 2, - 7, 0, 3, 128, 0, 0, - 235, 176, 66, 0, 0, 3, - 7, 0, 15, 128, 7, 0, - 228, 128, 5, 8, 228, 160, + 1, 0, 255, 128, 11, 0, + 106, 161, 3, 0, 228, 128, 6, 0, 0, 2, 0, 0, - 8, 128, 7, 0, 255, 128, + 8, 128, 3, 0, 255, 128, + 5, 0, 0, 3, 4, 0, + 7, 128, 0, 0, 255, 128, + 3, 0, 228, 128, 88, 0, + 0, 4, 4, 0, 7, 128, + 2, 0, 255, 161, 3, 0, + 228, 128, 4, 0, 228, 128, + 2, 0, 0, 3, 5, 0, + 3, 128, 4, 0, 233, 129, + 4, 0, 228, 128, 88, 0, + 0, 4, 5, 0, 12, 128, + 5, 0, 0, 128, 4, 0, + 68, 128, 4, 0, 20, 128, + 11, 0, 0, 3, 0, 0, + 8, 128, 5, 0, 170, 128, + 4, 0, 170, 128, 10, 0, + 0, 3, 1, 0, 8, 128, + 4, 0, 170, 128, 5, 0, + 255, 128, 2, 0, 0, 3, + 7, 0, 8, 128, 0, 0, + 255, 128, 1, 0, 255, 129, + 6, 0, 0, 2, 0, 0, + 8, 128, 6, 0, 255, 128, 5, 0, 0, 3, 8, 0, 7, 128, 0, 0, 255, 128, - 7, 0, 228, 128, 4, 0, + 6, 0, 228, 128, 4, 0, 0, 4, 5, 0, 12, 128, - 7, 0, 100, 128, 0, 0, + 6, 0, 100, 128, 0, 0, 255, 128, 8, 0, 132, 129, 5, 0, 0, 3, 9, 0, - 3, 128, 6, 0, 255, 128, + 3, 128, 7, 0, 255, 128, 5, 0, 238, 128, 4, 0, - 0, 4, 10, 0, 15, 128, - 7, 0, 129, 128, 0, 0, + 0, 4, 11, 0, 15, 128, + 6, 0, 129, 128, 0, 0, 255, 128, 8, 0, 88, 129, 6, 0, 0, 2, 1, 0, - 8, 128, 10, 0, 0, 128, - 5, 0, 0, 3, 6, 0, + 8, 128, 11, 0, 0, 128, + 5, 0, 0, 3, 7, 0, 2, 128, 1, 0, 255, 128, 9, 0, 0, 128, 88, 0, 0, 4, 1, 0, 6, 128, - 10, 0, 170, 128, 11, 0, - 170, 161, 6, 0, 220, 128, - 5, 0, 0, 3, 11, 0, - 15, 128, 6, 0, 255, 128, - 10, 0, 228, 128, 6, 0, + 11, 0, 170, 128, 11, 0, + 170, 161, 7, 0, 220, 128, + 5, 0, 0, 3, 12, 0, + 15, 128, 7, 0, 255, 128, + 11, 0, 228, 128, 6, 0, 0, 2, 1, 0, 8, 128, 5, 0, 255, 128, 5, 0, - 0, 3, 6, 0, 1, 128, - 1, 0, 255, 128, 11, 0, + 0, 3, 7, 0, 1, 128, + 1, 0, 255, 128, 12, 0, 85, 128, 88, 0, 0, 4, - 2, 0, 3, 128, 10, 0, + 2, 0, 3, 128, 11, 0, 255, 128, 11, 0, 170, 161, - 6, 0, 236, 128, 88, 0, + 7, 0, 236, 128, 88, 0, 0, 4, 1, 0, 7, 128, 5, 0, 170, 128, 1, 0, 228, 128, 2, 0, 228, 128, 6, 0, 0, 2, 1, 0, 8, 128, 5, 0, 170, 128, - 5, 0, 0, 3, 6, 0, + 5, 0, 0, 3, 7, 0, 4, 128, 1, 0, 255, 128, - 11, 0, 0, 128, 88, 0, + 12, 0, 0, 128, 88, 0, 0, 4, 0, 0, 6, 128, - 10, 0, 85, 128, 11, 0, - 170, 161, 6, 0, 248, 128, + 11, 0, 85, 128, 11, 0, + 170, 161, 7, 0, 248, 128, 88, 0, 0, 4, 0, 0, - 7, 128, 10, 0, 255, 128, + 7, 128, 11, 0, 255, 128, 0, 0, 228, 128, 1, 0, 228, 128, 1, 0, 0, 2, 1, 0, 2, 128, 11, 0, 170, 161, 1, 0, 0, 2, 2, 0, 2, 128, 11, 0, 170, 161, 1, 0, 0, 2, - 12, 0, 4, 128, 11, 0, + 10, 0, 4, 128, 11, 0, 170, 161, 6, 0, 0, 2, - 1, 0, 8, 128, 10, 0, + 1, 0, 8, 128, 11, 0, 170, 128, 5, 0, 0, 3, - 6, 0, 2, 128, 1, 0, - 255, 128, 11, 0, 255, 128, + 7, 0, 2, 128, 1, 0, + 255, 128, 12, 0, 255, 128, 88, 0, 0, 4, 2, 0, - 5, 128, 10, 0, 0, 128, - 11, 0, 170, 161, 6, 0, + 5, 128, 11, 0, 0, 128, + 11, 0, 170, 161, 7, 0, 215, 128, 6, 0, 0, 2, - 1, 0, 8, 128, 10, 0, + 1, 0, 8, 128, 11, 0, 85, 128, 5, 0, 0, 3, - 6, 0, 1, 128, 1, 0, + 7, 0, 1, 128, 1, 0, 255, 128, 9, 0, 85, 128, - 88, 0, 0, 4, 12, 0, + 88, 0, 0, 4, 10, 0, 3, 128, 5, 0, 170, 128, - 11, 0, 170, 161, 6, 0, + 11, 0, 170, 161, 7, 0, 227, 128, 88, 0, 0, 4, - 2, 0, 7, 128, 10, 0, + 2, 0, 7, 128, 11, 0, 255, 128, 2, 0, 228, 128, - 12, 0, 228, 128, 6, 0, + 10, 0, 228, 128, 6, 0, 0, 2, 1, 0, 8, 128, - 10, 0, 255, 128, 5, 0, - 0, 3, 6, 0, 4, 128, - 1, 0, 255, 128, 11, 0, + 11, 0, 255, 128, 5, 0, + 0, 3, 7, 0, 4, 128, + 1, 0, 255, 128, 12, 0, 170, 128, 88, 0, 0, 4, 1, 0, 5, 128, 5, 0, 255, 128, 11, 0, 170, 161, - 6, 0, 246, 128, 88, 0, + 7, 0, 246, 128, 88, 0, 0, 4, 1, 0, 7, 128, 5, 0, 170, 128, 1, 0, 228, 128, 2, 0, 228, 128, 88, 0, 0, 4, 0, 0, - 7, 128, 10, 0, 0, 128, + 7, 128, 11, 0, 0, 128, 0, 0, 228, 128, 1, 0, 228, 128, 88, 0, 0, 4, - 1, 0, 3, 128, 10, 0, + 1, 0, 3, 128, 11, 0, 170, 128, 8, 0, 228, 128, 8, 0, 225, 128, 8, 0, 0, 3, 4, 0, 8, 128, @@ -8271,168 +6930,168 @@ const BYTE BlendShader[] = 1, 0, 0, 2, 4, 0, 8, 128, 2, 0, 170, 160, 2, 0, 0, 3, 1, 0, - 12, 128, 4, 0, 255, 128, - 8, 0, 228, 160, 5, 0, - 0, 3, 1, 0, 12, 128, - 1, 0, 228, 128, 1, 0, - 228, 128, 8, 0, 0, 3, - 2, 0, 1, 128, 10, 0, + 4, 128, 4, 0, 255, 128, + 8, 0, 170, 160, 5, 0, + 0, 3, 1, 0, 4, 128, + 1, 0, 170, 128, 1, 0, + 170, 128, 8, 0, 0, 3, + 1, 0, 8, 128, 10, 0, 228, 160, 4, 0, 228, 128, 2, 0, 0, 3, 2, 0, - 2, 128, 8, 0, 255, 129, - 2, 0, 0, 128, 2, 0, - 0, 3, 2, 0, 1, 128, - 2, 0, 0, 129, 8, 0, + 1, 128, 8, 0, 255, 129, + 1, 0, 255, 128, 2, 0, + 0, 3, 1, 0, 8, 128, + 1, 0, 255, 129, 8, 0, 255, 128, 2, 0, 0, 3, - 2, 0, 13, 128, 2, 0, - 0, 128, 4, 0, 148, 128, - 4, 0, 0, 4, 6, 0, - 7, 128, 7, 0, 228, 128, + 2, 0, 14, 128, 1, 0, + 255, 128, 4, 0, 144, 128, + 4, 0, 0, 4, 7, 0, + 7, 128, 6, 0, 228, 128, 0, 0, 255, 128, 2, 0, - 85, 128, 2, 0, 0, 3, - 6, 0, 8, 128, 6, 0, - 85, 129, 6, 0, 0, 128, - 88, 0, 0, 4, 5, 0, - 12, 128, 6, 0, 255, 128, - 6, 0, 20, 128, 6, 0, - 68, 128, 10, 0, 0, 3, - 2, 0, 2, 128, 6, 0, - 170, 128, 5, 0, 170, 128, - 11, 0, 0, 3, 9, 0, - 1, 128, 5, 0, 255, 128, - 6, 0, 170, 128, 8, 0, - 0, 3, 6, 0, 8, 128, - 10, 0, 228, 160, 6, 0, - 228, 128, 2, 0, 0, 3, - 5, 0, 4, 128, 2, 0, - 85, 129, 6, 0, 255, 128, - 6, 0, 0, 2, 5, 0, - 4, 128, 5, 0, 170, 128, - 2, 0, 0, 3, 9, 0, - 14, 128, 6, 0, 255, 129, - 6, 0, 144, 128, 5, 0, - 0, 3, 9, 0, 14, 128, - 6, 0, 255, 128, 9, 0, - 228, 128, 4, 0, 0, 4, - 9, 0, 14, 128, 9, 0, - 228, 128, 5, 0, 170, 128, - 6, 0, 255, 128, 88, 0, - 0, 4, 6, 0, 7, 128, - 2, 0, 85, 128, 6, 0, - 228, 128, 9, 0, 249, 128, - 2, 0, 0, 3, 9, 0, - 14, 128, 6, 0, 255, 129, - 6, 0, 144, 128, 2, 0, - 0, 3, 2, 0, 2, 128, - 6, 0, 255, 129, 3, 0, - 0, 161, 5, 0, 0, 3, - 9, 0, 14, 128, 2, 0, - 85, 128, 9, 0, 228, 128, - 2, 0, 0, 3, 2, 0, - 2, 128, 6, 0, 255, 129, - 9, 0, 0, 128, 2, 0, - 0, 3, 5, 0, 4, 128, - 9, 0, 0, 129, 3, 0, - 0, 161, 6, 0, 0, 2, - 5, 0, 8, 128, 2, 0, - 85, 128, 4, 0, 0, 4, - 9, 0, 7, 128, 9, 0, - 249, 128, 5, 0, 255, 128, - 6, 0, 255, 128, 88, 0, - 0, 4, 6, 0, 7, 128, - 5, 0, 170, 128, 6, 0, - 228, 128, 9, 0, 228, 128, - 88, 0, 0, 4, 6, 0, - 7, 128, 1, 0, 255, 129, - 6, 0, 228, 128, 11, 0, - 170, 161, 2, 0, 0, 3, - 1, 0, 8, 128, 2, 0, - 170, 129, 2, 0, 0, 128, + 0, 128, 2, 0, 0, 3, + 1, 0, 8, 128, 7, 0, + 85, 129, 7, 0, 0, 128, 88, 0, 0, 4, 5, 0, 12, 128, 1, 0, 255, 128, - 2, 0, 36, 128, 2, 0, - 132, 128, 10, 0, 0, 3, - 1, 0, 8, 128, 2, 0, - 255, 128, 5, 0, 170, 128, - 11, 0, 0, 3, 6, 0, - 8, 128, 5, 0, 255, 128, - 2, 0, 255, 128, 8, 0, - 0, 3, 2, 0, 2, 128, - 10, 0, 228, 160, 2, 0, - 248, 128, 2, 0, 0, 3, + 7, 0, 20, 128, 7, 0, + 68, 128, 10, 0, 0, 3, + 1, 0, 8, 128, 7, 0, + 170, 128, 5, 0, 170, 128, + 11, 0, 0, 3, 2, 0, + 1, 128, 5, 0, 255, 128, + 7, 0, 170, 128, 8, 0, + 0, 3, 7, 0, 8, 128, + 10, 0, 228, 160, 7, 0, + 228, 128, 2, 0, 0, 3, 5, 0, 4, 128, 1, 0, - 255, 129, 2, 0, 85, 128, + 255, 129, 7, 0, 255, 128, 6, 0, 0, 2, 5, 0, 4, 128, 5, 0, 170, 128, 2, 0, 0, 3, 9, 0, - 7, 128, 2, 0, 85, 129, - 2, 0, 248, 128, 5, 0, + 7, 128, 7, 0, 255, 129, + 7, 0, 228, 128, 5, 0, 0, 3, 9, 0, 7, 128, - 2, 0, 85, 128, 9, 0, + 7, 0, 255, 128, 9, 0, 228, 128, 4, 0, 0, 4, 9, 0, 7, 128, 9, 0, 228, 128, 5, 0, 170, 128, - 2, 0, 85, 128, 88, 0, - 0, 4, 2, 0, 13, 128, - 1, 0, 255, 128, 2, 0, - 228, 128, 9, 0, 148, 128, + 7, 0, 255, 128, 88, 0, + 0, 4, 7, 0, 7, 128, + 1, 0, 255, 128, 7, 0, + 228, 128, 9, 0, 228, 128, 2, 0, 0, 3, 9, 0, - 7, 128, 2, 0, 85, 129, - 2, 0, 248, 128, 2, 0, + 7, 128, 7, 0, 255, 129, + 7, 0, 228, 128, 2, 0, 0, 3, 1, 0, 8, 128, - 2, 0, 85, 129, 3, 0, + 7, 0, 255, 129, 3, 0, 0, 161, 5, 0, 0, 3, 9, 0, 7, 128, 1, 0, 255, 128, 9, 0, 228, 128, 2, 0, 0, 3, 1, 0, - 8, 128, 2, 0, 85, 129, - 6, 0, 255, 128, 2, 0, - 0, 3, 6, 0, 8, 128, - 6, 0, 255, 129, 3, 0, + 8, 128, 2, 0, 0, 128, + 7, 0, 255, 129, 2, 0, + 0, 3, 9, 0, 8, 128, + 2, 0, 0, 129, 3, 0, 0, 161, 6, 0, 0, 2, 1, 0, 8, 128, 1, 0, 255, 128, 4, 0, 0, 4, 9, 0, 7, 128, 9, 0, 228, 128, 1, 0, 255, 128, - 2, 0, 85, 128, 88, 0, - 0, 4, 2, 0, 7, 128, - 6, 0, 255, 128, 2, 0, - 248, 128, 9, 0, 228, 128, - 88, 0, 0, 4, 2, 0, + 7, 0, 255, 128, 88, 0, + 0, 4, 7, 0, 7, 128, + 9, 0, 255, 128, 7, 0, + 228, 128, 9, 0, 228, 128, + 88, 0, 0, 4, 7, 0, 7, 128, 1, 0, 170, 129, - 2, 0, 228, 128, 6, 0, - 228, 128, 2, 0, 0, 3, - 6, 0, 15, 128, 4, 0, - 255, 128, 9, 0, 228, 160, - 5, 0, 0, 3, 6, 0, - 15, 128, 6, 0, 228, 128, - 6, 0, 228, 128, 88, 0, + 7, 0, 228, 128, 11, 0, + 170, 161, 2, 0, 0, 3, + 7, 0, 8, 128, 2, 0, + 170, 129, 2, 0, 85, 128, + 88, 0, 0, 4, 1, 0, + 12, 128, 7, 0, 255, 128, + 2, 0, 100, 128, 2, 0, + 148, 128, 10, 0, 0, 3, + 7, 0, 8, 128, 2, 0, + 255, 128, 1, 0, 170, 128, + 11, 0, 0, 3, 5, 0, + 4, 128, 1, 0, 255, 128, + 2, 0, 255, 128, 8, 0, + 0, 3, 5, 0, 8, 128, + 10, 0, 228, 160, 2, 0, + 249, 128, 2, 0, 0, 3, + 1, 0, 4, 128, 7, 0, + 255, 129, 5, 0, 255, 128, + 6, 0, 0, 2, 1, 0, + 4, 128, 1, 0, 170, 128, + 2, 0, 0, 3, 9, 0, + 7, 128, 2, 0, 249, 128, + 5, 0, 255, 129, 5, 0, + 0, 3, 9, 0, 7, 128, + 5, 0, 255, 128, 9, 0, + 228, 128, 4, 0, 0, 4, + 9, 0, 7, 128, 9, 0, + 228, 128, 1, 0, 170, 128, + 5, 0, 255, 128, 88, 0, + 0, 4, 2, 0, 7, 128, + 7, 0, 255, 128, 2, 0, + 249, 128, 9, 0, 228, 128, + 2, 0, 0, 3, 9, 0, + 7, 128, 5, 0, 255, 129, + 2, 0, 228, 128, 2, 0, + 0, 3, 2, 0, 8, 128, + 5, 0, 255, 129, 3, 0, + 0, 161, 5, 0, 0, 3, + 9, 0, 7, 128, 2, 0, + 255, 128, 9, 0, 228, 128, + 2, 0, 0, 3, 2, 0, + 8, 128, 5, 0, 255, 129, + 5, 0, 170, 128, 2, 0, + 0, 3, 7, 0, 8, 128, + 5, 0, 170, 129, 3, 0, + 0, 161, 6, 0, 0, 2, + 2, 0, 8, 128, 2, 0, + 255, 128, 4, 0, 0, 4, + 9, 0, 7, 128, 9, 0, + 228, 128, 2, 0, 255, 128, + 5, 0, 255, 128, 88, 0, + 0, 4, 2, 0, 7, 128, + 7, 0, 255, 128, 2, 0, + 228, 128, 9, 0, 228, 128, + 2, 0, 0, 3, 9, 0, + 15, 128, 4, 0, 255, 128, + 9, 0, 228, 160, 5, 0, + 0, 3, 9, 0, 15, 128, + 9, 0, 228, 128, 9, 0, + 228, 128, 88, 0, 0, 4, + 2, 0, 7, 128, 9, 0, + 255, 129, 2, 0, 228, 128, + 7, 0, 228, 128, 88, 0, 0, 4, 0, 0, 7, 128, - 6, 0, 255, 129, 0, 0, + 9, 0, 170, 129, 0, 0, 228, 128, 2, 0, 228, 128, 2, 0, 0, 3, 2, 0, 15, 128, 4, 0, 96, 129, 4, 0, 137, 128, 1, 0, - 0, 2, 9, 0, 2, 128, + 0, 2, 7, 0, 2, 128, 11, 0, 170, 161, 1, 0, 0, 2, 10, 0, 2, 128, 11, 0, 170, 161, 1, 0, 0, 2, 11, 0, 4, 128, 11, 0, 170, 161, 6, 0, - 0, 2, 6, 0, 8, 128, + 0, 2, 7, 0, 8, 128, 2, 0, 170, 128, 11, 0, - 0, 3, 9, 0, 8, 128, + 0, 3, 11, 0, 8, 128, 1, 0, 0, 128, 8, 0, 170, 128, 10, 0, 0, 3, - 10, 0, 8, 128, 8, 0, + 5, 0, 4, 128, 8, 0, 170, 128, 1, 0, 85, 128, 2, 0, 0, 3, 1, 0, - 8, 128, 9, 0, 255, 128, - 10, 0, 255, 129, 5, 0, + 8, 128, 5, 0, 170, 129, + 11, 0, 255, 128, 5, 0, 0, 3, 5, 0, 12, 128, 1, 0, 255, 128, 5, 0, 68, 128, 5, 0, 0, 3, - 1, 0, 1, 128, 6, 0, + 1, 0, 1, 128, 7, 0, 255, 128, 5, 0, 255, 128, 88, 0, 0, 4, 11, 0, 3, 128, 2, 0, 85, 128, @@ -8456,12 +7115,12 @@ const BYTE BlendShader[] = 255, 128, 5, 0, 0, 3, 1, 0, 4, 128, 5, 0, 255, 128, 5, 0, 170, 128, - 88, 0, 0, 4, 9, 0, + 88, 0, 0, 4, 7, 0, 5, 128, 5, 0, 85, 128, 11, 0, 170, 161, 1, 0, 246, 128, 88, 0, 0, 4, - 9, 0, 7, 128, 2, 0, - 85, 128, 9, 0, 228, 128, + 7, 0, 7, 128, 2, 0, + 85, 128, 7, 0, 228, 128, 10, 0, 228, 128, 1, 0, 0, 2, 10, 0, 1, 128, 11, 0, 170, 161, 1, 0, @@ -8469,18 +7128,18 @@ const BYTE BlendShader[] = 11, 0, 170, 161, 1, 0, 0, 2, 13, 0, 4, 128, 11, 0, 170, 161, 6, 0, - 0, 2, 6, 0, 8, 128, + 0, 2, 7, 0, 8, 128, 2, 0, 0, 128, 5, 0, 0, 3, 1, 0, 2, 128, - 6, 0, 255, 128, 12, 0, + 7, 0, 255, 128, 12, 0, 85, 128, 88, 0, 0, 4, 11, 0, 6, 128, 5, 0, 0, 128, 11, 0, 170, 161, 1, 0, 220, 128, 6, 0, - 0, 2, 6, 0, 8, 128, + 0, 2, 7, 0, 8, 128, 5, 0, 85, 128, 5, 0, 0, 3, 1, 0, 1, 128, - 6, 0, 255, 128, 12, 0, + 7, 0, 255, 128, 12, 0, 170, 128, 88, 0, 0, 4, 13, 0, 3, 128, 2, 0, 255, 128, 11, 0, 170, 161, @@ -8502,7 +7161,7 @@ const BYTE BlendShader[] = 228, 128, 88, 0, 0, 4, 1, 0, 7, 128, 2, 0, 0, 128, 1, 0, 228, 128, - 9, 0, 228, 128, 8, 0, + 7, 0, 228, 128, 8, 0, 0, 3, 1, 0, 8, 128, 10, 0, 228, 160, 1, 0, 228, 128, 2, 0, 0, 3, @@ -8517,16 +7176,16 @@ const BYTE BlendShader[] = 2, 0, 3, 128, 1, 0, 255, 128, 1, 0, 225, 128, 1, 0, 228, 128, 10, 0, - 0, 3, 6, 0, 8, 128, + 0, 3, 8, 0, 8, 128, 1, 0, 170, 128, 2, 0, 0, 128, 11, 0, 0, 3, - 8, 0, 8, 128, 2, 0, + 5, 0, 1, 128, 2, 0, 85, 128, 1, 0, 170, 128, 8, 0, 0, 3, 1, 0, 8, 128, 10, 0, 228, 160, 1, 0, 228, 128, 2, 0, 0, 3, 2, 0, 1, 128, - 6, 0, 255, 129, 1, 0, + 8, 0, 255, 129, 1, 0, 255, 128, 6, 0, 0, 2, 2, 0, 1, 128, 2, 0, 0, 128, 2, 0, 0, 3, @@ -8539,7 +7198,7 @@ const BYTE BlendShader[] = 2, 0, 249, 128, 2, 0, 0, 128, 1, 0, 255, 128, 88, 0, 0, 4, 1, 0, - 7, 128, 6, 0, 255, 128, + 7, 128, 8, 0, 255, 128, 1, 0, 228, 128, 2, 0, 228, 128, 2, 0, 0, 3, 2, 0, 7, 128, 1, 0, @@ -8551,9 +7210,9 @@ const BYTE BlendShader[] = 2, 0, 255, 128, 2, 0, 228, 128, 2, 0, 0, 3, 2, 0, 8, 128, 1, 0, - 255, 129, 8, 0, 255, 128, - 2, 0, 0, 3, 6, 0, - 8, 128, 8, 0, 255, 129, + 255, 129, 5, 0, 0, 128, + 2, 0, 0, 3, 8, 0, + 8, 128, 5, 0, 0, 129, 3, 0, 0, 161, 6, 0, 0, 2, 2, 0, 8, 128, 2, 0, 255, 128, 4, 0, @@ -8561,14 +7220,14 @@ const BYTE BlendShader[] = 2, 0, 228, 128, 2, 0, 255, 128, 1, 0, 255, 128, 88, 0, 0, 4, 1, 0, - 7, 128, 6, 0, 255, 128, + 7, 128, 8, 0, 255, 128, 1, 0, 228, 128, 2, 0, 228, 128, 88, 0, 0, 4, - 0, 0, 7, 128, 6, 0, - 170, 129, 1, 0, 228, 128, + 0, 0, 7, 128, 9, 0, + 85, 129, 1, 0, 228, 128, 0, 0, 228, 128, 4, 0, 0, 4, 1, 0, 7, 128, - 7, 0, 228, 128, 0, 0, + 6, 0, 228, 128, 0, 0, 255, 128, 4, 0, 228, 128, 5, 0, 0, 3, 2, 0, 7, 128, 4, 0, 228, 128, @@ -8580,89 +7239,89 @@ const BYTE BlendShader[] = 7, 128, 8, 0, 228, 128, 4, 0, 228, 129, 1, 0, 228, 128, 88, 0, 0, 4, - 0, 0, 7, 128, 6, 0, - 85, 129, 5, 0, 228, 128, + 0, 0, 7, 128, 9, 0, + 0, 129, 5, 0, 228, 128, 0, 0, 228, 128, 4, 0, 0, 4, 5, 0, 7, 128, - 7, 0, 228, 128, 0, 0, + 6, 0, 228, 128, 0, 0, 255, 128, 4, 0, 228, 129, 35, 0, 0, 2, 5, 0, 7, 128, 5, 0, 228, 128, - 88, 0, 0, 4, 0, 0, - 7, 128, 6, 0, 0, 129, - 5, 0, 228, 128, 0, 0, - 228, 128, 2, 0, 0, 3, - 5, 0, 3, 128, 4, 0, - 233, 129, 11, 0, 255, 161, - 4, 0, 0, 4, 6, 0, - 7, 128, 4, 0, 228, 128, - 7, 0, 170, 160, 7, 0, - 255, 160, 4, 0, 0, 4, - 1, 0, 8, 128, 7, 0, - 170, 128, 0, 0, 255, 129, - 7, 0, 85, 160, 4, 0, - 0, 4, 9, 0, 7, 128, - 8, 0, 228, 128, 8, 0, - 0, 160, 8, 0, 85, 160, - 4, 0, 0, 4, 9, 0, - 7, 128, 9, 0, 228, 128, - 8, 0, 228, 128, 5, 0, - 255, 161, 5, 0, 0, 3, - 9, 0, 7, 128, 8, 0, - 228, 128, 9, 0, 228, 128, - 7, 0, 0, 2, 2, 0, - 8, 128, 8, 0, 170, 128, - 6, 0, 0, 2, 2, 0, - 8, 128, 2, 0, 255, 128, - 88, 0, 0, 4, 1, 0, - 8, 128, 1, 0, 255, 128, - 9, 0, 170, 128, 2, 0, - 255, 128, 4, 0, 0, 4, - 1, 0, 8, 128, 7, 0, - 170, 128, 0, 0, 255, 129, - 1, 0, 255, 128, 4, 0, + 2, 0, 0, 3, 7, 0, + 15, 128, 4, 0, 255, 128, + 6, 0, 228, 160, 5, 0, + 0, 3, 7, 0, 15, 128, + 7, 0, 228, 128, 7, 0, + 228, 128, 88, 0, 0, 4, + 0, 0, 7, 128, 7, 0, + 255, 129, 5, 0, 228, 128, + 0, 0, 228, 128, 2, 0, + 0, 3, 5, 0, 3, 128, + 4, 0, 233, 129, 11, 0, + 255, 161, 4, 0, 0, 4, + 9, 0, 7, 128, 4, 0, + 228, 128, 7, 0, 170, 160, + 7, 0, 255, 160, 4, 0, 0, 4, 1, 0, 8, 128, - 6, 0, 170, 128, 1, 0, - 255, 128, 8, 0, 170, 128, + 6, 0, 170, 128, 0, 0, + 255, 129, 7, 0, 85, 160, 4, 0, 0, 4, 10, 0, - 7, 128, 4, 0, 228, 128, - 3, 0, 85, 160, 3, 0, - 0, 161, 5, 0, 0, 3, - 10, 0, 7, 128, 8, 0, - 228, 128, 10, 0, 228, 128, - 4, 0, 0, 4, 11, 0, - 15, 128, 7, 0, 73, 128, - 0, 0, 255, 129, 7, 0, - 80, 160, 4, 0, 0, 4, - 5, 0, 12, 128, 10, 0, - 148, 128, 11, 0, 68, 129, - 8, 0, 148, 128, 88, 0, - 0, 4, 12, 0, 4, 128, - 5, 0, 85, 128, 5, 0, - 255, 128, 1, 0, 255, 128, - 7, 0, 0, 2, 1, 0, - 8, 128, 8, 0, 85, 128, - 6, 0, 0, 2, 1, 0, - 8, 128, 1, 0, 255, 128, - 88, 0, 0, 4, 1, 0, - 8, 128, 11, 0, 255, 128, - 9, 0, 85, 128, 1, 0, - 255, 128, 4, 0, 0, 4, - 1, 0, 8, 128, 7, 0, - 85, 128, 0, 0, 255, 129, + 7, 128, 8, 0, 228, 128, + 8, 0, 0, 160, 8, 0, + 85, 160, 4, 0, 0, 4, + 10, 0, 7, 128, 10, 0, + 228, 128, 8, 0, 228, 128, + 5, 0, 170, 161, 5, 0, + 0, 3, 10, 0, 7, 128, + 8, 0, 228, 128, 10, 0, + 228, 128, 7, 0, 0, 2, + 2, 0, 8, 128, 8, 0, + 170, 128, 6, 0, 0, 2, + 2, 0, 8, 128, 2, 0, + 255, 128, 88, 0, 0, 4, + 1, 0, 8, 128, 1, 0, + 255, 128, 10, 0, 170, 128, + 2, 0, 255, 128, 4, 0, + 0, 4, 1, 0, 8, 128, + 6, 0, 170, 128, 0, 0, + 255, 129, 1, 0, 255, 128, + 4, 0, 0, 4, 1, 0, + 8, 128, 9, 0, 170, 128, + 1, 0, 255, 128, 8, 0, + 170, 128, 4, 0, 0, 4, + 11, 0, 7, 128, 4, 0, + 228, 128, 3, 0, 85, 160, + 3, 0, 0, 161, 5, 0, + 0, 3, 11, 0, 7, 128, + 8, 0, 228, 128, 11, 0, + 228, 128, 4, 0, 0, 4, + 12, 0, 15, 128, 6, 0, + 73, 128, 0, 0, 255, 129, + 7, 0, 80, 160, 4, 0, + 0, 4, 5, 0, 12, 128, + 11, 0, 148, 128, 12, 0, + 68, 129, 8, 0, 148, 128, + 88, 0, 0, 4, 13, 0, + 4, 128, 5, 0, 85, 128, + 5, 0, 255, 128, 1, 0, + 255, 128, 7, 0, 0, 2, + 1, 0, 8, 128, 8, 0, + 85, 128, 6, 0, 0, 2, + 1, 0, 8, 128, 1, 0, + 255, 128, 88, 0, 0, 4, + 1, 0, 8, 128, 12, 0, + 255, 128, 10, 0, 85, 128, 1, 0, 255, 128, 4, 0, 0, 4, 1, 0, 8, 128, - 6, 0, 85, 128, 1, 0, - 255, 128, 8, 0, 85, 128, - 88, 0, 0, 4, 12, 0, - 2, 128, 5, 0, 0, 128, - 5, 0, 170, 128, 1, 0, - 255, 128, 2, 0, 0, 3, - 13, 0, 15, 128, 4, 0, - 255, 128, 6, 0, 228, 160, - 5, 0, 0, 3, 13, 0, - 15, 128, 13, 0, 228, 128, - 13, 0, 228, 128, 2, 0, + 6, 0, 85, 128, 0, 0, + 255, 129, 1, 0, 255, 128, + 4, 0, 0, 4, 1, 0, + 8, 128, 9, 0, 85, 128, + 1, 0, 255, 128, 8, 0, + 85, 128, 88, 0, 0, 4, + 13, 0, 2, 128, 5, 0, + 0, 128, 5, 0, 170, 128, + 1, 0, 255, 128, 2, 0, 0, 3, 14, 0, 15, 128, 4, 0, 36, 129, 11, 0, 213, 161, 7, 0, 0, 2, @@ -8670,61 +7329,61 @@ const BYTE BlendShader[] = 0, 128, 6, 0, 0, 2, 1, 0, 8, 128, 1, 0, 255, 128, 88, 0, 0, 4, - 1, 0, 8, 128, 11, 0, - 170, 128, 9, 0, 0, 128, + 1, 0, 8, 128, 12, 0, + 170, 128, 10, 0, 0, 128, 1, 0, 255, 128, 4, 0, 0, 4, 1, 0, 8, 128, - 7, 0, 0, 128, 0, 0, + 6, 0, 0, 128, 0, 0, 255, 129, 1, 0, 255, 128, 4, 0, 0, 4, 1, 0, - 8, 128, 6, 0, 0, 128, + 8, 128, 9, 0, 0, 128, 1, 0, 255, 128, 8, 0, 0, 128, 4, 0, 0, 4, - 6, 0, 15, 128, 7, 0, + 9, 0, 15, 128, 6, 0, 36, 128, 0, 0, 255, 129, 11, 0, 127, 161, 4, 0, - 0, 4, 9, 0, 7, 128, - 7, 0, 228, 128, 0, 0, + 0, 4, 10, 0, 7, 128, + 6, 0, 228, 128, 0, 0, 255, 128, 3, 0, 0, 160, - 5, 0, 0, 3, 9, 0, - 7, 128, 9, 0, 228, 128, - 9, 0, 228, 128, 4, 0, + 5, 0, 0, 3, 10, 0, + 7, 128, 10, 0, 228, 128, + 10, 0, 228, 128, 4, 0, 0, 4, 0, 0, 8, 128, - 10, 0, 0, 128, 6, 0, + 11, 0, 0, 128, 9, 0, 255, 129, 8, 0, 0, 128, - 88, 0, 0, 4, 12, 0, + 88, 0, 0, 4, 13, 0, 1, 128, 14, 0, 255, 128, 0, 0, 255, 128, 1, 0, 255, 128, 88, 0, 0, 4, - 0, 0, 7, 128, 13, 0, - 255, 129, 12, 0, 228, 128, + 0, 0, 7, 128, 7, 0, + 170, 129, 13, 0, 228, 128, 0, 0, 228, 128, 2, 0, - 0, 3, 10, 0, 7, 128, + 0, 3, 11, 0, 7, 128, 8, 0, 228, 128, 8, 0, 228, 128, 4, 0, 0, 4, - 12, 0, 7, 128, 4, 0, + 13, 0, 7, 128, 4, 0, 228, 128, 3, 0, 85, 161, - 10, 0, 228, 128, 2, 0, - 0, 3, 12, 0, 7, 128, - 12, 0, 228, 128, 3, 0, + 11, 0, 228, 128, 2, 0, + 0, 3, 13, 0, 7, 128, + 13, 0, 228, 128, 3, 0, 0, 160, 4, 0, 0, 4, 15, 0, 7, 128, 4, 0, - 228, 128, 10, 0, 228, 129, - 12, 0, 228, 128, 5, 0, - 0, 3, 10, 0, 7, 128, - 4, 0, 228, 128, 10, 0, + 228, 128, 11, 0, 228, 129, + 13, 0, 228, 128, 5, 0, + 0, 3, 11, 0, 7, 128, + 4, 0, 228, 128, 11, 0, 228, 128, 2, 0, 0, 3, 16, 0, 7, 128, 4, 0, 228, 128, 4, 0, 228, 128, 5, 0, 0, 3, 17, 0, 7, 128, 8, 0, 228, 128, 16, 0, 228, 128, 4, 0, - 0, 4, 12, 0, 7, 128, + 0, 4, 13, 0, 7, 128, 16, 0, 228, 128, 8, 0, - 228, 129, 12, 0, 228, 128, - 88, 0, 0, 4, 6, 0, - 7, 128, 6, 0, 228, 128, - 10, 0, 228, 128, 12, 0, + 228, 129, 13, 0, 228, 128, + 88, 0, 0, 4, 9, 0, + 7, 128, 9, 0, 228, 128, + 11, 0, 228, 128, 13, 0, 228, 128, 88, 0, 0, 4, 5, 0, 6, 128, 5, 0, 208, 128, 17, 0, 228, 128, @@ -8733,12 +7392,12 @@ const BYTE BlendShader[] = 14, 0, 255, 128, 17, 0, 0, 128, 15, 0, 0, 128, 88, 0, 0, 4, 0, 0, - 7, 128, 13, 0, 170, 129, + 7, 128, 7, 0, 85, 129, 5, 0, 228, 128, 0, 0, 228, 128, 6, 0, 0, 2, 0, 0, 8, 128, 4, 0, 0, 128, 4, 0, 0, 4, - 0, 0, 8, 128, 6, 0, + 0, 0, 8, 128, 9, 0, 255, 128, 0, 0, 255, 129, 3, 0, 0, 161, 11, 0, 0, 3, 1, 0, 8, 128, @@ -8750,13 +7409,13 @@ const BYTE BlendShader[] = 8, 128, 5, 0, 0, 129, 11, 0, 170, 161, 1, 0, 255, 128, 88, 0, 0, 4, - 10, 0, 1, 128, 9, 0, + 11, 0, 1, 128, 10, 0, 0, 129, 3, 0, 0, 161, 0, 0, 255, 128, 6, 0, 0, 2, 0, 0, 8, 128, 4, 0, 85, 128, 4, 0, 0, 4, 0, 0, 8, 128, - 11, 0, 0, 128, 0, 0, + 12, 0, 0, 128, 0, 0, 255, 129, 3, 0, 0, 161, 11, 0, 0, 3, 1, 0, 8, 128, 0, 0, 255, 128, @@ -8764,13 +7423,13 @@ const BYTE BlendShader[] = 0, 4, 0, 0, 8, 128, 5, 0, 85, 129, 11, 0, 170, 161, 1, 0, 255, 128, - 88, 0, 0, 4, 10, 0, - 2, 128, 9, 0, 85, 129, + 88, 0, 0, 4, 11, 0, + 2, 128, 10, 0, 85, 129, 3, 0, 0, 161, 0, 0, 255, 128, 6, 0, 0, 2, 0, 0, 8, 128, 4, 0, 170, 128, 4, 0, 0, 4, - 0, 0, 8, 128, 11, 0, + 0, 0, 8, 128, 12, 0, 85, 128, 0, 0, 255, 129, 3, 0, 0, 161, 11, 0, 0, 3, 1, 0, 8, 128, @@ -8779,95 +7438,95 @@ const BYTE BlendShader[] = 0, 0, 8, 128, 5, 0, 170, 129, 11, 0, 170, 161, 1, 0, 255, 128, 88, 0, - 0, 4, 10, 0, 4, 128, - 9, 0, 170, 129, 3, 0, + 0, 4, 11, 0, 4, 128, + 10, 0, 170, 129, 3, 0, 0, 161, 0, 0, 255, 128, 88, 0, 0, 4, 0, 0, - 7, 128, 13, 0, 85, 129, - 10, 0, 228, 128, 0, 0, + 7, 128, 7, 0, 0, 129, + 11, 0, 228, 128, 0, 0, 228, 128, 2, 0, 0, 3, - 5, 0, 7, 128, 4, 0, - 228, 128, 3, 0, 0, 160, + 5, 0, 15, 128, 4, 0, + 255, 128, 5, 0, 228, 160, 5, 0, 0, 3, 5, 0, - 7, 128, 5, 0, 228, 128, - 5, 0, 228, 128, 6, 0, + 15, 128, 5, 0, 228, 128, + 5, 0, 228, 128, 2, 0, + 0, 3, 7, 0, 7, 128, + 4, 0, 228, 128, 3, 0, + 0, 160, 5, 0, 0, 3, + 7, 0, 7, 128, 7, 0, + 228, 128, 7, 0, 228, 128, + 6, 0, 0, 2, 0, 0, + 8, 128, 14, 0, 0, 128, + 5, 0, 0, 3, 0, 0, + 8, 128, 0, 0, 255, 128, + 8, 0, 0, 128, 10, 0, + 0, 3, 1, 0, 8, 128, + 0, 0, 255, 128, 3, 0, + 0, 161, 88, 0, 0, 4, + 0, 0, 8, 128, 7, 0, + 0, 129, 3, 0, 0, 161, + 1, 0, 255, 128, 5, 0, + 0, 3, 10, 0, 7, 128, + 8, 0, 228, 128, 8, 0, + 228, 128, 88, 0, 0, 4, + 11, 0, 1, 128, 10, 0, + 0, 129, 11, 0, 170, 161, + 0, 0, 255, 128, 6, 0, 0, 2, 0, 0, 8, 128, - 14, 0, 0, 128, 5, 0, + 14, 0, 85, 128, 6, 0, + 0, 2, 1, 0, 8, 128, + 14, 0, 170, 128, 5, 0, + 0, 3, 1, 0, 8, 128, + 1, 0, 255, 128, 8, 0, + 170, 128, 10, 0, 0, 3, + 2, 0, 8, 128, 1, 0, + 255, 128, 3, 0, 0, 161, + 88, 0, 0, 4, 1, 0, + 8, 128, 7, 0, 170, 129, + 3, 0, 0, 161, 2, 0, + 255, 128, 88, 0, 0, 4, + 11, 0, 4, 128, 10, 0, + 170, 129, 11, 0, 170, 161, + 1, 0, 255, 128, 5, 0, 0, 3, 0, 0, 8, 128, 0, 0, 255, 128, 8, 0, - 0, 128, 10, 0, 0, 3, + 85, 128, 10, 0, 0, 3, 1, 0, 8, 128, 0, 0, 255, 128, 3, 0, 0, 161, 88, 0, 0, 4, 0, 0, - 8, 128, 5, 0, 0, 129, + 8, 128, 7, 0, 85, 129, 3, 0, 0, 161, 1, 0, - 255, 128, 5, 0, 0, 3, - 9, 0, 7, 128, 8, 0, - 228, 128, 8, 0, 228, 128, - 88, 0, 0, 4, 10, 0, - 1, 128, 9, 0, 0, 129, - 11, 0, 170, 161, 0, 0, - 255, 128, 6, 0, 0, 2, - 0, 0, 8, 128, 14, 0, - 85, 128, 6, 0, 0, 2, - 1, 0, 8, 128, 14, 0, - 170, 128, 5, 0, 0, 3, - 1, 0, 8, 128, 1, 0, - 255, 128, 8, 0, 170, 128, - 10, 0, 0, 3, 2, 0, - 8, 128, 1, 0, 255, 128, - 3, 0, 0, 161, 88, 0, - 0, 4, 1, 0, 8, 128, - 5, 0, 170, 129, 3, 0, - 0, 161, 2, 0, 255, 128, - 88, 0, 0, 4, 10, 0, - 4, 128, 9, 0, 170, 129, - 11, 0, 170, 161, 1, 0, - 255, 128, 5, 0, 0, 3, - 0, 0, 8, 128, 0, 0, - 255, 128, 8, 0, 85, 128, - 10, 0, 0, 3, 1, 0, - 8, 128, 0, 0, 255, 128, - 3, 0, 0, 161, 88, 0, - 0, 4, 0, 0, 8, 128, - 5, 0, 85, 129, 3, 0, - 0, 161, 1, 0, 255, 128, - 88, 0, 0, 4, 10, 0, - 2, 128, 9, 0, 85, 129, - 11, 0, 170, 161, 0, 0, 255, 128, 88, 0, 0, 4, - 0, 0, 7, 128, 13, 0, - 0, 129, 10, 0, 228, 128, - 0, 0, 228, 128, 2, 0, - 0, 3, 5, 0, 15, 128, - 4, 0, 255, 128, 5, 0, - 228, 160, 5, 0, 0, 3, - 5, 0, 15, 128, 5, 0, - 228, 128, 5, 0, 228, 128, - 11, 0, 0, 3, 9, 0, + 11, 0, 2, 128, 10, 0, + 85, 129, 11, 0, 170, 161, + 0, 0, 255, 128, 88, 0, + 0, 4, 0, 0, 7, 128, + 5, 0, 255, 129, 11, 0, + 228, 128, 0, 0, 228, 128, + 11, 0, 0, 3, 7, 0, 7, 128, 8, 0, 228, 128, 4, 0, 228, 128, 10, 0, 0, 3, 10, 0, 7, 128, 4, 0, 228, 128, 8, 0, 228, 128, 88, 0, 0, 4, 0, 0, 7, 128, 5, 0, - 255, 129, 9, 0, 228, 128, + 170, 129, 7, 0, 228, 128, 0, 0, 228, 128, 88, 0, 0, 4, 0, 0, 7, 128, - 5, 0, 170, 129, 10, 0, + 5, 0, 85, 129, 10, 0, 228, 128, 0, 0, 228, 128, 88, 0, 0, 4, 0, 0, - 7, 128, 5, 0, 85, 129, - 6, 0, 228, 128, 0, 0, + 7, 128, 5, 0, 0, 129, + 9, 0, 228, 128, 0, 0, 228, 128, 88, 0, 0, 4, - 0, 0, 7, 128, 5, 0, - 0, 129, 1, 0, 228, 128, + 0, 0, 7, 128, 10, 0, + 255, 129, 1, 0, 228, 128, 0, 0, 228, 128, 88, 0, 0, 4, 0, 0, 7, 128, 2, 0, 170, 161, 2, 0, 228, 128, 0, 0, 228, 128, 18, 0, 0, 4, 1, 0, - 7, 128, 7, 0, 255, 128, + 7, 128, 6, 0, 255, 128, 0, 0, 228, 128, 4, 0, 228, 128, 5, 0, 0, 3, 0, 0, 7, 128, 3, 0, @@ -8878,26 +7537,24 @@ const BYTE BlendShader[] = 0, 2, 0, 0, 8, 128, 3, 0, 255, 128, 88, 0, 0, 4, 0, 0, 15, 128, - 1, 0, 0, 129, 7, 0, + 1, 0, 0, 129, 6, 0, 228, 128, 0, 0, 228, 128, 5, 0, 0, 3, 1, 0, - 1, 128, 7, 0, 255, 128, - 7, 0, 255, 128, 88, 0, + 1, 128, 6, 0, 255, 128, + 6, 0, 255, 128, 88, 0, 0, 4, 0, 0, 15, 128, 1, 0, 0, 129, 3, 0, 228, 128, 0, 0, 228, 128, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83, 72, - 68, 82, 40, 40, 0, 0, - 64, 0, 0, 0, 10, 10, + 68, 82, 164, 39, 0, 0, + 64, 0, 0, 0, 233, 9, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, - 90, 0, 0, 3, 0, 96, - 16, 0, 1, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 88, 24, @@ -9074,13 +7731,13 @@ const BYTE BlendShader[] = 16, 0, 2, 0, 0, 0, 1, 64, 0, 0, 255, 255, 255, 255, 18, 0, 0, 1, - 32, 0, 0, 8, 34, 0, + 32, 0, 0, 8, 18, 0, 16, 0, 2, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 31, 0, 4, 3, - 26, 0, 16, 0, 2, 0, + 10, 0, 16, 0, 2, 0, 0, 0, 31, 0, 0, 4, 10, 128, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, @@ -9095,68 +7752,82 @@ const BYTE BlendShader[] = 70, 2, 16, 0, 3, 0, 0, 0, 6, 128, 32, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 4, 0, - 0, 0, 70, 16, 16, 0, - 2, 0, 0, 0, 70, 126, - 16, 0, 5, 0, 0, 0, - 0, 96, 16, 0, 0, 0, - 0, 0, 54, 0, 0, 6, - 130, 0, 16, 0, 3, 0, - 0, 0, 10, 128, 32, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 56, 0, 0, 7, - 242, 0, 16, 0, 1, 0, - 0, 0, 70, 14, 16, 0, - 3, 0, 0, 0, 6, 0, + 0, 0, 14, 0, 0, 7, + 98, 0, 16, 0, 2, 0, + 0, 0, 6, 17, 16, 0, + 2, 0, 0, 0, 166, 26, + 16, 0, 2, 0, 0, 0, + 69, 0, 0, 9, 242, 0, 16, 0, 4, 0, 0, 0, - 54, 0, 0, 5, 34, 0, - 16, 0, 2, 0, 0, 0, - 1, 64, 0, 0, 255, 255, - 255, 255, 18, 0, 0, 1, - 32, 0, 0, 8, 66, 0, - 16, 0, 2, 0, 0, 0, - 1, 64, 0, 0, 1, 0, - 0, 0, 10, 128, 32, 0, - 0, 0, 0, 0, 2, 0, - 0, 0, 31, 0, 4, 3, - 42, 0, 16, 0, 2, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 3, 0, - 0, 0, 70, 16, 16, 0, - 2, 0, 0, 0, 70, 126, - 16, 0, 5, 0, 0, 0, - 0, 96, 16, 0, 0, 0, - 0, 0, 69, 0, 0, 9, - 242, 0, 16, 0, 4, 0, - 0, 0, 70, 16, 16, 0, - 1, 0, 0, 0, 70, 126, + 150, 5, 16, 0, 2, 0, + 0, 0, 70, 126, 16, 0, + 5, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, - 0, 96, 16, 0, 0, 0, - 0, 0, 56, 0, 0, 8, - 242, 0, 16, 0, 4, 0, - 0, 0, 70, 14, 16, 0, - 4, 0, 0, 0, 6, 128, - 32, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 56, 0, - 0, 7, 242, 0, 16, 0, - 1, 0, 0, 0, 6, 0, + 54, 0, 0, 6, 130, 0, 16, 0, 3, 0, 0, 0, - 70, 14, 16, 0, 4, 0, - 0, 0, 54, 0, 0, 5, - 34, 0, 16, 0, 2, 0, - 0, 0, 1, 64, 0, 0, - 255, 255, 255, 255, 18, 0, - 0, 1, 32, 0, 0, 8, - 34, 0, 16, 0, 2, 0, - 0, 0, 1, 64, 0, 0, - 2, 0, 0, 0, 10, 128, - 32, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 31, 0, - 4, 3, 26, 0, 16, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 242, 0, + 16, 0, 1, 0, 0, 0, + 70, 14, 16, 0, 3, 0, + 0, 0, 6, 0, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 18, 0, 0, 1, 32, 0, + 0, 8, 66, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 1, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 42, 0, + 16, 0, 2, 0, 0, 0, + 14, 0, 0, 7, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 20, 16, 0, 2, 0, + 0, 0, 166, 26, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, - 3, 0, 0, 0, 70, 16, + 3, 0, 0, 0, 230, 10, + 16, 0, 2, 0, 0, 0, + 70, 126, 16, 0, 5, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 16, + 16, 0, 1, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 56, 0, + 0, 8, 242, 0, 16, 0, + 4, 0, 0, 0, 70, 14, + 16, 0, 4, 0, 0, 0, + 6, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 56, 0, 0, 7, 242, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 16, 0, 3, 0, + 0, 0, 70, 14, 16, 0, + 4, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 255, 255, 255, 255, + 18, 0, 0, 1, 32, 0, + 0, 8, 34, 0, 16, 0, + 2, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 2, 0, 0, 0, + 31, 0, 4, 3, 26, 0, + 16, 0, 2, 0, 0, 0, + 14, 0, 0, 7, 194, 0, + 16, 0, 2, 0, 0, 0, + 6, 20, 16, 0, 2, 0, + 0, 0, 166, 26, 16, 0, + 2, 0, 0, 0, 69, 0, + 0, 9, 242, 0, 16, 0, + 3, 0, 0, 0, 230, 10, 16, 0, 2, 0, 0, 0, 70, 126, 16, 0, 5, 0, 0, 0, 0, 96, 16, 0, @@ -9246,57 +7917,23 @@ const BYTE BlendShader[] = 0, 1, 21, 0, 0, 1, 21, 0, 0, 1, 31, 0, 0, 3, 26, 0, 16, 0, - 2, 0, 0, 0, 69, 0, - 0, 9, 242, 0, 16, 0, - 3, 0, 0, 0, 70, 16, + 2, 0, 0, 0, 14, 0, + 0, 7, 98, 0, 16, 0, + 2, 0, 0, 0, 6, 17, 16, 0, 2, 0, 0, 0, - 70, 126, 16, 0, 5, 0, - 0, 0, 0, 96, 16, 0, - 0, 0, 0, 0, 56, 0, - 0, 8, 242, 0, 16, 0, - 1, 0, 0, 0, 6, 0, - 16, 0, 3, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 21, 0, 0, 1, 54, 0, - 0, 5, 18, 0, 16, 0, - 2, 0, 0, 0, 1, 64, - 0, 0, 255, 255, 255, 255, - 18, 0, 0, 1, 32, 0, - 0, 8, 18, 0, 16, 0, - 2, 0, 0, 0, 1, 64, - 0, 0, 2, 0, 0, 0, - 26, 128, 32, 0, 0, 0, - 0, 0, 2, 0, 0, 0, - 31, 0, 4, 3, 10, 0, - 16, 0, 2, 0, 0, 0, - 14, 0, 0, 7, 98, 0, - 16, 0, 2, 0, 0, 0, - 6, 17, 16, 0, 2, 0, - 0, 0, 166, 26, 16, 0, - 2, 0, 0, 0, 69, 0, - 0, 9, 242, 0, 16, 0, - 3, 0, 0, 0, 150, 5, - 16, 0, 2, 0, 0, 0, - 70, 126, 16, 0, 5, 0, - 0, 0, 0, 96, 16, 0, - 1, 0, 0, 0, 69, 0, - 0, 9, 242, 0, 16, 0, - 4, 0, 0, 0, 70, 16, - 16, 0, 1, 0, 0, 0, - 70, 126, 16, 0, 0, 0, - 0, 0, 0, 96, 16, 0, - 0, 0, 0, 0, 56, 0, - 0, 8, 242, 0, 16, 0, - 4, 0, 0, 0, 70, 14, - 16, 0, 4, 0, 0, 0, - 6, 128, 32, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 56, 0, 0, 7, 242, 0, - 16, 0, 1, 0, 0, 0, - 6, 0, 16, 0, 3, 0, - 0, 0, 70, 14, 16, 0, - 4, 0, 0, 0, 21, 0, + 166, 26, 16, 0, 2, 0, + 0, 0, 69, 0, 0, 9, + 242, 0, 16, 0, 3, 0, + 0, 0, 150, 5, 16, 0, + 2, 0, 0, 0, 70, 126, + 16, 0, 5, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 56, 0, 0, 8, + 242, 0, 16, 0, 1, 0, + 0, 0, 6, 0, 16, 0, + 3, 0, 0, 0, 70, 142, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 21, 0, 0, 1, 21, 0, 0, 1, 21, 0, 0, 1, 55, 0, 0, 12, 242, 0, 16, 0, @@ -10604,214 +9241,205 @@ const BYTE BlendShader[] = 0, 0, 58, 0, 16, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, - 116, 0, 0, 0, 89, 1, + 116, 0, 0, 0, 83, 1, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 4, 0, - 0, 0, 196, 0, 0, 0, - 10, 0, 0, 0, 13, 0, - 0, 0, 14, 0, 0, 0, - 11, 0, 0, 0, 0, 0, + 0, 0, 197, 0, 0, 0, + 9, 0, 0, 0, 13, 0, + 0, 0, 13, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 17, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 25, 0, 0, 0, + 0, 0, 24, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 82, 68, 69, 70, 168, 3, + 82, 68, 69, 70, 112, 3, 0, 0, 1, 0, 0, 0, - 136, 1, 0, 0, 9, 0, + 80, 1, 0, 0, 8, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, - 0, 0, 116, 3, 0, 0, - 60, 1, 0, 0, 3, 0, + 0, 0, 60, 3, 0, 0, + 28, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 37, 1, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 42, 1, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 1, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 45, 1, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 2, 0, 0, 0, + 1, 0, 0, 0, 13, 0, + 0, 0, 49, 1, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 3, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 53, 1, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 4, 0, + 0, 0, 255, 255, 255, 255, + 5, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 59, 1, 0, 0, 2, 0, + 0, 0, 5, 0, 0, 0, + 4, 0, 0, 0, 255, 255, + 255, 255, 6, 0, 0, 0, + 1, 0, 0, 0, 13, 0, 0, 0, 69, 1, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 95, 1, + 0, 0, 0, 0, 115, 83, + 97, 109, 112, 108, 101, 114, + 0, 116, 82, 71, 66, 0, + 116, 89, 0, 116, 67, 98, + 0, 116, 67, 114, 0, 116, + 77, 97, 115, 107, 0, 116, + 66, 97, 99, 107, 100, 114, + 111, 112, 0, 36, 71, 108, + 111, 98, 97, 108, 115, 0, + 171, 171, 69, 1, 0, 0, + 10, 0, 0, 0, 104, 1, + 0, 0, 48, 1, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 88, 2, 0, 0, + 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 0, 0, 0, 0, 1, 0, - 0, 0, 13, 0, 0, 0, - 100, 1, 0, 0, 2, 0, - 0, 0, 5, 0, 0, 0, - 4, 0, 0, 0, 255, 255, - 255, 255, 1, 0, 0, 0, - 1, 0, 0, 0, 13, 0, - 0, 0, 103, 1, 0, 0, - 2, 0, 0, 0, 5, 0, - 0, 0, 4, 0, 0, 0, - 255, 255, 255, 255, 2, 0, - 0, 0, 1, 0, 0, 0, - 13, 0, 0, 0, 107, 1, + 100, 2, 0, 0, 0, 0, + 0, 0, 116, 2, 0, 0, + 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, - 5, 0, 0, 0, 4, 0, - 0, 0, 255, 255, 255, 255, - 3, 0, 0, 0, 1, 0, - 0, 0, 13, 0, 0, 0, - 111, 1, 0, 0, 2, 0, - 0, 0, 5, 0, 0, 0, - 4, 0, 0, 0, 255, 255, - 255, 255, 5, 0, 0, 0, - 1, 0, 0, 0, 13, 0, - 0, 0, 117, 1, 0, 0, - 2, 0, 0, 0, 5, 0, - 0, 0, 4, 0, 0, 0, - 255, 255, 255, 255, 6, 0, - 0, 0, 1, 0, 0, 0, - 13, 0, 0, 0, 127, 1, + 132, 2, 0, 0, 0, 0, + 0, 0, 148, 2, 0, 0, + 32, 0, 0, 0, 16, 0, + 0, 0, 2, 0, 0, 0, + 164, 2, 0, 0, 0, 0, + 0, 0, 180, 2, 0, 0, + 48, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 196, 2, 0, 0, 0, 0, + 0, 0, 212, 2, 0, 0, + 112, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 196, 2, 0, 0, 0, 0, + 0, 0, 224, 2, 0, 0, + 176, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, + 100, 2, 0, 0, 0, 0, + 0, 0, 244, 2, 0, 0, + 192, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 115, 83, 97, 109, 112, 108, - 101, 114, 0, 76, 97, 121, - 101, 114, 84, 101, 120, 116, - 117, 114, 101, 83, 97, 109, - 112, 108, 101, 114, 76, 105, - 110, 101, 97, 114, 0, 116, - 82, 71, 66, 0, 116, 89, - 0, 116, 67, 98, 0, 116, - 67, 114, 0, 116, 77, 97, - 115, 107, 0, 116, 66, 97, - 99, 107, 100, 114, 111, 112, - 0, 36, 71, 108, 111, 98, - 97, 108, 115, 0, 127, 1, - 0, 0, 10, 0, 0, 0, - 160, 1, 0, 0, 48, 1, + 4, 3, 0, 0, 0, 0, + 0, 0, 20, 3, 0, 0, + 208, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 144, 2, + 4, 3, 0, 0, 0, 0, + 0, 0, 31, 3, 0, 0, + 224, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 2, 0, - 0, 0, 156, 2, 0, 0, - 0, 0, 0, 0, 172, 2, - 0, 0, 16, 0, 0, 0, - 4, 0, 0, 0, 2, 0, - 0, 0, 188, 2, 0, 0, - 0, 0, 0, 0, 204, 2, - 0, 0, 32, 0, 0, 0, - 16, 0, 0, 0, 2, 0, - 0, 0, 220, 2, 0, 0, - 0, 0, 0, 0, 236, 2, - 0, 0, 48, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 252, 2, 0, 0, - 0, 0, 0, 0, 12, 3, - 0, 0, 112, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 252, 2, 0, 0, - 0, 0, 0, 0, 24, 3, - 0, 0, 176, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 156, 2, 0, 0, - 0, 0, 0, 0, 44, 3, - 0, 0, 192, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 60, 3, 0, 0, - 0, 0, 0, 0, 76, 3, - 0, 0, 208, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 60, 3, 0, 0, - 0, 0, 0, 0, 87, 3, - 0, 0, 224, 0, 0, 0, - 16, 0, 0, 0, 0, 0, - 0, 0, 60, 3, 0, 0, - 0, 0, 0, 0, 97, 3, - 0, 0, 240, 0, 0, 0, - 64, 0, 0, 0, 0, 0, - 0, 0, 252, 2, 0, 0, - 0, 0, 0, 0, 102, 76, - 97, 121, 101, 114, 67, 111, - 108, 111, 114, 0, 1, 0, - 3, 0, 1, 0, 4, 0, + 4, 3, 0, 0, 0, 0, + 0, 0, 41, 3, 0, 0, + 240, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 196, 2, 0, 0, 0, 0, 0, 0, 102, 76, 97, 121, - 101, 114, 79, 112, 97, 99, - 105, 116, 121, 0, 171, 171, - 0, 0, 3, 0, 1, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 105, 66, - 108, 101, 110, 100, 67, 111, - 110, 102, 105, 103, 0, 171, - 171, 171, 1, 0, 19, 0, + 101, 114, 67, 111, 108, 111, + 114, 0, 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 109, 76, 97, 121, 101, 114, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 3, 0, - 3, 0, 4, 0, 4, 0, + 102, 76, 97, 121, 101, 114, + 79, 112, 97, 99, 105, 116, + 121, 0, 171, 171, 0, 0, + 3, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 109, 80, 114, 111, - 106, 101, 99, 116, 105, 111, - 110, 0, 118, 82, 101, 110, - 100, 101, 114, 84, 97, 114, - 103, 101, 116, 79, 102, 102, - 115, 101, 116, 0, 118, 84, - 101, 120, 116, 117, 114, 101, - 67, 111, 111, 114, 100, 115, - 0, 171, 1, 0, 3, 0, - 1, 0, 4, 0, 0, 0, + 0, 0, 105, 66, 108, 101, + 110, 100, 67, 111, 110, 102, + 105, 103, 0, 171, 171, 171, + 1, 0, 19, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 109, 76, + 97, 121, 101, 114, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 3, 0, 3, 0, + 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 118, 76, 97, 121, 101, 114, - 81, 117, 97, 100, 0, 118, - 77, 97, 115, 107, 81, 117, - 97, 100, 0, 109, 66, 97, - 99, 107, 100, 114, 111, 112, - 84, 114, 97, 110, 115, 102, - 111, 114, 109, 0, 77, 105, - 99, 114, 111, 115, 111, 102, - 116, 32, 40, 82, 41, 32, - 72, 76, 83, 76, 32, 83, - 104, 97, 100, 101, 114, 32, - 67, 111, 109, 112, 105, 108, - 101, 114, 32, 54, 46, 51, - 46, 57, 54, 48, 48, 46, + 109, 80, 114, 111, 106, 101, + 99, 116, 105, 111, 110, 0, + 118, 82, 101, 110, 100, 101, + 114, 84, 97, 114, 103, 101, + 116, 79, 102, 102, 115, 101, + 116, 0, 118, 84, 101, 120, + 116, 117, 114, 101, 67, 111, + 111, 114, 100, 115, 0, 171, + 1, 0, 3, 0, 1, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 118, 76, + 97, 121, 101, 114, 81, 117, + 97, 100, 0, 118, 77, 97, + 115, 107, 81, 117, 97, 100, + 0, 109, 66, 97, 99, 107, + 100, 114, 111, 112, 84, 114, + 97, 110, 115, 102, 111, 114, + 109, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, 49, 54, 51, 56, 52, 0, - 171, 171, 73, 83, 71, 78, - 128, 0, 0, 0, 4, 0, - 0, 0, 8, 0, 0, 0, - 104, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 116, 0, 0, 0, 0, 0, + 73, 83, 71, 78, 128, 0, + 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 3, 3, 0, 0, - 116, 0, 0, 0, 2, 0, + 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 12, 12, 0, 0, - 116, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 2, 0, - 0, 0, 7, 7, 0, 0, - 83, 86, 95, 80, 111, 115, - 105, 116, 105, 111, 110, 0, - 84, 69, 88, 67, 79, 79, - 82, 68, 0, 171, 171, 171, - 79, 83, 71, 78, 44, 0, - 0, 0, 1, 0, 0, 0, - 8, 0, 0, 0, 32, 0, + 15, 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 3, 3, 0, 0, 116, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 12, 12, 0, 0, 116, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 2, 0, 0, 0, + 7, 7, 0, 0, 83, 86, + 95, 80, 111, 115, 105, 116, + 105, 111, 110, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 171, 171, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 15, 0, 0, 0, 83, 86, - 95, 84, 97, 114, 103, 101, - 116, 0, 171, 171 + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171 }; ShaderBytes sBlendShader = { BlendShader, sizeof(BlendShader) }; diff --git a/gfx/layers/d3d11/CompositorD3D11ShadersVR.h b/gfx/layers/d3d11/CompositorD3D11ShadersVR.h index 5fbb54181d..74f9f48cd6 100644 --- a/gfx/layers/d3d11/CompositorD3D11ShadersVR.h +++ b/gfx/layers/d3d11/CompositorD3D11ShadersVR.h @@ -1,6 +1,6 @@ #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Buffer Definitions: @@ -16,9 +16,9 @@ // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// $Globals cbuffer NA NA 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// $Globals cbuffer NA NA cb0 1 // // // @@ -80,7 +80,7 @@ // approximately 10 instruction slots used vs_4_0 -dcl_constantbuffer cb0[2], immediateIndexed +dcl_constantbuffer CB0[2], immediateIndexed dcl_input v0.xy dcl_input v1.xy dcl_input v2.xy @@ -106,10 +106,10 @@ ret const BYTE Oculus050VRDistortionVS[] = { - 68, 88, 66, 67, 3, 61, - 196, 122, 10, 53, 44, 234, - 18, 242, 195, 238, 42, 90, - 72, 193, 1, 0, 0, 0, + 68, 88, 66, 67, 92, 195, + 173, 230, 45, 84, 78, 45, + 143, 175, 88, 53, 65, 235, + 243, 174, 1, 0, 0, 0, 244, 5, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 108, 1, 0, 0, 44, 3, @@ -303,9 +303,9 @@ const BYTE Oculus050VRDistortionVS[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 54, 46, 51, 46, 57, - 54, 48, 48, 46, 49, 54, - 51, 56, 52, 0, 171, 171, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, 73, 83, 71, 78, 152, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 128, 0, @@ -364,15 +364,15 @@ const BYTE Oculus050VRDistortionVS[] = ShaderBytes sOculus050VRDistortionVS = { Oculus050VRDistortionVS, sizeof(Oculus050VRDistortionVS) }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // // Resource Bindings: // -// Name Type Format Dim Slot Elements -// ------------------------------ ---------- ------- ----------- ---- -------- -// Linear sampler NA NA 0 1 -// Texture texture float4 2d 0 1 +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// Linear sampler NA NA s0 1 +// Texture texture float4 2d t0 1 // // // @@ -442,10 +442,10 @@ ret const BYTE Oculus050VRDistortionPS[] = { - 68, 88, 66, 67, 108, 219, - 61, 216, 27, 0, 27, 222, - 242, 132, 183, 21, 166, 141, - 130, 39, 1, 0, 0, 0, + 68, 88, 66, 67, 17, 210, + 217, 234, 219, 61, 77, 84, + 3, 36, 81, 127, 138, 35, + 252, 53, 1, 0, 0, 0, 128, 4, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 60, 1, 0, 0, 132, 2, @@ -595,9 +595,9 @@ const BYTE Oculus050VRDistortionPS[] = 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, - 54, 46, 51, 46, 57, 54, - 48, 48, 46, 49, 54, 51, - 56, 52, 0, 171, 171, 171, + 49, 48, 46, 48, 46, 49, + 48, 48, 49, 49, 46, 49, + 54, 51, 56, 52, 0, 171, 73, 83, 71, 78, 156, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 128, 0, diff --git a/gfx/layers/d3d11/genshaders.sh b/gfx/layers/d3d11/genshaders.sh index 230da9b529..15dc0611f6 100755 --- a/gfx/layers/d3d11/genshaders.sh +++ b/gfx/layers/d3d11/genshaders.sh @@ -36,18 +36,15 @@ makeShaderPS RGBAShader makeShaderPS ComponentAlphaShader makeShaderPS YCbCrShader makeShaderVS LayerQuadMaskVS -makeShaderVS LayerQuadMask3DVS makeShaderPS SolidColorShaderMask makeShaderPS RGBShaderMask makeShaderPS RGBAShaderMask -makeShaderPS RGBAShaderMask3D makeShaderPS YCbCrShaderMask makeShaderPS ComponentAlphaShaderMask # Mix-blend shaders makeShaderVS LayerQuadBlendVS makeShaderVS LayerQuadBlendMaskVS -makeShaderVS LayerQuadBlendMask3DVS makeShaderPS BlendShader SRC=CompositorD3D11VR.hlsl diff --git a/gfx/layers/d3d9/CompositorD3D9.cpp b/gfx/layers/d3d9/CompositorD3D9.cpp index 27a5af089b..5199fda879 100644 --- a/gfx/layers/d3d9/CompositorD3D9.cpp +++ b/gfx/layers/d3d9/CompositorD3D9.cpp @@ -265,7 +265,7 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect, d3d9Device->SetVertexShaderConstantF(CBmLayerTransform, &aTransform._11, 4); IntPoint origin = mCurrentRT->GetOrigin(); - float renderTargetOffset[] = { origin.x, origin.y, 0, 0 }; + float renderTargetOffset[] = { float(origin.x), float(origin.y), 0, 0 }; d3d9Device->SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1); @@ -291,11 +291,7 @@ CompositorD3D9::DrawQuad(const gfx::Rect &aRect, MaskType maskType = MaskType::MaskNone; if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) { - if (aTransform.Is2D()) { - maskType = MaskType::Mask2d; - } else { - maskType = MaskType::Mask3d; - } + maskType = MaskType::Mask; } gfx::Rect backdropDest; @@ -682,6 +678,7 @@ void CompositorD3D9::BeginFrame(const nsIntRegion& aInvalidRegion, const Rect *aClipRectIn, const Rect& aRenderBounds, + bool aOpaque, Rect *aClipRectOut, Rect *aRenderBoundsOut) { diff --git a/gfx/layers/d3d9/CompositorD3D9.h b/gfx/layers/d3d9/CompositorD3D9.h index 8a4a099e9b..5330db54e4 100644 --- a/gfx/layers/d3d9/CompositorD3D9.h +++ b/gfx/layers/d3d9/CompositorD3D9.h @@ -64,6 +64,7 @@ public: virtual void BeginFrame(const nsIntRegion& aInvalidRegion, const gfx::Rect *aClipRectIn, const gfx::Rect& aRenderBounds, + bool aOpaque, gfx::Rect *aClipRectOut = nullptr, gfx::Rect *aRenderBoundsOut = nullptr) override; diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.cpp b/gfx/layers/d3d9/DeviceManagerD3D9.cpp index e0dd13db29..cf2842360f 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp +++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp @@ -424,13 +424,6 @@ DeviceManagerD3D9::Init() gfxCriticalError() << failCreateShaderMsg << "LayerQuadVSMask: " << gfx::hexa(hr); return false; } - hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVSMask3D, - getter_AddRefs(mLayerVSMask3D)); - - if (FAILED(hr)) { - gfxCriticalError() << failCreateShaderMsg << "LayerQuadVSMask3D: " << gfx::hexa(hr); - return false; - } hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPSMask, getter_AddRefs(mRGBPSMask)); @@ -448,14 +441,6 @@ DeviceManagerD3D9::Init() return false; } - hr = mDevice->CreatePixelShader((DWORD*)RGBAShaderPSMask3D, - getter_AddRefs(mRGBAPSMask3D)); - - if (FAILED(hr)) { - gfxCriticalError() << failCreateShaderMsg << "RGBAShaderPSMask3D: " << gfx::hexa(hr); - return false; - } - hr = mDevice->CreatePixelShader((DWORD*)ComponentPass1ShaderPSMask, getter_AddRefs(mComponentPass1PSMask)); @@ -625,13 +610,8 @@ DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType) maskTexRegister = 1; break; case RGBALAYER: - if (aMaskType == MaskType::Mask2d) { - mDevice->SetVertexShader(mLayerVSMask); - mDevice->SetPixelShader(mRGBAPSMask); - } else { - mDevice->SetVertexShader(mLayerVSMask3D); - mDevice->SetPixelShader(mRGBAPSMask3D); - } + mDevice->SetVertexShader(mLayerVSMask); + mDevice->SetPixelShader(mRGBAPSMask); maskTexRegister = 1; break; case COMPONENTLAYERPASS1: diff --git a/gfx/layers/d3d9/DeviceManagerD3D9.h b/gfx/layers/d3d9/DeviceManagerD3D9.h index 01120bc6e8..5be41069f4 100644 --- a/gfx/layers/d3d9/DeviceManagerD3D9.h +++ b/gfx/layers/d3d9/DeviceManagerD3D9.h @@ -272,10 +272,8 @@ private: /* As above, but using a mask layer */ RefPtr mLayerVSMask; - RefPtr mLayerVSMask3D; RefPtr mRGBPSMask; RefPtr mRGBAPSMask; - RefPtr mRGBAPSMask3D; RefPtr mComponentPass1PSMask; RefPtr mComponentPass2PSMask; RefPtr mYCbCrPSMask; diff --git a/gfx/layers/d3d9/LayerManagerD3D9Shaders.h b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h index 88f50930fa..7395636dc1 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9Shaders.h +++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h @@ -1,6 +1,6 @@ #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -47,7 +47,7 @@ const BYTE LayerQuadVS[] = { 0, 2, 254, 255, 254, 255, - 78, 0, 67, 84, 65, 66, + 79, 0, 67, 84, 65, 66, 28, 0, 0, 0, 2, 1, 0, 0, 0, 2, 254, 255, 5, 0, 0, 0, 28, 0, @@ -96,66 +96,66 @@ const BYTE LayerQuadVS[] = 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, - 105, 108, 101, 114, 32, 54, - 46, 51, 46, 57, 54, 48, - 48, 46, 49, 54, 51, 56, - 52, 0, 81, 0, 0, 5, - 11, 0, 15, 160, 0, 0, - 0, 191, 0, 0, 0, 0, + 105, 108, 101, 114, 32, 49, + 48, 46, 48, 46, 49, 48, + 48, 49, 49, 46, 49, 54, + 51, 56, 52, 0, 171, 171, + 81, 0, 0, 5, 11, 0, + 15, 160, 0, 0, 0, 191, 0, 0, 0, 0, 0, 0, - 0, 0, 31, 0, 0, 2, - 0, 0, 0, 128, 0, 0, - 15, 144, 4, 0, 0, 4, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 15, 144, + 4, 0, 0, 4, 0, 0, + 3, 128, 0, 0, 228, 144, + 10, 0, 238, 160, 10, 0, + 228, 160, 5, 0, 0, 3, + 1, 0, 15, 128, 0, 0, + 85, 128, 1, 0, 228, 160, + 4, 0, 0, 4, 0, 0, + 15, 128, 0, 0, 228, 160, + 0, 0, 0, 128, 1, 0, + 228, 128, 4, 0, 0, 4, + 0, 0, 15, 128, 2, 0, + 228, 160, 0, 0, 170, 144, + 0, 0, 228, 128, 4, 0, + 0, 4, 0, 0, 15, 128, + 3, 0, 228, 160, 0, 0, + 255, 144, 0, 0, 228, 128, + 6, 0, 0, 2, 1, 0, + 1, 128, 0, 0, 255, 128, + 5, 0, 0, 3, 0, 0, + 7, 128, 0, 0, 228, 128, + 1, 0, 0, 128, 2, 0, + 0, 3, 0, 0, 15, 128, + 0, 0, 228, 128, 8, 0, + 228, 161, 4, 0, 0, 4, 0, 0, 3, 128, 0, 0, - 228, 144, 10, 0, 238, 160, - 10, 0, 228, 160, 5, 0, + 228, 128, 0, 0, 255, 128, + 11, 0, 0, 160, 5, 0, 0, 3, 1, 0, 15, 128, - 0, 0, 85, 128, 1, 0, + 0, 0, 85, 128, 5, 0, 228, 160, 4, 0, 0, 4, - 0, 0, 15, 128, 0, 0, + 1, 0, 15, 128, 4, 0, + 228, 160, 0, 0, 0, 128, + 1, 0, 228, 128, 5, 0, + 0, 3, 0, 0, 1, 128, + 0, 0, 255, 128, 0, 0, + 170, 128, 4, 0, 0, 4, + 1, 0, 15, 128, 6, 0, 228, 160, 0, 0, 0, 128, 1, 0, 228, 128, 4, 0, - 0, 4, 0, 0, 15, 128, - 2, 0, 228, 160, 0, 0, - 170, 144, 0, 0, 228, 128, + 0, 4, 0, 0, 15, 192, + 7, 0, 228, 160, 0, 0, + 255, 128, 1, 0, 228, 128, 4, 0, 0, 4, 0, 0, - 15, 128, 3, 0, 228, 160, - 0, 0, 255, 144, 0, 0, - 228, 128, 6, 0, 0, 2, - 1, 0, 1, 128, 0, 0, - 255, 128, 5, 0, 0, 3, - 0, 0, 7, 128, 0, 0, - 228, 128, 1, 0, 0, 128, - 2, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 228, 128, - 8, 0, 228, 161, 4, 0, - 0, 4, 0, 0, 3, 128, - 0, 0, 228, 128, 0, 0, - 255, 128, 11, 0, 0, 160, - 5, 0, 0, 3, 1, 0, - 15, 128, 0, 0, 85, 128, - 5, 0, 228, 160, 4, 0, - 0, 4, 1, 0, 15, 128, - 4, 0, 228, 160, 0, 0, - 0, 128, 1, 0, 228, 128, - 5, 0, 0, 3, 0, 0, - 1, 128, 0, 0, 255, 128, - 0, 0, 170, 128, 4, 0, - 0, 4, 1, 0, 15, 128, - 6, 0, 228, 160, 0, 0, - 0, 128, 1, 0, 228, 128, - 4, 0, 0, 4, 0, 0, - 15, 192, 7, 0, 228, 160, - 0, 0, 255, 128, 1, 0, - 228, 128, 4, 0, 0, 4, - 0, 0, 3, 224, 0, 0, - 228, 144, 9, 0, 238, 160, - 9, 0, 228, 160, 255, 255, - 0, 0 + 3, 224, 0, 0, 228, 144, + 9, 0, 238, 160, 9, 0, + 228, 160, 255, 255, 0, 0 }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -212,9 +212,9 @@ const BYTE RGBAShaderPS[] = 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, - 54, 46, 51, 46, 57, 54, - 48, 48, 46, 49, 54, 51, - 56, 52, 0, 171, 171, 171, + 49, 48, 46, 48, 46, 49, + 48, 48, 49, 49, 46, 49, + 54, 51, 56, 52, 0, 171, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, @@ -230,7 +230,7 @@ const BYTE RGBAShaderPS[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -303,9 +303,9 @@ const BYTE ComponentPass1ShaderPS[] = 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, - 54, 46, 51, 46, 57, 54, - 48, 48, 46, 49, 54, 51, - 56, 52, 0, 171, 171, 171, + 49, 48, 46, 48, 46, 49, + 48, 48, 49, 49, 46, 49, + 54, 51, 56, 52, 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, @@ -337,7 +337,7 @@ const BYTE ComponentPass1ShaderPS[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -409,9 +409,9 @@ const BYTE ComponentPass2ShaderPS[] = 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, - 54, 46, 51, 46, 57, 54, - 48, 48, 46, 49, 54, 51, - 56, 52, 0, 171, 171, 171, + 49, 48, 46, 48, 46, 49, + 48, 48, 49, 49, 46, 49, + 54, 51, 56, 52, 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, @@ -441,7 +441,7 @@ const BYTE ComponentPass2ShaderPS[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -500,9 +500,9 @@ const BYTE RGBShaderPS[] = 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, - 54, 46, 51, 46, 57, 54, - 48, 48, 46, 49, 54, 51, - 56, 52, 0, 171, 171, 171, + 49, 48, 46, 48, 46, 49, + 48, 48, 49, 49, 46, 49, + 54, 51, 56, 52, 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, @@ -524,7 +524,7 @@ const BYTE RGBShaderPS[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -615,10 +615,10 @@ const BYTE YCbCrShaderPS[] = 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, - 114, 32, 54, 46, 51, 46, - 57, 54, 48, 48, 46, 49, - 54, 51, 56, 52, 0, 171, - 171, 171, 81, 0, 0, 5, + 114, 32, 49, 48, 46, 48, + 46, 49, 48, 48, 49, 49, + 46, 49, 54, 51, 56, 52, + 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 0, 191, 0, 0, 128, 189, 244, 253, 148, 63, 186, 73, @@ -677,7 +677,7 @@ const BYTE YCbCrShaderPS[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -720,194 +720,17 @@ const BYTE SolidColorShaderPS[] = 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, - 108, 101, 114, 32, 54, 46, - 51, 46, 57, 54, 48, 48, - 46, 49, 54, 51, 56, 52, - 0, 171, 171, 171, 1, 0, + 108, 101, 114, 32, 49, 48, + 46, 48, 46, 49, 48, 48, + 49, 49, 46, 49, 54, 51, + 56, 52, 0, 171, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 160, 255, 255, 0, 0 }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 -// -// Parameters: -// -// float4x4 mLayerTransform; -// float4x4 mProjection; -// float4 vLayerQuad; -// float4 vMaskQuad; -// float4 vRenderTargetOffset; -// float4 vTextureCoords; -// -// -// Registers: -// -// Name Reg Size -// ------------------- ----- ---- -// mLayerTransform c0 4 -// mProjection c4 4 -// vRenderTargetOffset c8 1 -// vTextureCoords c9 1 -// vLayerQuad c10 1 -// vMaskQuad c11 1 -// - - vs_2_0 - def c12, -0.5, 0, 0, 0 - dcl_position v0 - mad r0.xy, v0, c10.zwzw, c10 - mul r1, r0.y, c1 - mad r0, c0, r0.x, r1 - add r0, r0, c3 - rcp r1.x, r0.w - mul r1.xyz, r0, r1.x - mov r1.w, r0.w - add r0.xy, r0, -c11 - add r1, r1, -c8 - mad r0.zw, r1.xyxy, r1.w, c12.x - mul r2, r0.w, c5 - mad r2, c4, r0.z, r2 - mul r0.z, r1.w, r1.z - mad r2, c6, r0.z, r2 - mad oPos, c7, r1.w, r2 - rcp r0.z, c11.z - mul oT1.x, r0.z, r0.x - rcp r0.x, c11.w - mul oT1.y, r0.x, r0.y - mad oT0.xy, v0, c9.zwzw, c9 - -// approximately 20 instruction slots used -#endif - -const BYTE LayerQuadVSMask[] = -{ - 0, 2, 254, 255, 254, 255, - 86, 0, 67, 84, 65, 66, - 28, 0, 0, 0, 34, 1, - 0, 0, 0, 2, 254, 255, - 6, 0, 0, 0, 28, 0, - 0, 0, 0, 1, 0, 0, - 27, 1, 0, 0, 148, 0, - 0, 0, 2, 0, 0, 0, - 4, 0, 0, 0, 164, 0, - 0, 0, 0, 0, 0, 0, - 180, 0, 0, 0, 2, 0, - 4, 0, 4, 0, 0, 0, - 164, 0, 0, 0, 0, 0, - 0, 0, 192, 0, 0, 0, - 2, 0, 10, 0, 1, 0, - 0, 0, 204, 0, 0, 0, - 0, 0, 0, 0, 220, 0, - 0, 0, 2, 0, 11, 0, - 1, 0, 0, 0, 204, 0, - 0, 0, 0, 0, 0, 0, - 230, 0, 0, 0, 2, 0, - 8, 0, 1, 0, 0, 0, - 252, 0, 0, 0, 0, 0, - 0, 0, 12, 1, 0, 0, - 2, 0, 9, 0, 1, 0, - 0, 0, 204, 0, 0, 0, - 0, 0, 0, 0, 109, 76, - 97, 121, 101, 114, 84, 114, - 97, 110, 115, 102, 111, 114, - 109, 0, 3, 0, 3, 0, - 4, 0, 4, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 109, 80, 114, 111, 106, 101, - 99, 116, 105, 111, 110, 0, - 118, 76, 97, 121, 101, 114, - 81, 117, 97, 100, 0, 171, - 1, 0, 3, 0, 1, 0, - 4, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 118, 77, - 97, 115, 107, 81, 117, 97, - 100, 0, 118, 82, 101, 110, - 100, 101, 114, 84, 97, 114, - 103, 101, 116, 79, 102, 102, - 115, 101, 116, 0, 171, 171, - 1, 0, 3, 0, 1, 0, - 4, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 118, 84, - 101, 120, 116, 117, 114, 101, - 67, 111, 111, 114, 100, 115, - 0, 118, 115, 95, 50, 95, - 48, 0, 77, 105, 99, 114, - 111, 115, 111, 102, 116, 32, - 40, 82, 41, 32, 72, 76, - 83, 76, 32, 83, 104, 97, - 100, 101, 114, 32, 67, 111, - 109, 112, 105, 108, 101, 114, - 32, 54, 46, 51, 46, 57, - 54, 48, 48, 46, 49, 54, - 51, 56, 52, 0, 81, 0, - 0, 5, 12, 0, 15, 160, - 0, 0, 0, 191, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, - 0, 2, 0, 0, 0, 128, - 0, 0, 15, 144, 4, 0, - 0, 4, 0, 0, 3, 128, - 0, 0, 228, 144, 10, 0, - 238, 160, 10, 0, 228, 160, - 5, 0, 0, 3, 1, 0, - 15, 128, 0, 0, 85, 128, - 1, 0, 228, 160, 4, 0, - 0, 4, 0, 0, 15, 128, - 0, 0, 228, 160, 0, 0, - 0, 128, 1, 0, 228, 128, - 2, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 228, 128, - 3, 0, 228, 160, 6, 0, - 0, 2, 1, 0, 1, 128, - 0, 0, 255, 128, 5, 0, - 0, 3, 1, 0, 7, 128, - 0, 0, 228, 128, 1, 0, - 0, 128, 1, 0, 0, 2, - 1, 0, 8, 128, 0, 0, - 255, 128, 2, 0, 0, 3, - 0, 0, 3, 128, 0, 0, - 228, 128, 11, 0, 228, 161, - 2, 0, 0, 3, 1, 0, - 15, 128, 1, 0, 228, 128, - 8, 0, 228, 161, 4, 0, - 0, 4, 0, 0, 12, 128, - 1, 0, 68, 128, 1, 0, - 255, 128, 12, 0, 0, 160, - 5, 0, 0, 3, 2, 0, - 15, 128, 0, 0, 255, 128, - 5, 0, 228, 160, 4, 0, - 0, 4, 2, 0, 15, 128, - 4, 0, 228, 160, 0, 0, - 170, 128, 2, 0, 228, 128, - 5, 0, 0, 3, 0, 0, - 4, 128, 1, 0, 255, 128, - 1, 0, 170, 128, 4, 0, - 0, 4, 2, 0, 15, 128, - 6, 0, 228, 160, 0, 0, - 170, 128, 2, 0, 228, 128, - 4, 0, 0, 4, 0, 0, - 15, 192, 7, 0, 228, 160, - 1, 0, 255, 128, 2, 0, - 228, 128, 6, 0, 0, 2, - 0, 0, 4, 128, 11, 0, - 170, 160, 5, 0, 0, 3, - 1, 0, 1, 224, 0, 0, - 170, 128, 0, 0, 0, 128, - 6, 0, 0, 2, 0, 0, - 1, 128, 11, 0, 255, 160, - 5, 0, 0, 3, 1, 0, - 2, 224, 0, 0, 0, 128, - 0, 0, 85, 128, 4, 0, - 0, 4, 0, 0, 3, 224, - 0, 0, 228, 144, 9, 0, - 238, 160, 9, 0, 228, 160, - 255, 255, 0, 0 -}; -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -939,31 +762,31 @@ const BYTE LayerQuadVSMask[] = mad r0, c0, r0.x, r1 add r0, r0, c3 rcp r1.x, r0.w - mul r2.xyz, r0, r1.x - mad r0.xy, r0, r1.x, -c11 - mov r2.w, r0.w - add r1, r2, -c8 - mad r0.zw, r1.xyxy, r1.w, c12.x + mul r1.xyz, r0, r1.x + mov r1.w, r0.w + add r2, r1, -c8 + mad r0.zw, r2.xyxy, r2.w, c12.x mul r3, r0.w, c5 mad r3, c4, r0.z, r3 - mul r0.z, r1.w, r1.z + mul r0.z, r2.w, r2.z mad r3, c6, r0.z, r3 - mad oPos, c7, r1.w, r3 + mad oPos, c7, r2.w, r3 + add r0.xy, r0, -c11 rcp r0.z, c11.z mul r1.x, r0.z, r0.x rcp r0.x, c11.w mul r1.y, r0.x, r0.y mov r1.z, c12.y - mul oT1.xyz, r2.w, r1 + mul oT1.xyz, r1.w, r1 mad oT0.xy, v0, c9.zwzw, c9 // approximately 22 instruction slots used #endif -const BYTE LayerQuadVSMask3D[] = +const BYTE LayerQuadVSMask[] = { 0, 2, 254, 255, 254, 255, - 86, 0, 67, 84, 65, 66, + 87, 0, 67, 84, 65, 66, 28, 0, 0, 0, 34, 1, 0, 0, 0, 2, 254, 255, 6, 0, 0, 0, 28, 0, @@ -1018,58 +841,58 @@ const BYTE LayerQuadVSMask3D[] = 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, - 32, 54, 46, 51, 46, 57, - 54, 48, 48, 46, 49, 54, - 51, 56, 52, 0, 81, 0, - 0, 5, 12, 0, 15, 160, - 0, 0, 0, 191, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, - 0, 2, 0, 0, 0, 128, - 0, 0, 15, 144, 4, 0, - 0, 4, 0, 0, 3, 128, - 0, 0, 228, 144, 10, 0, - 238, 160, 10, 0, 228, 160, - 5, 0, 0, 3, 1, 0, - 15, 128, 0, 0, 85, 128, - 1, 0, 228, 160, 4, 0, - 0, 4, 0, 0, 15, 128, - 0, 0, 228, 160, 0, 0, - 0, 128, 1, 0, 228, 128, - 2, 0, 0, 3, 0, 0, - 15, 128, 0, 0, 228, 128, - 3, 0, 228, 160, 6, 0, - 0, 2, 1, 0, 1, 128, - 0, 0, 255, 128, 5, 0, - 0, 3, 2, 0, 7, 128, - 0, 0, 228, 128, 1, 0, - 0, 128, 4, 0, 0, 4, + 32, 49, 48, 46, 48, 46, + 49, 48, 48, 49, 49, 46, + 49, 54, 51, 56, 52, 0, + 171, 171, 81, 0, 0, 5, + 12, 0, 15, 160, 0, 0, + 0, 191, 0, 0, 128, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 2, + 0, 0, 0, 128, 0, 0, + 15, 144, 4, 0, 0, 4, 0, 0, 3, 128, 0, 0, - 228, 128, 1, 0, 0, 128, - 11, 0, 228, 161, 1, 0, - 0, 2, 2, 0, 8, 128, - 0, 0, 255, 128, 2, 0, + 228, 144, 10, 0, 238, 160, + 10, 0, 228, 160, 5, 0, 0, 3, 1, 0, 15, 128, - 2, 0, 228, 128, 8, 0, - 228, 161, 4, 0, 0, 4, - 0, 0, 12, 128, 1, 0, - 68, 128, 1, 0, 255, 128, - 12, 0, 0, 160, 5, 0, - 0, 3, 3, 0, 15, 128, - 0, 0, 255, 128, 5, 0, + 0, 0, 85, 128, 1, 0, 228, 160, 4, 0, 0, 4, - 3, 0, 15, 128, 4, 0, - 228, 160, 0, 0, 170, 128, - 3, 0, 228, 128, 5, 0, - 0, 3, 0, 0, 4, 128, - 1, 0, 255, 128, 1, 0, - 170, 128, 4, 0, 0, 4, - 3, 0, 15, 128, 6, 0, - 228, 160, 0, 0, 170, 128, - 3, 0, 228, 128, 4, 0, - 0, 4, 0, 0, 15, 192, - 7, 0, 228, 160, 1, 0, - 255, 128, 3, 0, 228, 128, + 0, 0, 15, 128, 0, 0, + 228, 160, 0, 0, 0, 128, + 1, 0, 228, 128, 2, 0, + 0, 3, 0, 0, 15, 128, + 0, 0, 228, 128, 3, 0, + 228, 160, 6, 0, 0, 2, + 1, 0, 1, 128, 0, 0, + 255, 128, 5, 0, 0, 3, + 1, 0, 7, 128, 0, 0, + 228, 128, 1, 0, 0, 128, + 1, 0, 0, 2, 1, 0, + 8, 128, 0, 0, 255, 128, + 2, 0, 0, 3, 2, 0, + 15, 128, 1, 0, 228, 128, + 8, 0, 228, 161, 4, 0, + 0, 4, 0, 0, 12, 128, + 2, 0, 68, 128, 2, 0, + 255, 128, 12, 0, 0, 160, + 5, 0, 0, 3, 3, 0, + 15, 128, 0, 0, 255, 128, + 5, 0, 228, 160, 4, 0, + 0, 4, 3, 0, 15, 128, + 4, 0, 228, 160, 0, 0, + 170, 128, 3, 0, 228, 128, + 5, 0, 0, 3, 0, 0, + 4, 128, 2, 0, 255, 128, + 2, 0, 170, 128, 4, 0, + 0, 4, 3, 0, 15, 128, + 6, 0, 228, 160, 0, 0, + 170, 128, 3, 0, 228, 128, + 4, 0, 0, 4, 0, 0, + 15, 192, 7, 0, 228, 160, + 2, 0, 255, 128, 3, 0, + 228, 128, 2, 0, 0, 3, + 0, 0, 3, 128, 0, 0, + 228, 128, 11, 0, 228, 161, 6, 0, 0, 2, 0, 0, 4, 128, 11, 0, 170, 160, 5, 0, 0, 3, 1, 0, @@ -1082,7 +905,7 @@ const BYTE LayerQuadVSMask3D[] = 85, 128, 1, 0, 0, 2, 1, 0, 4, 128, 12, 0, 85, 160, 5, 0, 0, 3, - 1, 0, 7, 224, 2, 0, + 1, 0, 7, 224, 1, 0, 255, 128, 1, 0, 228, 128, 4, 0, 0, 4, 0, 0, 3, 224, 0, 0, 228, 144, @@ -1091,7 +914,7 @@ const BYTE LayerQuadVSMask3D[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -1111,16 +934,18 @@ const BYTE LayerQuadVSMask3D[] = ps_2_0 dcl t0.xy - dcl t1.xy + dcl t1.xyz dcl_2d s0 dcl_2d s1 - texld r0, t0, s0 - texld r1, t1, s1 - mul r0, r0, c0.x - mul r0, r1.w, r0 + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r0, r0, s1 + texld r1, t0, s0 + mul r1, r1, c0.x + mul r0, r0.w, r1 mov oC0, r0 -// approximately 5 instruction slots used (2 texture, 3 arithmetic) +// approximately 7 instruction slots used (2 texture, 5 arithmetic) #endif const BYTE RGBAShaderPSMask[] = @@ -1161,110 +986,10 @@ const BYTE RGBAShaderPSMask[] = 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, - 114, 32, 54, 46, 51, 46, - 57, 54, 48, 48, 46, 49, - 54, 51, 56, 52, 0, 171, - 171, 171, 31, 0, 0, 2, - 0, 0, 0, 128, 0, 0, - 3, 176, 31, 0, 0, 2, - 0, 0, 0, 128, 1, 0, - 3, 176, 31, 0, 0, 2, - 0, 0, 0, 144, 0, 8, - 15, 160, 31, 0, 0, 2, - 0, 0, 0, 144, 1, 8, - 15, 160, 66, 0, 0, 3, - 0, 0, 15, 128, 0, 0, - 228, 176, 0, 8, 228, 160, - 66, 0, 0, 3, 1, 0, - 15, 128, 1, 0, 228, 176, - 1, 8, 228, 160, 5, 0, - 0, 3, 0, 0, 15, 128, - 0, 0, 228, 128, 0, 0, - 0, 160, 5, 0, 0, 3, - 0, 0, 15, 128, 1, 0, - 255, 128, 0, 0, 228, 128, - 1, 0, 0, 2, 0, 8, - 15, 128, 0, 0, 228, 128, - 255, 255, 0, 0 -}; -#if 0 -// -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 -// -// Parameters: -// -// float fLayerOpacity; -// sampler2D s2D; -// sampler2D s2DMask; -// -// -// Registers: -// -// Name Reg Size -// ------------- ----- ---- -// fLayerOpacity c0 1 -// s2D s0 1 -// s2DMask s1 1 -// - - ps_2_0 - dcl t0.xy - dcl t1.xyz - dcl_2d s0 - dcl_2d s1 - rcp r0.w, t1.z - mul r0.xy, r0.w, t1 - texld r0, r0, s1 - texld r1, t0, s0 - mul r1, r1, c0.x - mul r0, r0.w, r1 - mov oC0, r0 - -// approximately 7 instruction slots used (2 texture, 5 arithmetic) -#endif - -const BYTE RGBAShaderPSMask3D[] = -{ - 0, 2, 255, 255, 254, 255, - 57, 0, 67, 84, 65, 66, - 28, 0, 0, 0, 171, 0, - 0, 0, 0, 2, 255, 255, - 3, 0, 0, 0, 28, 0, - 0, 0, 0, 1, 0, 0, - 164, 0, 0, 0, 88, 0, - 0, 0, 2, 0, 0, 0, - 1, 0, 0, 0, 104, 0, - 0, 0, 0, 0, 0, 0, - 120, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 124, 0, 0, 0, 0, 0, - 0, 0, 140, 0, 0, 0, - 3, 0, 1, 0, 1, 0, - 0, 0, 148, 0, 0, 0, - 0, 0, 0, 0, 102, 76, - 97, 121, 101, 114, 79, 112, - 97, 99, 105, 116, 121, 0, - 171, 171, 0, 0, 3, 0, - 1, 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, - 115, 50, 68, 0, 4, 0, - 12, 0, 1, 0, 1, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 115, 50, 68, 77, - 97, 115, 107, 0, 4, 0, - 12, 0, 1, 0, 1, 0, - 1, 0, 0, 0, 0, 0, - 0, 0, 112, 115, 95, 50, - 95, 48, 0, 77, 105, 99, - 114, 111, 115, 111, 102, 116, - 32, 40, 82, 41, 32, 72, - 76, 83, 76, 32, 83, 104, - 97, 100, 101, 114, 32, 67, - 111, 109, 112, 105, 108, 101, - 114, 32, 54, 46, 51, 46, - 57, 54, 48, 48, 46, 49, - 54, 51, 56, 52, 0, 171, - 171, 171, 31, 0, 0, 2, + 114, 32, 49, 48, 46, 48, + 46, 49, 48, 48, 49, 49, + 46, 49, 54, 51, 56, 52, + 0, 171, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, @@ -1294,7 +1019,7 @@ const BYTE RGBAShaderPSMask3D[] = }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -1317,21 +1042,23 @@ const BYTE RGBAShaderPSMask3D[] = ps_2_0 def c1, 1, 0, 0, 0 dcl t0.xy - dcl t1.xy + dcl t1.xyz dcl_2d s0 dcl_2d s1 dcl_2d s2 - texld r0, t0, s0 - texld r1, t0, s1 - texld r2, t1, s2 - add r0.xyz, r0, -r1 + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r1, t0, s0 + texld r2, t0, s1 + texld r0, r0, s2 + add r0.xyz, r1, -r2 add r0.xyz, r0, c1.x mul r0.xyz, r0, c0.x - mul r0.xyz, r2.w, r0 + mul r0.xyz, r0.w, r0 mov r0.w, r0.y mov oC0, r0 -// approximately 9 instruction slots used (3 texture, 6 arithmetic) +// approximately 11 instruction slots used (3 texture, 8 arithmetic) #endif const BYTE ComponentPass1ShaderPSMask[] = @@ -1380,10 +1107,10 @@ const BYTE ComponentPass1ShaderPSMask[] = 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, - 114, 32, 54, 46, 51, 46, - 57, 54, 48, 48, 46, 49, - 54, 51, 56, 52, 0, 171, - 171, 171, 81, 0, 0, 5, + 114, 32, 49, 48, 46, 48, + 46, 49, 48, 48, 49, 49, + 46, 49, 54, 51, 56, 52, + 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1391,40 +1118,45 @@ const BYTE ComponentPass1ShaderPSMask[] = 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, - 3, 176, 31, 0, 0, 2, + 7, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 31, 0, 0, 2, 0, 0, 0, 144, 1, 8, 15, 160, 31, 0, 0, 2, 0, 0, 0, 144, 2, 8, - 15, 160, 66, 0, 0, 3, - 0, 0, 15, 128, 0, 0, - 228, 176, 0, 8, 228, 160, + 15, 160, 6, 0, 0, 2, + 0, 0, 8, 128, 1, 0, + 170, 176, 5, 0, 0, 3, + 0, 0, 3, 128, 0, 0, + 255, 128, 1, 0, 228, 176, 66, 0, 0, 3, 1, 0, 15, 128, 0, 0, 228, 176, - 1, 8, 228, 160, 66, 0, + 0, 8, 228, 160, 66, 0, 0, 3, 2, 0, 15, 128, - 1, 0, 228, 176, 2, 8, - 228, 160, 2, 0, 0, 3, - 0, 0, 7, 128, 0, 0, - 228, 128, 1, 0, 228, 129, + 0, 0, 228, 176, 1, 8, + 228, 160, 66, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 128, 2, 8, 228, 160, 2, 0, 0, 3, 0, 0, - 7, 128, 0, 0, 228, 128, - 1, 0, 0, 160, 5, 0, + 7, 128, 1, 0, 228, 128, + 2, 0, 228, 129, 2, 0, 0, 3, 0, 0, 7, 128, - 0, 0, 228, 128, 0, 0, + 0, 0, 228, 128, 1, 0, 0, 160, 5, 0, 0, 3, - 0, 0, 7, 128, 2, 0, - 255, 128, 0, 0, 228, 128, - 1, 0, 0, 2, 0, 0, - 8, 128, 0, 0, 85, 128, - 1, 0, 0, 2, 0, 8, - 15, 128, 0, 0, 228, 128, - 255, 255, 0, 0 + 0, 0, 7, 128, 0, 0, + 228, 128, 0, 0, 0, 160, + 5, 0, 0, 3, 0, 0, + 7, 128, 0, 0, 255, 128, + 0, 0, 228, 128, 1, 0, + 0, 2, 0, 0, 8, 128, + 0, 0, 85, 128, 1, 0, + 0, 2, 0, 8, 15, 128, + 0, 0, 228, 128, 255, 255, + 0, 0 }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -1447,20 +1179,22 @@ const BYTE ComponentPass1ShaderPSMask[] = ps_2_0 def c1, 1, 0, 0, 0 dcl t0.xy - dcl t1.xy + dcl t1.xyz dcl_2d s0 dcl_2d s1 dcl_2d s2 - texld r0, t0, s1 - texld r1, t0, s0 - texld r2, t1, s2 - add r0.x, -r0.y, r1.y - add r1.w, r0.x, c1.x - mul r0, r1, c0.x - mul r0, r2.w, r0 + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r1, t0, s1 + texld r2, t0, s0 + texld r0, r0, s2 + add r0.x, -r1.y, r2.y + add r2.w, r0.x, c1.x + mul r1, r2, c0.x + mul r0, r0.w, r1 mov oC0, r0 -// approximately 8 instruction slots used (3 texture, 5 arithmetic) +// approximately 10 instruction slots used (3 texture, 7 arithmetic) #endif const BYTE ComponentPass2ShaderPSMask[] = @@ -1509,10 +1243,10 @@ const BYTE ComponentPass2ShaderPSMask[] = 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, - 114, 32, 54, 46, 51, 46, - 57, 54, 48, 48, 46, 49, - 54, 51, 56, 52, 0, 171, - 171, 171, 81, 0, 0, 5, + 114, 32, 49, 48, 46, 48, + 46, 49, 48, 48, 49, 49, + 46, 49, 54, 51, 56, 52, + 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1520,38 +1254,43 @@ const BYTE ComponentPass2ShaderPSMask[] = 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, - 3, 176, 31, 0, 0, 2, + 7, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 31, 0, 0, 2, 0, 0, 0, 144, 1, 8, 15, 160, 31, 0, 0, 2, 0, 0, 0, 144, 2, 8, - 15, 160, 66, 0, 0, 3, - 0, 0, 15, 128, 0, 0, - 228, 176, 1, 8, 228, 160, + 15, 160, 6, 0, 0, 2, + 0, 0, 8, 128, 1, 0, + 170, 176, 5, 0, 0, 3, + 0, 0, 3, 128, 0, 0, + 255, 128, 1, 0, 228, 176, 66, 0, 0, 3, 1, 0, 15, 128, 0, 0, 228, 176, - 0, 8, 228, 160, 66, 0, + 1, 8, 228, 160, 66, 0, 0, 3, 2, 0, 15, 128, - 1, 0, 228, 176, 2, 8, - 228, 160, 2, 0, 0, 3, - 0, 0, 1, 128, 0, 0, - 85, 129, 1, 0, 85, 128, - 2, 0, 0, 3, 1, 0, - 8, 128, 0, 0, 0, 128, - 1, 0, 0, 160, 5, 0, - 0, 3, 0, 0, 15, 128, - 1, 0, 228, 128, 0, 0, + 0, 0, 228, 176, 0, 8, + 228, 160, 66, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 128, 2, 8, 228, 160, + 2, 0, 0, 3, 0, 0, + 1, 128, 1, 0, 85, 129, + 2, 0, 85, 128, 2, 0, + 0, 3, 2, 0, 8, 128, + 0, 0, 0, 128, 1, 0, 0, 160, 5, 0, 0, 3, - 0, 0, 15, 128, 2, 0, - 255, 128, 0, 0, 228, 128, - 1, 0, 0, 2, 0, 8, - 15, 128, 0, 0, 228, 128, - 255, 255, 0, 0 + 1, 0, 15, 128, 2, 0, + 228, 128, 0, 0, 0, 160, + 5, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 255, 128, + 1, 0, 228, 128, 1, 0, + 0, 2, 0, 8, 15, 128, + 0, 0, 228, 128, 255, 255, + 0, 0 }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -1572,17 +1311,19 @@ const BYTE ComponentPass2ShaderPSMask[] = ps_2_0 def c1, 1, 0, 0, 0 dcl t0.xy - dcl t1.xy + dcl t1.xyz dcl_2d s0 dcl_2d s1 - texld r0, t0, s0 - texld r1, t1, s1 - mov r0.w, c1.x - mul r0, r0, c0.x - mul r0, r1.w, r0 + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r1, t0, s0 + texld r0, r0, s1 + mov r1.w, c1.x + mul r1, r1, c0.x + mul r0, r0.w, r1 mov oC0, r0 -// approximately 6 instruction slots used (2 texture, 4 arithmetic) +// approximately 8 instruction slots used (2 texture, 6 arithmetic) #endif const BYTE RGBShaderPSMask[] = @@ -1623,10 +1364,10 @@ const BYTE RGBShaderPSMask[] = 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, - 114, 32, 54, 46, 51, 46, - 57, 54, 48, 48, 46, 49, - 54, 51, 56, 52, 0, 171, - 171, 171, 81, 0, 0, 5, + 114, 32, 49, 48, 46, 48, + 46, 49, 48, 48, 49, 49, + 46, 49, 54, 51, 56, 52, + 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1634,30 +1375,35 @@ const BYTE RGBShaderPSMask[] = 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 128, 1, 0, - 3, 176, 31, 0, 0, 2, + 7, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 31, 0, 0, 2, 0, 0, 0, 144, 1, 8, - 15, 160, 66, 0, 0, 3, - 0, 0, 15, 128, 0, 0, - 228, 176, 0, 8, 228, 160, + 15, 160, 6, 0, 0, 2, + 0, 0, 8, 128, 1, 0, + 170, 176, 5, 0, 0, 3, + 0, 0, 3, 128, 0, 0, + 255, 128, 1, 0, 228, 176, 66, 0, 0, 3, 1, 0, - 15, 128, 1, 0, 228, 176, - 1, 8, 228, 160, 1, 0, - 0, 2, 0, 0, 8, 128, - 1, 0, 0, 160, 5, 0, + 15, 128, 0, 0, 228, 176, + 0, 8, 228, 160, 66, 0, 0, 3, 0, 0, 15, 128, - 0, 0, 228, 128, 0, 0, + 0, 0, 228, 128, 1, 8, + 228, 160, 1, 0, 0, 2, + 1, 0, 8, 128, 1, 0, 0, 160, 5, 0, 0, 3, - 0, 0, 15, 128, 1, 0, - 255, 128, 0, 0, 228, 128, - 1, 0, 0, 2, 0, 8, - 15, 128, 0, 0, 228, 128, - 255, 255, 0, 0 + 1, 0, 15, 128, 1, 0, + 228, 128, 0, 0, 0, 160, + 5, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 255, 128, + 1, 0, 228, 128, 1, 0, + 0, 2, 0, 8, 15, 128, + 0, 0, 228, 128, 255, 255, + 0, 0 }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -1683,29 +1429,31 @@ const BYTE RGBShaderPSMask[] = def c1, -0.50195998, -0.0627499968, 1.16437995, 1.59603 def c2, 0.812969983, 0.391759992, 2.01723003, 1 dcl t0.xy - dcl t1.xy + dcl t1.xyz dcl_2d s0 dcl_2d s1 dcl_2d s2 dcl_2d s3 - texld r0, t0, s2 - texld r1, t0, s0 - texld r2, t0, s1 - texld r3, t1, s3 - add r0.x, r0.w, c1.x - add r0.y, r1.w, c1.y + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r1, t0, s2 + texld r2, t0, s0 + texld r3, t0, s1 + texld r0, r0, s3 + add r0.x, r1.w, c1.x + add r0.y, r2.w, c1.y mul r0.y, r0.y, c1.z mad r0.z, r0.x, -c2.x, r0.y mad r1.x, r0.x, c1.w, r0.y - add r0.x, r2.w, c1.x + add r0.x, r3.w, c1.x mad r1.y, r0.x, -c2.y, r0.z mad r1.z, r0.x, c2.z, r0.y mov r1.w, c2.w - mul r0, r1, c0.x - mul r0, r3.w, r0 + mul r1, r1, c0.x + mul r0, r0.w, r1 mov oC0, r0 -// approximately 16 instruction slots used (4 texture, 12 arithmetic) +// approximately 18 instruction slots used (4 texture, 14 arithmetic) #endif const BYTE YCbCrShaderPSMask[] = @@ -1761,10 +1509,10 @@ const BYTE YCbCrShaderPSMask[] = 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, - 108, 101, 114, 32, 54, 46, - 51, 46, 57, 54, 48, 48, - 46, 49, 54, 51, 56, 52, - 0, 171, 171, 171, 81, 0, + 108, 101, 114, 32, 49, 48, + 46, 48, 46, 49, 48, 48, + 49, 49, 46, 49, 54, 51, + 56, 52, 0, 171, 81, 0, 0, 5, 1, 0, 15, 160, 115, 128, 0, 191, 18, 131, 128, 189, 103, 10, 149, 63, @@ -1776,7 +1524,7 @@ const BYTE YCbCrShaderPSMask[] = 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 128, - 1, 0, 3, 176, 31, 0, + 1, 0, 7, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 31, 0, 0, 2, 0, 0, 0, 144, @@ -1784,56 +1532,60 @@ const BYTE YCbCrShaderPSMask[] = 0, 2, 0, 0, 0, 144, 2, 8, 15, 160, 31, 0, 0, 2, 0, 0, 0, 144, - 3, 8, 15, 160, 66, 0, - 0, 3, 0, 0, 15, 128, - 0, 0, 228, 176, 2, 8, - 228, 160, 66, 0, 0, 3, + 3, 8, 15, 160, 6, 0, + 0, 2, 0, 0, 8, 128, + 1, 0, 170, 176, 5, 0, + 0, 3, 0, 0, 3, 128, + 0, 0, 255, 128, 1, 0, + 228, 176, 66, 0, 0, 3, 1, 0, 15, 128, 0, 0, - 228, 176, 0, 8, 228, 160, + 228, 176, 2, 8, 228, 160, 66, 0, 0, 3, 2, 0, 15, 128, 0, 0, 228, 176, - 1, 8, 228, 160, 66, 0, + 0, 8, 228, 160, 66, 0, 0, 3, 3, 0, 15, 128, - 1, 0, 228, 176, 3, 8, - 228, 160, 2, 0, 0, 3, - 0, 0, 1, 128, 0, 0, - 255, 128, 1, 0, 0, 160, + 0, 0, 228, 176, 1, 8, + 228, 160, 66, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 128, 3, 8, 228, 160, 2, 0, 0, 3, 0, 0, - 2, 128, 1, 0, 255, 128, - 1, 0, 85, 160, 5, 0, + 1, 128, 1, 0, 255, 128, + 1, 0, 0, 160, 2, 0, 0, 3, 0, 0, 2, 128, - 0, 0, 85, 128, 1, 0, - 170, 160, 4, 0, 0, 4, - 0, 0, 4, 128, 0, 0, - 0, 128, 2, 0, 0, 161, - 0, 0, 85, 128, 4, 0, - 0, 4, 1, 0, 1, 128, - 0, 0, 0, 128, 1, 0, - 255, 160, 0, 0, 85, 128, - 2, 0, 0, 3, 0, 0, - 1, 128, 2, 0, 255, 128, - 1, 0, 0, 160, 4, 0, - 0, 4, 1, 0, 2, 128, - 0, 0, 0, 128, 2, 0, - 85, 161, 0, 0, 170, 128, - 4, 0, 0, 4, 1, 0, + 2, 0, 255, 128, 1, 0, + 85, 160, 5, 0, 0, 3, + 0, 0, 2, 128, 0, 0, + 85, 128, 1, 0, 170, 160, + 4, 0, 0, 4, 0, 0, 4, 128, 0, 0, 0, 128, - 2, 0, 170, 160, 0, 0, - 85, 128, 1, 0, 0, 2, - 1, 0, 8, 128, 2, 0, - 255, 160, 5, 0, 0, 3, - 0, 0, 15, 128, 1, 0, - 228, 128, 0, 0, 0, 160, - 5, 0, 0, 3, 0, 0, - 15, 128, 3, 0, 255, 128, - 0, 0, 228, 128, 1, 0, - 0, 2, 0, 8, 15, 128, - 0, 0, 228, 128, 255, 255, - 0, 0 + 2, 0, 0, 161, 0, 0, + 85, 128, 4, 0, 0, 4, + 1, 0, 1, 128, 0, 0, + 0, 128, 1, 0, 255, 160, + 0, 0, 85, 128, 2, 0, + 0, 3, 0, 0, 1, 128, + 3, 0, 255, 128, 1, 0, + 0, 160, 4, 0, 0, 4, + 1, 0, 2, 128, 0, 0, + 0, 128, 2, 0, 85, 161, + 0, 0, 170, 128, 4, 0, + 0, 4, 1, 0, 4, 128, + 0, 0, 0, 128, 2, 0, + 170, 160, 0, 0, 85, 128, + 1, 0, 0, 2, 1, 0, + 8, 128, 2, 0, 255, 160, + 5, 0, 0, 3, 1, 0, + 15, 128, 1, 0, 228, 128, + 0, 0, 0, 160, 5, 0, + 0, 3, 0, 0, 15, 128, + 0, 0, 255, 128, 1, 0, + 228, 128, 1, 0, 0, 2, + 0, 8, 15, 128, 0, 0, + 228, 128, 255, 255, 0, 0 }; #if 0 // -// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384 +// Generated by Microsoft (R) HLSL Shader Compiler 10.0.10011.16384 // // Parameters: // @@ -1850,13 +1602,15 @@ const BYTE YCbCrShaderPSMask[] = // ps_2_0 - dcl t1.xy + dcl t1.xyz dcl_2d s0 - texld r0, t1, s0 + rcp r0.w, t1.z + mul r0.xy, r0.w, t1 + texld r0, r0, s0 mul r0, r0.w, c0 mov oC0, r0 -// approximately 3 instruction slots used (1 texture, 2 arithmetic) +// approximately 5 instruction slots used (1 texture, 4 arithmetic) #endif const BYTE SolidColorShaderPSMask[] = @@ -1890,19 +1644,24 @@ const BYTE SolidColorShaderPSMask[] = 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, - 54, 46, 51, 46, 57, 54, - 48, 48, 46, 49, 54, 51, - 56, 52, 0, 171, 171, 171, + 49, 48, 46, 48, 46, 49, + 48, 48, 49, 49, 46, 49, + 54, 51, 56, 52, 0, 171, 31, 0, 0, 2, 0, 0, - 0, 128, 1, 0, 3, 176, + 0, 128, 1, 0, 7, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, - 66, 0, 0, 3, 0, 0, - 15, 128, 1, 0, 228, 176, - 0, 8, 228, 160, 5, 0, + 6, 0, 0, 2, 0, 0, + 8, 128, 1, 0, 170, 176, + 5, 0, 0, 3, 0, 0, + 3, 128, 0, 0, 255, 128, + 1, 0, 228, 176, 66, 0, 0, 3, 0, 0, 15, 128, - 0, 0, 255, 128, 0, 0, - 228, 160, 1, 0, 0, 2, - 0, 8, 15, 128, 0, 0, - 228, 128, 255, 255, 0, 0 + 0, 0, 228, 128, 0, 8, + 228, 160, 5, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 255, 128, 0, 0, 228, 160, + 1, 0, 0, 2, 0, 8, + 15, 128, 0, 0, 228, 128, + 255, 255, 0, 0 }; diff --git a/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl index 211f6fbff1..088ff28d04 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl +++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl @@ -29,12 +29,6 @@ struct VS_OUTPUT { }; struct VS_OUTPUT_MASK { - float4 vPosition : POSITION; - float2 vTexCoords : TEXCOORD0; - float2 vMaskCoords : TEXCOORD1; -}; - -struct VS_OUTPUT_MASK_3D { float4 vPosition : POSITION; float2 vTexCoords : TEXCOORD0; float3 vMaskCoords : TEXCOORD1; @@ -105,46 +99,7 @@ VS_OUTPUT_MASK LayerQuadVSMask(const VS_INPUT aVertex) // calculate the position on the mask texture outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z; outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w; - - size = vTextureCoords.zw; - outp.vTexCoords.x = vTextureCoords.x + aVertex.vPosition.x * size.x; - outp.vTexCoords.y = vTextureCoords.y + aVertex.vPosition.y * size.y; - - return outp; -} - -VS_OUTPUT_MASK_3D LayerQuadVSMask3D(const VS_INPUT aVertex) -{ - VS_OUTPUT_MASK_3D outp; - float4 position = float4(0, 0, 0, 1); - - // We use 4 component floats to uniquely describe a rectangle, by the structure - // of x, y, width, height. This allows us to easily generate the 4 corners - // of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the - // stream source for our LayerQuad vertex shader. We do this by doing: - // Xout = x + Xin * width - // Yout = y + Yin * height - float2 size = vLayerQuad.zw; - position.x = vLayerQuad.x + aVertex.vPosition.x * size.x; - position.y = vLayerQuad.y + aVertex.vPosition.y * size.y; - - position = mul(mLayerTransform, position); - outp.vPosition.w = position.w; - outp.vPosition.xyz = position.xyz / position.w; - outp.vPosition = outp.vPosition - vRenderTargetOffset; - outp.vPosition.xyz *= outp.vPosition.w; - - // adjust our vertices to match d3d9's pixel coordinate system - // which has pixel centers at integer locations - outp.vPosition.xy -= 0.5; - - outp.vPosition = mul(mProjection, outp.vPosition); - - // calculate the position on the mask texture - position.xyz /= position.w; - outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z; - outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w; - // correct for perspective correct interpolation, see comment in D3D10 shader + // correct for perspective correct interpolation, see comment in D3D11 shader outp.vMaskCoords.z = 1; outp.vMaskCoords *= position.w; @@ -211,7 +166,7 @@ float4 ComponentPass1ShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR float4 src = tex2D(s2D, aVertex.vTexCoords); float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src; alphas.a = alphas.g; - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tex2D(s2DMask, maskCoords).a; return alphas * fLayerOpacity * mask; } @@ -221,19 +176,12 @@ float4 ComponentPass2ShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR float4 src = tex2D(s2D, aVertex.vTexCoords); float4 alphas = 1.0 - tex2D(s2DWhite, aVertex.vTexCoords) + src; src.a = alphas.g; - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tex2D(s2DMask, maskCoords).a; return src * fLayerOpacity * mask; } float4 RGBAShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR -{ - float2 maskCoords = aVertex.vMaskCoords; - float mask = tex2D(s2DMask, maskCoords).a; - return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity * mask; -} - -float4 RGBAShaderMask3D(const VS_OUTPUT_MASK_3D aVertex) : COLOR { float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tex2D(s2DMask, maskCoords).a; @@ -245,7 +193,7 @@ float4 RGBShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR float4 result; result = tex2D(s2D, aVertex.vTexCoords); result.a = 1.0; - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tex2D(s2DMask, maskCoords).a; return result * fLayerOpacity * mask; } @@ -274,14 +222,14 @@ float4 YCbCrShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR color.b = yuv.g * 1.16438 + yuv.b * 2.01723; color.a = 1.0f; - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tex2D(s2DMask, maskCoords).a; return color * fLayerOpacity * mask; } float4 SolidColorShaderMask(const VS_OUTPUT_MASK aVertex) : COLOR { - float2 maskCoords = aVertex.vMaskCoords; + float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z; float mask = tex2D(s2DMask, maskCoords).a; return fLayerColor * mask; } diff --git a/gfx/layers/d3d9/genshaders.sh b/gfx/layers/d3d9/genshaders.sh index 85e92cedc4..f857624504 100755 --- a/gfx/layers/d3d9/genshaders.sh +++ b/gfx/layers/d3d9/genshaders.sh @@ -20,12 +20,8 @@ fxc LayerManagerD3D9Shaders.hlsl -ESolidColorShader -nologo -Tps_2_0 -Fh$tempfil cat $tempfile >> LayerManagerD3D9Shaders.h fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVSMask -nologo -Fh$tempfile -VnLayerQuadVSMask cat $tempfile >> LayerManagerD3D9Shaders.h -fxc LayerManagerD3D9Shaders.hlsl -ELayerQuadVSMask3D -nologo -Fh$tempfile -VnLayerQuadVSMask3D -cat $tempfile >> LayerManagerD3D9Shaders.h fxc LayerManagerD3D9Shaders.hlsl -ERGBAShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnRGBAShaderPSMask cat $tempfile >> LayerManagerD3D9Shaders.h -fxc LayerManagerD3D9Shaders.hlsl -ERGBAShaderMask3D -nologo -Tps_2_0 -Fh$tempfile -VnRGBAShaderPSMask3D -cat $tempfile >> LayerManagerD3D9Shaders.h fxc LayerManagerD3D9Shaders.hlsl -EComponentPass1ShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass1ShaderPSMask cat $tempfile >> LayerManagerD3D9Shaders.h fxc LayerManagerD3D9Shaders.hlsl -EComponentPass2ShaderMask -nologo -Tps_2_0 -Fh$tempfile -VnComponentPass2ShaderPSMask diff --git a/gfx/layers/ipc/CompositableTransactionParent.cpp b/gfx/layers/ipc/CompositableTransactionParent.cpp index 9a4f4ba90c..ac31b1be2c 100644 --- a/gfx/layers/ipc/CompositableTransactionParent.cpp +++ b/gfx/layers/ipc/CompositableTransactionParent.cpp @@ -133,7 +133,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation MOZ_ASSERT(tex.get()); compositable->RemoveTextureHost(tex); // send FenceHandle if present. - SendFenceHandleIfPresent(op.textureParent(), compositable); + SendFenceHandleIfPresent(op.textureParent()); break; } case CompositableOperation::TOpRemoveTextureAsync: { @@ -150,8 +150,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation GetChildProcessId(), op.holderId(), op.transactionId(), - op.textureParent(), - compositable); + op.textureParent()); // If the message is recievied via PLayerTransaction, // Send message back via PImageBridge. @@ -161,7 +160,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation op.transactionId())); } else { // send FenceHandle if present. - SendFenceHandleIfPresent(op.textureParent(), compositable); + SendFenceHandleIfPresent(op.textureParent()); ReplyRemoveTexture(OpReplyRemoveTexture(op.holderId(), op.transactionId())); diff --git a/gfx/layers/ipc/CompositableTransactionParent.h b/gfx/layers/ipc/CompositableTransactionParent.h index e6c8da760c..e751c61761 100644 --- a/gfx/layers/ipc/CompositableTransactionParent.h +++ b/gfx/layers/ipc/CompositableTransactionParent.h @@ -28,8 +28,7 @@ typedef std::vector EditReplyVector; class CompositableParentManager : public ISurfaceAllocator { public: - virtual void SendFenceHandleIfPresent(PTextureParent* aTexture, - CompositableHost* aCompositableHost) = 0; + virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) = 0; virtual void SendAsyncMessage(const InfallibleTArray& aMessage) = 0; diff --git a/gfx/layers/ipc/ImageBridgeParent.cpp b/gfx/layers/ipc/ImageBridgeParent.cpp index 2d95860f19..aaf63cb157 100644 --- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -447,25 +447,22 @@ ImageBridgeParent::ReplyRemoveTexture(base::ProcessId aChildProcessId, } void -ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture, - CompositableHost* aCompositableHost) +ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture) { RefPtr texture = TextureHost::AsTextureHost(aTexture); - if (!texture) { + if (!texture || !texture->NeedsFenceHandle()) { return; } // Send a ReleaseFence of CompositorOGL. - if (aCompositableHost && aCompositableHost->GetCompositor()) { - FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence(); - if (fence.IsValid()) { - mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr, - fence)); - } + FenceHandle fence = texture->GetCompositorReleaseFence(); + if (fence.IsValid()) { + mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr, + fence)); } - // Send a ReleaseFence that is set by HwcComposer2D. - FenceHandle fence = texture->GetAndResetReleaseFenceHandle(); + // Send a ReleaseFence that is set to TextureHost by HwcComposer2D. + fence = texture->GetAndResetReleaseFenceHandle(); if (fence.IsValid()) { mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr, fence)); @@ -475,26 +472,23 @@ ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture, void ImageBridgeParent::AppendDeliverFenceMessage(uint64_t aDestHolderId, uint64_t aTransactionId, - PTextureParent* aTexture, - CompositableHost* aCompositableHost) + PTextureParent* aTexture) { RefPtr texture = TextureHost::AsTextureHost(aTexture); - if (!texture) { + if (!texture || !texture->NeedsFenceHandle()) { return; } // Send a ReleaseFence of CompositorOGL. - if (aCompositableHost && aCompositableHost->GetCompositor()) { - FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence(); - if (fence.IsValid()) { - mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId, - aTransactionId, - fence)); - } + FenceHandle fence = texture->GetCompositorReleaseFence(); + if (fence.IsValid()) { + mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId, + aTransactionId, + fence)); } - // Send a ReleaseFence that is set by HwcComposer2D. - FenceHandle fence = texture->GetAndResetReleaseFenceHandle(); + // Send a ReleaseFence that is set to TextureHost by HwcComposer2D. + fence = texture->GetAndResetReleaseFenceHandle(); if (fence.IsValid()) { mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId, aTransactionId, @@ -506,8 +500,7 @@ ImageBridgeParent::AppendDeliverFenceMessage(uint64_t aDestHolderId, ImageBridgeParent::AppendDeliverFenceMessage(base::ProcessId aChildProcessId, uint64_t aDestHolderId, uint64_t aTransactionId, - PTextureParent* aTexture, - CompositableHost* aCompositableHost) + PTextureParent* aTexture) { ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId); if (!imageBridge) { @@ -515,8 +508,7 @@ ImageBridgeParent::AppendDeliverFenceMessage(base::ProcessId aChildProcessId, } imageBridge->AppendDeliverFenceMessage(aDestHolderId, aTransactionId, - aTexture, - aCompositableHost); + aTexture); } /*static*/ void diff --git a/gfx/layers/ipc/ImageBridgeParent.h b/gfx/layers/ipc/ImageBridgeParent.h index 1a551980e5..b95cb04365 100644 --- a/gfx/layers/ipc/ImageBridgeParent.h +++ b/gfx/layers/ipc/ImageBridgeParent.h @@ -59,8 +59,7 @@ public: Create(Transport* aTransport, ProcessId aChildProcessId); // CompositableParentManager - virtual void SendFenceHandleIfPresent(PTextureParent* aTexture, - CompositableHost* aCompositableHost) override; + virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) override; virtual void SendAsyncMessage(const InfallibleTArray& aMessage) override; @@ -121,14 +120,12 @@ public: void AppendDeliverFenceMessage(uint64_t aDestHolderId, uint64_t aTransactionId, - PTextureParent* aTexture, - CompositableHost* aCompositableHost); + PTextureParent* aTexture); static void AppendDeliverFenceMessage(base::ProcessId aChildProcessId, uint64_t aDestHolderId, uint64_t aTransactionId, - PTextureParent* aTexture, - CompositableHost* aCompositableHost); + PTextureParent* aTexture); using CompositableParentManager::SendPendingAsyncMessages; static void SendPendingAsyncMessages(base::ProcessId aChildProcessId); diff --git a/gfx/layers/ipc/LayerTransactionChild.h b/gfx/layers/ipc/LayerTransactionChild.h index 6d25d186bc..511f6e9ac1 100644 --- a/gfx/layers/ipc/LayerTransactionChild.h +++ b/gfx/layers/ipc/LayerTransactionChild.h @@ -19,11 +19,12 @@ namespace mozilla { namespace layout { class RenderFrameChild; -class ShadowLayerForwarder; } // namespace layout namespace layers { +class ShadowLayerForwarder; + class LayerTransactionChild : public PLayerTransactionChild , public AsyncTransactionTrackersHolder { diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index 886f60fed9..e79a8b06a9 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -798,6 +798,25 @@ GetAPZCForViewID(Layer* aLayer, FrameMetrics::ViewID aScrollID) return nullptr; } +bool +LayerTransactionParent::RecvUpdateScrollOffset( + const FrameMetrics::ViewID& aScrollID, + const uint32_t& aScrollGeneration, + const CSSPoint& aScrollOffset) +{ + if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { + return false; + } + + AsyncPanZoomController* controller = GetAPZCForViewID(mRoot, aScrollID); + if (!controller) { + return false; + } + controller->NotifyScrollUpdated(aScrollGeneration, aScrollOffset); + mShadowLayersManager->ForceComposite(this); + return true; +} + bool LayerTransactionParent::RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aScrollID, const float& aX, const float& aY) @@ -983,8 +1002,7 @@ LayerTransactionParent::RecvChildAsyncMessages(InfallibleTArray texture = TextureHost::AsTextureHost(aTexture); - if (!texture) { + if (!texture || !texture->NeedsFenceHandle()) { return; } // Send a ReleaseFence of CompositorOGL. - if (aCompositableHost && aCompositableHost->GetCompositor()) { - FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence(); - if (fence.IsValid()) { - mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr, - fence)); - } + FenceHandle fence = texture->GetCompositorReleaseFence(); + if (fence.IsValid()) { + mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr, + fence)); } - // Send a ReleaseFence that is set by HwcComposer2D. - FenceHandle fence = texture->GetAndResetReleaseFenceHandle(); + // Send a ReleaseFence that is set to TextureHost by HwcComposer2D. + fence = texture->GetAndResetReleaseFenceHandle(); if (fence.IsValid()) { mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr, fence)); diff --git a/gfx/layers/ipc/LayerTransactionParent.h b/gfx/layers/ipc/LayerTransactionParent.h index da48b2f243..215a7967f3 100644 --- a/gfx/layers/ipc/LayerTransactionParent.h +++ b/gfx/layers/ipc/LayerTransactionParent.h @@ -80,8 +80,7 @@ public: void SetPendingTransactionId(uint64_t aId) { mPendingTransaction = aId; } // CompositableParentManager - virtual void SendFenceHandleIfPresent(PTextureParent* aTexture, - CompositableHost* aCompositableHost) override; + virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) override; virtual void SendAsyncMessage(const InfallibleTArray& aMessage) override; @@ -131,6 +130,9 @@ protected: virtual bool RecvGetAnimationTransform(PLayerParent* aParent, MaybeTransform* aTransform) override; + virtual bool RecvUpdateScrollOffset(const FrameMetrics::ViewID& aScrollId, + const uint32_t& aScrollGeneration, + const CSSPoint& aScrollOffset) override; virtual bool RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aId, const float& aX, const float& aY) override; virtual bool RecvSetAsyncZoom(const FrameMetrics::ViewID& aId, diff --git a/gfx/layers/ipc/PLayerTransaction.ipdl b/gfx/layers/ipc/PLayerTransaction.ipdl index d99febd3a1..a0d51f73fa 100644 --- a/gfx/layers/ipc/PLayerTransaction.ipdl +++ b/gfx/layers/ipc/PLayerTransaction.ipdl @@ -22,6 +22,7 @@ using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h"; using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h"; using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h"; using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h"; +using mozilla::CSSPoint from "Units.h"; /** * The layers protocol is spoken between thread contexts that manage @@ -89,6 +90,10 @@ parent: // be void_t. sync GetAnimationTransform(PLayer layer) returns (MaybeTransform transform); + // Updates the scroll offset and generation counter on the APZC for the + // given scroll id. + sync UpdateScrollOffset(ViewID id, uint32_t generation, CSSPoint offset); + // The next time the layer tree is composited, add this async scroll offset in // CSS pixels for the given ViewID. // Useful for testing rendering of async scrolling. diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index f6673d684b..ba7c537326 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -259,6 +259,7 @@ UNIFIED_SOURCES += [ 'apz/src/AsyncPanZoomController.cpp', 'apz/src/Axis.cpp', 'apz/src/CheckerboardEvent.cpp', + 'apz/src/DragTracker.cpp', 'apz/src/GestureEventListener.cpp', 'apz/src/HitTestingTreeNode.cpp', 'apz/src/InputBlockState.cpp', diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index 9c38484452..812c9e17e6 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -629,6 +629,7 @@ void CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion, const Rect *aClipRectIn, const Rect& aRenderBounds, + bool aOpaque, Rect *aClipRectOut, Rect *aRenderBoundsOut) { @@ -878,8 +879,7 @@ CompositorOGL::GetShaderConfigFor(Effect *aEffect, } } config.SetColorMatrix(aColorMatrix); - config.SetMask2D(aMask == MaskType::Mask2d); - config.SetMask3D(aMask == MaskType::Mask3d); + config.SetMask(aMask == MaskType::Mask); config.SetDEAA(aDEAAEnabled); config.SetCompositionOp(aOp); return config; @@ -1069,9 +1069,7 @@ CompositorOGL::DrawQuad(const Rect& aRect, maskQuadTransform._41 = float(-bounds.x)/bounds.width; maskQuadTransform._42 = float(-bounds.y)/bounds.height; - maskType = effectMask->mIs3D - ? MaskType::Mask3d - : MaskType::Mask2d; + maskType = MaskType::Mask; } else { maskType = MaskType::MaskNone; } diff --git a/gfx/layers/opengl/CompositorOGL.h b/gfx/layers/opengl/CompositorOGL.h index 302f903af4..845c16ff6d 100644 --- a/gfx/layers/opengl/CompositorOGL.h +++ b/gfx/layers/opengl/CompositorOGL.h @@ -401,6 +401,7 @@ private: virtual void BeginFrame(const nsIntRegion& aInvalidRegion, const gfx::Rect *aClipRectIn, const gfx::Rect& aRenderBounds, + bool aOpaque, gfx::Rect *aClipRectOut = nullptr, gfx::Rect *aRenderBoundsOut = nullptr) override; diff --git a/gfx/layers/opengl/GrallocTextureHost.cpp b/gfx/layers/opengl/GrallocTextureHost.cpp index 62efd68365..70319208a1 100644 --- a/gfx/layers/opengl/GrallocTextureHost.cpp +++ b/gfx/layers/opengl/GrallocTextureHost.cpp @@ -466,5 +466,15 @@ GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureS return true; } +FenceHandle +GrallocTextureHostOGL::GetCompositorReleaseFence() +{ + if (!mCompositor) { + return FenceHandle(); + } + return mCompositor->GetReleaseFence(); +} + + } // namepsace layers } // namepsace mozilla diff --git a/gfx/layers/opengl/GrallocTextureHost.h b/gfx/layers/opengl/GrallocTextureHost.h index e3a7d08cf8..8cc5e9fbd7 100644 --- a/gfx/layers/opengl/GrallocTextureHost.h +++ b/gfx/layers/opengl/GrallocTextureHost.h @@ -60,6 +60,17 @@ public: gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; } + virtual bool NeedsFenceHandle() override + { +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 + return true; +#else + return false; +#endif + } + + virtual FenceHandle GetCompositorReleaseFence() override; + private: void DestroyEGLImage(); diff --git a/gfx/layers/opengl/OGLShaderProgram.cpp b/gfx/layers/opengl/OGLShaderProgram.cpp index 7b568d60de..f1009770d5 100644 --- a/gfx/layers/opengl/OGLShaderProgram.cpp +++ b/gfx/layers/opengl/OGLShaderProgram.cpp @@ -139,15 +139,9 @@ ShaderConfigOGL::SetBlur(bool aEnabled) } void -ShaderConfigOGL::SetMask2D(bool aEnabled) +ShaderConfigOGL::SetMask(bool aEnabled) { - SetFeature(ENABLE_MASK_2D, aEnabled); -} - -void -ShaderConfigOGL::SetMask3D(bool aEnabled) -{ - SetFeature(ENABLE_MASK_3D, aEnabled); + SetFeature(ENABLE_MASK, aEnabled); } void @@ -206,8 +200,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) vs << "varying vec2 vBackdropCoord;" << endl; } - if (aConfig.mFeatures & ENABLE_MASK_2D || - aConfig.mFeatures & ENABLE_MASK_3D) { + if (aConfig.mFeatures & ENABLE_MASK) { vs << "uniform mat4 uMaskTransform;" << endl; vs << "varying vec3 vMaskCoord;" << endl; } @@ -232,8 +225,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) vs << " ssPos = uMatrixProj * ssPos;" << endl; vs << " ssPos.xy = ((ssPos.xy/ssPos.w)*0.5+0.5)*uViewportSize;" << endl; - if (aConfig.mFeatures & ENABLE_MASK_2D || - aConfig.mFeatures & ENABLE_MASK_3D || + if (aConfig.mFeatures & ENABLE_MASK || !(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { vs << " vec4 coordAdjusted;" << endl; vs << " coordAdjusted.xy = aCoord.xy;" << endl; @@ -278,14 +270,11 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) vs << " vec2 texCoord = aCoord.xy * textureRect.zw + textureRect.xy;" << endl; vs << " vTexCoord = (uTextureTransform * vec4(texCoord, 0.0, 1.0)).xy;" << endl; } - if (aConfig.mFeatures & ENABLE_MASK_2D || - aConfig.mFeatures & ENABLE_MASK_3D) { + if (aConfig.mFeatures & ENABLE_MASK) { vs << " vMaskCoord.xy = (uMaskTransform * (finalPosition / finalPosition.w)).xy;" << endl; - if (aConfig.mFeatures & ENABLE_MASK_3D) { - // correct for perspective correct interpolation, see comment in D3D10 shader - vs << " vMaskCoord.z = 1.0;" << endl; - vs << " vMaskCoord *= finalPosition.w;" << endl; - } + // correct for perspective correct interpolation, see comment in D3D11 shader + vs << " vMaskCoord.z = 1.0;" << endl; + vs << " vMaskCoord *= finalPosition.w;" << endl; } vs << " finalPosition.xy -= uRenderTargetOffset * finalPosition.w;" << endl; vs << " finalPosition = uMatrixProj * finalPosition;" << endl; @@ -376,8 +365,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) fs << "uniform sampler2D uBackdropTexture;" << endl; } - if (aConfig.mFeatures & ENABLE_MASK_2D || - aConfig.mFeatures & ENABLE_MASK_3D) { + if (aConfig.mFeatures & ENABLE_MASK) { fs << "varying vec3 vMaskCoord;" << endl; fs << "uniform sampler2D uMaskTexture;" << endl; } @@ -512,13 +500,10 @@ For [0,1] instead of [0,255], and to 5 places: fs << " vec4 backdrop = texture2D(uBackdropTexture, vBackdropCoord);" << endl; fs << " color = mixAndBlend(backdrop, color);" << endl; } - if (aConfig.mFeatures & ENABLE_MASK_3D) { + if (aConfig.mFeatures & ENABLE_MASK) { fs << " vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;" << endl; fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, maskCoords).r;" << endl; fs << " color *= mask;" << endl; - } else if (aConfig.mFeatures & ENABLE_MASK_2D) { - fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, vMaskCoord.xy).r;" << endl; - fs << " color *= mask;" << endl; } else { fs << " COLOR_PRECISION float mask = 1.0;" << endl; fs << " color *= mask;" << endl; @@ -542,8 +527,7 @@ For [0,1] instead of [0,255], and to 5 places: result.mTextureCount = 1; } } - if (aConfig.mFeatures & ENABLE_MASK_2D || - aConfig.mFeatures & ENABLE_MASK_3D) { + if (aConfig.mFeatures & ENABLE_MASK) { result.mTextureCount = 1; } if (BlendOpIsMixBlendMode(blendOp)) { diff --git a/gfx/layers/opengl/OGLShaderProgram.h b/gfx/layers/opengl/OGLShaderProgram.h index d10749f50f..e2e28dfdb0 100644 --- a/gfx/layers/opengl/OGLShaderProgram.h +++ b/gfx/layers/opengl/OGLShaderProgram.h @@ -37,10 +37,9 @@ enum ShaderFeatures { ENABLE_OPACITY=0x100, ENABLE_BLUR=0x200, ENABLE_COLOR_MATRIX=0x400, - ENABLE_MASK_2D=0x800, - ENABLE_MASK_3D=0x1000, - ENABLE_NO_PREMUL_ALPHA=0x2000, - ENABLE_DEAA=0x4000 + ENABLE_MASK=0x800, + ENABLE_NO_PREMUL_ALPHA=0x1000, + ENABLE_DEAA=0x2000 }; class KnownUniform { @@ -223,8 +222,7 @@ public: void SetComponentAlpha(bool aEnabled); void SetColorMatrix(bool aEnabled); void SetBlur(bool aEnabled); - void SetMask2D(bool aEnabled); - void SetMask3D(bool aEnabled); + void SetMask(bool aEnabled); void SetDEAA(bool aEnabled); void SetCompositionOp(gfx::CompositionOp aOp); void SetNoPremultipliedAlpha(); diff --git a/image/Decoder.h b/image/Decoder.h index c0d9b166df..c962918ee1 100644 --- a/image/Decoder.h +++ b/image/Decoder.h @@ -285,6 +285,8 @@ public: protected: friend class nsICODecoder; + friend class PalettedSurfaceSink; + friend class SurfaceSink; virtual ~Decoder(); diff --git a/image/Deinterlacer.cpp b/image/Deinterlacer.cpp deleted file mode 100644 index 73ef29fd05..0000000000 --- a/image/Deinterlacer.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -#include "Downscaler.h" -#include "mozilla/UniquePtrExtensions.h" - -namespace mozilla { -namespace image { - -Deinterlacer::Deinterlacer(const nsIntSize& aImageSize) - : mImageSize(aImageSize) -{ - CheckedInt bufferSize = mImageSize.width; - bufferSize *= mImageSize.height; - bufferSize *= sizeof(uint32_t); - - if (!bufferSize.isValid()) { - return; - } - - mBuffer = MakeUniqueFallible(bufferSize.value()); -} - -uint32_t -Deinterlacer::RowSize() const -{ - return mImageSize.width * sizeof(uint32_t); -} - -uint8_t* -Deinterlacer::RowBuffer(uint32_t aRow) -{ - uint32_t offset = aRow * RowSize(); - MOZ_ASSERT(IsValid(), "Deinterlacer in invalid state"); - MOZ_ASSERT(offset < mImageSize.width * mImageSize.height * sizeof(uint32_t), - "Row is outside of image"); - return mBuffer.get() + offset; -} - -void -Deinterlacer::PropagatePassToDownscaler(Downscaler& aDownscaler) -{ - MOZ_ASSERT(IsValid(), "Deinterlacer in invalid state"); - for (int32_t row = 0 ; row < mImageSize.height ; ++row) { - memcpy(aDownscaler.RowBuffer(), RowBuffer(row), RowSize()); - aDownscaler.CommitRow(); - } -} - -} // namespace image -} // namespace mozilla diff --git a/image/Deinterlacer.h b/image/Deinterlacer.h deleted file mode 100644 index 93a720423d..0000000000 --- a/image/Deinterlacer.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - -/** - * Deinterlacer is a utility class to allow Downscaler to work with interlaced - * images. - - * Since Downscaler needs to receive rows in top-to-bottom or - * bottom-to-top order, it can't natively handle interlaced images, in which the - * rows arrive in an interleaved order. Deinterlacer solves this problem by - * acting as an intermediate buffer that records decoded rows. Unlike - * Downscaler, it allows the rows to be written in arbitrary order. After each - * pass, calling PropagatePassToDownscaler() will downscale every buffered row - * in a single operation. The rows remain in the buffer, so rows that were - * written in one pass will be included in subsequent passes. - */ - - -#ifndef mozilla_image_Deinterlacer_h -#define mozilla_image_Deinterlacer_h - -#include "Downscaler.h" - -namespace mozilla { -namespace image { - -class Deinterlacer -{ -public: - explicit Deinterlacer(const nsIntSize& aImageSize); - bool IsValid() { return !!mBuffer; } - - uint8_t* RowBuffer(uint32_t aRow); - void PropagatePassToDownscaler(Downscaler& aDownscaler); - -private: - uint32_t RowSize() const; - - nsIntSize mImageSize; - UniquePtr mBuffer; -}; - - -} // namespace image -} // namespace mozilla - -#endif // mozilla_image_Deinterlacer_h diff --git a/image/DownscalingFilter.h b/image/DownscalingFilter.h new file mode 100644 index 0000000000..564c577be3 --- /dev/null +++ b/image/DownscalingFilter.h @@ -0,0 +1,381 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +/** + * DownscalingSurfaceFilter is a SurfaceFilter implementation for use with + * SurfacePipe which performs Lanczos downscaling. + * + * It's in this header file, separated from the other SurfaceFilters, because + * some preprocessor magic is necessary to ensure that there aren't compilation + * issues on platforms where Skia is unavailable. + */ + +#ifndef mozilla_image_DownscalingFilter_h +#define mozilla_image_DownscalingFilter_h + +#include +#include +#include +#include + +#include "mozilla/Maybe.h" +#include "mozilla/SSE.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/gfx/2D.h" +#include "gfxPrefs.h" + +#ifdef MOZ_ENABLE_SKIA +#include "convolver.h" +#include "image_operations.h" +#include "skia/include/core/SkTypes.h" +#endif + +#include "SurfacePipe.h" + +namespace mozilla { +namespace image { + +////////////////////////////////////////////////////////////////////////////// +// DownscalingFilter +////////////////////////////////////////////////////////////////////////////// + +template class DownscalingFilter; + +/** + * A configuration struct for DownscalingConfig. + */ +struct DownscalingConfig +{ + template using Filter = DownscalingFilter; + gfx::IntSize mInputSize; /// The size of the input image. We'll downscale + /// from this size to the input size of the next + /// SurfaceFilter in the chain. + gfx::SurfaceFormat mFormat; /// The pixel format - BGRA or BGRX. (BGRX has + /// slightly better performance.) +}; + +#ifndef MOZ_ENABLE_SKIA + +/** + * DownscalingFilter requires Skia. This is a fallback implementation for + * non-Skia builds that fails when Configure() is called (which will prevent + * SurfacePipeFactory from returning an instance of it) and crashes if a caller + * manually constructs an instance and attempts to actually use it. Callers + * should avoid this by ensuring that they do not request downscaling in + * non-Skia builds. + */ +template +class DownscalingFilter final : public SurfaceFilter +{ +public: + uint8_t* AdvanceRow() override { MOZ_CRASH(); return nullptr; } + Maybe TakeInvalidRect() override { return Nothing(); } + + template + nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest) + { + return NS_ERROR_FAILURE; + } + +protected: + uint8_t* DoResetToFirstRow() override { MOZ_CRASH(); return nullptr; } +}; + +#else + +/** + * DownscalingFilter performs Lanczos downscaling, taking image input data at one size + * and outputting it rescaled to a different size. + * + * The 'Next' template parameter specifies the next filter in the chain. + */ +template +class DownscalingFilter final : public SurfaceFilter +{ +public: + DownscalingFilter() + : mXFilter(MakeUnique()) + , mYFilter(MakeUnique()) + , mWindowCapacity(0) + , mRowsInWindow(0) + , mInputRow(0) + , mOutputRow(0) + , mHasAlpha(true) + { + MOZ_ASSERT(gfxPrefs::ImageDownscaleDuringDecodeEnabled(), + "Downscaling even though downscale-during-decode is disabled?"); + } + + ~DownscalingFilter() + { + ReleaseWindow(); + } + + template + nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest) + { + nsresult rv = mNext.Configure(aRest...); + if (NS_FAILED(rv)) { + return rv; + } + + if (mNext.IsValidPalettedPipe()) { + NS_WARNING("Created a downscaler for a paletted surface?"); + return NS_ERROR_INVALID_ARG; + } + if (mNext.InputSize() == aConfig.mInputSize) { + NS_WARNING("Created a downscaler, but not downscaling?"); + return NS_ERROR_INVALID_ARG; + } + if (mNext.InputSize().width > aConfig.mInputSize.width) { + NS_WARNING("Created a downscaler, but width is larger"); + return NS_ERROR_INVALID_ARG; + } + if (mNext.InputSize().height > aConfig.mInputSize.height) { + NS_WARNING("Created a downscaler, but height is larger"); + return NS_ERROR_INVALID_ARG; + } + if (aConfig.mInputSize.width <= 0 || aConfig.mInputSize.height <= 0) { + NS_WARNING("Invalid input size for DownscalingFilter"); + return NS_ERROR_INVALID_ARG; + } + + mInputSize = aConfig.mInputSize; + gfx::IntSize outputSize = mNext.InputSize(); + mScale = gfxSize(double(mInputSize.width) / outputSize.width, + double(mInputSize.height) / outputSize.height); + mHasAlpha = aConfig.mFormat == gfx::SurfaceFormat::B8G8R8A8; + + ReleaseWindow(); + + auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3; + + skia::resize::ComputeFilters(resizeMethod, + mInputSize.width, outputSize.width, + 0, outputSize.width, + mXFilter.get()); + + skia::resize::ComputeFilters(resizeMethod, + mInputSize.height, outputSize.height, + 0, outputSize.height, + mYFilter.get()); + + // Allocate the buffer, which contains scanlines of the input image. + mRowBuffer.reset(new (fallible) + uint8_t[PaddedWidthInBytes(mInputSize.width)]); + if (MOZ_UNLIKELY(!mRowBuffer)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + // Clear the buffer to avoid writing uninitialized memory to the output. + memset(mRowBuffer.get(), 0, PaddedWidthInBytes(mInputSize.width)); + + // Allocate the window, which contains horizontally downscaled scanlines. (We + // can store scanlines which are already downscaled because our downscaling + // filter is separable.) + mWindowCapacity = mYFilter->max_filter(); + mWindow.reset(new (fallible) uint8_t*[mWindowCapacity]); + if (MOZ_UNLIKELY(!mWindow)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + // Allocate the "window" of recent rows that we keep in memory as input for + // the downscaling code. We intentionally iterate through the entire array + // even if an allocation fails, to ensure that all the pointers in it are + // either valid or nullptr. That in turn ensures that ReleaseWindow() can + // clean up correctly. + bool anyAllocationFailed = false; + const uint32_t windowRowSizeInBytes = PaddedWidthInBytes(outputSize.width); + for (int32_t i = 0; i < mWindowCapacity; ++i) { + mWindow[i] = new (fallible) uint8_t[windowRowSizeInBytes]; + anyAllocationFailed = anyAllocationFailed || mWindow[i] == nullptr; + } + + if (MOZ_UNLIKELY(anyAllocationFailed)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + ConfigureFilter(mInputSize, sizeof(uint32_t)); + return NS_OK; + } + + Maybe TakeInvalidRect() override + { + Maybe invalidRect = mNext.TakeInvalidRect(); + + if (invalidRect) { + // Compute the input space invalid rect by scaling. + invalidRect->mInputSpaceRect.ScaleRoundOut(mScale.width, mScale.height); + } + + return invalidRect; + } + + uint8_t* AdvanceRow() override + { + if (mInputRow >= mInputSize.height) { + NS_WARNING("Advancing DownscalingFilter past the end of the input"); + return nullptr; + } + + if (mOutputRow >= mNext.InputSize().height) { + NS_WARNING("Advancing DownscalingFilter past the end of the output"); + return nullptr; + } + + int32_t filterOffset = 0; + int32_t filterLength = 0; + GetFilterOffsetAndLength(mYFilter, mOutputRow, + &filterOffset, &filterLength); + + int32_t inputRowToRead = filterOffset + mRowsInWindow; + MOZ_ASSERT(mInputRow <= inputRowToRead, "Reading past end of input"); + if (mInputRow == inputRowToRead) { + skia::ConvolveHorizontally(mRowBuffer.get(), *mXFilter, + mWindow[mRowsInWindow++], mHasAlpha, + supports_sse2()); + } + + MOZ_ASSERT(mOutputRow < mNext.InputSize().height, + "Writing past end of output"); + + while (mRowsInWindow == filterLength) { + DownscaleInputRow(); + + if (mOutputRow == mNext.InputSize().height) { + break; // We're done. + } + + GetFilterOffsetAndLength(mYFilter, mOutputRow, + &filterOffset, &filterLength); + } + + mInputRow++; + + return mInputRow < mInputSize.height ? GetRowPointer() + : nullptr; + } + +protected: + uint8_t* DoResetToFirstRow() override + { + mNext.ResetToFirstRow(); + + mInputRow = 0; + mOutputRow = 0; + mRowsInWindow = 0; + + return GetRowPointer(); + } + +private: + uint8_t* GetRowPointer() const { return mRowBuffer.get(); } + + static uint32_t PaddedWidthInBytes(uint32_t aLogicalWidth) + { + // Convert from width in BGRA/BGRX pixels to width in bytes, padding by 15 + // to handle overreads by the SIMD code inside Skia. + return aLogicalWidth * sizeof(uint32_t) + 15; + } + + static void + GetFilterOffsetAndLength(UniquePtr& aFilter, + int32_t aOutputImagePosition, + int32_t* aFilterOffsetOut, + int32_t* aFilterLengthOut) + { + MOZ_ASSERT(aOutputImagePosition < aFilter->num_values()); + aFilter->FilterForValue(aOutputImagePosition, + aFilterOffsetOut, + aFilterLengthOut); + } + + void DownscaleInputRow() + { + typedef skia::ConvolutionFilter1D::Fixed FilterValue; + + MOZ_ASSERT(mOutputRow < mNext.InputSize().height, + "Writing past end of output"); + + int32_t filterOffset = 0; + int32_t filterLength = 0; + MOZ_ASSERT(mOutputRow < mYFilter->num_values()); + auto filterValues = + mYFilter->FilterForValue(mOutputRow, &filterOffset, &filterLength); + + mNext.template WriteRows([&](uint32_t* aRow, uint32_t aLength) + -> Maybe { + skia::ConvolveVertically(static_cast(filterValues), + filterLength, mWindow.get(), mXFilter->num_values(), + reinterpret_cast(aRow), mHasAlpha, + supports_sse2()); + return Some(WriteState::NEED_MORE_DATA); + }); + + mOutputRow++; + + if (mOutputRow == mNext.InputSize().height) { + return; // We're done. + } + + int32_t newFilterOffset = 0; + int32_t newFilterLength = 0; + GetFilterOffsetAndLength(mYFilter, mOutputRow, + &newFilterOffset, &newFilterLength); + + int diff = newFilterOffset - filterOffset; + MOZ_ASSERT(diff >= 0, "Moving backwards in the filter?"); + + // Shift the buffer. We're just moving pointers here, so this is cheap. + mRowsInWindow -= diff; + mRowsInWindow = std::max(mRowsInWindow, 0); + for (int32_t i = 0; i < mRowsInWindow; ++i) { + std::swap(mWindow[i], mWindow[filterLength - mRowsInWindow + i]); + } + } + + void ReleaseWindow() + { + if (!mWindow) { + return; + } + + for (int32_t i = 0; i < mWindowCapacity; ++i) { + delete[] mWindow[i]; + } + + mWindow = nullptr; + mWindowCapacity = 0; + } + + Next mNext; /// The next SurfaceFilter in the chain. + + gfx::IntSize mInputSize; /// The size of the input image. + gfxSize mScale; /// The scale factors in each dimension. + /// Computed from @mInputSize and + /// the next filter's input size. + + UniquePtr mRowBuffer; /// The buffer into which input is written. + UniquePtr mWindow; /// The last few rows which were written. + + UniquePtr mXFilter; /// The Lanczos filter in X. + UniquePtr mYFilter; /// The Lanczos filter in Y. + + int32_t mWindowCapacity; /// How many rows the window contains. + + int32_t mRowsInWindow; /// How many rows we've buffered in the window. + int32_t mInputRow; /// The current row we're reading. (0-indexed) + int32_t mOutputRow; /// The current row we're writing. (0-indexed) + + bool mHasAlpha; /// If true, the image has transparency. +}; + +#endif + +} // namespace image +} // namespace mozilla + +#endif // mozilla_image_DownscalingFilter_h diff --git a/image/SurfaceFilters.h b/image/SurfaceFilters.h new file mode 100644 index 0000000000..05ee42fce2 --- /dev/null +++ b/image/SurfaceFilters.h @@ -0,0 +1,560 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +/** + * This header contains various SurfaceFilter implementations that apply + * transformations to image data, for usage with SurfacePipe. + */ + +#ifndef mozilla_image_SurfaceFilters_h +#define mozilla_image_SurfaceFilters_h + +#include +#include + +#include "mozilla/Likely.h" +#include "mozilla/Maybe.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/gfx/2D.h" + +#include "DownscalingFilter.h" +#include "SurfacePipe.h" + +namespace mozilla { +namespace image { + +////////////////////////////////////////////////////////////////////////////// +// DeinterlacingFilter +////////////////////////////////////////////////////////////////////////////// + +template class DeinterlacingFilter; + +/** + * A configuration struct for DeinterlacingFilter. + * + * The 'PixelType' template parameter should be either uint32_t (for output to a + * SurfaceSink) or uint8_t (for output to a PalettedSurfaceSink). + */ +template +struct DeinterlacingConfig +{ + template using Filter = DeinterlacingFilter; + bool mProgressiveDisplay; /// If true, duplicate rows during deinterlacing + /// to make progressive display look better, at + /// the cost of some performance. +}; + +/** + * DeinterlacingFilter performs deinterlacing by reordering the rows that are + * written to it. + * + * The 'PixelType' template parameter should be either uint32_t (for output to a + * SurfaceSink) or uint8_t (for output to a PalettedSurfaceSink). + * + * The 'Next' template parameter specifies the next filter in the chain. + */ +template +class DeinterlacingFilter final : public SurfaceFilter +{ +public: + DeinterlacingFilter() + : mInputRow(0) + , mOutputRow(0) + , mPass(0) + , mProgressiveDisplay(true) + { } + + template + nsresult Configure(const DeinterlacingConfig& aConfig, Rest... aRest) + { + nsresult rv = mNext.Configure(aRest...); + if (NS_FAILED(rv)) { + return rv; + } + + if (sizeof(PixelType) == 1 && !mNext.IsValidPalettedPipe()) { + NS_WARNING("Paletted DeinterlacingFilter used with non-paletted pipe?"); + return NS_ERROR_INVALID_ARG; + } + if (sizeof(PixelType) == 4 && mNext.IsValidPalettedPipe()) { + NS_WARNING("Non-paletted DeinterlacingFilter used with paletted pipe?"); + return NS_ERROR_INVALID_ARG; + } + + gfx::IntSize outputSize = mNext.InputSize(); + mProgressiveDisplay = aConfig.mProgressiveDisplay; + + const uint32_t bufferSize = outputSize.width * + outputSize.height * + sizeof(PixelType); + + // Allocate the buffer, which contains deinterlaced scanlines of the image. + // The buffer is necessary so that we can output rows which have already + // been deinterlaced again on subsequent passes. Since a later stage in the + // pipeline may be transforming the rows it receives (for example, by + // downscaling them), the rows may no longer exist in their original form on + // the surface itself. + mBuffer.reset(new (fallible) uint8_t[bufferSize]); + if (MOZ_UNLIKELY(!mBuffer)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + // Clear the buffer to avoid writing uninitialized memory to the output. + memset(mBuffer.get(), 0, bufferSize); + + ConfigureFilter(outputSize, sizeof(PixelType)); + return NS_OK; + } + + bool IsValidPalettedPipe() const override + { + return sizeof(PixelType) == 1 && mNext.IsValidPalettedPipe(); + } + + Maybe TakeInvalidRect() override + { + return mNext.TakeInvalidRect(); + } + + uint8_t* AdvanceRow() override + { + if (mPass >= 4) { + return nullptr; // We already finished all passes. + } + if (mInputRow >= InputSize().height) { + return nullptr; // We already got all the input rows we expect. + } + + // Duplicate from the first Haeberli row to the remaining Haeberli rows + // within the buffer. + DuplicateRows(HaeberliOutputStartRow(mPass, mProgressiveDisplay, mOutputRow), + HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), mOutputRow)); + + // Write the current set of Haeberli rows (which contains the current row) + // to the next stage in the pipeline. + OutputRows(HaeberliOutputStartRow(mPass, mProgressiveDisplay, mOutputRow), + HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), mOutputRow)); + + // Determine which output row the next input row corresponds to. + bool advancedPass = false; + uint32_t stride = InterlaceStride(mPass); + int32_t nextOutputRow = mOutputRow + stride; + while (nextOutputRow >= InputSize().height) { + // Copy any remaining rows from the buffer. + if (!advancedPass) { + DuplicateRows(HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), mOutputRow), + InputSize().height); + OutputRows(HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), mOutputRow), + InputSize().height); + } + + // We finished the current pass; advance to the next one. + mPass++; + if (mPass >= 4) { + return nullptr; // Finished all passes. + } + + // Tell the next pipeline stage that we're starting the next pass. + mNext.ResetToFirstRow(); + + // Update our state to reflect the pass change. + advancedPass = true; + stride = InterlaceStride(mPass); + nextOutputRow = InterlaceOffset(mPass); + } + + MOZ_ASSERT(nextOutputRow >= 0); + MOZ_ASSERT(nextOutputRow < InputSize().height); + + MOZ_ASSERT(HaeberliOutputStartRow(mPass, mProgressiveDisplay, + nextOutputRow) >= 0); + MOZ_ASSERT(HaeberliOutputStartRow(mPass, mProgressiveDisplay, + nextOutputRow) < InputSize().height); + MOZ_ASSERT(HaeberliOutputStartRow(mPass, mProgressiveDisplay, + nextOutputRow) <= nextOutputRow); + + MOZ_ASSERT(HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), nextOutputRow) >= 0); + MOZ_ASSERT(HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), nextOutputRow) + <= InputSize().height); + MOZ_ASSERT(HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), nextOutputRow) + > nextOutputRow); + + int32_t nextHaeberliOutputRow = + HaeberliOutputStartRow(mPass, mProgressiveDisplay, nextOutputRow); + + // Copy rows from the buffer until we reach the desired output row. + if (advancedPass) { + OutputRows(0, nextHaeberliOutputRow); + } else { + OutputRows(HaeberliOutputUntilRow(mPass, mProgressiveDisplay, + InputSize(), mOutputRow), + nextHaeberliOutputRow); + } + + // Update our position within the buffer. + mInputRow++; + mOutputRow = nextOutputRow; + + // We'll actually write to the first Haeberli output row, then copy it until + // we reach the last Haeberli output row. The assertions above make sure + // this always includes mOutputRow. + return GetRowPointer(nextHaeberliOutputRow); + } + +protected: + uint8_t* DoResetToFirstRow() override + { + mNext.ResetToFirstRow(); + mPass = 0; + mInputRow = 0; + mOutputRow = InterlaceOffset(mPass);; + return GetRowPointer(mOutputRow); + } + +private: + static uint32_t InterlaceOffset(uint32_t aPass) + { + MOZ_ASSERT(aPass < 4, "Invalid pass"); + static const uint8_t offset[] = { 0, 4, 2, 1 }; + return offset[aPass]; + } + + static uint32_t InterlaceStride(uint32_t aPass) + { + MOZ_ASSERT(aPass < 4, "Invalid pass"); + static const uint8_t stride[] = { 8, 8, 4, 2 }; + return stride[aPass]; + } + + static int32_t HaeberliOutputStartRow(uint32_t aPass, + bool aProgressiveDisplay, + int32_t aOutputRow) + { + MOZ_ASSERT(aPass < 4, "Invalid pass"); + static const uint8_t firstRowOffset[] = { 3, 1, 0, 0 }; + + if (aProgressiveDisplay) { + return std::max(aOutputRow - firstRowOffset[aPass], 0); + } else { + return aOutputRow; + } + } + + static int32_t HaeberliOutputUntilRow(uint32_t aPass, + bool aProgressiveDisplay, + const gfx::IntSize& aInputSize, + int32_t aOutputRow) + { + MOZ_ASSERT(aPass < 4, "Invalid pass"); + static const uint8_t lastRowOffset[] = { 4, 2, 1, 0 }; + + if (aProgressiveDisplay) { + return std::min(aOutputRow + lastRowOffset[aPass], + aInputSize.height - 1) + + 1; // Add one because this is an open interval on the right. + } else { + return aOutputRow + 1; + } + } + + void DuplicateRows(int32_t aStart, int32_t aUntil) + { + MOZ_ASSERT(aStart >= 0); + MOZ_ASSERT(aUntil >= 0); + + if (aUntil <= aStart || aStart >= InputSize().height) { + return; + } + + // The source row is the first row in the range. + const uint8_t* sourceRowPointer = GetRowPointer(aStart); + + // We duplicate the source row into each subsequent row in the range. + for (int32_t destRow = aStart + 1 ; destRow < aUntil ; ++destRow) { + uint8_t* destRowPointer = GetRowPointer(destRow); + memcpy(destRowPointer, sourceRowPointer, InputSize().width * sizeof(PixelType)); + } + } + + void OutputRows(int32_t aStart, int32_t aUntil) + { + MOZ_ASSERT(aStart >= 0); + MOZ_ASSERT(aUntil >= 0); + + if (aUntil <= aStart || aStart >= InputSize().height) { + return; + } + + int32_t rowToOutput = aStart; + mNext.template WriteRows([&](PixelType* aRow, uint32_t aLength) { + const uint8_t* rowToOutputPointer = GetRowPointer(rowToOutput); + memcpy(aRow, rowToOutputPointer, aLength * sizeof(PixelType)); + + rowToOutput++; + return rowToOutput >= aUntil ? Some(WriteState::NEED_MORE_DATA) + : Nothing(); + }); + } + + uint8_t* GetRowPointer(uint32_t aRow) const + { + uint32_t offset = aRow * InputSize().width * sizeof(PixelType); + MOZ_ASSERT(offset < InputSize().width * InputSize().height * sizeof(PixelType), + "Start of row is outside of image"); + MOZ_ASSERT(offset + InputSize().width * sizeof(PixelType) + <= InputSize().width * InputSize().height * sizeof(PixelType), + "End of row is outside of image"); + return mBuffer.get() + offset; + } + + Next mNext; /// The next SurfaceFilter in the chain. + + UniquePtr mBuffer; /// The buffer used to store reordered rows. + int32_t mInputRow; /// The current row we're reading. (0-indexed) + int32_t mOutputRow; /// The current row we're writing. (0-indexed) + uint8_t mPass; /// Which pass we're on. (0-indexed) + bool mProgressiveDisplay; /// If true, duplicate rows to optimize for + /// progressive display. +}; + + +////////////////////////////////////////////////////////////////////////////// +// RemoveFrameRectFilter +////////////////////////////////////////////////////////////////////////////// + +template class RemoveFrameRectFilter; + +/** + * A configuration struct for RemoveFrameRectFilter. + */ +struct RemoveFrameRectConfig +{ + template using Filter = RemoveFrameRectFilter; + gfx::IntRect mFrameRect; /// The surface subrect which contains data. +}; + +/** + * RemoveFrameRectFilter turns an image with a frame rect that does not match + * its logical size into an image with no frame rect. It does this by writing + * transparent pixels into any padding regions and throwing away excess data. + * + * The 'Next' template parameter specifies the next filter in the chain. + */ +template +class RemoveFrameRectFilter final : public SurfaceFilter +{ +public: + RemoveFrameRectFilter() + : mRow(0) + { } + + template + nsresult Configure(const RemoveFrameRectConfig& aConfig, Rest... aRest) + { + nsresult rv = mNext.Configure(aRest...); + if (NS_FAILED(rv)) { + return rv; + } + + if (mNext.IsValidPalettedPipe()) { + NS_WARNING("RemoveFrameRectFilter used with paletted pipe?"); + return NS_ERROR_INVALID_ARG; + } + + mFrameRect = mUnclampedFrameRect = aConfig.mFrameRect; + gfx::IntSize outputSize = mNext.InputSize(); + + // Forbid frame rects with negative size. + if (aConfig.mFrameRect.width < 0 || aConfig.mFrameRect.height < 0) { + return NS_ERROR_INVALID_ARG; + } + + // Clamp mFrameRect to the output size. + gfx::IntRect outputRect(0, 0, outputSize.width, outputSize.height); + mFrameRect = mFrameRect.Intersect(outputRect); + + // If there's no intersection, |mFrameRect| will be an empty rect positioned + // at the maximum of |inputRect|'s and |aFrameRect|'s coordinates, which is + // not what we want. Force it to (0, 0) in that case. + if (mFrameRect.IsEmpty()) { + mFrameRect.MoveTo(0, 0); + } + + // We don't need an intermediate buffer unless the unclamped frame rect + // width is larger than the clamped frame rect width. In that case, the + // caller will end up writing data that won't end up in the final image at + // all, and we'll need a buffer to give that data a place to go. + if (mFrameRect.width < mUnclampedFrameRect.width) { + mBuffer.reset(new (fallible) uint8_t[mUnclampedFrameRect.width * + sizeof(uint32_t)]); + if (MOZ_UNLIKELY(!mBuffer)) { + return NS_ERROR_OUT_OF_MEMORY; + } + + memset(mBuffer.get(), 0, mUnclampedFrameRect.width * sizeof(uint32_t)); + } + + ConfigureFilter(mUnclampedFrameRect.Size(), sizeof(uint32_t)); + return NS_OK; + } + + Maybe TakeInvalidRect() override + { + return mNext.TakeInvalidRect(); + } + + uint8_t* AdvanceRow() override + { + uint8_t* rowPtr = nullptr; + + const int32_t currentRow = mRow; + mRow++; + + if (currentRow < mFrameRect.y) { + // This row is outside of the frame rect, so just drop it on the floor. + rowPtr = mBuffer ? mBuffer.get() : mNext.CurrentRowPointer(); + return AdjustRowPointer(rowPtr); + } else if (currentRow >= mFrameRect.YMost()) { + NS_WARNING("RemoveFrameRectFilter: Advancing past end of frame rect"); + return nullptr; + } + + // If we had to buffer, copy the data. Otherwise, just advance the row. + if (mBuffer) { + mNext.template WriteRows([&](uint32_t* aRow, uint32_t aLength) { + // Clear the part of the row before the clamped frame rect. + MOZ_ASSERT(mFrameRect.x >= 0); + MOZ_ASSERT(uint32_t(mFrameRect.x) < aLength); + memset(aRow, 0, mFrameRect.x * sizeof(uint32_t)); + + // Write the part of the row that's inside the clamped frame rect. + MOZ_ASSERT(mFrameRect.width >= 0); + aRow += mFrameRect.x; + aLength -= std::min(aLength, uint32_t(mFrameRect.x)); + uint32_t toWrite = std::min(aLength, uint32_t(mFrameRect.width)); + uint8_t* source = mBuffer.get() - + std::min(mUnclampedFrameRect.x, 0) * sizeof(uint32_t); + MOZ_ASSERT(source >= mBuffer.get()); + MOZ_ASSERT(source + toWrite * sizeof(uint32_t) + <= mBuffer.get() + mUnclampedFrameRect.width * sizeof(uint32_t)); + memcpy(aRow, source, toWrite * sizeof(uint32_t)); + + // Clear the part of the row after the clamped frame rect. + aRow += toWrite; + aLength -= std::min(aLength, toWrite); + memset(aRow, 0, aLength * sizeof(uint32_t)); + + return Some(WriteState::NEED_MORE_DATA); + }); + + rowPtr = mBuffer.get(); + } else { + rowPtr = mNext.AdvanceRow(); + } + + // If there's still more data coming, just adjust the pointer and return. + if (mRow < mFrameRect.YMost() || rowPtr == nullptr) { + return AdjustRowPointer(rowPtr); + } + + // We've finished the region specified by the frame rect. Advance to the end + // of the next pipeline stage's buffer, outputting blank rows. + mNext.template WriteRows([&](uint32_t* aRow, uint32_t aLength) { + memset(rowPtr, 0, aLength * sizeof(uint32_t)); + return Nothing(); + }); + + return nullptr; // We're done. + } + +protected: + uint8_t* DoResetToFirstRow() override + { + uint8_t* rowPtr = mNext.ResetToFirstRow(); + if (rowPtr == nullptr) { + mRow = InputSize().height; + return nullptr; + } + + mRow = mUnclampedFrameRect.y; + + // Advance the next pipeline stage to the beginning of the frame rect, + // outputting blank rows. + if (mFrameRect.y > 0) { + int32_t rowsToWrite = mFrameRect.y; + mNext.template WriteRows([&](uint32_t* aRow, uint32_t aLength) + -> Maybe { + memset(aRow, 0, aLength * sizeof(uint32_t)); + rowsToWrite--; + return rowsToWrite > 0 ? Nothing() + : Some(WriteState::NEED_MORE_DATA); + }); + } + + // We're at the beginning of the frame rect now, so return if we're either + // ready for input or we're already done. + rowPtr = mBuffer ? mBuffer.get() : mNext.CurrentRowPointer(); + if (!mFrameRect.IsEmpty() || rowPtr == nullptr) { + // Note that the pointer we're returning is for the next row we're + // actually going to write to, but we may discard writes before that point + // if mRow < mFrameRect.y. + return AdjustRowPointer(rowPtr); + } + + // We've finished the region specified by the frame rect, but the frame rect + // is empty, so we need to output the rest of the image immediately. Advance + // to the end of the next pipeline stage's buffer, outputting blank rows. + int32_t rowsWritten = 0; + mNext.template WriteRows([&](uint32_t* aRow, uint32_t aLength) { + rowsWritten++; + memset(aRow, 0, aLength * sizeof(uint32_t)); + return Nothing(); + }); + + mRow = InputSize().height; + return nullptr; // We're done. + } + +private: + uint8_t* AdjustRowPointer(uint8_t* aNextRowPointer) const + { + if (mBuffer) { + MOZ_ASSERT(aNextRowPointer == mBuffer.get()); + return aNextRowPointer; // No adjustment needed for an intermediate buffer. + } + + if (mFrameRect.IsEmpty() || + mRow >= mFrameRect.YMost() || + aNextRowPointer == nullptr) { + return nullptr; // Nothing left to write. + } + + return aNextRowPointer + mFrameRect.x * sizeof(uint32_t); + } + + Next mNext; /// The next SurfaceFilter in the chain. + + gfx::IntRect mFrameRect; /// The surface subrect which contains data, + /// clamped to the image size. + gfx::IntRect mUnclampedFrameRect; /// The frame rect before clamping. + UniquePtr mBuffer; /// The intermediate buffer, if one is + /// necessary because the frame rect width + /// is larger than the image's logical width. + int32_t mRow; /// The row in unclamped frame rect space + /// that we're currently writing. +}; + +} // namespace image +} // namespace mozilla + +#endif // mozilla_image_SurfaceFilters_h diff --git a/image/SurfacePipe.cpp b/image/SurfacePipe.cpp new file mode 100644 index 0000000000..72f54ab877 --- /dev/null +++ b/image/SurfacePipe.cpp @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "SurfacePipe.h" + +#include + +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/DebugOnly.h" +#include "Decoder.h" + +namespace mozilla { +namespace image { + +using namespace gfx; + +using std::min; + +/* static */ UniquePtr NullSurfaceSink::sSingleton; + +/* static */ NullSurfaceSink* +NullSurfaceSink::Singleton() +{ + if (!sSingleton) { + MOZ_ASSERT(NS_IsMainThread()); + sSingleton = MakeUnique(); + ClearOnShutdown(&sSingleton); + + DebugOnly rv = sSingleton->Configure(NullSurfaceConfig { }); + MOZ_ASSERT(NS_SUCCEEDED(rv), "Couldn't configure a NullSurfaceSink?"); + } + + return sSingleton.get(); +} + +nsresult +NullSurfaceSink::Configure(const NullSurfaceConfig& aConfig) +{ + // Note that the choice of uint32_t as the pixel size here is more or less + // arbitrary, since you cannot write to a NullSurfaceSink anyway, but uint32_t + // is a natural choice since most SurfacePipes will be for BGRA/BGRX surfaces. + ConfigureFilter(IntSize(), sizeof(uint32_t)); + return NS_OK; +} + +Maybe +AbstractSurfaceSink::TakeInvalidRect() +{ + if (mInvalidRect.IsEmpty()) { + return Nothing(); + } + + SurfaceInvalidRect invalidRect; + invalidRect.mInputSpaceRect = invalidRect.mOutputSpaceRect = mInvalidRect; + + // Forget about the invalid rect we're returning. + mInvalidRect = IntRect(); + + return Some(invalidRect); +} + +uint8_t* +AbstractSurfaceSink::DoResetToFirstRow() +{ + mRow = 0; + return GetRowPointer(); +} + +uint8_t* +AbstractSurfaceSink::AdvanceRow() +{ + if (mRow >= uint32_t(InputSize().height)) { + return nullptr; + } + + // If we're vertically flipping the output, we need to flip the invalid rect. Since we're + // dealing with an axis-aligned rect, only the y coordinate needs to change. + int32_t invalidY = mFlipVertically + ? InputSize().height - (mRow + 1) + : mRow; + mInvalidRect.UnionRect(mInvalidRect, + IntRect(0, invalidY, InputSize().width, 1)); + + mRow = min(uint32_t(InputSize().height), mRow + 1); + + return mRow < uint32_t(InputSize().height) ? GetRowPointer() + : nullptr; +} + +nsresult +SurfaceSink::Configure(const SurfaceConfig& aConfig) +{ + // For non-paletted surfaces, the surface size is just the output size. + IntSize surfaceSize = aConfig.mOutputSize; + + // Non-paletted surfaces should not have frame rects, so we just pass + // AllocateFrame() a frame rect which covers the entire surface. + IntRect frameRect(0, 0, surfaceSize.width, surfaceSize.height); + + // Allocate the frame. + // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want + // to allocate the frame directly here and get rid of Decoder::AllocateFrame + // altogether. + nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum, + surfaceSize, + frameRect, + aConfig.mFormat); + if (NS_FAILED(rv)) { + return rv; + } + + mImageData = aConfig.mDecoder->mImageData; + mImageDataLength = aConfig.mDecoder->mImageDataLength; + mFlipVertically = aConfig.mFlipVertically; + + MOZ_ASSERT(mImageData); + MOZ_ASSERT(mImageDataLength == + uint32_t(surfaceSize.width * surfaceSize.height * sizeof(uint32_t))); + + ConfigureFilter(surfaceSize, sizeof(uint32_t)); + return NS_OK; +} + +uint8_t* +SurfaceSink::GetRowPointer() const +{ + // If we're flipping vertically, reverse the order in which we traverse the + // rows. + uint32_t row = mFlipVertically + ? InputSize().height - (mRow + 1) + : mRow; + + uint8_t* rowPtr = mImageData + row * InputSize().width * sizeof(uint32_t); + + MOZ_ASSERT(rowPtr >= mImageData); + MOZ_ASSERT(rowPtr < mImageData + mImageDataLength); + MOZ_ASSERT(rowPtr + InputSize().width * sizeof(uint32_t) <= + mImageData + mImageDataLength); + + return rowPtr; +} + + +nsresult +PalettedSurfaceSink::Configure(const PalettedSurfaceConfig& aConfig) +{ + // For paletted surfaces, the surface size is the size of the frame rect. + IntSize surfaceSize = aConfig.mFrameRect.Size(); + + // Allocate the frame. + // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want + // to allocate the frame directly here and get rid of Decoder::AllocateFrame + // altogether. + nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum, + aConfig.mOutputSize, + aConfig.mFrameRect, + aConfig.mFormat, + aConfig.mPaletteDepth); + if (NS_FAILED(rv)) { + return rv; + } + + mImageData = aConfig.mDecoder->mImageData; + mImageDataLength = aConfig.mDecoder->mImageDataLength; + mFlipVertically = aConfig.mFlipVertically; + mFrameRect = aConfig.mFrameRect; + + MOZ_ASSERT(mImageData); + MOZ_ASSERT(mImageDataLength == + uint32_t(mFrameRect.width * mFrameRect.height * sizeof(uint8_t))); + + ConfigureFilter(surfaceSize, sizeof(uint8_t)); + return NS_OK; +} + +uint8_t* +PalettedSurfaceSink::GetRowPointer() const +{ + // If we're flipping vertically, reverse the order in which we traverse the + // rows. + uint32_t row = mFlipVertically + ? InputSize().height - (mRow + 1) + : mRow; + + uint8_t* rowPtr = mImageData + row * InputSize().width * sizeof(uint8_t); + + MOZ_ASSERT(rowPtr >= mImageData); + MOZ_ASSERT(rowPtr < mImageData + mImageDataLength); + MOZ_ASSERT(rowPtr + InputSize().width * sizeof(uint8_t) <= + mImageData + mImageDataLength); + + return rowPtr; +} + +} // namespace image +} // namespace mozilla diff --git a/image/SurfacePipe.h b/image/SurfacePipe.h new file mode 100644 index 0000000000..e96f13f251 --- /dev/null +++ b/image/SurfacePipe.h @@ -0,0 +1,570 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +/** + * A SurfacePipe is a pipeline that consists of a series of SurfaceFilters + * terminating in a SurfaceSink. Each SurfaceFilter transforms the image data in + * some way before the SurfaceSink ultimately writes it to the surface. This + * design allows for each transformation to be tested independently, for the + * transformations to be combined as needed to meet the needs of different + * situations, and for all image decoders to share the same code for these + * transformations. + * + * Writing to the SurfacePipe is done using lambdas that act as generator + * functions. Because the SurfacePipe machinery controls where the writes take + * place, a bug in an image decoder cannot cause a buffer overflow of the + * underlying surface. In particular, when using WritePixels() a buffer overflow + * is impossible as long as the SurfacePipe code is correct. + */ + +#ifndef mozilla_image_SurfacePipe_h +#define mozilla_image_SurfacePipe_h + +#include + +#include "mozilla/Maybe.h" +#include "mozilla/Move.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/unused.h" +#include "mozilla/Variant.h" +#include "mozilla/gfx/2D.h" + +namespace mozilla { +namespace image { + +class Decoder; + +/** + * An invalid rect for a surface. Results are given both in the space of the + * input image (i.e., before any SurfaceFilters are applied) and in the space + * of the output surface (after all SurfaceFilters). + */ +struct SurfaceInvalidRect +{ + gfx::IntRect mInputSpaceRect; /// The invalid rect in pre-SurfacePipe space. + gfx::IntRect mOutputSpaceRect; /// The invalid rect in post-SurfacePipe space. +}; + +/** + * An enum used to allow the lambdas passed to WritePixels() and WriteRows() to + * communicate their state to the caller. + */ +enum class WriteState : uint8_t +{ + NEED_MORE_DATA, /// The lambda ran out of data. + + FINISHED, /// The lambda is done writing to the surface; future writes + /// will fail. + + FAILURE /// The lambda encountered an error. The caller may recover + /// if possible and continue to write. (This never indicates + /// an error in the SurfacePipe machinery itself; it's only + /// generated by the lambdas.) +}; + +/** + * A template alias used to make the return value of WritePixels() lambdas + * (which may return either a pixel value or a WriteState) easier to specify. + * WriteRows() doesn't need such a template alias since WriteRows() lambdas + * don't return a pixel value. + */ +template +using NextPixel = Variant; + +/** + * SurfaceFilter is the abstract superclass of SurfacePipe pipeline stages. + * It implements the the code that actually writes to the surface - + * WritePixels() and WriteRows() - which are non-virtual for efficiency. + * + * SurfaceFilter's API is nonpublic; only SurfacePipe and other SurfaceFilters + * should use it. Non-SurfacePipe code should use the methods on SurfacePipe. + * + * To implement a SurfaceFilter, it's necessary to subclass SurfaceFilter and + * implement, at a minimum, the pure virtual methods. It's also necessary to + * define a Config struct with a Filter typedef member that identifies the + * matching SurfaceFilter class, and a Configure() template method. See an + * existing SurfaceFilter subclass, such as RemoveFrameRectFilter, for an + * example of how the Configure() method must be implemented. It takes a list of + * Config structs, passes the tail of the list to the next filter in the chain's + * Configure() method, and then uses the head of the list to configure itself. A + * SurfaceFilter's Configure() method must also call + * SurfaceFilter::ConfigureFilter() to provide WritePixels() and WriteRows() + * with the information they need to do their jobs. + */ +class SurfaceFilter +{ +public: + SurfaceFilter() + : mRowPointer(nullptr) + , mCol(0) + , mPixelSize(0) + { } + + virtual ~SurfaceFilter() { } + + /** + * Reset this surface to the first row. It's legal for this filter to throw + * away any previously written data at this point, as all rows must be written + * to on every pass. + * + * @return a pointer to the buffer for the first row. + */ + uint8_t* ResetToFirstRow() + { + mCol = 0; + mRowPointer = DoResetToFirstRow(); + return mRowPointer; + } + + /// @return a pointer to the buffer for the current row. + uint8_t* CurrentRowPointer() const { return mRowPointer; } + + /// @return true if we've finished writing to the surface. + bool IsSurfaceFinished() const { return mRowPointer == nullptr; } + + /// @return the input size this filter expects. + gfx::IntSize InputSize() const { return mInputSize; } + + /** + * Write pixels to the surface one at a time by repeatedly calling a lambda + * that yields pixels. WritePixels() should be preferred over WriteRows() + * whenever using it will not introduce additional copies or other performance + * penalties, because it is completely memory safe. + * + * Writing continues until every pixel in the surface has been written to + * (i.e., IsSurfaceFinished() returns true) or the lambda returns a WriteState + * which WritePixels() will return to the caller. + * + * The template parameter PixelType must be uint8_t (for paletted surfaces) or + * uint32_t (for BGRA/BGRX surfaces) and must be in agreement with the pixel + * size passed to ConfigureFilter(). + * + * XXX(seth): We'll remove all support for paletted surfaces in bug 1247520, + * which means we can remove the PixelType template parameter from this + * method. + * + * @param aFunc A lambda that functions as a generator, yielding the next + * pixel in the surface each time it's called. The lambda must + * return a NextPixel value. + * + * @return A WriteState value indicating the lambda generator's state. + * WritePixels() itself will return WriteState::FINISHED if writing + * has finished, regardless of the lambda's internal state. + */ + template + WriteState WritePixels(Func aFunc) + { + MOZ_ASSERT(mPixelSize == 1 || mPixelSize == 4); + MOZ_ASSERT_IF(mPixelSize == 1, sizeof(PixelType) == sizeof(uint8_t)); + MOZ_ASSERT_IF(mPixelSize == 4, sizeof(PixelType) == sizeof(uint32_t)); + + while (!IsSurfaceFinished()) { + PixelType* rowPtr = reinterpret_cast(mRowPointer); + + for (; mCol < mInputSize.width; ++mCol) { + NextPixel result = aFunc(); + if (result.template is()) { + rowPtr[mCol] = result.template as(); + continue; + } + + switch (result.template as()) { + case WriteState::NEED_MORE_DATA: + return WriteState::NEED_MORE_DATA; + + case WriteState::FINISHED: + // Make sure that IsSurfaceFinished() returns true so the caller + // can't write anything else to the pipeline. + mRowPointer = nullptr; + mCol = 0; + return WriteState::FINISHED; + + case WriteState::FAILURE: + // Note that we don't need to record this anywhere, because this + // indicates an error in aFunc, and there's nothing wrong with our + // machinery. The caller can recover as needed and continue writing to + // the row. + return WriteState::FAILURE; + } + } + + // We've finished the row. + mRowPointer = AdvanceRow(); + mCol = 0; + } + + // We've finished the entire surface. + return WriteState::FINISHED; + } + + /** + * Write rows to the surface one at a time by repeatedly calling a lambda + * that yields rows. Because WriteRows() is not completely memory safe, + * WritePixels() should be preferred whenever it can be used without + * introducing additional copies or other performance penalties. + * + * Writing continues until every row in the surface has been written to (i.e., + * IsSurfaceFinished() returns true) or the lambda returns a WriteState which + * WriteRows() will return to the caller. + * + * The template parameter PixelType must be uint8_t (for paletted surfaces) or + * uint32_t (for BGRA/BGRX surfaces) and must be in agreement with the pixel + * size passed to ConfigureFilter(). + * + * XXX(seth): We'll remove all support for paletted surfaces in bug 1247520, + * which means we can remove the PixelType template parameter from this + * method. + * + * @param aFunc A lambda that functions as a generator, yielding the next + * row in the surface each time it's called. The lambda must + * return a Maybe value; if Some(), the return value + * indicates a WriteState to return to the caller, while + * Nothing() indicates that the lambda can generate more rows. + * + * @return A WriteState value indicating the lambda generator's state. + * WriteRows() itself will return WriteState::FINISHED if writing + * has finished, regardless of the lambda's internal state. + */ + template + WriteState WriteRows(Func aFunc) + { + MOZ_ASSERT(mPixelSize == 1 || mPixelSize == 4); + MOZ_ASSERT_IF(mPixelSize == 1, sizeof(PixelType) == sizeof(uint8_t)); + MOZ_ASSERT_IF(mPixelSize == 4, sizeof(PixelType) == sizeof(uint32_t)); + + if (IsSurfaceFinished()) { + return WriteState::FINISHED; // Already done. + } + + while (true) { + PixelType* rowPtr = reinterpret_cast(mRowPointer); + + Maybe result = aFunc(rowPtr, mInputSize.width); + if (result != Some(WriteState::FAILURE)) { + mCol = 0; + mRowPointer = AdvanceRow(); // We've finished the row. + } + + if (IsSurfaceFinished()) { + break; + } + + if (result == Some(WriteState::FINISHED)) { + // Make sure that IsSurfaceFinished() returns true so the caller can't + // write anything else to the pipeline. + mRowPointer = nullptr; + mCol = 0; + } + + if (result) { + return *result; + } + } + + // We've finished the entire surface. + return WriteState::FINISHED; + } + + ////////////////////////////////////////////////////////////////////////////// + // Methods Subclasses Should Override + ////////////////////////////////////////////////////////////////////////////// + + /// @return true if this SurfaceFilter can be used with paletted surfaces. + virtual bool IsValidPalettedPipe() const { return false; } + + /** + * Called by WritePixels() and WriteRows() to advance this filter to the next + * row. + * + * @return a pointer to the buffer for the next row, or nullptr to indicate + * that we've finished the entire surface. + */ + virtual uint8_t* AdvanceRow() = 0; + + /** + * @return a SurfaceInvalidRect representing the region of the surface that + * has been written to since the last time TakeInvalidRect() was + * called, or Nothing() if the region is empty (i.e. nothing has been + * written). + */ + virtual Maybe TakeInvalidRect() = 0; + +protected: + + /** + * Called by ResetToFirstRow() to actually perform the reset. It's legal to + * throw away any previously written data at this point, as all rows must be + * written to on every pass. + */ + virtual uint8_t* DoResetToFirstRow() = 0; + + + ////////////////////////////////////////////////////////////////////////////// + // Methods For Internal Use By Subclasses + ////////////////////////////////////////////////////////////////////////////// + + /** + * Called by subclasses' Configure() methods to initialize the configuration + * of this filter. After the filter is configured, calls ResetToFirstRow(). + * + * @param aInputSize The input size of this filter, in pixels. The previous + * filter in the chain will expect to write into rows + * |aInputSize.width| pixels wide. + * @param aPixelSize How large, in bytes, each pixel in the surface is. This + * should be either 1 for paletted images or 4 for BGRA/BGRX + * images. + */ + void ConfigureFilter(gfx::IntSize aInputSize, uint8_t aPixelSize) + { + mInputSize = aInputSize; + mPixelSize = aPixelSize; + + ResetToFirstRow(); + } + +private: + gfx::IntSize mInputSize; /// The size of the input this filter expects. + uint8_t* mRowPointer; /// Pointer to the current row or null if finished. + int32_t mCol; /// The current column we're writing to. (0-indexed) + uint8_t mPixelSize; /// How large each pixel in the surface is, in bytes. +}; + +class NullSurfaceSink; + +/// A trivial configuration struct for NullSurfaceSink. +struct NullSurfaceConfig +{ + using Filter = NullSurfaceSink; +}; + +/** + * NullSurfaceSink is a trivial SurfaceFilter implementation that behaves as if + * it were a zero-size SurfaceSink. It's used as the default filter chain for an + * uninitialized SurfacePipe. + * + * To avoid unnecessary allocations when creating SurfacePipe objects, + * NullSurfaceSink is a singleton. (This implies that the implementation must be + * stateless.) + */ +class NullSurfaceSink final : public SurfaceFilter +{ +public: + /// Returns the singleton instance of NullSurfaceSink. + static NullSurfaceSink* Singleton(); + + virtual ~NullSurfaceSink() { } + + nsresult Configure(const NullSurfaceConfig& aConfig); + + Maybe TakeInvalidRect() override { return Nothing(); } + uint8_t* AdvanceRow() override { return nullptr; } + +protected: + uint8_t* DoResetToFirstRow() override { return nullptr; } + +private: + static UniquePtr sSingleton; /// The singleton instance. +}; + + +/** + * SurfacePipe is the public API that decoders should use to interact with a + * SurfaceFilter pipeline. + */ +class SurfacePipe +{ +public: + /// Initialize global state used by all SurfacePipes. + static void Initialize() { NullSurfaceSink::Singleton(); } + + SurfacePipe() + : mHead(NullSurfaceSink::Singleton()) + { } + + SurfacePipe(SurfacePipe&& aOther) + : mHead(Move(aOther.mHead)) + { } + + ~SurfacePipe() + { + // Ensure that we don't free the NullSurfaceSink singleton. + if (mHead.get() == NullSurfaceSink::Singleton()) { + Unused << mHead.release(); + } + } + + SurfacePipe& operator=(SurfacePipe&& aOther) + { + MOZ_ASSERT(this != &aOther); + + // Ensure that we don't free the NullSurfaceSink singleton. + if (mHead.get() == NullSurfaceSink::Singleton()) { + Unused << mHead.release(); + } + + mHead = Move(aOther.mHead); + return *this; + } + + /// Begins a new pass, seeking to the first row of the surface. + void ResetToFirstRow() { mHead->ResetToFirstRow(); } + + /** + * Write pixels to the surface one at a time by repeatedly calling a lambda + * that yields pixels. WritePixels() should be preferred over WriteRows() + * whenever using it will not introduce additional copies or other performance + * penalties, because it is completely memory safe. + * + * @see SurfaceFilter::WritePixels() for the canonical documentation. + */ + template + WriteState WritePixels(Func aFunc) + { + return mHead->WritePixels(Forward(aFunc)); + } + + /** + * Write rows to the surface one at a time by repeatedly calling a lambda + * that yields rows. Because WriteRows() is not completely memory safe, + * WritePixels() should be preferred whenever it can be used without + * introducing additional copies or other performance penalties. + * + * @see SurfaceFilter::WriteRows() for the canonical documentation. + */ + template + WriteState WriteRows(Func aFunc) + { + return mHead->WriteRows(Forward(aFunc)); + } + + /// @return true if we've finished writing to the surface. + bool IsSurfaceFinished() const { return mHead->IsSurfaceFinished(); } + + /// @see SurfaceFilter::TakeInvalidRect() for the canonical documentation. + Maybe TakeInvalidRect() const + { + return mHead->TakeInvalidRect(); + } + +private: + friend class SurfacePipeFactory; + friend class TestSurfacePipeFactory; + + explicit SurfacePipe(UniquePtr&& aHead) + : mHead(Move(aHead)) + { } + + SurfacePipe(const SurfacePipe&) = delete; + SurfacePipe& operator=(const SurfacePipe&) = delete; + + UniquePtr mHead; /// The first filter in the chain. +}; + +/** + * AbstractSurfaceSink contains shared implementation for both SurfaceSink and + * PalettedSurfaceSink. + */ +class AbstractSurfaceSink : public SurfaceFilter +{ +public: + AbstractSurfaceSink() + : mImageData(nullptr) + , mImageDataLength(0) + , mRow(0) + , mFlipVertically(false) + { } + + Maybe TakeInvalidRect() override final; + uint8_t* AdvanceRow() override final; + +protected: + uint8_t* DoResetToFirstRow() override final; + virtual uint8_t* GetRowPointer() const = 0; + + gfx::IntRect mInvalidRect; /// The region of the surface that has been written + /// to since the last call to TakeInvalidRect(). + uint8_t* mImageData; /// A pointer to the beginning of the surface data. + uint32_t mImageDataLength; /// The length of the surface data. + uint32_t mRow; /// The row to which we're writing. (0-indexed) + bool mFlipVertically; /// If true, write the rows from top to bottom. +}; + +class SurfaceSink; + +/// A configuration struct for SurfaceSink. +struct SurfaceConfig +{ + using Filter = SurfaceSink; + Decoder* mDecoder; /// Which Decoder to use to allocate the surface. + uint32_t mFrameNum; /// Which frame of animation this surface is for. + gfx::IntSize mOutputSize; /// The size of the surface. + gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX). + bool mFlipVertically; /// If true, write the rows from bottom to top. +}; + +/** + * A sink for normal (i.e., non-paletted) surfaces. It handles the allocation of + * the surface and protects against buffer overflow. This sink should be used + * for all non-animated images and for the first frame of animated images. + * + * Sinks must always be at the end of the SurfaceFilter chain. + */ +class SurfaceSink final : public AbstractSurfaceSink +{ +public: + nsresult Configure(const SurfaceConfig& aConfig); + +protected: + uint8_t* GetRowPointer() const override; +}; + +class PalettedSurfaceSink; + +struct PalettedSurfaceConfig +{ + using Filter = PalettedSurfaceSink; + Decoder* mDecoder; /// Which Decoder to use to allocate the surface. + uint32_t mFrameNum; /// Which frame of animation this surface is for. + gfx::IntSize mOutputSize; /// The logical size of the surface. + gfx::IntRect mFrameRect; /// The surface subrect which contains data. + gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX). + uint8_t mPaletteDepth; /// The palette depth of this surface. + bool mFlipVertically; /// If true, write the rows from bottom to top. +}; + +/** + * A sink for paletted surfaces. It handles the allocation of the surface and + * protects against buffer overflow. This sink can be used for frames of + * animated images except the first. + * + * Sinks must always be at the end of the SurfaceFilter chain. + * + * XXX(seth): We'll remove all support for paletted surfaces in bug 1247520, + * which means we can remove PalettedSurfaceSink entirely. + */ +class PalettedSurfaceSink final : public AbstractSurfaceSink +{ +public: + bool IsValidPalettedPipe() const override { return true; } + + nsresult Configure(const PalettedSurfaceConfig& aConfig); + +protected: + uint8_t* GetRowPointer() const override; + +private: + /** + * The surface subrect which contains data. Note that the surface size we + * actually allocate is the size of the frame rect, not the logical size of + * the surface. + */ + gfx::IntRect mFrameRect; +}; + +} // namespace image +} // namespace mozilla + +#endif // mozilla_image_SurfacePipe_h diff --git a/image/SurfacePipeFactory.h b/image/SurfacePipeFactory.h new file mode 100644 index 0000000000..0aac62133b --- /dev/null +++ b/image/SurfacePipeFactory.h @@ -0,0 +1,227 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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_image_SurfacePipeFactory_h +#define mozilla_image_SurfacePipeFactory_h + +#include "SurfacePipe.h" +#include "SurfaceFilters.h" + +namespace mozilla { +namespace image { + +namespace detail { + +/** + * FilterPipeline is a helper template for SurfacePipeFactory that determines + * the full type of the sequence of SurfaceFilters that a sequence of + * configuration structs corresponds to. To make this work, all configuration + * structs must include a typedef 'Filter' that identifies the SurfaceFilter + * they configure. + */ +template +struct FilterPipeline; + +template +struct FilterPipeline +{ + typedef typename Config::template Filter::Type> Type; +}; + +template +struct FilterPipeline +{ + typedef typename Config::Filter Type; +}; + +} // namespace detail + +/** + * Flags for SurfacePipeFactory, used in conjuction with the factory functions + * in SurfacePipeFactory to enable or disable various SurfacePipe + * functionality. + */ +enum class SurfacePipeFlags +{ + DEINTERLACE = 1 << 0, // If set, deinterlace the image. + + FLIP_VERTICALLY = 1 << 1, // If set, flip the image vertically. + + PROGRESSIVE_DISPLAY = 1 << 2 // If set, we expect the image to be displayed + // progressively. This enables features that + // result in a better user experience for + // progressive display but which may be more + // computationally expensive. +}; +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SurfacePipeFlags) + +class SurfacePipeFactory +{ +public: + /** + * Creates and initializes a normal (i.e., non-paletted) SurfacePipe. + * + * @param aDecoder The decoder whose current frame the SurfacePipe will write + * to. + * @param aFrameNum Which frame the SurfacePipe will write to. This will be 0 + * for non-animated images. + * @param aInputSize The original size of the image. + * @param aOutputSize The size the SurfacePipe should output. Must be the same + * as @aInputSize or smaller. If smaller, the image will be + * downscaled during decoding. + * @param aFrameRect The portion of the image that actually contains data. + * @param aFormat The surface format of the image; generally B8G8R8A8 or + * B8G8R8X8. + * @param aFlags Flags enabling or disabling various functionality for the + * SurfacePipe; see the SurfacePipeFlags documentation for more + * information. + * + * @return A SurfacePipe if the parameters allowed one to be created + * successfully, or Nothing() if the SurfacePipe could not be + * initialized. + */ + static Maybe + CreateSurfacePipe(Decoder* aDecoder, + uint32_t aFrameNum, + const nsIntSize& aInputSize, + const nsIntSize& aOutputSize, + const nsIntRect& aFrameRect, + gfx::SurfaceFormat aFormat, + SurfacePipeFlags aFlags) + { + const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); + const bool flipVertically = bool(aFlags & SurfacePipeFlags::FLIP_VERTICALLY); + const bool progressiveDisplay = bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY); + const bool downscale = aInputSize != aOutputSize; + const bool removeFrameRect = + !aFrameRect.IsEqualEdges(nsIntRect(0, 0, aInputSize.width, aInputSize.height)); + + // Construct configurations for the SurfaceFilters. Note that the order of + // these filters is significant. We want to deinterlace raw input rows, + // before any other transformations, and we want to remove the frame rect + // (which may involve adding blank rows or columns to the image) before any + // downscaling, so that the new rows and columns are taken into account. + DeinterlacingConfig deinterlacingConfig { progressiveDisplay }; + RemoveFrameRectConfig removeFrameRectConfig { aFrameRect }; + DownscalingConfig downscalingConfig { aInputSize, aFormat }; + SurfaceConfig surfaceConfig { aDecoder, aFrameNum, aOutputSize, + aFormat, flipVertically }; + + Maybe pipe; + + if (downscale) { + if (removeFrameRect) { + if (deinterlace) { + pipe = MakePipe(aFrameRect.Size(), deinterlacingConfig, + removeFrameRectConfig, downscalingConfig, + surfaceConfig); + } else { // (deinterlace is false) + pipe = MakePipe(aFrameRect.Size(), removeFrameRectConfig, + downscalingConfig, surfaceConfig); + } + } else { // (removeFrameRect is false) + if (deinterlace) { + pipe = MakePipe(aInputSize, deinterlacingConfig, + downscalingConfig, surfaceConfig); + } else { // (deinterlace is false) + pipe = MakePipe(aInputSize, downscalingConfig, surfaceConfig); + } + } + } else { // (downscale is false) + if (removeFrameRect) { + if (deinterlace) { + pipe = MakePipe(aFrameRect.Size(), deinterlacingConfig, + removeFrameRectConfig, surfaceConfig); + } else { // (deinterlace is false) + pipe = MakePipe(aFrameRect.Size(), removeFrameRectConfig, surfaceConfig); + } + } else { // (removeFrameRect is false) + if (deinterlace) { + pipe = MakePipe(aInputSize, deinterlacingConfig, surfaceConfig); + } else { // (deinterlace is false) + pipe = MakePipe(aInputSize, surfaceConfig); + } + } + } + + return pipe; + } + + /** + * Creates and initializes a paletted SurfacePipe. + * + * XXX(seth): We'll remove all support for paletted surfaces in bug 1247520, + * which means we can remove CreatePalettedSurfacePipe() entirely. + * + * @param aDecoder The decoder whose current frame the SurfacePipe will write + * to. + * @param aFrameNum Which frame the SurfacePipe will write to. This will be 0 + * for non-animated images. + * @param aInputSize The original size of the image. + * @param aFrameRect The portion of the image that actually contains data. + * @param aFormat The surface format of the image; generally B8G8R8A8 or + * B8G8R8X8. + * @param aPaletteDepth The palette depth of the image. + * @param aFlags Flags enabling or disabling various functionality for the + * SurfacePipe; see the SurfacePipeFlags documentation for more + * information. + * + * @return A SurfacePipe if the parameters allowed one to be created + * successfully, or Nothing() if the SurfacePipe could not be + * initialized. + */ + static Maybe + CreatePalettedSurfacePipe(Decoder* aDecoder, + uint32_t aFrameNum, + const nsIntSize& aInputSize, + const nsIntRect& aFrameRect, + gfx::SurfaceFormat aFormat, + uint8_t aPaletteDepth, + SurfacePipeFlags aFlags) + { + const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); + const bool flipVertically = bool(aFlags & SurfacePipeFlags::FLIP_VERTICALLY); + const bool progressiveDisplay = bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY); + + // Construct configurations for the SurfaceFilters. + DeinterlacingConfig deinterlacingConfig { progressiveDisplay }; + PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aFrameNum, aInputSize, + aFrameRect, aFormat, aPaletteDepth, + flipVertically }; + + Maybe pipe; + + if (deinterlace) { + pipe = MakePipe(aFrameRect.Size(), deinterlacingConfig, + palettedSurfaceConfig); + } else { + pipe = MakePipe(aFrameRect.Size(), palettedSurfaceConfig); + } + + return pipe; + } + +private: + template + static Maybe + MakePipe(const nsIntSize& aInputSize, Configs... aConfigs) + { + auto pipe = MakeUnique::Type>(); + nsresult rv = pipe->Configure(aConfigs...); + if (NS_FAILED(rv)) { + return Nothing(); + } + + return Some(SurfacePipe { Move(pipe) } ); + } + + virtual ~SurfacePipeFactory() = 0; +}; + +} // namespace image +} // namespace mozilla + +#endif // mozilla_image_SurfacePipeFactory_h diff --git a/image/build/nsImageModule.cpp b/image/build/nsImageModule.cpp index 3ca22ef2a7..92f8a8913d 100644 --- a/image/build/nsImageModule.cpp +++ b/image/build/nsImageModule.cpp @@ -13,6 +13,7 @@ #include "ImageFactory.h" #include "ShutdownTracker.h" #include "SurfaceCache.h" +#include "SurfacePipe.h" #include "gfxPrefs.h" #include "imgLoader.h" @@ -99,6 +100,7 @@ mozilla::image::InitModule() mozilla::image::ImageFactory::Initialize(); mozilla::image::DecodePool::Initialize(); mozilla::image::SurfaceCache::Initialize(); + mozilla::image::SurfacePipe::Initialize(); imgLoader::GlobalInit(); sInitialized = true; return NS_OK; diff --git a/image/decoders/GIF2.h b/image/decoders/GIF2.h index c8052c40fd..1094347566 100644 --- a/image/decoders/GIF2.h +++ b/image/decoders/GIF2.h @@ -29,7 +29,6 @@ typedef enum { gif_global_colormap, gif_image_start, gif_image_header, - gif_image_header_continue, gif_image_colormap, gif_lzw_start, gif_lzw, @@ -67,16 +66,9 @@ typedef struct gif_struct { int32_t datum; // 32-bit input buffer // Output state machine - int ipass; // Interlace pass; Ranges 1-4 if interlaced. - unsigned rows_remaining; // Rows remaining to be output - unsigned irow; // Current output row, starting at zero - uint8_t* rowp; // Current output pointer + int64_t pixels_remaining; // Pixels remaining to be output. // Parameters for image frame currently being decoded - unsigned x_offset, y_offset; // With respect to "screen" origin - unsigned height, width; - unsigned clamped_height; // Size of the frame rectangle clamped to the - unsigned clamped_width; // global logical size after x_ and y_offset. int tpixel; // Index of transparent pixel int32_t disposal_method; // Restore to background, leave in place, etc. uint32_t* local_colormap; // Per-image colormap @@ -86,16 +78,14 @@ typedef struct gif_struct { // Global (multi-image) state int version; // Either 89 for GIF89 or 87 for GIF87 - unsigned screen_width; // Logical screen width & height - unsigned screen_height; + int32_t screen_width; // Logical screen width & height + int32_t screen_height; uint32_t global_colormap_depth; // Depth of global colormap array int images_decoded; // Counts images for multi-part GIFs int loop_count; // Netscape specific extension block to control // the number of animation loops a GIF // renders. - bool progressive_display; // If TRUE, do Haeberli interlace hack - bool interlaced; // TRUE, if scanlines arrive interlaced order bool is_transparent; // TRUE, if tpixel is valid uint16_t prefix[MAX_BITS]; // LZW decoding tables diff --git a/image/decoders/moz.build b/image/decoders/moz.build index 92e1301176..67d27db605 100644 --- a/image/decoders/moz.build +++ b/image/decoders/moz.build @@ -36,9 +36,15 @@ UNIFIED_SOURCES += [ if CONFIG['MOZ_JXR']: SOURCES += ['nsJXRDecoder.cpp'] -# Decoders need RasterImage.h +include('/ipc/chromium/chromium-config.mozbuild') + LOCAL_INCLUDES += [ + # Access to Skia headers for Downscaler. + '/gfx/2d', + # Decoders need ImageLib headers. '/image', ] +LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES'] + FINAL_LIBRARY = 'xul' diff --git a/image/decoders/nsBMPDecoder.cpp b/image/decoders/nsBMPDecoder.cpp index 51c675a6be..72227b3cb5 100644 --- a/image/decoders/nsBMPDecoder.cpp +++ b/image/decoders/nsBMPDecoder.cpp @@ -262,7 +262,7 @@ nsBMPDecoder::FinishInternal() MOZ_ASSERT(mMayHaveTransparency); PostFrameStop(Opacity::SOME_TRANSPARENCY); } else { - PostFrameStop(Opacity::OPAQUE); + PostFrameStop(Opacity::FULLY_OPAQUE); } PostDecodeDone(); } diff --git a/image/decoders/nsGIFDecoder2.cpp b/image/decoders/nsGIFDecoder2.cpp index 6f404485bd..4d1f4558dd 100644 --- a/image/decoders/nsGIFDecoder2.cpp +++ b/image/decoders/nsGIFDecoder2.cpp @@ -40,9 +40,12 @@ mailing address. #include +#include "imgFrame.h" #include "nsGIFDecoder2.h" #include "nsIInputStream.h" #include "RasterImage.h" +#include "SurfaceFilters.h" +#include "SurfacePipeFactory.h" #include "gfxColor.h" #include "gfxPlatform.h" @@ -73,12 +76,8 @@ namespace image { nsGIFDecoder2::nsGIFDecoder2(RasterImage* aImage) : Decoder(aImage) - , mCurrentRow(-1) - , mLastFlushedRow(-1) , mOldColor(0) , mCurrentFrameIndex(-1) - , mCurrentPass(0) - , mLastFlushedPass(0) , mGIFOpen(false) , mSawTransparency(false) { @@ -99,40 +98,6 @@ nsGIFDecoder2::~nsGIFDecoder2() moz_free(mGIFStruct.hold); } -uint8_t* -nsGIFDecoder2::GetCurrentRowBuffer() -{ - if (!mDownscaler) { - MOZ_ASSERT(!mDeinterlacer, "Deinterlacer without downscaler?"); - uint32_t bpp = mGIFStruct.images_decoded == 0 ? sizeof(uint32_t) - : sizeof(uint8_t); - return mImageData + mGIFStruct.irow * mGIFStruct.width * bpp; - } - - if (!mDeinterlacer) { - return mDownscaler->RowBuffer(); - } - - return mDeinterlacer->RowBuffer(mGIFStruct.irow); -} - -uint8_t* -nsGIFDecoder2::GetRowBuffer(uint32_t aRow) -{ - MOZ_ASSERT(mGIFStruct.images_decoded == 0, - "Calling GetRowBuffer on a frame other than the first suggests " - "we're deinterlacing animated frames"); - MOZ_ASSERT(!mDownscaler || mDeinterlacer, - "Can't get buffer for a specific row if downscaling " - "but not deinterlacing"); - - if (mDownscaler) { - return mDeinterlacer->RowBuffer(aRow); - } - - return mImageData + aRow * mGIFStruct.width * sizeof(uint32_t); -} - void nsGIFDecoder2::FinishInternal() { @@ -148,45 +113,16 @@ nsGIFDecoder2::FinishInternal() } } -// Push any new rows according to mCurrentPass/mLastFlushedPass and -// mCurrentRow/mLastFlushedRow. Note: caller is responsible for -// updating mlastFlushed{Row,Pass}. -void -nsGIFDecoder2::FlushImageData(uint32_t fromRow, uint32_t rows) -{ - nsIntRect r(mGIFStruct.x_offset, mGIFStruct.y_offset + fromRow, - mGIFStruct.width, rows); - PostInvalidation(r); -} - void nsGIFDecoder2::FlushImageData() { - if (mDownscaler) { - if (mDownscaler->HasInvalidation()) { - DownscalerInvalidRect invalidRect = mDownscaler->TakeInvalidRect(); - PostInvalidation(invalidRect.mOriginalSizeRect, - Some(invalidRect.mTargetSizeRect)); - } + Maybe invalidRect = mPipe.TakeInvalidRect(); + if (!invalidRect) { return; } - switch (mCurrentPass - mLastFlushedPass) { - case 0: // same pass - if (mCurrentRow - mLastFlushedRow) { - FlushImageData(mLastFlushedRow + 1, mCurrentRow - mLastFlushedRow); - } - break; - - case 1: // one pass on - need to handle bottom & top rects - FlushImageData(0, mCurrentRow + 1); - FlushImageData(mLastFlushedRow + 1, - mGIFStruct.clamped_height - (mLastFlushedRow + 1)); - break; - - default: // more than one pass on - push the whole frame - FlushImageData(0, mGIFStruct.clamped_height); - } + PostInvalidation(invalidRect->mInputSpaceRect, + Some(invalidRect->mOutputSpaceRect)); } //****************************************************************************** @@ -249,53 +185,59 @@ nsGIFDecoder2::ClampToImageRect(const IntRect& aRect) //****************************************************************************** nsresult -nsGIFDecoder2::BeginImageFrame(uint16_t aDepth) +nsGIFDecoder2::BeginImageFrame(const IntRect& aFrameRect, + uint16_t aDepth, + bool aIsInterlaced) { MOZ_ASSERT(HasSize()); - IntRect frameRect(mGIFStruct.x_offset, mGIFStruct.y_offset, - mGIFStruct.width, mGIFStruct.height); - - bool hasTransparency = CheckForTransparency(frameRect); + bool hasTransparency = CheckForTransparency(aFrameRect); gfx::SurfaceFormat format = hasTransparency ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8; // Make sure there's no animation if we're downscaling. MOZ_ASSERT_IF(mDownscaler, !GetImageMetadata().HasAnimation()); - // Compute the target size and target frame rect. If we're downscaling, - // Downscaler will automatically strip out first-frame padding, so the target - // frame rect takes up the entire frame regardless. - IntSize targetSize = mDownscaler ? mDownscaler->TargetSize() - : GetSize(); - IntRect targetFrameRect = mDownscaler ? IntRect(IntPoint(), targetSize) - : frameRect; + SurfacePipeFlags pipeFlags = aIsInterlaced + ? SurfacePipeFlags::DEINTERLACE + : SurfacePipeFlags(); - // Use correct format, RGB for first frame, PAL for following frames - // and include transparency to allow for optimization of opaque images - nsresult rv = NS_OK; - if (mGIFStruct.images_decoded) { - // Image data is stored with original depth and palette. - rv = AllocateFrame(mGIFStruct.images_decoded, targetSize, - targetFrameRect, format, aDepth); + Maybe pipe; + if (mGIFStruct.images_decoded == 0) { + // This is the first frame. We may be downscaling, so compute the target + // size and target frame rect. + IntSize targetSize = mDownscaler ? mDownscaler->TargetSize() + : GetSize(); + IntRect targetFrameRect = mDownscaler ? IntRect(IntPoint(), targetSize) + : aFrameRect; + + // The first frame may be displayed progressively. + pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY; + + // The first frame is always decoded into an RGB surface. + pipe = + SurfacePipeFactory::CreateSurfacePipe(this, mGIFStruct.images_decoded, + GetSize(), targetSize, + targetFrameRect, format, pipeFlags); } else { - // Regardless of depth of input, the first frame is decoded into 24bit RGB. - rv = AllocateFrame(mGIFStruct.images_decoded, targetSize, - targetFrameRect, format); + // This is an animation frame (and not the first). To minimize the memory + // usage of animations, the image data is stored in paletted form. + MOZ_ASSERT(!mDownscaler); + pipe = + SurfacePipeFactory::CreatePalettedSurfacePipe(this, mGIFStruct.images_decoded, + GetSize(), aFrameRect, format, + aDepth, pipeFlags); } mCurrentFrameIndex = mGIFStruct.images_decoded; - if (NS_FAILED(rv)) { - return rv; + if (!pipe) { + mPipe = SurfacePipe(); + return NS_ERROR_FAILURE; } - if (mDownscaler) { - rv = mDownscaler->BeginFrame(GetSize(), Some(ClampToImageRect(frameRect)), - mImageData, hasTransparency); - } - - return rv; + mPipe = Move(*pipe); + return NS_OK; } @@ -306,45 +248,16 @@ nsGIFDecoder2::EndImageFrame() Opacity opacity = Opacity::SOME_TRANSPARENCY; // First flush all pending image data - if (!mGIFStruct.images_decoded) { + if (mGIFStruct.images_decoded == 0) { // Only need to flush first frame FlushImageData(); - // If the first frame is smaller in height than the entire image, send an - // invalidation for the area it does not have data for. - // This will clear the remaining bits of the placeholder. (Bug 37589) - const uint32_t realFrameHeight = mGIFStruct.height + mGIFStruct.y_offset; - if (realFrameHeight < mGIFStruct.screen_height) { - if (mDownscaler) { - IntRect targetRect = IntRect(IntPoint(), mDownscaler->TargetSize()); - PostInvalidation(IntRect(IntPoint(), GetSize()), Some(targetRect)); - } else { - nsIntRect r(0, realFrameHeight, - mGIFStruct.screen_width, - mGIFStruct.screen_height - realFrameHeight); - PostInvalidation(r); - } - } - // The first frame was preallocated with alpha; if it wasn't transparent, we // should fix that. We can also mark it opaque unconditionally if we didn't // actually see any transparent pixels - this test is only valid for the // first frame. if (!mGIFStruct.is_transparent && !mSawTransparency) { - opacity = Opacity::OPAQUE; - } - } - mCurrentRow = mLastFlushedRow = -1; - mCurrentPass = mLastFlushedPass = 0; - - // Only add frame if we have any rows at all - if (mGIFStruct.rows_remaining != mGIFStruct.clamped_height) { - if (mGIFStruct.rows_remaining && mGIFStruct.images_decoded) { - // Clear the remaining rows (only needed for the animation frames) - uint8_t* rowp = - mImageData + ((mGIFStruct.clamped_height - mGIFStruct.rows_remaining) * - mGIFStruct.width); - memset(rowp, 0, mGIFStruct.rows_remaining * mGIFStruct.width); + opacity = Opacity::FULLY_OPAQUE; } } @@ -368,286 +281,163 @@ nsGIFDecoder2::EndImageFrame() mCurrentFrameIndex = -1; } - -//****************************************************************************** -// Send the data to the display front-end. -uint32_t -nsGIFDecoder2::OutputRow() +template +PixelSize +nsGIFDecoder2::ColormapIndexToPixel(uint8_t aIndex) { - // Initialize the region in which we're duplicating rows (for the - // Haeberli-inspired hack below) to |irow|, which is the row we're writing to - // now. - int drow_start = mGIFStruct.irow; - int drow_end = mGIFStruct.irow; + MOZ_ASSERT(sizeof(PixelSize) == sizeof(uint32_t)); - // Protect against too much image data - if ((unsigned)drow_start >= mGIFStruct.clamped_height) { - NS_WARNING("GIF2.cpp::OutputRow - too much image data"); - return 0; + // Retrieve the next color, clamping to the size of the colormap. + uint32_t color = mColormap[aIndex & mColorMask]; + + // Check for transparency. + if (mGIFStruct.is_transparent) { + mSawTransparency = mSawTransparency || color == 0; } - if (!mGIFStruct.images_decoded) { - // Haeberli-inspired hack for interlaced GIFs: Replicate lines while - // displaying to diminish the "venetian-blind" effect as the image is - // loaded. Adjust pixel vertical positions to avoid the appearance of the - // image crawling up the screen as successive passes are drawn. - if (mGIFStruct.progressive_display && mGIFStruct.interlaced && - (mGIFStruct.ipass < 4)) { - // ipass = 1,2,3 results in resp. row_dup = 7,3,1 and row_shift = 3,1,0 - const uint32_t row_dup = 15 >> mGIFStruct.ipass; - const uint32_t row_shift = row_dup >> 1; - - drow_start -= row_shift; - drow_end = drow_start + row_dup; - - // Extend if bottom edge isn't covered because of the shift upward. - if (((mGIFStruct.clamped_height - 1) - drow_end) <= row_shift) { - drow_end = mGIFStruct.clamped_height - 1; - } - - // Clamp first and last rows to upper and lower edge of image. - if (drow_start < 0) { - drow_start = 0; - } - if ((unsigned)drow_end >= mGIFStruct.clamped_height) { - drow_end = mGIFStruct.clamped_height - 1; - } - } - - // Row to process - uint8_t* rowp = GetCurrentRowBuffer(); - - // Convert color indices to Cairo pixels - uint8_t* from = rowp + mGIFStruct.clamped_width; - uint32_t* to = ((uint32_t*)rowp) + mGIFStruct.clamped_width; - uint32_t* cmap = mColormap; - for (uint32_t c = mGIFStruct.clamped_width; c > 0; c--) { - *--to = cmap[*--from]; - } - - // check for alpha (only for first frame) - if (mGIFStruct.is_transparent && !mSawTransparency) { - const uint32_t* rgb = (uint32_t*)rowp; - for (uint32_t i = mGIFStruct.clamped_width; i > 0; i--) { - if (*rgb++ == 0) { - mSawTransparency = true; - break; - } - } - } - - // If we're downscaling but not deinterlacing, we're done with this row and - // can commit it now. Otherwise, we'll let Deinterlacer do the committing - // when we call PropagatePassToDownscaler() at the end of this pass. - if (mDownscaler && !mDeinterlacer) { - mDownscaler->CommitRow(); - } - - if (drow_end > drow_start) { - // Duplicate rows if needed to reduce the "venetian blind" effect mentioned - // above. This writes out scanlines of the image in a way that isn't ordered - // vertically, which is incompatible with the filter that we use for - // downscale-during-decode, so we can't do this if we're downscaling. - MOZ_ASSERT_IF(mDownscaler, mDeinterlacer); - const uint32_t bpr = sizeof(uint32_t) * mGIFStruct.clamped_width; - for (int r = drow_start; r <= drow_end; r++) { - // Skip the row we wrote to above; that's what we're copying *from*. - if (r != int(mGIFStruct.irow)) { - memcpy(GetRowBuffer(r), rowp, bpr); - } - } - } - } - - mCurrentRow = drow_end; - mCurrentPass = mGIFStruct.ipass; - if (mGIFStruct.ipass == 1) { - mLastFlushedPass = mGIFStruct.ipass; // interlaced starts at 1 - } - - if (!mGIFStruct.interlaced) { - MOZ_ASSERT(!mDeinterlacer); - mGIFStruct.irow++; - } else { - static const uint8_t kjump[5] = { 1, 8, 8, 4, 2 }; - int currentPass = mGIFStruct.ipass; - - do { - // Row increments resp. per 8,8,4,2 rows - mGIFStruct.irow += kjump[mGIFStruct.ipass]; - if (mGIFStruct.irow >= mGIFStruct.clamped_height) { - // Next pass starts resp. at row 4,2,1,0 - mGIFStruct.irow = 8 >> mGIFStruct.ipass; - mGIFStruct.ipass++; - } - } while (mGIFStruct.irow >= mGIFStruct.clamped_height); - - // We've finished a pass. If we're downscaling, it's time to propagate the - // rows we've decoded so far from our Deinterlacer to our Downscaler. - if (mGIFStruct.ipass > currentPass && mDownscaler) { - MOZ_ASSERT(mDeinterlacer); - mDeinterlacer->PropagatePassToDownscaler(*mDownscaler); - FlushImageData(); - mDownscaler->ResetForNextProgressivePass(); - } - } - - return --mGIFStruct.rows_remaining; + return color; } -//****************************************************************************** -// Perform Lempel-Ziv-Welch decoding -bool -nsGIFDecoder2::DoLzw(const uint8_t* q) +template <> +uint8_t +nsGIFDecoder2::ColormapIndexToPixel(uint8_t aIndex) { - if (!mGIFStruct.rows_remaining) { - return true; - } - if (MOZ_UNLIKELY(mDownscaler && mDownscaler->IsFrameComplete())) { - return true; + return aIndex & mColorMask; +} + +template +NextPixel +nsGIFDecoder2::YieldPixel(const uint8_t*& aCurrentByteInOut) +{ + MOZ_ASSERT(mGIFStruct.stackp >= mGIFStruct.stack); + + // If we don't have any decoded data to yield, try to read some input and + // produce some. + if (mGIFStruct.stackp == mGIFStruct.stack) { + while (mGIFStruct.bits < mGIFStruct.codesize && mGIFStruct.count > 0) { + // Feed the next byte into the decoder's 32-bit input buffer. + mGIFStruct.datum += int32_t(*aCurrentByteInOut) << mGIFStruct.bits; + mGIFStruct.bits += 8; + ++aCurrentByteInOut; + --mGIFStruct.count; + } + + if (mGIFStruct.bits < mGIFStruct.codesize) { + return AsVariant(WriteState::NEED_MORE_DATA); + } + + // Get the leading variable-length symbol from the data stream. + int code = mGIFStruct.datum & mGIFStruct.codemask; + mGIFStruct.datum >>= mGIFStruct.codesize; + mGIFStruct.bits -= mGIFStruct.codesize; + + const int clearCode = ClearCode(); + + // Reset the dictionary to its original state, if requested + if (code == clearCode) { + mGIFStruct.codesize = mGIFStruct.datasize + 1; + mGIFStruct.codemask = (1 << mGIFStruct.codesize) - 1; + mGIFStruct.avail = clearCode + 2; + mGIFStruct.oldcode = -1; + return AsVariant(WriteState::NEED_MORE_DATA); + } + + // Check for explicit end-of-stream code. It should only appear after all + // image data, but if that was the case we wouldn't be in this function, so + // this is always an error condition. + if (code == (clearCode + 1)) { + return AsVariant(WriteState::FAILURE); + } + + if (mGIFStruct.oldcode == -1) { + if (code >= MAX_BITS) { + return AsVariant(WriteState::FAILURE); // The code's too big; something's wrong. + } + + mGIFStruct.firstchar = mGIFStruct.oldcode = code; + + // Yield a pixel at the appropriate index in the colormap. + mGIFStruct.pixels_remaining--; + return AsVariant(ColormapIndexToPixel(mGIFStruct.suffix[code])); + } + + int incode = code; + if (code >= mGIFStruct.avail) { + *mGIFStruct.stackp++ = mGIFStruct.firstchar; + code = mGIFStruct.oldcode; + + if (mGIFStruct.stackp >= mGIFStruct.stack + MAX_BITS) { + return AsVariant(WriteState::FAILURE); // Stack overflow; something's wrong. + } + } + + while (code >= clearCode) { + if ((code >= MAX_BITS) || (code == mGIFStruct.prefix[code])) { + return AsVariant(WriteState::FAILURE); + } + + *mGIFStruct.stackp++ = mGIFStruct.suffix[code]; + code = mGIFStruct.prefix[code]; + + if (mGIFStruct.stackp >= mGIFStruct.stack + MAX_BITS) { + return AsVariant(WriteState::FAILURE); // Stack overflow; something's wrong. + } + } + + *mGIFStruct.stackp++ = mGIFStruct.firstchar = mGIFStruct.suffix[code]; + + // Define a new codeword in the dictionary. + if (mGIFStruct.avail < 4096) { + mGIFStruct.prefix[mGIFStruct.avail] = mGIFStruct.oldcode; + mGIFStruct.suffix[mGIFStruct.avail] = mGIFStruct.firstchar; + mGIFStruct.avail++; + + // If we've used up all the codewords of a given length increase the + // length of codewords by one bit, but don't exceed the specified maximum + // codeword size of 12 bits. + if (((mGIFStruct.avail & mGIFStruct.codemask) == 0) && + (mGIFStruct.avail < 4096)) { + mGIFStruct.codesize++; + mGIFStruct.codemask += mGIFStruct.avail; + } + } + + mGIFStruct.oldcode = incode; } - // Copy all the decoder state variables into locals so the compiler - // won't worry about them being aliased. The locals will be homed - // back into the GIF decoder structure when we exit. - int avail = mGIFStruct.avail; - int bits = mGIFStruct.bits; - int codesize = mGIFStruct.codesize; - int codemask = mGIFStruct.codemask; - int count = mGIFStruct.count; - int oldcode = mGIFStruct.oldcode; - const int clear_code = ClearCode(); - uint8_t firstchar = mGIFStruct.firstchar; - int32_t datum = mGIFStruct.datum; - uint16_t* prefix = mGIFStruct.prefix; - uint8_t* stackp = mGIFStruct.stackp; - uint8_t* suffix = mGIFStruct.suffix; - uint8_t* stack = mGIFStruct.stack; - uint8_t* rowp = mGIFStruct.rowp; + if (MOZ_UNLIKELY(mGIFStruct.stackp <= mGIFStruct.stack)) { + MOZ_ASSERT_UNREACHABLE("No decoded data but we didn't return early?"); + return AsVariant(WriteState::FAILURE); + } - uint8_t* rowend = GetCurrentRowBuffer() + mGIFStruct.clamped_width; + // Yield a pixel at the appropriate index in the colormap. + mGIFStruct.pixels_remaining--; + return AsVariant(ColormapIndexToPixel(*--mGIFStruct.stackp)); +} -#define OUTPUT_ROW() \ - PR_BEGIN_MACRO \ - if (!OutputRow()) \ - goto END; \ - rowp = GetCurrentRowBuffer(); \ - rowend = rowp + mGIFStruct.clamped_width; \ - PR_END_MACRO +bool +nsGIFDecoder2::DoLzw(const uint8_t* aData) +{ + const uint8_t* currentByte = aData; + while (mGIFStruct.count > 0 && mGIFStruct.pixels_remaining > 0) { + auto result = mGIFStruct.images_decoded > 0 + ? mPipe.WritePixels([&]() { return YieldPixel(currentByte); }) + : mPipe.WritePixels([&]() { return YieldPixel(currentByte); }); - for (const uint8_t* ch = q; count-- > 0; ch++) { - // Feed the next byte into the decoder's 32-bit input buffer. - datum += ((int32_t)* ch) << bits; - bits += 8; - - // Check for underflow of decoder's 32-bit input buffer. - while (bits >= codesize) { - // Get the leading variable-length symbol from the data stream - int code = datum & codemask; - datum >>= codesize; - bits -= codesize; - - // Reset the dictionary to its original state, if requested - if (code == clear_code) { - codesize = mGIFStruct.datasize + 1; - codemask = (1 << codesize) - 1; - avail = clear_code + 2; - oldcode = -1; + switch (result) { + case WriteState::NEED_MORE_DATA: continue; - } - // Check for explicit end-of-stream code - if (code == (clear_code + 1)) { - // end-of-stream should only appear after all image data - return (mGIFStruct.rows_remaining == 0); - } + case WriteState::FINISHED: + NS_WARN_IF(mGIFStruct.pixels_remaining > 0); + mGIFStruct.pixels_remaining = 0; + return true; - if (MOZ_UNLIKELY(mDownscaler && mDownscaler->IsFrameComplete())) { - goto END; - } - - if (oldcode == -1) { - if (code >= MAX_BITS) { - return false; - } - *rowp++ = suffix[code] & mColorMask; // ensure index is within colormap - if (rowp == rowend) { - OUTPUT_ROW(); - } - - firstchar = oldcode = code; - continue; - } - - int incode = code; - if (code >= avail) { - *stackp++ = firstchar; - code = oldcode; - - if (stackp >= stack + MAX_BITS) { - return false; - } - } - - while (code >= clear_code) { - if ((code >= MAX_BITS) || (code == prefix[code])) { - return false; - } - - *stackp++ = suffix[code]; - code = prefix[code]; - - if (stackp == stack + MAX_BITS) { - return false; - } - } - - *stackp++ = firstchar = suffix[code]; - - // Define a new codeword in the dictionary. - if (avail < 4096) { - prefix[avail] = oldcode; - suffix[avail] = firstchar; - avail++; - - // If we've used up all the codewords of a given length - // increase the length of codewords by one bit, but don't - // exceed the specified maximum codeword size of 12 bits. - if (((avail & codemask) == 0) && (avail < 4096)) { - codesize++; - codemask += avail; - } - } - oldcode = incode; - - // Copy the decoded data out to the scanline buffer. - do { - *rowp++ = *--stackp & mColorMask; // ensure index is within colormap - if (rowp == rowend) { - OUTPUT_ROW(); - - // Consume decoded data that falls past the end of the clamped width. - stackp -= mGIFStruct.width - mGIFStruct.clamped_width; - stackp = std::max(stackp, stack); - } - } while (stackp > stack); + case WriteState::FAILURE: + return false; } } - END: - - // Home the local copies of the GIF decoder state variables - mGIFStruct.avail = avail; - mGIFStruct.bits = bits; - mGIFStruct.codesize = codesize; - mGIFStruct.codemask = codemask; - mGIFStruct.count = count; - mGIFStruct.oldcode = oldcode; - mGIFStruct.firstchar = firstchar; - mGIFStruct.datum = datum; - mGIFStruct.stackp = stackp; - mGIFStruct.rowp = rowp; - return true; } @@ -1065,25 +855,26 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) } } + IntRect frameRect; + // Get image offsets, with respect to the screen origin - mGIFStruct.x_offset = GETINT16(q); - mGIFStruct.y_offset = GETINT16(q + 2); + frameRect.x = GETINT16(q); + frameRect.y = GETINT16(q + 2); // Get image width and height. - mGIFStruct.width = GETINT16(q + 4); - mGIFStruct.height = GETINT16(q + 6); + frameRect.width = GETINT16(q + 4); + frameRect.height = GETINT16(q + 6); if (!mGIFStruct.images_decoded) { // Work around broken GIF files where the logical screen // size has weird width or height. We assume that GIF87a // files don't contain animations. - if ((mGIFStruct.screen_height < mGIFStruct.height) || - (mGIFStruct.screen_width < mGIFStruct.width) || + if ((mGIFStruct.screen_height < frameRect.height) || + (mGIFStruct.screen_width < frameRect.width) || (mGIFStruct.version == 87)) { - mGIFStruct.screen_height = mGIFStruct.height; - mGIFStruct.screen_width = mGIFStruct.width; - mGIFStruct.x_offset = 0; - mGIFStruct.y_offset = 0; + mGIFStruct.screen_height = frameRect.height; + mGIFStruct.screen_width = frameRect.width; + frameRect.MoveTo(0, 0); } // Create the image container with the right size. BeginGIF(); @@ -1095,38 +886,21 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) // If we were doing a metadata decode, we're done. if (IsMetadataDecode()) { - IntRect frameRect(mGIFStruct.x_offset, mGIFStruct.y_offset, - mGIFStruct.width, mGIFStruct.height); CheckForTransparency(frameRect); return; } } // Work around more broken GIF files that have zero image width or height - if (!mGIFStruct.height || !mGIFStruct.width) { - mGIFStruct.height = mGIFStruct.screen_height; - mGIFStruct.width = mGIFStruct.screen_width; - if (!mGIFStruct.height || !mGIFStruct.width) { + if (!frameRect.height || !frameRect.width) { + frameRect.height = mGIFStruct.screen_height; + frameRect.width = mGIFStruct.screen_width; + if (!frameRect.height || !frameRect.width) { mGIFStruct.state = gif_error; break; } } - // Hack around GIFs with frame rects outside the given screen bounds. - IntRect clampedRect = - ClampToImageRect(IntRect(mGIFStruct.x_offset, mGIFStruct.y_offset, - mGIFStruct.width, mGIFStruct.height)); - if (clampedRect.IsEmpty()) { - // XXX Bug 1227546 - Maybe we should treat this as valid? - mGIFStruct.state = gif_error; - break; - } - mGIFStruct.clamped_width = clampedRect.width; - mGIFStruct.clamped_height = clampedRect.height; - - MOZ_ASSERT(mGIFStruct.clamped_width <= mGIFStruct.width); - MOZ_ASSERT(mGIFStruct.clamped_height <= mGIFStruct.height); - // Depth of colors is determined by colormap // (q[8] & 0x80) indicates local colormap // bits per pixel is (q[8]&0x07 + 1) when local colormap is set @@ -1138,17 +912,18 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) while (mGIFStruct.tpixel >= (1 << realDepth) && (realDepth < 8)) { realDepth++; } + // Mask to limit the color values within the colormap mColorMask = 0xFF >> (8 - realDepth); - if (NS_FAILED(BeginImageFrame(realDepth))) { + // Determine if this frame is interlaced or not. + const bool isInterlaced = q[8] & 0x40; + + if (NS_FAILED(BeginImageFrame(frameRect, realDepth, isInterlaced))) { mGIFStruct.state = gif_error; return; } - MOZ_FALLTHROUGH; // to continue decoding header. - } - case gif_image_header_continue: { // While decoders can reuse frames, we unconditionally increment // mGIFStruct.images_decoded when we're done with a frame, so we both can // and need to zero out the colormap and image data after every new frame. @@ -1157,57 +932,9 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) memset(mColormap, 0, mColormapSize); } - if (!mGIFStruct.images_decoded) { - // Send a onetime invalidation for the first frame if it has a y-axis - // offset. Otherwise, the area may never be refreshed and the - // placeholder will remain on the screen. (Bug 37589) - if (mGIFStruct.y_offset > 0) { - if (mDownscaler) { - IntRect targetRect = IntRect(IntPoint(), mDownscaler->TargetSize()); - PostInvalidation(IntRect(IntPoint(), GetSize()), Some(targetRect)); - } else { - nsIntRect r(0, 0, mGIFStruct.screen_width, mGIFStruct.y_offset); - PostInvalidation(r); - } - } - } - - if (q[8] & 0x40) { - mGIFStruct.interlaced = true; - mGIFStruct.ipass = 1; - if (mDownscaler) { - mDeinterlacer.emplace(mDownscaler->FrameSize()); - - if (!mDeinterlacer->IsValid()) { - mDeinterlacer.reset(); - mGIFStruct.state = gif_error; - break; - } - } - } else { - mGIFStruct.interlaced = false; - mGIFStruct.ipass = 0; - } - - // Only apply the Haeberli display hack on the first frame - mGIFStruct.progressive_display = (mGIFStruct.images_decoded == 0); - // Clear state from last image - mGIFStruct.irow = 0; - mGIFStruct.rows_remaining = mGIFStruct.clamped_height; - mGIFStruct.rowp = GetCurrentRowBuffer(); + mGIFStruct.pixels_remaining = frameRect.width * frameRect.height; - // Depth of colors is determined by colormap - // (q[8] & 0x80) indicates local colormap - // bits per pixel is (q[8]&0x07 + 1) when local colormap is set - uint32_t depth = mGIFStruct.global_colormap_depth; - if (q[8] & 0x80) { - depth = (q[8]&0x07) + 1; - } - uint32_t realDepth = depth; - while (mGIFStruct.tpixel >= (1 << realDepth) && (realDepth < 8)) { - realDepth++; - } // has a local colormap? if (q[8] & 0x80) { mGIFStruct.local_colormap_size = 1 << depth; @@ -1260,9 +987,9 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) mGIFStruct.count = *q; if (mGIFStruct.count) { // Still working on the same image: Process next LZW data block - // Make sure there are still rows left. If the GIF data + // Make sure there are still pixels left. If the GIF data // is corrupt, we may not get an explicit terminator. - if (!mGIFStruct.rows_remaining) { + if (mGIFStruct.pixels_remaining <= 0) { #ifdef DONT_TOLERATE_BROKEN_GIFS mGIFStruct.state = gif_error; break; @@ -1332,8 +1059,6 @@ nsGIFDecoder2::WriteInternal(const char* aBuffer, uint32_t aCount) done: if (!mGIFStruct.images_decoded) { FlushImageData(); - mLastFlushedRow = mCurrentRow; - mLastFlushedPass = mCurrentPass; } } diff --git a/image/decoders/nsGIFDecoder2.h b/image/decoders/nsGIFDecoder2.h index a73102a157..e0900f0c46 100644 --- a/image/decoders/nsGIFDecoder2.h +++ b/image/decoders/nsGIFDecoder2.h @@ -8,9 +8,8 @@ #define mozilla_image_decoders_nsGIFDecoder2_h #include "Decoder.h" -#include "Deinterlacer.h" #include "GIF2.h" -#include "nsCOMPtr.h" +#include "SurfacePipe.h" namespace mozilla { namespace image { @@ -34,20 +33,40 @@ private: // Decoders should only be instantiated via DecoderFactory. explicit nsGIFDecoder2(RasterImage* aImage); - uint8_t* GetCurrentRowBuffer(); - uint8_t* GetRowBuffer(uint32_t aRow); - - // These functions will be called when the decoder has a decoded row, - // frame size information, etc. + /// Called when we begin decoding the image. void BeginGIF(); - nsresult BeginImageFrame(uint16_t aDepth); + + /** + * Called when we begin decoding a frame. + * + * @param aFrameRect The region of the image that contains data. The region + * outside this rect is transparent. + * @param aDepth The palette depth of this frame. + * @param aIsInterlaced If true, this frame is an interlaced frame. + */ + nsresult BeginImageFrame(const gfx::IntRect& aFrameRect, + uint16_t aDepth, + bool aIsInterlaced); + + /// Called when we finish decoding a frame. void EndImageFrame(); + + /// Called when we finish decoding the entire image. void FlushImageData(); - void FlushImageData(uint32_t fromRow, uint32_t rows); nsresult GifWrite(const uint8_t* buf, uint32_t numbytes); - uint32_t OutputRow(); - bool DoLzw(const uint8_t* q); + + /// Transforms a palette index into a pixel. + template PixelSize + ColormapIndexToPixel(uint8_t aIndex); + + /// A generator function that performs LZW decompression and yields pixels. + template NextPixel + YieldPixel(const uint8_t*& aCurrentByte); + + /// The entry point for LZW decompression. + bool DoLzw(const uint8_t* aData); + bool SetHold(const uint8_t* buf, uint32_t count, const uint8_t* buf2 = nullptr, uint32_t count2 = 0); bool CheckForTransparency(const gfx::IntRect& aFrameRect); @@ -55,23 +74,19 @@ private: inline int ClearCode() const { return 1 << mGIFStruct.datasize; } - int32_t mCurrentRow; - int32_t mLastFlushedRow; - uint32_t mOldColor; // The old value of the transparent pixel // The frame number of the currently-decoding frame when we're in the middle // of decoding it, and -1 otherwise. int32_t mCurrentFrameIndex; - uint8_t mCurrentPass; - uint8_t mLastFlushedPass; uint8_t mColorMask; // Apply this to the pixel to keep within colormap bool mGIFOpen; bool mSawTransparency; gif_struct mGIFStruct; - Maybe mDeinterlacer; + + SurfacePipe mPipe; /// The SurfacePipe used to write to the output surface. }; } // namespace image diff --git a/image/decoders/nsJPEGDecoder.cpp b/image/decoders/nsJPEGDecoder.cpp index 56c35505e7..28bd835ef5 100644 --- a/image/decoders/nsJPEGDecoder.cpp +++ b/image/decoders/nsJPEGDecoder.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ImageLogging.h" +#include "imgFrame.h" #include "nsJPEGDecoder.h" #include "Orientation.h" #include "EXIF.h" @@ -583,7 +584,7 @@ nsJPEGDecoder::ReadOrientationFromEXIF() void nsJPEGDecoder::NotifyDone() { - PostFrameStop(Opacity::OPAQUE); + PostFrameStop(Opacity::FULLY_OPAQUE); PostDecodeDone(); } diff --git a/image/decoders/nsJXRDecoder.cpp b/image/decoders/nsJXRDecoder.cpp index a41bfa8eb6..186b3879ef 100644 --- a/image/decoders/nsJXRDecoder.cpp +++ b/image/decoders/nsJXRDecoder.cpp @@ -2787,7 +2787,7 @@ void nsJXRDecoder::FinishInternal() } else { - PostFrameStop(Opacity::OPAQUE); + PostFrameStop(Opacity::FULLY_OPAQUE); } PostDecodeDone(); diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index 8fa9fa162a..43f8e0995d 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -7,6 +7,7 @@ #include "ImageLogging.h" // Must appear first #include "gfxColor.h" #include "gfxPlatform.h" +#include "imgFrame.h" #include "nsColor.h" #include "nsIInputStream.h" #include "nsMemory.h" @@ -221,7 +222,7 @@ nsPNGDecoder::EndImageFrame() Opacity opacity = Opacity::SOME_TRANSPARENCY; if (format == gfx::SurfaceFormat::B8G8R8X8) { - opacity = Opacity::OPAQUE; + opacity = Opacity::FULLY_OPAQUE; } PostFrameStop(opacity, mAnimInfo.mDispose, mAnimInfo.mTimeout, diff --git a/image/imgFrame.cpp b/image/imgFrame.cpp index 96741f9d70..af9d534e55 100644 --- a/image/imgFrame.cpp +++ b/image/imgFrame.cpp @@ -643,7 +643,7 @@ imgFrame::Finish(Opacity aFrameOpacity /* = Opacity::SOME_TRANSPARENCY */, MonitorAutoLock lock(mMonitor); MOZ_ASSERT(mLockCount > 0, "Image data should be locked"); - if (aFrameOpacity == Opacity::OPAQUE) { + if (aFrameOpacity == Opacity::FULLY_OPAQUE) { mHasNoAlpha = true; } diff --git a/image/imgFrame.h b/image/imgFrame.h index 5f114fd5b0..305a1164e3 100644 --- a/image/imgFrame.h +++ b/image/imgFrame.h @@ -41,7 +41,7 @@ enum class DisposalMethod : int8_t { }; enum class Opacity : uint8_t { - OPAQUE, + FULLY_OPAQUE, SOME_TRANSPARENCY }; diff --git a/image/moz.build b/image/moz.build index 2efdb2190a..0e2788e779 100644 --- a/image/moz.build +++ b/image/moz.build @@ -55,7 +55,6 @@ UNIFIED_SOURCES += [ 'DecodePool.cpp', 'Decoder.cpp', 'DecoderFactory.cpp', - 'Deinterlacer.cpp', 'DynamicImage.cpp', 'FrameAnimator.cpp', 'FrozenImage.cpp', @@ -72,6 +71,7 @@ UNIFIED_SOURCES += [ 'ShutdownTracker.cpp', 'SourceBuffer.cpp', 'SurfaceCache.cpp', + 'SurfacePipe.cpp', 'SVGDocumentWrapper.cpp', 'VectorImage.cpp', ] diff --git a/image/test/gtest/Common.cpp b/image/test/gtest/Common.cpp index 736b59c4b3..1a5e873b01 100644 --- a/image/test/gtest/Common.cpp +++ b/image/test/gtest/Common.cpp @@ -6,7 +6,6 @@ #include "Common.h" #include -#include "gtest/gtest.h" #include "nsDirectoryServiceDefs.h" #include "nsIDirectoryService.h" @@ -19,13 +18,14 @@ #include "nsString.h" namespace mozilla { +namespace image { using namespace gfx; using std::abs; /////////////////////////////////////////////////////////////////////////////// -// Helpers +// General Helpers /////////////////////////////////////////////////////////////////////////////// // These macros work like gtest's ASSERT_* macros, except that they can be used @@ -85,13 +85,41 @@ LoadFile(const char* aRelativePath) } bool -IsSolidColor(SourceSurface* aSurface, BGRAColor aColor, bool aFuzzy) +IsSolidColor(SourceSurface* aSurface, + BGRAColor aColor, + uint8_t aFuzz /* = 0 */) { + IntSize size = aSurface->GetSize(); + return RectIsSolidColor(aSurface, IntRect(0, 0, size.width, size.height), + aColor, aFuzz); +} + +bool +RowsAreSolidColor(SourceSurface* aSurface, + int32_t aStartRow, + int32_t aRowCount, + BGRAColor aColor, + uint8_t aFuzz /* = 0 */) +{ + IntSize size = aSurface->GetSize(); + return RectIsSolidColor(aSurface, IntRect(0, aStartRow, size.width, aRowCount), + aColor, aFuzz); +} + +bool +RectIsSolidColor(SourceSurface* aSurface, + const IntRect& aRect, + BGRAColor aColor, + uint8_t aFuzz /* = 0 */) +{ + IntSize surfaceSize = aSurface->GetSize(); + IntRect rect = + aRect.Intersect(IntRect(0, 0, surfaceSize.width, surfaceSize.height)); + RefPtr dataSurface = aSurface->GetDataSurface(); ASSERT_TRUE_OR_RETURN(dataSurface != nullptr, false); - ASSERT_EQ_OR_RETURN(dataSurface->Stride(), aSurface->GetSize().width * 4, - false); + ASSERT_EQ_OR_RETURN(dataSurface->Stride(), surfaceSize.width * 4, false); DataSourceSurface::ScopedMap mapping(dataSurface, DataSourceSurface::MapType::READ); @@ -100,18 +128,21 @@ IsSolidColor(SourceSurface* aSurface, BGRAColor aColor, bool aFuzzy) uint8_t* data = dataSurface->GetData(); ASSERT_TRUE_OR_RETURN(data != nullptr, false); - int32_t length = dataSurface->Stride() * aSurface->GetSize().height; - for (int32_t i = 0 ; i < length ; i += 4) { - if (aFuzzy) { - ASSERT_LE_OR_RETURN(abs(aColor.mBlue - data[i + 0]), 1, false); - ASSERT_LE_OR_RETURN(abs(aColor.mGreen - data[i + 1]), 1, false); - ASSERT_LE_OR_RETURN(abs(aColor.mRed - data[i + 2]), 1, false); - ASSERT_LE_OR_RETURN(abs(aColor.mAlpha - data[i + 3]), 1, false); - } else { - ASSERT_EQ_OR_RETURN(aColor.mBlue, data[i + 0], false); - ASSERT_EQ_OR_RETURN(aColor.mGreen, data[i + 1], false); - ASSERT_EQ_OR_RETURN(aColor.mRed, data[i + 2], false); - ASSERT_EQ_OR_RETURN(aColor.mAlpha, data[i + 3], false); + int32_t rowLength = dataSurface->Stride(); + for (int32_t row = rect.y; row < rect.YMost(); ++row) { + for (int32_t col = rect.x; col < rect.XMost(); ++col) { + int32_t i = row * rowLength + col * 4; + if (aFuzz != 0) { + ASSERT_LE_OR_RETURN(abs(aColor.mBlue - data[i + 0]), aFuzz, false); + ASSERT_LE_OR_RETURN(abs(aColor.mGreen - data[i + 1]), aFuzz, false); + ASSERT_LE_OR_RETURN(abs(aColor.mRed - data[i + 2]), aFuzz, false); + ASSERT_LE_OR_RETURN(abs(aColor.mAlpha - data[i + 3]), aFuzz, false); + } else { + ASSERT_EQ_OR_RETURN(aColor.mBlue, data[i + 0], false); + ASSERT_EQ_OR_RETURN(aColor.mGreen, data[i + 1], false); + ASSERT_EQ_OR_RETURN(aColor.mRed, data[i + 2], false); + ASSERT_EQ_OR_RETURN(aColor.mAlpha, data[i + 3], false); + } } } @@ -119,6 +150,261 @@ IsSolidColor(SourceSurface* aSurface, BGRAColor aColor, bool aFuzzy) } +/////////////////////////////////////////////////////////////////////////////// +// SurfacePipe Helpers +/////////////////////////////////////////////////////////////////////////////// + +already_AddRefed +CreateTrivialDecoder() +{ + gfxPrefs::GetSingleton(); + DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif"); + RefPtr sourceBuffer = new SourceBuffer(); + RefPtr decoder = + DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, + DefaultSurfaceFlags()); + return decoder.forget(); +} + +void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter, + const gfx::IntRect& aInputSpaceRect, + const gfx::IntRect& aOutputSpaceRect) +{ + EXPECT_TRUE(aFilter->IsSurfaceFinished()); + Maybe invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect); + EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect); +} + +void +CheckGeneratedImage(Decoder* aDecoder, + const IntRect& aRect, + uint8_t aFuzz /* = 0 */) +{ + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + const IntSize surfaceSize = surface->GetSize(); + + // This diagram shows how the surface is divided into regions that the code + // below tests for the correct content. The output rect is the bounds of the + // region labeled 'C'. + // + // +---------------------------+ + // | A | + // +---------+--------+--------+ + // | B | C | D | + // +---------+--------+--------+ + // | E | + // +---------------------------+ + + // Check that the output rect itself is green. (Region 'C'.) + EXPECT_TRUE(RectIsSolidColor(surface, aRect, BGRAColor::Green(), aFuzz)); + + // Check that the area above the output rect is transparent. (Region 'A'.) + EXPECT_TRUE(RectIsSolidColor(surface, + IntRect(0, 0, surfaceSize.width, aRect.y), + BGRAColor::Transparent(), aFuzz)); + + // Check that the area to the left of the output rect is transparent. (Region 'B'.) + EXPECT_TRUE(RectIsSolidColor(surface, + IntRect(0, aRect.y, aRect.x, aRect.YMost()), + BGRAColor::Transparent(), aFuzz)); + + // Check that the area to the right of the output rect is transparent. (Region 'D'.) + const int32_t widthOnRight = surfaceSize.width - aRect.XMost(); + EXPECT_TRUE(RectIsSolidColor(surface, + IntRect(aRect.XMost(), aRect.y, widthOnRight, aRect.YMost()), + BGRAColor::Transparent(), aFuzz)); + + // Check that the area below the output rect is transparent. (Region 'E'.) + const int32_t heightBelow = surfaceSize.height - aRect.YMost(); + EXPECT_TRUE(RectIsSolidColor(surface, + IntRect(0, aRect.YMost(), surfaceSize.width, heightBelow), + BGRAColor::Transparent(), aFuzz)); +} + +template void +CheckSurfacePipeWrite(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect, + Maybe aInputRect, + Maybe aInputWriteRect, + Maybe aOutputWriteRect, + uint8_t aFuzz, + Func aFunc) +{ + IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100)); + IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100)); + IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect); + IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect); + + // Fill the image. + int32_t count = 0; + auto result = aFunc(count); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(inputWriteRect.width * inputWriteRect.height, count); + + AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect); + + // Attempt to write more data and make sure nothing changes. + const int32_t oldCount = count; + result = aFunc(count); + EXPECT_EQ(oldCount, count); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_TRUE(aFilter->IsSurfaceFinished()); + Maybe invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Attempt to advance to the next row and make sure nothing changes. + aFilter->AdvanceRow(); + EXPECT_TRUE(aFilter->IsSurfaceFinished()); + invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Check that the generated image is correct. + CheckGeneratedImage(aDecoder, outputWriteRect, aFuzz); +} + +void +CheckWritePixels(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect /* = Nothing() */, + Maybe aInputRect /* = Nothing() */, + Maybe aInputWriteRect /* = Nothing() */, + Maybe aOutputWriteRect /* = Nothing() */, + uint8_t aFuzz /* = 0 */) +{ + CheckSurfacePipeWrite(aDecoder, aFilter, + aOutputRect, aInputRect, + aInputWriteRect, aOutputWriteRect, + aFuzz, + [&](int32_t& aCount) { + return aFilter->WritePixels([&] { + ++aCount; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + }); +} + +void +CheckWriteRows(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect /* = Nothing() */, + Maybe aInputRect /* = Nothing() */, + Maybe aInputWriteRect /* = Nothing() */, + Maybe aOutputWriteRect /* = Nothing() */, + uint8_t aFuzz /* = 0 */) +{ + CheckSurfacePipeWrite(aDecoder, aFilter, + aOutputRect, aInputRect, + aInputWriteRect, aOutputWriteRect, + aFuzz, + [&](int32_t& aCount) { + return aFilter->WriteRows([&](uint32_t* aRow, uint32_t aLength) { + for (; aLength > 0; --aLength, ++aRow, ++aCount) { + *aRow = BGRAColor::Green().AsPixel(); + } + return Nothing(); + }); + }); +} + +template void +CheckPalettedSurfacePipeWrite(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect, + Maybe aInputRect, + Maybe aInputWriteRect, + Maybe aOutputWriteRect, + uint8_t aFuzz, + Func aFunc) +{ + IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100)); + IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100)); + IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect); + IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect); + + // Fill the image. + int32_t count = 0; + auto result = aFunc(count); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(inputWriteRect.width * inputWriteRect.height, count); + + AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect); + + // Attempt to write more data and make sure nothing changes. + const int32_t oldCount = count; + result = aFunc(count); + EXPECT_EQ(oldCount, count); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_TRUE(aFilter->IsSurfaceFinished()); + Maybe invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Attempt to advance to the next row and make sure nothing changes. + aFilter->AdvanceRow(); + EXPECT_TRUE(aFilter->IsSurfaceFinished()); + invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + uint8_t* imageData; + uint32_t imageLength; + currentFrame->GetImageData(&imageData, &imageLength); + ASSERT_TRUE(imageData != nullptr); + ASSERT_EQ(outputWriteRect.width * outputWriteRect.height, int32_t(imageLength)); + for (uint32_t i = 0; i < imageLength; ++i) { + ASSERT_EQ(uint8_t(255), imageData[i]); + } +} + +void +CheckPalettedWritePixels(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect /* = Nothing() */, + Maybe aInputRect /* = Nothing() */, + Maybe aInputWriteRect /* = Nothing() */, + Maybe aOutputWriteRect /* = Nothing() */, + uint8_t aFuzz /* = 0 */) +{ + CheckPalettedSurfacePipeWrite(aDecoder, aFilter, + aOutputRect, aInputRect, + aInputWriteRect, aOutputWriteRect, + aFuzz, + [&](int32_t& aCount) { + return aFilter->WritePixels([&] { + ++aCount; + return AsVariant(uint8_t(255)); + }); + }); +} + +void +CheckPalettedWriteRows(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect /* = Nothing() */, + Maybe aInputRect /* = Nothing() */, + Maybe aInputWriteRect /* = Nothing() */, + Maybe aOutputWriteRect /* = Nothing() */, + uint8_t aFuzz /* = 0*/) +{ + CheckPalettedSurfacePipeWrite(aDecoder, aFilter, + aOutputRect, aInputRect, + aInputWriteRect, aOutputWriteRect, + aFuzz, + [&](int32_t& aCount) { + return aFilter->WriteRows([&](uint8_t* aRow, uint32_t aLength) { + for (; aLength > 0; --aLength, ++aRow, ++aCount) { + *aRow = uint8_t(255); + } + return Nothing(); + }); + }); +} + + /////////////////////////////////////////////////////////////////////////////// // Test Data /////////////////////////////////////////////////////////////////////////////// @@ -224,4 +510,5 @@ ImageTestCase NoFrameDelayGIFTestCase() return ImageTestCase("no-frame-delay.gif", "image/gif", IntSize(100, 100)); } +} // namespace image } // namespace mozilla diff --git a/image/test/gtest/Common.h b/image/test/gtest/Common.h index 80daeb038e..46637485c5 100644 --- a/image/test/gtest/Common.h +++ b/image/test/gtest/Common.h @@ -6,12 +6,21 @@ #ifndef mozilla_image_test_gtest_Common_h #define mozilla_image_test_gtest_Common_h +#include "gtest/gtest.h" + +#include "mozilla/Maybe.h" +#include "mozilla/UniquePtr.h" #include "mozilla/gfx/2D.h" +#include "Decoder.h" +#include "gfxColor.h" #include "nsCOMPtr.h" +#include "SurfacePipe.h" +#include "SurfacePipeFactory.h" class nsIInputStream; namespace mozilla { +namespace image { /////////////////////////////////////////////////////////////////////////////// // Types @@ -54,6 +63,10 @@ struct BGRAColor { } static BGRAColor Green() { return BGRAColor(0x00, 0xFF, 0x00, 0xFF); } + static BGRAColor Red() { return BGRAColor(0x00, 0x00, 0xFF, 0xFF); } + static BGRAColor Transparent() { return BGRAColor(0x00, 0x00, 0x00, 0x00); } + + uint32_t AsPixel() const { return gfxPackedPixel(mAlpha, mRed, mGreen, mBlue); } uint8_t mBlue; uint8_t mGreen; @@ -63,7 +76,7 @@ struct BGRAColor /////////////////////////////////////////////////////////////////////////////// -// Helpers +// General Helpers /////////////////////////////////////////////////////////////////////////////// /// Loads a file from the current directory. @return an nsIInputStream for it. @@ -72,12 +85,206 @@ already_AddRefed LoadFile(const char* aRelativePath); /** * @returns true if every pixel of @aSurface is @aColor. * - * If @aFuzzy is true, a tolerance of 1 is allowed in each color component. This - * may be necessary for tests that involve JPEG images. + * If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color + * component. This may be necessary for tests that involve JPEG images or + * downscaling. */ bool IsSolidColor(gfx::SourceSurface* aSurface, BGRAColor aColor, - bool aFuzzy = false); + uint8_t aFuzz = 0); + +/** + * @returns true if every pixel in the range of rows specified by @aStartRow and + * @aRowCount of @aSurface is @aColor. + * + * If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color + * component. This may be necessary for tests that involve JPEG images or + * downscaling. + */ +bool RowsAreSolidColor(gfx::SourceSurface* aSurface, + int32_t aStartRow, + int32_t aRowCount, + BGRAColor aColor, + uint8_t aFuzz = 0); + +/** + * @returns true if every pixel in the rect specified by @aRect is @aColor. + * + * If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color + * component. This may be necessary for tests that involve JPEG images or + * downscaling. + */ +bool RectIsSolidColor(gfx::SourceSurface* aSurface, + const gfx::IntRect& aRect, + BGRAColor aColor, + uint8_t aFuzz = 0); + + +/////////////////////////////////////////////////////////////////////////////// +// SurfacePipe Helpers +/////////////////////////////////////////////////////////////////////////////// + +/** + * Creates a decoder with no data associated with, suitable for testing code + * that requires a decoder to initialize or to allocate surfaces but doesn't + * actually need the decoder to do any decoding. + * + * XXX(seth): We only need this because SurfaceSink and PalettedSurfaceSink + * defer to the decoder for surface allocation. Once all decoders use + * SurfacePipe we won't need to do that anymore and we can remove this function. + */ +already_AddRefed CreateTrivialDecoder(); + +/** + * Creates a pipeline of SurfaceFilters from a list of Config structs and passes + * it to the provided lambda @aFunc. Assertions that the pipeline is constructly + * correctly and cleanup of any allocated surfaces is handled automatically. + * + * @param aDecoder The decoder to use for allocating surfaces. + * @param aFunc The lambda function to pass the filter pipeline to. + * @param aConfigs The configuration for the pipeline. + */ +template +void WithFilterPipeline(Decoder* aDecoder, Func aFunc, Configs... aConfigs) +{ + auto pipe = MakeUnique::Type>(); + nsresult rv = pipe->Configure(aConfigs...); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + aFunc(aDecoder, pipe.get()); + + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + if (currentFrame) { + currentFrame->Finish(); + } +} + +/** + * Creates a pipeline of SurfaceFilters from a list of Config structs and + * asserts that configuring it fails. Cleanup of any allocated surfaces is + * handled automatically. + * + * @param aDecoder The decoder to use for allocating surfaces. + * @param aConfigs The configuration for the pipeline. + */ +template +void AssertConfiguringPipelineFails(Decoder* aDecoder, Configs... aConfigs) +{ + auto pipe = MakeUnique::Type>(); + nsresult rv = pipe->Configure(aConfigs...); + + // Callers expect configuring the pipeline to fail. + ASSERT_TRUE(NS_FAILED(rv)); + + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + if (currentFrame) { + currentFrame->Finish(); + } +} + +/** + * Asserts that the provided filter pipeline is in the correct final state, + * which is to say, the entire surface has been written to (IsSurfaceFinished() + * returns true) and the invalid rects are as expected. + * + * @param aFilter The filter pipeline to check. + * @param aInputSpaceRect The expect invalid rect, in input space. + * @param aoutputSpaceRect The expect invalid rect, in output space. + */ +void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter, + const gfx::IntRect& aInputSpaceRect, + const gfx::IntRect& aOutputSpaceRect); + +/** + * Checks a generated image for correctness. Reports any unexpected deviation + * from the expected image as GTest failures. + * + * @param aDecoder The decoder which contains the image. The decoder's current + * frame will be checked. + * @param aRect The region in the space of the output surface that the filter + * pipeline will actually write to. It's expected that pixels in + * this region are green, while pixels outside this region are + * transparent. Defaults to the entire output rect. + * @param aFuzz The amount of fuzz to use in pixel comparisons. + */ +void CheckGeneratedImage(Decoder* aDecoder, + const gfx::IntRect& aRect, + uint8_t aFuzz = 0); + +/** + * Tests the result of calling WritePixels() using the provided SurfaceFilter + * pipeline. The pipeline must be a normal (i.e., non-paletted) pipeline. + * + * The arguments are specified in the an order intended to minimize the number + * of arguments that most test cases need to pass. + * + * @param aDecoder The decoder whose current frame will be written to. + * @param aFilter The SurfaceFilter pipeline to use. + * @param aOutputRect The region in the space of the output surface that will be + * invalidated by the filter pipeline. Defaults to + * (0, 0, 100, 100). + * @param aInputRect The region in the space of the input image that will be + * invalidated by the filter pipeline. Defaults to + * (0, 0, 100, 100). + * @param aInputWriteRect The region in the space of the input image that the + * filter pipeline will allow writes to. Note the + * difference from @aInputRect: @aInputRect is the actual + * region invalidated, while @aInputWriteRect is the + * region that is written to. These can differ in cases + * where the input is not clipped to the size of the image. + * Defaults to the entire input rect. + * @param aOutputWriteRect The region in the space of the output surface that + * the filter pipeline will actually write to. It's + * expected that pixels in this region are green, while + * pixels outside this region are transparent. Defaults + * to the entire output rect. + */ +void CheckWritePixels(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect = Nothing(), + Maybe aInputRect = Nothing(), + Maybe aInputWriteRect = Nothing(), + Maybe aOutputWriteRect = Nothing(), + uint8_t aFuzz = 0); + +/** + * Tests the result of calling WriteRows() using the provided SurfaceFilter + * pipeline. The pipeline must be a normal (i.e., non-paletted) pipeline. + * @see CheckWritePixels() for documentation of the arguments. + */ +void CheckWriteRows(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect = Nothing(), + Maybe aInputRect = Nothing(), + Maybe aInputWriteRect = Nothing(), + Maybe aOutputWriteRect = Nothing(), + uint8_t aFuzz = 0); + +/** + * Tests the result of calling WritePixels() using the provided SurfaceFilter + * pipeline. The pipeline must be a paletted pipeline. + * @see CheckWritePixels() for documentation of the arguments. + */ +void CheckPalettedWritePixels(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect = Nothing(), + Maybe aInputRect = Nothing(), + Maybe aInputWriteRect = Nothing(), + Maybe aOutputWriteRect = Nothing(), + uint8_t aFuzz = 0); + +/** + * Tests the result of calling WriteRows() using the provided SurfaceFilter + * pipeline. The pipeline must be a paletted pipeline. + * @see CheckWritePixels() for documentation of the arguments. + */ +void CheckPalettedWriteRows(Decoder* aDecoder, + SurfaceFilter* aFilter, + Maybe aOutputRect = Nothing(), + Maybe aInputRect = Nothing(), + Maybe aInputWriteRect = Nothing(), + Maybe aOutputWriteRect = Nothing(), + uint8_t aFuzz = 0); /////////////////////////////////////////////////////////////////////////////// @@ -105,6 +312,7 @@ ImageTestCase TransparentBMPWhenBMPAlphaEnabledTestCase(); ImageTestCase RLE4BMPTestCase(); ImageTestCase RLE8BMPTestCase(); +} // namespace image } // namespace mozilla #endif // mozilla_image_test_gtest_Common_h diff --git a/image/test/gtest/TestDecodeToSurface.cpp b/image/test/gtest/TestDecodeToSurface.cpp index 0657dc87fc..70ce27e07f 100644 --- a/image/test/gtest/TestDecodeToSurface.cpp +++ b/image/test/gtest/TestDecodeToSurface.cpp @@ -22,7 +22,6 @@ using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::image; - TEST(ImageDecodeToSurface, ImageModuleAvailable) { // We can run into problems if XPCOM modules get initialized in the wrong @@ -36,9 +35,11 @@ TEST(ImageDecodeToSurface, ImageModuleAvailable) class DecodeToSurfaceRunnable : public nsRunnable { public: - DecodeToSurfaceRunnable(nsIInputStream* aInputStream, + DecodeToSurfaceRunnable(RefPtr& aSurface, + nsIInputStream* aInputStream, const ImageTestCase& aTestCase) - : mInputStream(aInputStream) + : mSurface(aSurface) + , mInputStream(aInputStream) , mTestCase(aTestCase) { } @@ -50,22 +51,23 @@ public: void Go() { - RefPtr surface = + mSurface = ImageOps::DecodeToSurface(mInputStream, nsAutoCString(mTestCase.mMimeType), imgIContainer::DECODE_FLAGS_DEFAULT); - ASSERT_TRUE(surface != nullptr); + ASSERT_TRUE(mSurface != nullptr); - EXPECT_EQ(SurfaceType::DATA, surface->GetType()); - EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 || - surface->GetFormat() == SurfaceFormat::B8G8R8A8); - EXPECT_EQ(mTestCase.mSize, surface->GetSize()); + EXPECT_EQ(SurfaceType::DATA, mSurface->GetType()); + EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::B8G8R8X8 || + mSurface->GetFormat() == SurfaceFormat::B8G8R8A8); + EXPECT_EQ(mTestCase.mSize, mSurface->GetSize()); - EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(), - mTestCase.mFlags & TEST_CASE_IS_FUZZY)); + EXPECT_TRUE(IsSolidColor(mSurface, BGRAColor::Green(), + mTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0)); } private: + RefPtr& mSurface; nsCOMPtr mInputStream; ImageTestCase mTestCase; }; @@ -82,11 +84,15 @@ RunDecodeToSurface(const ImageTestCase& aTestCase) // We run the DecodeToSurface tests off-main-thread to ensure that // DecodeToSurface doesn't require any main-thread-only code. + RefPtr surface; nsCOMPtr runnable = - new DecodeToSurfaceRunnable(inputStream, aTestCase); + new DecodeToSurfaceRunnable(surface, inputStream, aTestCase); thread->Dispatch(runnable, nsIThread::DISPATCH_SYNC); thread->Shutdown(); + + // Explicitly release the SourceSurface on the main thread. + surface = nullptr; } TEST(ImageDecodeToSurface, PNG) { RunDecodeToSurface(GreenPNGTestCase()); } diff --git a/image/test/gtest/TestDecoders.cpp b/image/test/gtest/TestDecoders.cpp index e12c760782..039cacb819 100644 --- a/image/test/gtest/TestDecoders.cpp +++ b/image/test/gtest/TestDecoders.cpp @@ -79,7 +79,7 @@ CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder) surface->GetFormat() == SurfaceFormat::B8G8R8A8); EXPECT_EQ(aTestCase.mSize, surface->GetSize()); EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(), - aTestCase.mFlags & TEST_CASE_IS_FUZZY)); + aTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0)); } static void diff --git a/image/test/gtest/TestDeinterlacingFilter.cpp b/image/test/gtest/TestDeinterlacingFilter.cpp new file mode 100644 index 0000000000..cc256ce781 --- /dev/null +++ b/image/test/gtest/TestDeinterlacingFilter.cpp @@ -0,0 +1,636 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "gtest/gtest.h" + +#include "mozilla/gfx/2D.h" +#include "Common.h" +#include "Decoder.h" +#include "DecoderFactory.h" +#include "SourceBuffer.h" +#include "SurfaceFilters.h" +#include "SurfacePipe.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::image; + +template void +WithDeinterlacingFilter(const IntSize& aSize, + bool aProgressiveDisplay, + Func aFunc) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(bool(decoder)); + + WithFilterPipeline(decoder, Forward(aFunc), + DeinterlacingConfig { aProgressiveDisplay }, + SurfaceConfig { decoder, 0, aSize, + SurfaceFormat::B8G8R8A8, false }); +} + +template void +WithPalettedDeinterlacingFilter(const IntSize& aSize, + Func aFunc) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + WithFilterPipeline(decoder, Forward(aFunc), + DeinterlacingConfig { /* mProgressiveDisplay = */ true }, + PalettedSurfaceConfig { decoder, 0, aSize, + IntRect(0, 0, 100, 100), + SurfaceFormat::B8G8R8A8, 8, + false }); +} + +void +AssertConfiguringDeinterlacingFilterFails(const IntSize& aSize) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + AssertConfiguringPipelineFails(decoder, + DeinterlacingConfig { /* mProgressiveDisplay = */ true}, + SurfaceConfig { decoder, 0, aSize, + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageDeinterlacingFilter, WritePixels100_100) +{ + WithDeinterlacingFilter(IntSize(100, 100), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100))); + }); +} + +TEST(ImageDeinterlacingFilter, WriteRows100_100) +{ + WithDeinterlacingFilter(IntSize(100, 100), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100))); + }); +} + +TEST(ImageDeinterlacingFilter, WritePixels99_99) +{ + WithDeinterlacingFilter(IntSize(99, 99), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 99)), + /* aInputRect = */ Some(IntRect(0, 0, 99, 99))); + }); +} + +TEST(ImageDeinterlacingFilter, WriteRows99_99) +{ + WithDeinterlacingFilter(IntSize(99, 99), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 99)), + /* aInputRect = */ Some(IntRect(0, 0, 99, 99))); + }); +} + +TEST(ImageDeinterlacingFilter, WritePixels8_8) +{ + WithDeinterlacingFilter(IntSize(8, 8), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 8, 8)), + /* aInputRect = */ Some(IntRect(0, 0, 8, 8))); + }); +} + +TEST(ImageDeinterlacingFilter, WriteRows8_8) +{ + WithDeinterlacingFilter(IntSize(8, 8), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 8, 8)), + /* aInputRect = */ Some(IntRect(0, 0, 8, 8))); + }); +} + +TEST(ImageDeinterlacingFilter, WritePixels7_7) +{ + WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 7, 7)), + /* aInputRect = */ Some(IntRect(0, 0, 7, 7))); + }); +} + +TEST(ImageDeinterlacingFilter, WriteRows7_7) +{ + WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 7, 7)), + /* aInputRect = */ Some(IntRect(0, 0, 7, 7))); + }); +} + +TEST(ImageDeinterlacingFilter, WritePixels3_3) +{ + WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 3, 3)), + /* aInputRect = */ Some(IntRect(0, 0, 3, 3))); + }); +} + +TEST(ImageDeinterlacingFilter, WriteRows3_3) +{ + WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 3, 3)), + /* aInputRect = */ Some(IntRect(0, 0, 3, 3))); + }); +} + +TEST(ImageDeinterlacingFilter, WritePixels1_1) +{ + WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 1, 1)), + /* aInputRect = */ Some(IntRect(0, 0, 1, 1))); + }); +} + +TEST(ImageDeinterlacingFilter, WriteRows1_1) +{ + WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 1, 1)), + /* aInputRect = */ Some(IntRect(0, 0, 1, 1))); + }); +} + +TEST(ImageDeinterlacingFilter, PalettedWritePixels) +{ + WithPalettedDeinterlacingFilter(IntSize(100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckPalettedWritePixels(aDecoder, aFilter); + }); +} + +TEST(ImageDeinterlacingFilter, PalettedWriteRows) +{ + WithPalettedDeinterlacingFilter(IntSize(100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckPalettedWriteRows(aDecoder, aFilter); + }); +} + +TEST(ImageDeinterlacingFilter, WritePixelsOutput20_20) +{ + WithDeinterlacingFilter(IntSize(20, 20), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. The output should be green for even rows and red for odd + // rows but we need to write the rows in the order that the deinterlacer + // expects them. + uint32_t count = 0; + auto result = aFilter->WritePixels([&]() { + uint32_t row = count / 20; // Integer division. + ++count; + + switch (row) { + // First pass. Output rows are positioned at 8n + 0. + case 0: // Output row 0. + case 1: // Output row 8. + case 2: // Output row 16. + return AsVariant(BGRAColor::Green().AsPixel()); + + // Second pass. Rows are positioned at 8n + 4. + case 3: // Output row 4. + case 4: // Output row 12. + return AsVariant(BGRAColor::Green().AsPixel()); + + // Third pass. Rows are positioned at 4n + 2. + case 5: // Output row 2. + case 6: // Output row 6. + case 7: // Output row 10. + case 8: // Output row 14. + case 9: // Output row 18. + return AsVariant(BGRAColor::Green().AsPixel()); + + // Fourth pass. Rows are positioned at 2n + 1. + case 10: // Output row 1. + case 11: // Output row 3. + case 12: // Output row 5. + case 13: // Output row 7. + case 14: // Output row 9. + case 15: // Output row 11. + case 16: // Output row 13. + case 17: // Output row 15. + case 18: // Output row 17. + case 19: // Output row 19. + return AsVariant(BGRAColor::Red().AsPixel()); + + default: + MOZ_ASSERT_UNREACHABLE("Unexpected row"); + return AsVariant(BGRAColor::Transparent().AsPixel()); + } + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(20u * 20u, count); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 20, 20), + IntRect(0, 0, 20, 20)); + + // Check that the generated image is correct. As mentioned above, we expect + // even rows to be green and odd rows to be red. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + + for (uint32_t row = 0; row < 20; ++row) { + EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, + row % 2 == 0 ? BGRAColor::Green() + : BGRAColor::Red())); + } + }); +} + +TEST(ImageDeinterlacingFilter, WriteRowsOutput7_7) +{ + WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. The output should be a repeating pattern of two green + // rows followed by two red rows but we need to write the rows in the order + // that the deinterlacer expects them. + uint32_t count = 0; + uint32_t row = 0; + auto result = aFilter->WriteRows([&](uint32_t* aRow, uint32_t aLength) { + uint32_t color = 0; + switch (row) { + // First pass. Output rows are positioned at 8n + 0. + case 0: // Output row 0. + color = BGRAColor::Green().AsPixel(); + break; + + // Second pass. Rows are positioned at 8n + 4. + case 1: // Output row 4. + color = BGRAColor::Green().AsPixel(); + break; + + // Third pass. Rows are positioned at 4n + 2. + case 2: // Output row 2. + case 3: // Output row 6. + color = BGRAColor::Red().AsPixel(); + break; + + // Fourth pass. Rows are positioned at 2n + 1. + case 4: // Output row 1. + color = BGRAColor::Green().AsPixel(); + break; + + case 5: // Output row 3. + color = BGRAColor::Red().AsPixel(); + break; + + case 6: // Output row 5. + color = BGRAColor::Green().AsPixel(); + break; + + default: + MOZ_ASSERT_UNREACHABLE("Unexpected row"); + } + + ++row; + + for (; aLength > 0; --aLength, ++aRow, ++count) { + *aRow = color; + } + + return Nothing(); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(7u * 7u, count); + EXPECT_EQ(7u, row); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 7, 7), + IntRect(0, 0, 7, 7)); + + // Check that the generated image is correct. As mentioned above, we expect + // two green rows, followed by two red rows, then two green rows, etc. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + + for (uint32_t row = 0; row < 7; ++row) { + BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 + ? BGRAColor::Green() + : BGRAColor::Red(); + EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); + } + }); +} + +TEST(ImageDeinterlacingFilter, WritePixelsOutput3_3) +{ + WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. The output should be green, red, green in that order, but + // we need to write the rows in the order that the deinterlacer expects + // them. + uint32_t count = 0; + auto result = aFilter->WritePixels([&]() { + uint32_t row = count / 3; // Integer division. + ++count; + + switch (row) { + // First pass. Output rows are positioned at 8n + 0. + case 0: // Output row 0. + return AsVariant(BGRAColor::Green().AsPixel()); + + // Second pass. Rows are positioned at 8n + 4. + // No rows for this pass. + + // Third pass. Rows are positioned at 4n + 2. + case 1: // Output row 2. + return AsVariant(BGRAColor::Green().AsPixel()); + + // Fourth pass. Rows are positioned at 2n + 1. + case 2: // Output row 1. + return AsVariant(BGRAColor::Red().AsPixel()); + + default: + MOZ_ASSERT_UNREACHABLE("Unexpected row"); + return AsVariant(BGRAColor::Transparent().AsPixel()); + } + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(3u * 3u, count); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 3, 3), + IntRect(0, 0, 3, 3)); + + // Check that the generated image is correct. As mentioned above, we expect + // green, red, green in that order. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + + for (uint32_t row = 0; row < 3; ++row) { + EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, + row == 0 || row == 2 ? BGRAColor::Green() + : BGRAColor::Red())); + } + }); +} + +TEST(ImageDeinterlacingFilter, WritePixelsOutput1_1) +{ + WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. The output should be a single red row. + uint32_t count = 0; + auto result = aFilter->WritePixels([&]() { + ++count; + return AsVariant(BGRAColor::Red().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(1u, count); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 1, 1), + IntRect(0, 0, 1, 1)); + + // Check that the generated image is correct. As mentioned above, we expect + // a single red row. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + + EXPECT_TRUE(RowsAreSolidColor(surface, 0, 1, BGRAColor::Red())); + }); +} + +void +WriteRowAndCheckInterlacerOutput(Decoder* aDecoder, + SurfaceFilter* aFilter, + BGRAColor aColor, + WriteState aNextState, + IntRect aInvalidRect, + uint32_t aFirstHaeberliRow, + uint32_t aLastHaeberliRow) +{ + uint32_t count = 0; + + auto result = aFilter->WriteRows([&](uint32_t* aRow, uint32_t aLength) { + for (; aLength > 0; --aLength, ++aRow, ++count) { + *aRow = aColor.AsPixel(); + } + return Some(WriteState::NEED_MORE_DATA); + }); + + EXPECT_EQ(aNextState, result); + EXPECT_EQ(7u, count); + + // Assert that we got the expected invalidation region. + Maybe invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(aInvalidRect, invalidRect->mInputSpaceRect); + EXPECT_EQ(aInvalidRect, invalidRect->mOutputSpaceRect); + + // Check that the portion of the image generated so far is correct. The rows + // from aFirstHaeberliRow to aLastHaeberliRow should be filled with aColor. + // Note that this is not the same as the set of rows in aInvalidRect, because + // after writing a row the deinterlacer seeks to the next row to write, which + // may involve copying previously-written rows in the buffer to the output + // even though they don't change in this pass. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + + for (uint32_t row = aFirstHaeberliRow; row <= aLastHaeberliRow; ++row) { + EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, aColor)); + } +} + +TEST(ImageDeinterlacingFilter, WriteRowsIntermediateOutput7_7) +{ + WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. The output should be a repeating pattern of two green + // rows followed by two red rows but we need to write the rows in the order + // that the deinterlacer expects them. + + // First pass. Output rows are positioned at 8n + 0. + + // Output row 0. The invalid rect is the entire image because this is the + // end of the first pass. + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::NEED_MORE_DATA, + IntRect(0, 0, 7, 7), 0, 4); + + // Second pass. Rows are positioned at 8n + 4. + + // Output row 4. The invalid rect is the entire image because this is the + // end of the second pass. + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::NEED_MORE_DATA, + IntRect(0, 0, 7, 7), 1, 4); + + // Third pass. Rows are positioned at 4n + 2. + + // Output row 2. The invalid rect contains the Haeberli rows for this output + // row (rows 2 and 3) as well as the rows that we copy from previous passes + // when seeking to the next output row (rows 4 and 5). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), + WriteState::NEED_MORE_DATA, + IntRect(0, 2, 7, 4), 2, 3); + + // Output row 6. The invalid rect is the entire image because this is the + // end of the third pass. + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), + WriteState::NEED_MORE_DATA, + IntRect(0, 0, 7, 7), 6, 6); + + // Fourth pass. Rows are positioned at 2n + 1. + + // Output row 1. The invalid rect contains the Haeberli rows for this output + // row (just row 1) as well as the rows that we copy from previous passes + // when seeking to the next output row (row 2). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::NEED_MORE_DATA, + IntRect(0, 1, 7, 2), 1, 1); + + // Output row 3. The invalid rect contains the Haeberli rows for this output + // row (just row 3) as well as the rows that we copy from previous passes + // when seeking to the next output row (row 4). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), + WriteState::NEED_MORE_DATA, + IntRect(0, 3, 7, 2), 3, 3); + + // Output row 5. The invalid rect contains the Haeberli rows for this output + // row (just row 5) as well as the rows that we copy from previous passes + // when seeking to the next output row (row 6). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::FINISHED, + IntRect(0, 5, 7, 2), 5, 5); + + // Assert that we're in the expected final state. + EXPECT_TRUE(aFilter->IsSurfaceFinished()); + Maybe invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Check that the generated image is correct. As mentioned above, we expect + // two green rows, followed by two red rows, then two green rows, etc. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + + for (uint32_t row = 0; row < 7; ++row) { + BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 + ? BGRAColor::Green() + : BGRAColor::Red(); + EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); + } + }); +} + +TEST(ImageDeinterlacingFilter, WriteRowsNonProgressiveIntermediateOutput7_7) +{ + WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ false, + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. The output should be a repeating pattern of two green + // rows followed by two red rows but we need to write the rows in the order + // that the deinterlacer expects them. + + // First pass. Output rows are positioned at 8n + 0. + + // Output row 0. The invalid rect is the entire image because this is the + // end of the first pass. + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::NEED_MORE_DATA, + IntRect(0, 0, 7, 7), 0, 0); + + // Second pass. Rows are positioned at 8n + 4. + + // Output row 4. The invalid rect is the entire image because this is the + // end of the second pass. + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::NEED_MORE_DATA, + IntRect(0, 0, 7, 7), 4, 4); + + // Third pass. Rows are positioned at 4n + 2. + + // Output row 2. The invalid rect contains the Haeberli rows for this output + // row (rows 2 and 3) as well as the rows that we copy from previous passes + // when seeking to the next output row (rows 4 and 5). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), + WriteState::NEED_MORE_DATA, + IntRect(0, 2, 7, 4), 2, 2); + + // Output row 6. The invalid rect is the entire image because this is the + // end of the third pass. + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), + WriteState::NEED_MORE_DATA, + IntRect(0, 0, 7, 7), 6, 6); + + // Fourth pass. Rows are positioned at 2n + 1. + + // Output row 1. The invalid rect contains the Haeberli rows for this output + // row (just row 1) as well as the rows that we copy from previous passes + // when seeking to the next output row (row 2). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::NEED_MORE_DATA, + IntRect(0, 1, 7, 2), 1, 1); + + // Output row 3. The invalid rect contains the Haeberli rows for this output + // row (just row 3) as well as the rows that we copy from previous passes + // when seeking to the next output row (row 4). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), + WriteState::NEED_MORE_DATA, + IntRect(0, 3, 7, 2), 3, 3); + + // Output row 5. The invalid rect contains the Haeberli rows for this output + // row (just row 5) as well as the rows that we copy from previous passes + // when seeking to the next output row (row 6). + WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), + WriteState::FINISHED, + IntRect(0, 5, 7, 2), 5, 5); + + // Assert that we're in the expected final state. + EXPECT_TRUE(aFilter->IsSurfaceFinished()); + Maybe invalidRect = aFilter->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Check that the generated image is correct. As mentioned above, we expect + // two green rows, followed by two red rows, then two green rows, etc. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + + for (uint32_t row = 0; row < 7; ++row) { + BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 + ? BGRAColor::Green() + : BGRAColor::Red(); + EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); + } + }); +} + + +TEST(ImageDeinterlacingFilter, DeinterlacingFailsFor0_0) +{ + // A 0x0 input size is invalid, so configuration should fail. + AssertConfiguringDeinterlacingFilterFails(IntSize(0, 0)); +} + +TEST(ImageDeinterlacingFilter, DeinterlacingFailsForMinus1_Minus1) +{ + // A negative input size is invalid, so configuration should fail. + AssertConfiguringDeinterlacingFilterFails(IntSize(-1, -1)); +} diff --git a/image/test/gtest/TestDownscalingFilter.cpp b/image/test/gtest/TestDownscalingFilter.cpp new file mode 100644 index 0000000000..9ede21c3f6 --- /dev/null +++ b/image/test/gtest/TestDownscalingFilter.cpp @@ -0,0 +1,364 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "gtest/gtest.h" + +#include "mozilla/gfx/2D.h" +#include "Common.h" +#include "Decoder.h" +#include "DecoderFactory.h" +#include "SourceBuffer.h" +#include "SurfaceFilters.h" +#include "SurfacePipe.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::image; + +template void +WithDownscalingFilter(const IntSize& aInputSize, + const IntSize& aOutputSize, + Func aFunc) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + WithFilterPipeline(decoder, Forward(aFunc), + DownscalingConfig { aInputSize, + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, aOutputSize, + SurfaceFormat::B8G8R8A8, false }); +} + +void +AssertConfiguringDownscalingFilterFails(const IntSize& aInputSize, + const IntSize& aOutputSize) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + AssertConfiguringPipelineFails(decoder, + DownscalingConfig { aInputSize, + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, aOutputSize, + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageDownscalingFilter, WritePixels100_100to99_99) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(99, 99), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 99))); + }); +} + +TEST(ImageDownscalingFilter, WriteRows100_100to99_99) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(99, 99), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 99))); + }); +} + +TEST(ImageDownscalingFilter, WritePixels100_100to33_33) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(33, 33), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 33, 33))); + }); +} + +TEST(ImageDownscalingFilter, WriteRows100_100to33_33) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(33, 33), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 33, 33))); + }); +} + +TEST(ImageDownscalingFilter, WritePixels100_100to1_1) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(1, 1), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 1, 1))); + }); +} + +TEST(ImageDownscalingFilter, WriteRows100_100to1_1) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(1, 1), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 1, 1))); + }); +} + +TEST(ImageDownscalingFilter, WritePixels100_100to33_99) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(33, 99), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 33, 99))); + }); +} + +TEST(ImageDownscalingFilter, WriteRows100_100to33_99) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(33, 99), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 33, 99))); + }); +} + +TEST(ImageDownscalingFilter, WritePixels100_100to99_33) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(99, 33), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 33))); + }); +} + +TEST(ImageDownscalingFilter, WriteRows100_100to99_33) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(99, 33), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 33))); + }); +} + +TEST(ImageDownscalingFilter, WritePixels100_100to99_1) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(99, 1), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 1))); + }); +} + +TEST(ImageDownscalingFilter, WriteRows100_100to99_1) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(99, 1), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 99, 1))); + }); +} + +TEST(ImageDownscalingFilter, WritePixels100_100to1_99) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(1, 99), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 1, 99))); + }); +} + +TEST(ImageDownscalingFilter, WriteRows100_100to1_99) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(1, 99), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 1, 99))); + }); +} + +TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to101_101) +{ + // Upscaling is disallowed. + AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(101, 101)); +} + +TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to100_100) +{ + // "Scaling" to the same size is disallowed. + AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(100, 100)); +} + +TEST(ImageDownscalingFilter, DownscalingFailsFor0_0toMinus1_Minus1) +{ + // A 0x0 input size is disallowed. + AssertConfiguringDownscalingFilterFails(IntSize(0, 0), IntSize(-1, -1)); +} + +TEST(ImageDownscalingFilter, DownscalingFailsForMinus1_Minus1toMinus2_Minus2) +{ + // A negative input size is disallowed. + AssertConfiguringDownscalingFilterFails(IntSize(-1, -1), IntSize(-2, -2)); +} + +TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to0_0) +{ + // A 0x0 output size is disallowed. + AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(0, 0)); +} + +TEST(ImageDownscalingFilter, DownscalingFailsFor100_100toMinus1_Minus1) +{ + // A negative output size is disallowed. + AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(-1, -1)); +} + +TEST(ImageDownscalingFilter, WritePixelsOutput100_100to20_20) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(20, 20), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. It consists of 25 lines of green, followed by 25 lines of + // red, followed by 25 lines of green, followed by 25 more lines of red. + uint32_t count = 0; + auto result = aFilter->WritePixels([&]() -> NextPixel { + uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) + ? BGRAColor::Green().AsPixel() + : BGRAColor::Red().AsPixel(); + ++count; + return AsVariant(color); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 100u, count); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 100, 100), + IntRect(0, 0, 20, 20)); + + // Check that the generated image is correct. Note that we skip rows near + // the transitions between colors, since the downscaler does not produce a + // sharp boundary at these points. Even some of the rows we test need a + // small amount of fuzz; this is just the nature of Lanczos downscaling. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2)); + EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3)); + }); +} + +TEST(ImageDownscalingFilter, WriteRowsOutput100_100to20_20) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(20, 20), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. It consists of 25 lines of green, followed by 25 lines of + // red, followed by 25 lines of green, followed by 25 more lines of red. + uint32_t count = 0; + auto result = aFilter->WriteRows([&](uint32_t* aRow, uint32_t aLength) { + uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) + ? BGRAColor::Green().AsPixel() + : BGRAColor::Red().AsPixel(); + for (; aLength > 0; --aLength, ++aRow, ++count) { + *aRow = color; + } + return Nothing(); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 100u, count); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 100, 100), + IntRect(0, 0, 20, 20)); + + // Check that the generated image is correct. (Note that we skip rows near + // the transitions between colors, since the downscaler does not produce a + // sharp boundary at these points.) + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2)); + EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3)); + }); +} + +TEST(ImageDownscalingFilter, WritePixelsOutput100_100to10_20) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(10, 20), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. It consists of 25 lines of green, followed by 25 lines of + // red, followed by 25 lines of green, followed by 25 more lines of red. + uint32_t count = 0; + auto result = aFilter->WritePixels([&]() -> NextPixel { + uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) + ? BGRAColor::Green().AsPixel() + : BGRAColor::Red().AsPixel(); + ++count; + return AsVariant(color); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 100u, count); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 100, 100), + IntRect(0, 0, 10, 20)); + + // Check that the generated image is correct. Note that we skip rows near + // the transitions between colors, since the downscaler does not produce a + // sharp boundary at these points. Even some of the rows we test need a + // small amount of fuzz; this is just the nature of Lanczos downscaling. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2)); + EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3)); + }); +} + +TEST(ImageDownscalingFilter, WriteRowsOutput100_100to10_20) +{ + WithDownscalingFilter(IntSize(100, 100), IntSize(10, 20), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Fill the image. It consists of 25 lines of green, followed by 25 lines of + // red, followed by 25 lines of green, followed by 25 more lines of red. + uint32_t count = 0; + auto result = aFilter->WriteRows([&](uint32_t* aRow, uint32_t aLength) { + uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) + ? BGRAColor::Green().AsPixel() + : BGRAColor::Red().AsPixel(); + for (; aLength > 0; --aLength, ++aRow, ++count) { + *aRow = color; + } + return Nothing(); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 100u, count); + + AssertCorrectPipelineFinalState(aFilter, + IntRect(0, 0, 100, 100), + IntRect(0, 0, 10, 20)); + + // Check that the generated image is correct. (Note that we skip rows near + // the transitions between colors, since the downscaler does not produce a + // sharp boundary at these points.) + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2)); + EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3)); + EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3)); + }); +} + +TEST(ImageDownscalingFilter, ConfiguringPalettedDownscaleFails) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // DownscalingFilter does not support paletted images, so configuration should + // fail. + AssertConfiguringPipelineFails(decoder, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + PalettedSurfaceConfig { decoder, 0, IntSize(20, 20), + IntRect(0, 0, 20, 20), + SurfaceFormat::B8G8R8A8, 8, + false }); +} diff --git a/image/test/gtest/TestDownscalingFilterNoSkia.cpp b/image/test/gtest/TestDownscalingFilterNoSkia.cpp new file mode 100644 index 0000000000..c62ca018da --- /dev/null +++ b/image/test/gtest/TestDownscalingFilterNoSkia.cpp @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "gtest/gtest.h" + +#include "mozilla/gfx/2D.h" +#include "Decoder.h" +#include "DecoderFactory.h" +#include "SourceBuffer.h" +#include "SurfacePipe.h" + +// We want to ensure that we're testing the non-Skia fallback version of +// DownscalingFilter, but there are two issues: +// (1) We don't know whether Skia is currently enabled. +// (2) If we force disable it, the disabled version will get linked into the +// binary and will cause the tests in TestDownscalingFilter to fail. +// To avoid these problems, we ensure that MOZ_ENABLE_SKIA is defined when +// including DownscalingFilter.h, and we use the preprocessor to redefine the +// DownscalingFilter class to DownscalingFilterNoSkia. + +#define DownscalingFilter DownscalingFilterNoSkia + +#ifdef MOZ_ENABLE_SKIA + +#undef MOZ_ENABLE_SKIA +#include "Common.h" +#include "DownscalingFilter.h" +#define MOZ_ENABLE_SKIA + +#else + +#include "Common.h" +#include "DownscalingFilter.h" + +#endif + +#undef DownscalingFilter + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::image; + +TEST(ImageDownscalingFilter, NoSkia) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(bool(decoder)); + + // Configuring a DownscalingFilter should fail without Skia. + AssertConfiguringPipelineFails(decoder, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(50, 50), + SurfaceFormat::B8G8R8A8, false }); +} diff --git a/image/test/gtest/TestRemoveFrameRectFilter.cpp b/image/test/gtest/TestRemoveFrameRectFilter.cpp new file mode 100644 index 0000000000..d1b7afa84c --- /dev/null +++ b/image/test/gtest/TestRemoveFrameRectFilter.cpp @@ -0,0 +1,565 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "gtest/gtest.h" + +#include "mozilla/gfx/2D.h" +#include "Common.h" +#include "Decoder.h" +#include "DecoderFactory.h" +#include "SourceBuffer.h" +#include "SurfaceFilters.h" +#include "SurfacePipe.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::image; + +template void +WithRemoveFrameRectFilter(const IntSize& aSize, + const IntRect& aFrameRect, + Func aFunc) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + WithFilterPipeline(decoder, Forward(aFunc), + RemoveFrameRectConfig { aFrameRect }, + SurfaceConfig { decoder, 0, aSize, + SurfaceFormat::B8G8R8A8, false }); +} + +void +AssertConfiguringRemoveFrameRectFilterFails(const IntSize& aSize, + const IntRect& aFrameRect) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + AssertConfiguringPipelineFails(decoder, + RemoveFrameRectConfig { aFrameRect }, + SurfaceConfig { decoder, 0, aSize, + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_0_0_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(0, 0, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_0_0_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(0, 0, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_0_0_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(0, 0, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_0_0_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(0, 0, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_50_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-50, 50, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus50_50_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-50, 50, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_Minus50_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(50, -50, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_50_Minus50_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(50, -50, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_150_50_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(150, 50, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_150_50_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(150, 50, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_150_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(50, 150, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_50_150_0_0) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(50, 150, 0, 0), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_200_200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(200, 200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_200_200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(200, 200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus200_25_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-200, 25, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus200_25_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-200, 25, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_Minus200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, -200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_Minus200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, -200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_200_25_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(200, 25, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_200_25_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(200, 25, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, 200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, 200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is zero-size because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus200_Minus200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-200, -200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus200_Minus200_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-200, -200, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_Minus50_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-50, -50, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus50_Minus50_100_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-50, -50, 100, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)), + /* aOutputWriteRect = */ Some(IntRect(0, 0, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_25_100_50) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-50, 25, 100, 50), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)), + /* aOutputWriteRect = */ Some(IntRect(0, 25, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus50_25_100_50) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(-50, 25, 100, 50), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)), + /* aOutputWriteRect = */ Some(IntRect(0, 25, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_Minus50_50_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, -50, 50, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 50, 100)), + /* aOutputWriteRect = */ Some(IntRect(25, 0, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_Minus50_50_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, -50, 50, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 50, 100)), + /* aOutputWriteRect = */ Some(IntRect(25, 0, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_25_100_50) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(50, 25, 100, 50), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)), + /* aOutputWriteRect = */ Some(IntRect(50, 25, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_50_25_100_50) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(50, 25, 100, 50), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)), + /* aOutputWriteRect = */ Some(IntRect(50, 25, 50, 50))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_50_50_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, 50, 50, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is 50x50 because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(25, 50, 50, 100))); + }); +} + +TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_50_50_100) +{ + WithRemoveFrameRectFilter(IntSize(100, 100), + IntRect(25, 50, 50, 100), + [](Decoder* aDecoder, SurfaceFilter* aFilter) { + // Note that aInputRect is 50x50 because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows + // unfortunately can't be ignored.) + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(0, 0, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(25, 50, 50, 100))); + }); +} + +TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor0_0_to_0_0_100_100) +{ + // A zero-size image is disallowed. + AssertConfiguringRemoveFrameRectFilterFails(IntSize(0, 0), + IntRect(0, 0, 100, 100)); +} + +TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsForMinus1_Minus1_to_0_0_100_100) +{ + // A negative-size image is disallowed. + AssertConfiguringRemoveFrameRectFilterFails(IntSize(-1, -1), + IntRect(0, 0, 100, 100)); +} + +TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor100_100_to_0_0_0_0) +{ + // A zero size frame rect is disallowed. + AssertConfiguringRemoveFrameRectFilterFails(IntSize(100, 100), + IntRect(0, 0, -1, -1)); +} + +TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor100_100_to_0_0_Minus1_Minus1) +{ + // A negative size frame rect is disallowed. + AssertConfiguringRemoveFrameRectFilterFails(IntSize(100, 100), + IntRect(0, 0, -1, -1)); +} + +TEST(ImageRemoveFrameRectFilter, ConfiguringPalettedRemoveFrameRectFails) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // RemoveFrameRectFilter does not support paletted images, so configuration + // should fail. + AssertConfiguringPipelineFails(decoder, + RemoveFrameRectConfig { IntRect(0, 0, 50, 50) }, + PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + IntRect(0, 0, 50, 50), + SurfaceFormat::B8G8R8A8, 8, + false }); +} diff --git a/image/test/gtest/TestSurfacePipeIntegration.cpp b/image/test/gtest/TestSurfacePipeIntegration.cpp new file mode 100644 index 0000000000..d992005e95 --- /dev/null +++ b/image/test/gtest/TestSurfacePipeIntegration.cpp @@ -0,0 +1,322 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "gtest/gtest.h" + +#include "mozilla/gfx/2D.h" +#include "Common.h" +#include "Decoder.h" +#include "DecoderFactory.h" +#include "SourceBuffer.h" +#include "SurfacePipe.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::image; + +namespace mozilla { +namespace image { + +class TestSurfacePipeFactory +{ +public: + static SurfacePipe SimpleSurfacePipe() + { + SurfacePipe pipe; + return Move(pipe); + } + + template + static SurfacePipe SurfacePipeFromPipeline(T&& aPipeline) + { + return SurfacePipe { Move(aPipeline) }; + } + +private: + TestSurfacePipeFactory() { } +}; + +} // namespace image +} // namespace mozilla + +TEST(ImageSurfacePipeIntegration, SurfacePipe) +{ + // Test that SurfacePipe objects can be initialized and move constructed. + SurfacePipe pipe = TestSurfacePipeFactory::SimpleSurfacePipe(); + + // Test that SurfacePipe objects can be move assigned. + pipe = TestSurfacePipeFactory::SimpleSurfacePipe(); + + // Test that SurfacePipe objects can be initialized with a pipeline. + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + auto sink = MakeUnique(); + nsresult rv = + sink->Configure(SurfaceConfig { decoder.get(), 0, IntSize(100, 100), + SurfaceFormat::B8G8R8A8, false }); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + pipe = TestSurfacePipeFactory::SurfacePipeFromPipeline(sink); + + // Test that SurfacePipe passes through method calls to the underlying pipeline. + int32_t count = 0; + auto result = pipe.WritePixels([&]() { + ++count; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100 * 100, count); + + // Note that we're explicitly testing the SurfacePipe versions of these + // methods, so we don't want to use AssertCorrectPipelineFinalState() here. + EXPECT_TRUE(pipe.IsSurfaceFinished()); + Maybe invalidRect = pipe.TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect); + EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect); + + CheckGeneratedImage(decoder, IntRect(0, 0, 100, 100)); + + pipe.ResetToFirstRow(); + EXPECT_FALSE(pipe.IsSurfaceFinished()); + + RawAccessFrameRef currentFrame = decoder->GetCurrentFrameRef(); + currentFrame->Finish(); +} + +TEST(ImageSurfacePipeIntegration, DeinterlaceDownscaleWritePixels) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 25, 25))); + }; + + WithFilterPipeline(decoder, test, + DeinterlacingConfig { /* mProgressiveDisplay = */ true }, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(25, 25), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, DeinterlaceDownscaleWriteRows) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 25, 25))); + }; + + WithFilterPipeline(decoder, test, + DeinterlacingConfig { /* mProgressiveDisplay = */ true }, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(25, 25), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWritePixels) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // Note that aInputWriteRect is 100x50 because RemoveFrameRectFilter ignores + // trailing rows that don't show up in the output. (Leading rows unfortunately + // can't be ignored.) So the action of the pipeline is as follows: + // + // (1) RemoveFrameRectFilter reads a 100x50 region of the input. + // (aInputWriteRect captures this fact.) The remaining 50 rows are ignored + // because they extend off the bottom of the image due to the frame rect's + // (50, 50) offset. The 50 columns on the right also don't end up in the + // output, so ultimately only a 50x50 region in the output contains data + // from the input. The filter's output is not 50x50, though, but 100x100, + // because what RemoveFrameRectFilter does is introduce blank rows or + // columns as necessary to transform an image that needs a frame rect into + // an image that doesn't. + // + // (2) DownscalingFilter reads the output of RemoveFrameRectFilter (100x100) + // and downscales it to 20x20. + // + // (3) The surface owned by SurfaceSink logically has only a 10x10 region + // region in it that's non-blank; this is the downscaled version of the + // 50x50 region discussed in (1). (aOutputWriteRect captures this fact.) + // Some fuzz, as usual, is necessary when dealing with Lanczos downscaling. + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 20, 20)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 50)), + /* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)), + /* aFuzz = */ 0x33); + }; + + WithFilterPipeline(decoder, test, + RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(20, 20), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWriteRows) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // See the WritePixels version of this test for a discussion of where the + // numbers below come from. + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 20, 20)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 50)), + /* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)), + /* aFuzz = */ 0x33); + }; + + WithFilterPipeline(decoder, test, + RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(20, 20), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // Note that aInputRect is the full 100x100 size even though + // RemoveFrameRectFilter is part of this pipeline, because deinterlacing + // requires reading every row. + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)), + /* aOutputWriteRect = */ Some(IntRect(50, 50, 50, 50))); + }; + + WithFilterPipeline(decoder, test, + DeinterlacingConfig { /* mProgressiveDisplay = */ true }, + RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, + SurfaceConfig { decoder, 0, IntSize(100, 100), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWriteRows) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // Note that aInputRect is the full 100x100 size even though + // RemoveFrameRectFilter is part of this pipeline, because deinterlacing + // requires reading every row. + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)), + /* aOutputWriteRect = */ Some(IntRect(50, 50, 50, 50))); + }; + + WithFilterPipeline(decoder, test, + DeinterlacingConfig { /* mProgressiveDisplay = */ true }, + RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, + SurfaceConfig { decoder, 0, IntSize(100, 100), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWritePixels) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWritePixels(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 20, 20)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)), + /* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)), + /* aFuzz = */ 33); + }; + + WithFilterPipeline(decoder, test, + DeinterlacingConfig { /* mProgressiveDisplay = */ true }, + RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(20, 20), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWriteRows) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) { + CheckWriteRows(aDecoder, aFilter, + /* aOutputRect = */ Some(IntRect(0, 0, 20, 20)), + /* aInputRect = */ Some(IntRect(0, 0, 100, 100)), + /* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)), + /* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)), + /* aFuzz = */ 33); + }; + + WithFilterPipeline(decoder, test, + DeinterlacingConfig { /* mProgressiveDisplay = */ true }, + RemoveFrameRectConfig { IntRect(50, 50, 100, 100) }, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(20, 20), + SurfaceFormat::B8G8R8A8, false }); +} + +TEST(ImageSurfacePipeIntegration, ConfiguringPalettedRemoveFrameRectDownscaleFails) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // This is an invalid pipeline for paletted images, so configuration should + // fail. + AssertConfiguringPipelineFails(decoder, + RemoveFrameRectConfig { IntRect(0, 0, 50, 50) }, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + IntRect(0, 0, 50, 50), + SurfaceFormat::B8G8R8A8, 8, + false }); +} + +TEST(ImageSurfacePipeIntegration, ConfiguringPalettedDeinterlaceDownscaleFails) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // This is an invalid pipeline for paletted images, so configuration should + // fail. + AssertConfiguringPipelineFails(decoder, + DeinterlacingConfig { /* mProgressiveDisplay = */ true}, + DownscalingConfig { IntSize(100, 100), + SurfaceFormat::B8G8R8A8 }, + PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + IntRect(0, 0, 20, 20), + SurfaceFormat::B8G8R8A8, 8, + false }); +} diff --git a/image/test/gtest/TestSurfaceSink.cpp b/image/test/gtest/TestSurfaceSink.cpp new file mode 100644 index 0000000000..6d3e5750b8 --- /dev/null +++ b/image/test/gtest/TestSurfaceSink.cpp @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "gtest/gtest.h" + +#include "mozilla/gfx/2D.h" +#include "Common.h" +#include "Decoder.h" +#include "DecoderFactory.h" +#include "SourceBuffer.h" +#include "SurfacePipe.h" + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace mozilla::image; + +enum class Orient +{ + NORMAL, + FLIP_VERTICALLY +}; + +template void +WithSurfaceSink(Func aFunc) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + const bool flipVertically = Orientation == Orient::FLIP_VERTICALLY; + + WithFilterPipeline(decoder, Forward(aFunc), + SurfaceConfig { decoder, 0, IntSize(100, 100), + SurfaceFormat::B8G8R8A8, flipVertically }); +} + +template void +WithPalettedSurfaceSink(const IntRect& aFrameRect, Func aFunc) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + WithFilterPipeline(decoder, Forward(aFunc), + PalettedSurfaceConfig { decoder, 0, IntSize(100, 100), + aFrameRect, SurfaceFormat::B8G8R8A8, + 8, false }); +} + +TEST(ImageSurfaceSink, NullSurfaceSink) +{ + // Create the NullSurfaceSink. + NullSurfaceSink sink; + nsresult rv = sink.Configure(NullSurfaceConfig { }); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + EXPECT_TRUE(!sink.IsValidPalettedPipe()); + + // Ensure that we can't write anything. + bool gotCalled = false; + auto result = sink.WritePixels([&]() { + gotCalled = true; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_FALSE(gotCalled); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_TRUE(sink.IsSurfaceFinished()); + Maybe invalidRect = sink.TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + result = sink.WriteRows([&](uint32_t* aRow, uint32_t aLength) { + gotCalled = true; + for (; aLength > 0; --aLength, ++aRow) { + *aRow = BGRAColor::Green().AsPixel(); + } + return Nothing(); + }); + EXPECT_FALSE(gotCalled); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_TRUE(sink.IsSurfaceFinished()); + invalidRect = sink.TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Attempt to advance to the next row and make sure nothing changes. + sink.AdvanceRow(); + EXPECT_TRUE(sink.IsSurfaceFinished()); + invalidRect = sink.TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Attempt to advance to the next pass and make sure nothing changes. + sink.ResetToFirstRow(); + EXPECT_TRUE(sink.IsSurfaceFinished()); + invalidRect = sink.TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); +} + +TEST(ImageSurfaceSink, SurfaceSinkWritePixels) +{ + WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { + CheckWritePixels(aDecoder, aSink); + }); +} + +TEST(ImageSurfaceSink, SurfaceSinkWriteRows) +{ + WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { + CheckWriteRows(aDecoder, aSink); + }); +} + +TEST(ImageSurfaceSink, SurfaceSinkWritePixelsFinish) +{ + WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { + // Write nothing into the surface; just finish immediately. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() { + count++; + return AsVariant(WriteState::FINISHED); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(1u, count); + EXPECT_TRUE(aSink->IsSurfaceFinished()); + + // Attempt to write more and make sure that nothing gets written. + count = 0; + result = aSink->WritePixels([&]() { + count++; + return AsVariant(BGRAColor::Red().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(0u, count); + EXPECT_TRUE(aSink->IsSurfaceFinished()); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Transparent())); + }); +} + +TEST(ImageSurfaceSink, SurfaceSinkWriteRowsFinish) +{ + WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { + // Write nothing into the surface; just finish immediately. + uint32_t count = 0; + auto result = aSink->WriteRows([&](uint32_t* aRow, uint32_t aLength) { + count++; + return Some(WriteState::FINISHED); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(1u, count); + EXPECT_TRUE(aSink->IsSurfaceFinished()); + + // Attempt to write more and make sure that nothing gets written. + count = 0; + result = aSink->WriteRows([&](uint32_t* aRow, uint32_t aLength) { + count++; + for (; aLength > 0; --aLength, ++aRow) { + *aRow = BGRAColor::Green().AsPixel(); + } + return Nothing(); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(0u, count); + EXPECT_TRUE(aSink->IsSurfaceFinished()); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Transparent())); + }); +} + +TEST(ImageSurfaceSink, SurfaceSinkProgressivePasses) +{ + WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { + { + // Fill the image with a first pass of red. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() { + ++count; + return AsVariant(BGRAColor::Red().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 100u, count); + + AssertCorrectPipelineFinalState(aSink, + IntRect(0, 0, 100, 100), + IntRect(0, 0, 100, 100)); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); + } + + { + // Reset for the second pass. + aSink->ResetToFirstRow(); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Check that the generated image is still the first pass image. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); + } + + { + // Fill the image with a second pass of green. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() { + ++count; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 100u, count); + + AssertCorrectPipelineFinalState(aSink, + IntRect(0, 0, 100, 100), + IntRect(0, 0, 100, 100)); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green())); + } + }); +} + +TEST(ImageSurfaceSink, SurfaceSinkInvalidRect) +{ + WithSurfaceSink([](Decoder* aDecoder, SurfaceSink* aSink) { + { + // Write one row. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() -> NextPixel { + if (count == 100) { + return AsVariant(WriteState::NEED_MORE_DATA); + } + count++; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::NEED_MORE_DATA, result); + EXPECT_EQ(100u, count); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + + // Assert that we have the right invalid rect. + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mInputSpaceRect); + EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mOutputSpaceRect); + } + + { + // Write eight rows. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() -> NextPixel { + if (count == 100 * 8) { + return AsVariant(WriteState::NEED_MORE_DATA); + } + count++; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::NEED_MORE_DATA, result); + EXPECT_EQ(100u * 8u, count); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + + // Assert that we have the right invalid rect. + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mInputSpaceRect); + EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mOutputSpaceRect); + } + + { + // Write the left half of one row. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() -> NextPixel { + if (count == 50) { + return AsVariant(WriteState::NEED_MORE_DATA); + } + count++; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::NEED_MORE_DATA, result); + EXPECT_EQ(50u, count); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + + // Assert that we don't have an invalid rect, since the invalid rect only + // gets updated when a row gets completed. + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + } + + { + // Write the right half of the same row. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() -> NextPixel { + if (count == 50) { + return AsVariant(WriteState::NEED_MORE_DATA); + } + count++; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::NEED_MORE_DATA, result); + EXPECT_EQ(50u, count); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + + // Assert that we have the right invalid rect, which will include both the + // left and right halves of this row now that we've completed it. + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mInputSpaceRect); + EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mOutputSpaceRect); + } + + { + // Write no rows. + auto result = aSink->WritePixels([&]() { + return AsVariant(WriteState::NEED_MORE_DATA); + }); + EXPECT_EQ(WriteState::NEED_MORE_DATA, result); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + + // Assert that we don't have an invalid rect. + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + } + + { + // Fill the rest of the image. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() { + count++; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 90u, count); + EXPECT_TRUE(aSink->IsSurfaceFinished()); + + // Assert that we have the right invalid rect. + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mInputSpaceRect); + EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mOutputSpaceRect); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green())); + } + }); +} + +TEST(ImageSurfaceSink, SurfaceSinkFlipVertically) +{ + WithSurfaceSink([](Decoder* aDecoder, + SurfaceSink* aSink) { + { + // Fill the image with a first pass of red. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() { + ++count; + return AsVariant(BGRAColor::Red().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(100u * 100u, count); + + AssertCorrectPipelineFinalState(aSink, + IntRect(0, 0, 100, 100), + IntRect(0, 0, 100, 100)); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); + } + + { + // Reset for the second pass. + aSink->ResetToFirstRow(); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isNothing()); + + // Check that the generated image is still the first pass image. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red())); + } + + { + // Fill 25 rows of the image with green and make sure everything is OK. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() -> NextPixel { + if (count == 25 * 100) { + return AsVariant(WriteState::NEED_MORE_DATA); + } + count++; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::NEED_MORE_DATA, result); + EXPECT_EQ(25u * 100u, count); + EXPECT_FALSE(aSink->IsSurfaceFinished()); + + // Assert that we have the right invalid rect, which should include the + // *bottom* (since we're flipping vertically) 25 rows of the image. + Maybe invalidRect = aSink->TakeInvalidRect(); + EXPECT_TRUE(invalidRect.isSome()); + EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mInputSpaceRect); + EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mOutputSpaceRect); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(RowsAreSolidColor(surface, 0, 75, BGRAColor::Red())); + EXPECT_TRUE(RowsAreSolidColor(surface, 75, 25, BGRAColor::Green())); + } + + { + // Fill the rest of the image with a second pass of green. + uint32_t count = 0; + auto result = aSink->WritePixels([&]() { + ++count; + return AsVariant(BGRAColor::Green().AsPixel()); + }); + EXPECT_EQ(WriteState::FINISHED, result); + EXPECT_EQ(75u * 100u, count); + + AssertCorrectPipelineFinalState(aSink, + IntRect(0, 0, 100, 75), + IntRect(0, 0, 100, 75)); + + // Check that the generated image is correct. + RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); + RefPtr surface = currentFrame->GetSurface(); + EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green())); + } + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor0_0_100_100) +{ + WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWritePixels(aDecoder, aSink); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor0_0_100_100) +{ + WithPalettedSurfaceSink(IntRect(0, 0, 100, 100), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWriteRows(aDecoder, aSink); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor25_25_50_50) +{ + WithPalettedSurfaceSink(IntRect(25, 25, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWritePixels(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(25, 25, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(25, 25, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor25_25_50_50) +{ + WithPalettedSurfaceSink(IntRect(25, 25, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWriteRows(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(25, 25, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(25, 25, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsForMinus25_Minus25_50_50) +{ + WithPalettedSurfaceSink(IntRect(-25, -25, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWritePixels(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(-25, -25, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(-25, -25, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsForMinus25_Minus25_50_50) +{ + WithPalettedSurfaceSink(IntRect(-25, -25, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWriteRows(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(-25, -25, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(-25, -25, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor75_Minus25_50_50) +{ + WithPalettedSurfaceSink(IntRect(75, -25, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWritePixels(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(75, -25, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(75, -25, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor75_Minus25_50_50) +{ + WithPalettedSurfaceSink(IntRect(75, -25, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWriteRows(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(75, -25, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(75, -25, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsForMinus25_75_50_50) +{ + WithPalettedSurfaceSink(IntRect(-25, 75, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWritePixels(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(-25, 75, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(-25, 75, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsForMinus25_75_50_50) +{ + WithPalettedSurfaceSink(IntRect(-25, 75, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWriteRows(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(-25, 75, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(-25, 75, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor75_75_50_50) +{ + WithPalettedSurfaceSink(IntRect(75, 75, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWritePixels(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(75, 75, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(75, 75, 50, 50))); + }); +} + +TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor75_75_50_50) +{ + WithPalettedSurfaceSink(IntRect(75, 75, 50, 50), + [](Decoder* aDecoder, PalettedSurfaceSink* aSink) { + CheckPalettedWriteRows(aDecoder, aSink, + /* aOutputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputRect = */ Some(IntRect(0, 0, 50, 50)), + /* aInputWriteRect = */ Some(IntRect(75, 75, 50, 50)), + /* aOutputWriteRect = */ Some(IntRect(75, 75, 50, 50))); + }); +} diff --git a/image/test/gtest/moz.build b/image/test/gtest/moz.build index dd23f42aaa..c2a7038021 100644 --- a/image/test/gtest/moz.build +++ b/image/test/gtest/moz.build @@ -11,8 +11,22 @@ UNIFIED_SOURCES = [ 'TestCopyOnWrite.cpp', 'TestDecoders.cpp', 'TestDecodeToSurface.cpp', + 'TestDeinterlacingFilter.cpp', 'TestMetadata.cpp', + 'TestRemoveFrameRectFilter.cpp', 'TestStreamingLexer.cpp', + 'TestSurfaceSink.cpp', +] + +if CONFIG['MOZ_ENABLE_SKIA']: + UNIFIED_SOURCES += [ + 'TestDownscalingFilter.cpp', + 'TestSurfacePipeIntegration.cpp', + ] + +SOURCES += [ + # Can't be unified because it manipulates the preprocessor environment. + 'TestDownscalingFilterNoSkia.cpp', ] TEST_HARNESS_FILES.gtest += [ @@ -34,8 +48,14 @@ TEST_HARNESS_FILES.gtest += [ 'transparent.png', ] +include('/ipc/chromium/chromium-config.mozbuild') + LOCAL_INCLUDES += [ + '/dom/base', + '/gfx/2d', '/image', ] +LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES'] + FINAL_LIBRARY = 'xul-gtest' diff --git a/js/src/jsapi-tests/testThreadingMutex.cpp b/js/src/jsapi-tests/testThreadingMutex.cpp index ed5e8833fa..f0d3d408e4 100644 --- a/js/src/jsapi-tests/testThreadingMutex.cpp +++ b/js/src/jsapi-tests/testThreadingMutex.cpp @@ -34,3 +34,17 @@ BEGIN_TEST(testThreadingUnlockGuard) return true; } END_TEST(testThreadingUnlockGuard) + +BEGIN_TEST(testThreadingMoveMutex) +{ + js::Mutex mutex; + mutex.lock(); + mutex.unlock(); + + js::Mutex another(mozilla::Move(mutex)); + another.lock(); + another.unlock(); + + return true; +} +END_TEST(testThreadingMoveMutex) diff --git a/js/src/threading/Mutex.h b/js/src/threading/Mutex.h index c92a7ab7f4..8db25c060a 100644 --- a/js/src/threading/Mutex.h +++ b/js/src/threading/Mutex.h @@ -7,7 +7,12 @@ #ifndef threading_Mutex_h #define threading_Mutex_h +#include "mozilla/Assertions.h" #include "mozilla/Attributes.h" +#include "mozilla/Move.h" + +#include +#include namespace js { @@ -22,28 +27,29 @@ public: void lock(); void unlock(); + Mutex(Mutex&& rhs) + : platformData_(rhs.platformData_) + { + MOZ_ASSERT(this != &rhs, "self move disallowed!"); + rhs.platformData_ = nullptr; + } + + Mutex& operator=(Mutex&& rhs) { + this->~Mutex(); + new (this) Mutex(mozilla::Move(rhs)); + return *this; + } + private: Mutex(const Mutex&) = delete; void operator=(const Mutex&) = delete; - Mutex(Mutex&&) = delete; - void operator=(Mutex&&) = delete; - PlatformData* platformData(); + PlatformData* platformData() { + MOZ_ASSERT(platformData_); + return platformData_; + }; -// Linux and maybe other platforms define the storage size of pthread_mutex_t in -// bytes. However, we must define it as an array of void pointers to ensure -// proper alignment. -#if defined(__APPLE__) && defined(__MACH__) && defined(__i386__) - void* platformData_[11]; -#elif defined(__APPLE__) && defined(__MACH__) && defined(__amd64__) - void* platformData_[8]; -#elif defined(__linux__) - void* platformData_[40 / sizeof(void*)]; -#elif defined(_WIN32) - void* platformData_[6]; -#else -#error "Mutex platform data size isn't known for this platform" -#endif + PlatformData* platformData_; }; } // namespace js diff --git a/js/src/threading/posix/Mutex.cpp b/js/src/threading/posix/Mutex.cpp index 3e26178edc..bef5b2102a 100644 --- a/js/src/threading/posix/Mutex.cpp +++ b/js/src/threading/posix/Mutex.cpp @@ -4,23 +4,32 @@ * 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 "mozilla/Assertions.h" - #include +#include "js/Utility.h" + #include "threading/Mutex.h" #include "threading/posix/MutexPlatformData.h" js::Mutex::Mutex() { + AutoEnterOOMUnsafeRegion oom; + platformData_ = js_new(); + if (!platformData_) + oom.crash("js::Mutex::Mutex"); + int r = pthread_mutex_init(&platformData()->ptMutex, NULL); MOZ_RELEASE_ASSERT(r == 0); } js::Mutex::~Mutex() { + if (!platformData_) + return; + int r = pthread_mutex_destroy(&platformData()->ptMutex); MOZ_RELEASE_ASSERT(r == 0); + js_delete(platformData()); } void @@ -36,11 +45,3 @@ js::Mutex::unlock() int r = pthread_mutex_unlock(&platformData()->ptMutex); MOZ_RELEASE_ASSERT(r == 0); } - -js::Mutex::PlatformData* -js::Mutex::platformData() -{ - static_assert(sizeof(platformData_) >= sizeof(PlatformData), - "platformData_ is too small"); - return reinterpret_cast(platformData_); -} diff --git a/js/src/threading/windows/Mutex.cpp b/js/src/threading/windows/Mutex.cpp index ec638100e2..e3277c3149 100644 --- a/js/src/threading/windows/Mutex.cpp +++ b/js/src/threading/windows/Mutex.cpp @@ -4,11 +4,12 @@ * 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 "mozilla/Assertions.h" #include "mozilla/DebugOnly.h" #include "jswin.h" +#include "js/Utility.h" + #include "threading/Mutex.h" #include "threading/windows/MutexPlatformData.h" @@ -43,6 +44,11 @@ static MutexNativeImports NativeImports; js::Mutex::Mutex() { + AutoEnterOOMUnsafeRegion oom; + platformData_ = js_new(); + if (!platformData_) + oom.crash("js::Mutex::Mutex"); + // This number was adopted from NSPR. const static DWORD LockSpinCount = 1500; BOOL r; @@ -59,7 +65,11 @@ js::Mutex::Mutex() js::Mutex::~Mutex() { + if (!platformData_) + return; + DeleteCriticalSection(&platformData()->criticalSection); + js_delete(platformData()); } void @@ -73,11 +83,3 @@ js::Mutex::unlock() { LeaveCriticalSection(&platformData()->criticalSection); } - -js::Mutex::PlatformData* -js::Mutex::platformData() -{ - static_assert(sizeof(platformData_) >= sizeof(PlatformData), - "platformData_ is too small"); - return reinterpret_cast(platformData_); -} diff --git a/layout/base/tests/chrome/test_transformed_scrolling_repaints.html b/layout/base/tests/chrome/test_transformed_scrolling_repaints.html index 29e23ce06f..9c35828cd1 100644 --- a/layout/base/tests/chrome/test_transformed_scrolling_repaints.html +++ b/layout/base/tests/chrome/test_transformed_scrolling_repaints.html @@ -6,8 +6,7 @@ - - +
Hello
Kitty
@@ -54,6 +53,15 @@ function startTest() { }); }); } +function setPrefAndStartTest() { + SpecialPowers.pushPrefEnv( + {"set": [["layers.single-tile.enabled", false]]}, + // Need a timeout here to allow paint unsuppression before we start the test + function() { + setTimeout(startTest, 0); + } + ); +} diff --git a/layout/base/tests/chrome/test_transformed_scrolling_repaints_2.html b/layout/base/tests/chrome/test_transformed_scrolling_repaints_2.html index 9ff72dde6a..7adae20e3a 100644 --- a/layout/base/tests/chrome/test_transformed_scrolling_repaints_2.html +++ b/layout/base/tests/chrome/test_transformed_scrolling_repaints_2.html @@ -6,8 +6,7 @@ - - +
@@ -41,6 +40,15 @@ function startTest() { }); }); } +function setPrefAndStartTest() { + SpecialPowers.pushPrefEnv( + {"set": [["layers.single-tile.enabled", false]]}, + // Need a timeout here to allow paint unsuppression before we start the test + function() { + setTimeout(startTest, 0); + } + ); +} diff --git a/layout/base/tests/chrome/test_transformed_scrolling_repaints_3.html b/layout/base/tests/chrome/test_transformed_scrolling_repaints_3.html index 55fdb461cf..f9a8240f41 100644 --- a/layout/base/tests/chrome/test_transformed_scrolling_repaints_3.html +++ b/layout/base/tests/chrome/test_transformed_scrolling_repaints_3.html @@ -12,9 +12,14 @@ diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 00ef0d63ed..0c20ac78c4 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -63,12 +63,18 @@ #include "nsPluginFrame.h" #include #include +#include "mozilla/layers/LayerTransactionChild.h" #include "mozilla/layers/ScrollLinkedEffectDetector.h" +#include "mozilla/layers/ShadowLayers.h" #include "mozilla/unused.h" +#include "LayersLogging.h" // for Stringify #include #include // for std::abs(int/long) #include // for std::abs(float/double) +#define PAINT_SKIP_LOG(...) +// #define PAINT_SKIP_LOG(...) printf_stderr("PSKIP: " __VA_ARGS__) + using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::layout; @@ -1119,6 +1125,12 @@ static bool IsFocused(nsIContent* aContent) } #endif +void +ScrollFrameHelper::SetScrollableByAPZ(bool aScrollable) +{ + mScrollableByAPZ = aScrollable; +} + void ScrollFrameHelper::SetZoomableByAPZ(bool aZoomable) { @@ -1878,6 +1890,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, , mHasBeenScrolled(false) , mIgnoreMomentumScroll(false) , mTransformingByAPZ(false) + , mScrollableByAPZ(false) , mZoomableByAPZ(false) , mVelocityQueue(aOuter->PresContext()) , mAsyncScrollEvent(END_DOM) @@ -2010,8 +2023,13 @@ ScrollFrameHelper::CompleteAsyncScroll(const nsRect &aRange, nsIAtom* aOrigin) #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) struct PluginSearchCtx { + enum PluginAction { + UPDATE, // Update the scroll visibility of any plugin frames using |value| + QUERY // Set |value| to true if plugin frames were found + }; + PluginAction action; nsIFrame* outer; - bool begin; + bool value; }; static void NotifyPluginFramesCallback(nsISupports* aSupports, void* aCtx) @@ -2026,7 +2044,11 @@ NotifyPluginFramesCallback(nsISupports* aSupports, void* aCtx) // Check to be sure this plugin is contained within a subframe of // the nsGfxScrollFrame that initiated this callback. if (nsLayoutUtils::IsAncestorFrameCrossDoc(pCtx->outer, plugin, nullptr)) { - plugin->SetScrollVisibility(pCtx->begin); + if (pCtx->action == PluginSearchCtx::UPDATE) { + plugin->SetScrollVisibility(pCtx->value); + } else if (pCtx->action == PluginSearchCtx::QUERY) { + pCtx->value = true; + } } } } @@ -2056,7 +2078,7 @@ ScrollFrameHelper::NotifyPluginFrames(AsyncScrollEventType aEvent) } if (aEvent != mAsyncScrollEvent) { nsPresContext* presContext = mOuter->PresContext(); - PluginSearchCtx ctx = { mOuter, (aEvent == BEGIN_APZ || aEvent == BEGIN_DOM) }; + PluginSearchCtx ctx = { PluginSearchCtx::UPDATE, mOuter, (aEvent == BEGIN_APZ || aEvent == BEGIN_DOM) }; presContext->Document()->EnumerateActivityObservers(NotifyPluginFramesCallback, (void*)&ctx); presContext->Document()->EnumerateSubDocuments(NotifyPluginSubframesCallback, @@ -2068,6 +2090,28 @@ ScrollFrameHelper::NotifyPluginFrames(AsyncScrollEventType aEvent) #endif } +bool +ScrollFrameHelper::HasPluginFrames() +{ +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) + if (XRE_IsContentProcess()) { + nsPresContext* presContext = mOuter->PresContext(); + PluginSearchCtx ctx = { PluginSearchCtx::QUERY, mOuter, false }; + presContext->Document()->EnumerateActivityObservers(NotifyPluginFramesCallback, + (void*)&ctx); + if (ctx.value) { + return true; + } + presContext->Document()->EnumerateSubDocuments(NotifyPluginSubframesCallback, + (void*)&ctx); + if (ctx.value) { + return true; + } + } +#endif + return false; +} + void ScrollFrameHelper::ScrollToCSSPixels(const CSSIntPoint& aScrollPosition, nsIScrollableFrame::ScrollMode aMode) @@ -2387,6 +2431,9 @@ RemoveDisplayPortCallback(nsITimer* aTimer, void* aClosure) nsLayoutUtils::RemoveDisplayPort(helper->mOuter->GetContent()); nsLayoutUtils::ExpireDisplayPortOnAsyncScrollableAncestor(helper->mOuter); helper->mOuter->SchedulePaint(); + // Be conservative and unflag this this scrollframe as being scrollable by + // APZ. If it is still scrollable this will get flipped back soon enough. + helper->mScrollableByAPZ = false; } void ScrollFrameHelper::MarkNotRecentlyScrolled() @@ -2661,7 +2708,8 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri } nsRect oldDisplayPort; - nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &oldDisplayPort); + nsIContent* content = mOuter->GetContent(); + nsLayoutUtils::GetDisplayPort(content, &oldDisplayPort); oldDisplayPort.MoveBy(-mScrolledFrame->GetPosition()); // Update frame position for scrolling @@ -2672,25 +2720,52 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri ScrollVisual(); - if (LastScrollOrigin() == nsGkAtoms::apz && gfxPrefs::APZPaintSkipping()) { - // If this was an apz scroll and the displayport (relative to the - // scrolled frame) hasn't changed, then this won't trigger - // any painting, so no need to schedule one. + bool schedulePaint = true; + if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) && gfxPrefs::APZPaintSkipping()) { + // If APZ is enabled with paint-skipping, there are certain conditions in + // which we can skip paints: + // 1) If APZ triggered this scroll, and the tile-aligned displayport is + // unchanged. + // 2) If non-APZ triggered this scroll, but we can handle it by just asking + // APZ to update the scroll position. Again we make this conditional on + // the tile-aligned displayport being unchanged. + // We do the displayport check first since it's common to all scenarios, + // and then if the displayport is unchanged, we check if APZ triggered, + // or can handle, this scroll. If so, we set schedulePaint to false and + // skip the paint. nsRect displayPort; - DebugOnly usingDisplayPort = - nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort); - NS_ASSERTION(usingDisplayPort, "Must have a displayport for apz scrolls!"); - + bool usingDisplayPort = + nsLayoutUtils::GetDisplayPort(content, &displayPort); displayPort.MoveBy(-mScrolledFrame->GetPosition()); - if (!displayPort.IsEqualEdges(oldDisplayPort)) { - mOuter->SchedulePaint(); - - if (needImageVisibilityUpdate) { - presContext->PresShell()->ScheduleImageVisibilityUpdate(); + PAINT_SKIP_LOG("New scrollpos %s usingDP %d dpEqual %d scrollableByApz %d plugins %d sle %d\n", + Stringify(CSSPoint::FromAppUnits(GetScrollPosition())).c_str(), + usingDisplayPort, displayPort.IsEqualEdges(oldDisplayPort), + mScrollableByAPZ, HasPluginFrames(), + content->GetComposedDoc()->HasScrollLinkedEffect()); + if (usingDisplayPort && displayPort.IsEqualEdges(oldDisplayPort)) { + if (LastScrollOrigin() == nsGkAtoms::apz) { + schedulePaint = false; + PAINT_SKIP_LOG("Skipping due to APZ scroll\n"); + } else if (mScrollableByAPZ && !HasPluginFrames() && + !content->GetComposedDoc()->HasScrollLinkedEffect()) { + nsIWidget* widget = presContext->GetNearestWidget(); + LayerManager* manager = widget ? widget->GetLayerManager() : nullptr; + ShadowLayerForwarder* forwarder = manager ? manager->AsShadowForwarder() : nullptr; + if (forwarder && forwarder->HasShadowManager()) { + mozilla::layers::FrameMetrics::ViewID id; + DebugOnly success = nsLayoutUtils::FindIDFor(content, &id); + MOZ_ASSERT(success); // we have a displayport, we better have an ID + forwarder->GetShadowManager()->SendUpdateScrollOffset(id, + mScrollGeneration, CSSPoint::FromAppUnits(GetScrollPosition())); + schedulePaint = false; + PAINT_SKIP_LOG("Skipping due to APZ-forwarded main-thread scroll\n"); + } } } - } else { + } + + if (schedulePaint) { mOuter->SchedulePaint(); if (needImageVisibilityUpdate) { @@ -2705,11 +2780,16 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri } ScheduleSyntheticMouseMove(); - nsWeakFrame weakFrame(mOuter); - UpdateScrollbarPosition(); - if (!weakFrame.IsAlive()) { - return; + + { // scope the AutoScrollbarRepaintSuppression + AutoScrollbarRepaintSuppression repaintSuppression(this, !schedulePaint); + nsWeakFrame weakFrame(mOuter); + UpdateScrollbarPosition(); + if (!weakFrame.IsAlive()) { + return; + } } + PostScrollEvent(); // notify the listeners. @@ -3398,6 +3478,13 @@ ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder, nsRect rootCompBounds = nsRect(nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(rootFrame)); + // If rootFrame is the RCD-RSF then CalculateCompositionSizeForFrame + // did not take the document's resolution into account, so we must. + if (rootPresContext->IsRootContentDocument() && + rootFrame == rootPresShell->GetRootScrollFrame()) { + rootCompBounds = rootCompBounds.RemoveResolution(rootPresShell->GetResolution()); + } + nsLayoutUtils::TransformRect(rootFrame, mOuter, rootCompBounds); displayportBase = displayportBase.Intersect(rootCompBounds); @@ -4409,13 +4496,13 @@ ScrollFrameHelper::ScrollEvent::ScrollEvent(ScrollFrameHelper* aHelper) : mHelper(aHelper) { mDriver = mHelper->mOuter->PresContext()->RefreshDriver(); - mDriver->AddRefreshObserver(this, Flush_Style); + mDriver->AddRefreshObserver(this, Flush_Layout); } ScrollFrameHelper::ScrollEvent::~ScrollEvent() { if (mDriver) { - mDriver->RemoveRefreshObserver(this, Flush_Style); + mDriver->RemoveRefreshObserver(this, Flush_Layout); mDriver = nullptr; } } @@ -4423,7 +4510,7 @@ ScrollFrameHelper::ScrollEvent::~ScrollEvent() void ScrollFrameHelper::ScrollEvent::WillRefresh(mozilla::TimeStamp aTime) { - mDriver->RemoveRefreshObserver(this, Flush_Style); + mDriver->RemoveRefreshObserver(this, Flush_Layout); mDriver = nullptr; mHelper->FireScrollEvent(); } diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index a935b77d5f..a8ffd30d94 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -102,6 +102,29 @@ public: bool IsSmoothScrollingEnabled(); + /** + * This class handles the dispatching of scroll events to content. + * + * nsRefreshDriver maintains three lists of refresh observers, one for each + * flush type: Flush_Style, Flush_Layout, and Flush_Display. + * + * During a tick, it runs through each list of observers, in order, and runs + * them. To iterate over each list, it uses an EndLimitedIterator, which is + * designed to iterate only over elements present when the iterator was + * created, not elements added afterwards. This means that, for a given flush + * type, a refresh observer added during the execution of another refresh + * observer of that flush type, will not run until the next tick. + * + * During main-thread animation-driven scrolling, ScrollEvents are *posted* + * by AsyncScroll::WillRefresh(). AsyncScroll registers itself as a Flush_Style + * refresh observer. + * + * Posting a scroll event, as of bug 1250550, registers a Flush_Layout + * refresh observer, which *fires* the event when run. This allows the event + * to be fired to content in the same refresh driver tick as it is posted. + * This is an important invariant to maintain to reduce scroll event latency + * for main-thread scrolling. + */ class ScrollEvent : public nsARefreshObserver { public: NS_INLINE_DECL_REFCOUNTING(ScrollEvent, override) @@ -362,6 +385,7 @@ public: bool IsTransformingByAPZ() const { return mTransformingByAPZ; } + void SetScrollableByAPZ(bool aScrollable); void SetZoomableByAPZ(bool aZoomable); bool UsesContainerScrolling() const; @@ -418,6 +442,9 @@ public: nsIScrollableFrame::ScrollUnit aUnit, nsIScrollbarMediator::ScrollSnapMode aSnap = nsIScrollbarMediator::DISABLE_SNAP); + bool ShouldSuppressScrollbarRepaints() const { + return mSuppressScrollbarRepaints; + } // owning references to the nsIAnonymousContentCreator-built content nsCOMPtr mHScrollbarContent; @@ -543,12 +570,40 @@ public: // (as best as we can tell on the main thread, anyway). bool mTransformingByAPZ:1; + // True if APZ can scroll this frame asynchronously (i.e. it has an APZC + // set up for this frame and it's not a scrollinfo layer). + bool mScrollableByAPZ:1; + // True if the APZ is allowed to zoom this scrollframe. bool mZoomableByAPZ:1; + // True if we don't want the scrollbar to repaint itself right now. + bool mSuppressScrollbarRepaints:1; + mozilla::layout::ScrollVelocityQueue mVelocityQueue; protected: + class AutoScrollbarRepaintSuppression; + friend class AutoScrollbarRepaintSuppression; + class AutoScrollbarRepaintSuppression { + public: + AutoScrollbarRepaintSuppression(ScrollFrameHelper* aHelper, bool aSuppress) + : mHelper(aHelper) + , mOldSuppressValue(aHelper->mSuppressScrollbarRepaints) + { + mHelper->mSuppressScrollbarRepaints = aSuppress; + } + + ~AutoScrollbarRepaintSuppression() + { + mHelper->mSuppressScrollbarRepaints = mOldSuppressValue; + } + + private: + ScrollFrameHelper* mHelper; + bool mOldSuppressValue; + }; + /** * @note This method might destroy the frame, pres shell and other objects. */ @@ -568,6 +623,7 @@ protected: enum AsyncScrollEventType { BEGIN_DOM, BEGIN_APZ, END_DOM, END_APZ }; void NotifyPluginFrames(AsyncScrollEventType aEvent); AsyncScrollEventType mAsyncScrollEvent; + bool HasPluginFrames(); static void EnsureImageVisPrefsCached(); static bool sImageVisPrefsCached; @@ -937,12 +993,19 @@ public: return mHelper.IsScrollbarOnRight(); } + virtual bool ShouldSuppressScrollbarRepaints() const override { + return mHelper.ShouldSuppressScrollbarRepaints(); + } + virtual void SetTransformingByAPZ(bool aTransforming) override { mHelper.SetTransformingByAPZ(aTransforming); } bool IsTransformingByAPZ() const override { return mHelper.IsTransformingByAPZ(); } + void SetScrollableByAPZ(bool aScrollable) override { + mHelper.SetScrollableByAPZ(aScrollable); + } void SetZoomableByAPZ(bool aZoomable) override { mHelper.SetZoomableByAPZ(aZoomable); } @@ -1332,6 +1395,10 @@ public: return mHelper.IsScrollbarOnRight(); } + virtual bool ShouldSuppressScrollbarRepaints() const override { + return mHelper.ShouldSuppressScrollbarRepaints(); + } + virtual void SetTransformingByAPZ(bool aTransforming) override { mHelper.SetTransformingByAPZ(aTransforming); } @@ -1341,6 +1408,9 @@ public: bool IsTransformingByAPZ() const override { return mHelper.IsTransformingByAPZ(); } + void SetScrollableByAPZ(bool aScrollable) override { + mHelper.SetScrollableByAPZ(aScrollable); + } void SetZoomableByAPZ(bool aZoomable) override { mHelper.SetZoomableByAPZ(aZoomable); } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 843ed7e512..773e99922d 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -421,6 +421,14 @@ public: virtual void SetTransformingByAPZ(bool aTransforming) = 0; virtual bool IsTransformingByAPZ() const = 0; + /** + * Notify this scroll frame that it can be scrolled by APZ. In particular, + * this is called *after* the APZ code has created an APZC for this scroll + * frame and verified that it is not a scrollinfo layer. Therefore, setting an + * async transform on it is actually user visible. + */ + virtual void SetScrollableByAPZ(bool aScrollable) = 0; + /** * Notify this scroll frame that it can be zoomed by APZ. */ diff --git a/layout/reftests/invalidation/reftest.list b/layout/reftests/invalidation/reftest.list index d61a041942..31387f5bb2 100644 --- a/layout/reftests/invalidation/reftest.list +++ b/layout/reftests/invalidation/reftest.list @@ -50,7 +50,7 @@ pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == t != clipped-animated-transform-1.html about:blank != paintedlayer-recycling-1.html about:blank != paintedlayer-recycling-2.html about:blank -!= paintedlayer-recycling-3.html about:blank +pref(layers.single-tile.enabled,false) != paintedlayer-recycling-3.html about:blank != paintedlayer-recycling-4.html about:blank != paintedlayer-recycling-5.html about:blank != paintedlayer-recycling-6.html about:blank @@ -64,9 +64,9 @@ pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == t != layer-splitting-5.html about:blank != layer-splitting-6.html about:blank != layer-splitting-7.html about:blank -fuzzy-if(gtkWidget,2,4) == image-scrolling-zoom-1.html image-scrolling-zoom-1-ref.html +fuzzy-if(gtkWidget,2,4) fuzzy-if(asyncPan,2,3955) fuzzy-if(OSX,179,30) fuzzy-if(skiaContent,16,3230) == image-scrolling-zoom-1.html image-scrolling-zoom-1-ref.html != image-scrolling-zoom-1-ref.html image-scrolling-zoom-1-notref.html -!= fast-scrolling.html about:blank +pref(layers.single-tile.enabled,false) != fast-scrolling.html about:blank != fractional-transform-1.html about:blank != fractional-transform-2.html about:blank != fractional-transform-3.html about:blank diff --git a/layout/reftests/layers/mask-layer-transform-ref.html b/layout/reftests/layers/mask-layer-transform-ref.html new file mode 100644 index 0000000000..54cd38607f --- /dev/null +++ b/layout/reftests/layers/mask-layer-transform-ref.html @@ -0,0 +1,8 @@ + + +
+
+
+ + + diff --git a/layout/reftests/layers/mask-layer-transform.html b/layout/reftests/layers/mask-layer-transform.html new file mode 100644 index 0000000000..0a809c50bd --- /dev/null +++ b/layout/reftests/layers/mask-layer-transform.html @@ -0,0 +1,10 @@ + + +
+
+
+
+
+ + + diff --git a/layout/reftests/layers/reftest.list b/layout/reftests/layers/reftest.list index a37058eb54..031dac6837 100644 --- a/layout/reftests/layers/reftest.list +++ b/layout/reftests/layers/reftest.list @@ -18,3 +18,4 @@ skip-if(!asyncPan) != pull-background-displayport-4.html about:blank # fails wit skip-if(!asyncPan) != pull-background-displayport-5.html about:blank skip-if(!asyncPan) != pull-background-displayport-6.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515 fuzzy(2,30150) == opacity-blending.html opacity-blending-ref.html +fuzzy(1,5) == mask-layer-transform.html mask-layer-transform-ref.html diff --git a/layout/xul/nsIScrollbarMediator.h b/layout/xul/nsIScrollbarMediator.h index 52c7e32af0..87b82e3d92 100644 --- a/layout/xul/nsIScrollbarMediator.h +++ b/layout/xul/nsIScrollbarMediator.h @@ -79,6 +79,12 @@ public: virtual void ScrollbarActivityStopped() const = 0; virtual bool IsScrollbarOnRight() const = 0; + + /** + * Returns true if the mediator is asking the scrollbar to suppress + * repainting itself on changes. + */ + virtual bool ShouldSuppressScrollbarRepaints() const = 0; }; #endif diff --git a/layout/xul/nsListBoxBodyFrame.h b/layout/xul/nsListBoxBodyFrame.h index 0ed306612e..1af819ddee 100644 --- a/layout/xul/nsListBoxBodyFrame.h +++ b/layout/xul/nsListBoxBodyFrame.h @@ -75,6 +75,9 @@ public: virtual bool IsScrollbarOnRight() const override { return (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR); } + virtual bool ShouldSuppressScrollbarRepaints() const override { + return false; + } // nsIReflowCallback diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index d7a86d57f3..ba68f005f6 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -759,12 +759,11 @@ nsSliderFrame::CurrentPositionChanged() // set the rect thumbFrame->SetRect(newThumbRect); - // Request a repaint of the scrollbar unless we have paint-skipping enabled - // and this is an APZ scroll. - nsIScrollableFrame* scrollableFrame = do_QueryFrame(GetScrollbar()->GetParent()); - if (!gfxPrefs::APZPaintSkipping() || - !scrollableFrame || - scrollableFrame->LastScrollOrigin() != nsGkAtoms::apz) { + // Request a repaint of the scrollbar + nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox); + nsIScrollbarMediator* mediator = scrollbarFrame + ? scrollbarFrame->GetScrollbarMediator() : nullptr; + if (!mediator || !mediator->ShouldSuppressScrollbarRepaints()) { SchedulePaint(); } diff --git a/layout/xul/tree/nsTreeBodyFrame.h b/layout/xul/tree/nsTreeBodyFrame.h index a84b27f4b8..4f8172c044 100644 --- a/layout/xul/tree/nsTreeBodyFrame.h +++ b/layout/xul/tree/nsTreeBodyFrame.h @@ -160,6 +160,9 @@ public: virtual bool IsScrollbarOnRight() const override { return (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR); } + virtual bool ShouldSuppressScrollbarRepaints() const override { + return false; + } // Overridden from nsIFrame to cache our pres context. virtual void Init(nsIContent* aContent, diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 2ffbc1e935..c1f7d4a8f6 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4645,6 +4645,7 @@ pref("layers.draw-tile-borders", false); pref("layers.draw-bigimage-borders", false); pref("layers.frame-counter", false); pref("layers.enable-tiles", false); +pref("layers.single-tile.enabled", true); pref("layers.tiled-drawtarget.enabled", false); pref("layers.low-precision-buffer", false); pref("layers.progressive-paint", false); diff --git a/security/certverifier/NSSCertDBTrustDomain.cpp b/security/certverifier/NSSCertDBTrustDomain.cpp index d3cfd81355..2610e99520 100644 --- a/security/certverifier/NSSCertDBTrustDomain.cpp +++ b/security/certverifier/NSSCertDBTrustDomain.cpp @@ -263,7 +263,6 @@ NSSCertDBTrustDomain::DigestBuf(Input item, DigestAlgorithm digestAlg, return DigestBufNSS(item, digestAlg, digestBuf, digestBufLen); } - static PRIntervalTime OCSPFetchingTypeToTimeoutTime(NSSCertDBTrustDomain::OCSPFetching ocspFetching) { @@ -278,9 +277,10 @@ OCSPFetchingTypeToTimeoutTime(NSSCertDBTrustDomain::OCSPFetching ocspFetching) case NSSCertDBTrustDomain::NeverFetchOCSP: case NSSCertDBTrustDomain::LocalOnlyOCSPForEV: PR_NOT_REACHED("we should never see this OCSPFetching type here"); - default: - PR_NOT_REACHED("we're not handling every OCSPFetching type"); + break; } + + PR_NOT_REACHED("we're not handling every OCSPFetching type"); return PR_SecondsToInterval(2); } @@ -428,8 +428,8 @@ NSSCertDBTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA, // expired. Don't return with either of these statuses yet - we may be // able to fetch a more recent one. MOZ_LOG(gCertVerifierLog, LogLevel::Debug, - ("NSSCertDBTrustDomain: cached OCSP response: error %ld valid " - "until %lld", cachedResponseResult, cachedResponseValidThrough)); + ("NSSCertDBTrustDomain: cached OCSP response: error %d", + cachedResponseResult)); // When a good cached response has expired, it is more convenient // to convert that to an error code and just deal with // cachedResponseResult from here on out. @@ -550,12 +550,15 @@ NSSCertDBTrustDomain::CheckRevocation(EndEntityOrCA endEntityOrCA, static_cast(ocspRequestLength) }; // Owned by arena - const SECItem* responseSECItem = + SECItem* responseSECItem = nullptr; + Result tempRV = DoOCSPRequest(arena.get(), url, &ocspRequestItem, OCSPFetchingTypeToTimeoutTime(mOCSPFetching), - mOCSPGetConfig == CertVerifier::ocspGetEnabled); - if (!responseSECItem) { - rv = MapPRErrorCodeToResult(PR_GetError()); + mOCSPGetConfig == CertVerifier::ocspGetEnabled, + responseSECItem); + MOZ_ASSERT((tempRV != Success) || responseSECItem); + if (tempRV != Success) { + rv = tempRV; } else if (response.Init(responseSECItem->data, responseSECItem->len) != Success) { rv = Result::ERROR_OCSP_MALFORMED_RESPONSE; // too big diff --git a/security/certverifier/OCSPCache.cpp b/security/certverifier/OCSPCache.cpp index 3999e00cc6..8b1679fe4e 100644 --- a/security/certverifier/OCSPCache.cpp +++ b/security/certverifier/OCSPCache.cpp @@ -149,7 +149,9 @@ OCSPCache::MakeMostRecentlyUsed(size_t aIndex, // Since mEntries is sorted with the most-recently-used entry at the end, // aIndex is likely to be near the end, so this is likely to be fast. mEntries.erase(mEntries.begin() + aIndex); - mEntries.append(entry); + // erase() does not shrink or realloc memory, so the append below should + // always succeed. + MOZ_RELEASE_ASSERT(mEntries.append(entry)); } bool @@ -252,7 +254,10 @@ OCSPCache::Put(const CertID& aCertID, Result aResult, delete newEntry; return rv; } - mEntries.append(newEntry); + if (!mEntries.append(newEntry)) { + delete newEntry; + return Result::FATAL_ERROR_NO_MEMORY; + } LogWithCertID("OCSPCache::Put(%p) added to cache", aCertID); return Success; } diff --git a/security/certverifier/OCSPRequestor.cpp b/security/certverifier/OCSPRequestor.cpp index 8ac370aaed..f1281bd4b1 100644 --- a/security/certverifier/OCSPRequestor.cpp +++ b/security/certverifier/OCSPRequestor.cpp @@ -70,25 +70,23 @@ AppendEscapedBase64Item(const SECItem* encodedRequest, nsACString& path) return NS_OK; } -SECItem* +Result DoOCSPRequest(PLArenaPool* arena, const char* url, const SECItem* encodedRequest, PRIntervalTime timeout, - bool useGET) + bool useGET, + /*out*/ SECItem*& encodedResponse) { if (!arena || !url || !encodedRequest || !encodedRequest->data) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); - return nullptr; + return Result::FATAL_ERROR_INVALID_ARGS; } uint32_t urlLen = PL_strlen(url); if (urlLen > static_cast(std::numeric_limits::max())) { - PR_SetError(SEC_ERROR_INVALID_ARGS, 0); - return nullptr; + return Result::FATAL_ERROR_INVALID_ARGS; } nsCOMPtr urlParser = do_GetService(NS_STDURLPARSER_CONTRACTID); if (!urlParser) { - PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); - return nullptr; + return Result::FATAL_ERROR_LIBRARY_FAILURE; } uint32_t schemePos; @@ -97,58 +95,52 @@ DoOCSPRequest(PLArenaPool* arena, const char* url, int32_t authorityLen; uint32_t pathPos; int32_t pathLen; - nsresult rv = urlParser->ParseURL(url, static_cast(urlLen), - &schemePos, &schemeLen, - &authorityPos, &authorityLen, - &pathPos, &pathLen); - if (NS_FAILED(rv)) { - PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); - return nullptr; + nsresult nsrv = urlParser->ParseURL(url, static_cast(urlLen), + &schemePos, &schemeLen, + &authorityPos, &authorityLen, + &pathPos, &pathLen); + if (NS_FAILED(nsrv)) { + return Result::ERROR_CERT_BAD_ACCESS_LOCATION; } if (schemeLen < 0 || authorityLen < 0) { - PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); - return nullptr; + return Result::ERROR_CERT_BAD_ACCESS_LOCATION; } nsAutoCString scheme(url + schemePos, static_cast(schemeLen)); if (!scheme.LowerCaseEqualsLiteral("http")) { - // We dont support https:// to avoid loops see Bug 92923 - PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); - return nullptr; + // We don't support HTTPS to avoid loops. See Bug 92923. + // We also in general only support HTTP. + return Result::ERROR_CERT_BAD_ACCESS_LOCATION; } uint32_t hostnamePos; int32_t hostnameLen; int32_t port; - // We do not support urls with user@pass sections in the URL, - // In cas we find them we will ignore and try to connect with - rv = urlParser->ParseAuthority(url + authorityPos, authorityLen, - nullptr, nullptr, nullptr, nullptr, - &hostnamePos, &hostnameLen, &port); - if (NS_FAILED(rv)) { - PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); - return nullptr; + // We ignore user:password sections: if one is present, we send an OCSP + // request to the URL as normal without sending the username or password. + nsrv = urlParser->ParseAuthority(url + authorityPos, authorityLen, + nullptr, nullptr, nullptr, nullptr, + &hostnamePos, &hostnameLen, &port); + if (NS_FAILED(nsrv)) { + return Result::ERROR_CERT_BAD_ACCESS_LOCATION; } if (hostnameLen < 0) { - PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); - return nullptr; + return Result::ERROR_CERT_BAD_ACCESS_LOCATION; } if (port == -1) { port = 80; } else if (port < 0 || port > 0xffff) { - PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); - return nullptr; + return Result::ERROR_CERT_BAD_ACCESS_LOCATION; } nsAutoCString hostname(url + authorityPos + hostnamePos, static_cast(hostnameLen)); SEC_HTTP_SERVER_SESSION serverSessionPtr = nullptr; - if (nsNSSHttpInterface::createSessionFcn(hostname.BeginReading(), - static_cast(port), - &serverSessionPtr) != SECSuccess) { - PR_SetError(SEC_ERROR_NO_MEMORY, 0); - return nullptr; + Result rv = nsNSSHttpInterface::createSessionFcn( + hostname.BeginReading(), static_cast(port), &serverSessionPtr); + if (rv != Success) { + return rv; } ScopedHTTPServerSession serverSession( reinterpret_cast(serverSessionPtr)); @@ -168,59 +160,53 @@ DoOCSPRequest(PLArenaPool* arena, const char* url, if (!StringEndsWith(path, NS_LITERAL_CSTRING("/"))) { path.Append("/"); } - nsresult rv = AppendEscapedBase64Item(encodedRequest, path); - if (NS_WARN_IF(NS_FAILED(rv))) { - return nullptr; + nsresult nsrv = AppendEscapedBase64Item(encodedRequest, path); + if (NS_WARN_IF(NS_FAILED(nsrv))) { + return Result::FATAL_ERROR_LIBRARY_FAILURE; } } SEC_HTTP_REQUEST_SESSION requestSessionPtr; - if (nsNSSHttpInterface::createFcn(serverSession.get(), "http", - path.get(), method.get(), - timeout, &requestSessionPtr) - != SECSuccess) { - PR_SetError(SEC_ERROR_NO_MEMORY, 0); - return nullptr; + rv = nsNSSHttpInterface::createFcn(serverSession.get(), "http", path.get(), + method.get(), timeout, &requestSessionPtr); + if (rv != Success) { + return rv; } ScopedHTTPRequestSession requestSession( reinterpret_cast(requestSessionPtr)); if (!useGET) { - if (nsNSSHttpInterface::setPostDataFcn(requestSession.get(), - reinterpret_cast(encodedRequest->data), encodedRequest->len, - "application/ocsp-request") != SECSuccess) { - PR_SetError(SEC_ERROR_NO_MEMORY, 0); - return nullptr; + rv = nsNSSHttpInterface::setPostDataFcn( + requestSession.get(), reinterpret_cast(encodedRequest->data), + encodedRequest->len, "application/ocsp-request"); + if (rv != Success) { + return rv; } } uint16_t httpResponseCode; const char* httpResponseData; uint32_t httpResponseDataLen = 0; // 0 means any response size is acceptable - if (nsNSSHttpInterface::trySendAndReceiveFcn(requestSession.get(), nullptr, - &httpResponseCode, nullptr, - nullptr, &httpResponseData, - &httpResponseDataLen) - != SECSuccess) { - PR_SetError(SEC_ERROR_OCSP_SERVER_ERROR, 0); - return nullptr; + rv = nsNSSHttpInterface::trySendAndReceiveFcn(requestSession.get(), nullptr, + &httpResponseCode, nullptr, + nullptr, &httpResponseData, + &httpResponseDataLen); + if (rv != Success) { + return rv; } if (httpResponseCode != 200) { - PR_SetError(SEC_ERROR_OCSP_SERVER_ERROR, 0); - return nullptr; + return Result::ERROR_OCSP_SERVER_ERROR; } - SECItem* encodedResponse = SECITEM_AllocItem(arena, nullptr, - httpResponseDataLen); + encodedResponse = SECITEM_AllocItem(arena, nullptr, httpResponseDataLen); if (!encodedResponse) { - PR_SetError(SEC_ERROR_NO_MEMORY, 0); - return nullptr; + return Result::FATAL_ERROR_NO_MEMORY; } memcpy(encodedResponse->data, httpResponseData, httpResponseDataLen); - return encodedResponse; + return Success; } } } // namespace mozilla::psm diff --git a/security/certverifier/OCSPRequestor.h b/security/certverifier/OCSPRequestor.h index 9fc2107441..2310c8cdb4 100644 --- a/security/certverifier/OCSPRequestor.h +++ b/security/certverifier/OCSPRequestor.h @@ -12,10 +12,11 @@ namespace mozilla { namespace psm { -// The memory returned is owned by the given arena. -SECItem* DoOCSPRequest(PLArenaPool* arena, const char* url, - const SECItem* encodedRequest, PRIntervalTime timeout, - bool useGET); +// The memory returned via |encodedResponse| is owned by the given arena. +Result DoOCSPRequest(PLArenaPool* arena, const char* url, + const SECItem* encodedRequest, PRIntervalTime timeout, + bool useGET, + /*out*/ SECItem*& encodedResponse); } } // namespace mozilla::psm diff --git a/security/certverifier/moz.build b/security/certverifier/moz.build index 18afd6ce60..be3548360e 100644 --- a/security/certverifier/moz.build +++ b/security/certverifier/moz.build @@ -46,6 +46,8 @@ if CONFIG['_MSC_VER']: '-wd4610', # struct 'symbol' can never be instantiated - user defined # constructor required '-wd4619', # pragma warning: there is no warning 'warning' + '-wd4623', # default constructor could not be generated because a base + # class default constructor is inaccessible or deleted '-wd4625', # copy constructor could not be generated because a base # class copy constructor is inaccessible or deleted '-wd4626', # assignment operator could not be generated because a base @@ -63,6 +65,12 @@ if CONFIG['_MSC_VER']: '-wd4987', # nonstandard extension used ] + # MSVC 2015 triggers these + CXXFLAGS += [ + '-wd4456', # declaration of 'rv' hides previous local declaration + '-wd4458', # declaration of 'input' hides class member + ] + # Gecko headers aren't warning-free enough for us to enable these warnings CXXFLAGS += [ '-wd4100', # 'symbol' : unreferenced formal parameter diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.properties b/security/manager/locales/en-US/chrome/pippki/pippki.properties index 67232999f9..cabf09a1b0 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.properties +++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties @@ -143,7 +143,3 @@ addExceptionCheckingShort=Checking Information addExceptionCheckingLong2=Attempting to identify this site… addExceptionNoCertShort=No Information Available addExceptionNoCertLong2=Unable to obtain identification status for this site. - -#Certificate Exists in database -caCertExistsTitle=Certificate Exists -caCertExistsMessage=The Certificate already exists. diff --git a/security/manager/pki/nsNSSDialogs.cpp b/security/manager/pki/nsNSSDialogs.cpp index 5ed46fcc4d..f83f424fbb 100644 --- a/security/manager/pki/nsNSSDialogs.cpp +++ b/security/manager/pki/nsNSSDialogs.cpp @@ -158,36 +158,13 @@ nsNSSDialogs::ConfirmDownloadCACert(nsIInterfaceRequestor *ctx, return rv; } -NS_IMETHODIMP -nsNSSDialogs::NotifyCACertExists(nsIInterfaceRequestor *ctx) -{ - nsresult rv; - - nsCOMPtr promptSvc(do_GetService(NS_PROMPTSERVICE_CONTRACTID)); - if (!promptSvc) - return NS_ERROR_FAILURE; - - // Get the parent window for the dialog - nsCOMPtr parent = do_GetInterface(ctx); - - nsAutoString title; - rv = mPIPStringBundle->GetStringFromName(MOZ_UTF16("caCertExistsTitle"), - getter_Copies(title)); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoString msg; - rv = mPIPStringBundle->GetStringFromName(MOZ_UTF16("caCertExistsMessage"), - getter_Copies(msg)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = promptSvc->Alert(parent, title.get(), msg.get()); - - return rv; -} - - NS_IMETHODIMP -nsNSSDialogs::ChooseCertificate(nsIInterfaceRequestor *ctx, const char16_t *cn, const char16_t *organization, const char16_t *issuer, const char16_t **certNickList, const char16_t **certDetailsList, uint32_t count, int32_t *selectedIndex, bool *canceled) +nsNSSDialogs::ChooseCertificate(nsIInterfaceRequestor* ctx, const char16_t* cn, + const char16_t* organization, + const char16_t* issuer, + const char16_t** certNickList, + const char16_t** certDetailsList, uint32_t count, + int32_t* selectedIndex, bool* canceled) { nsresult rv; uint32_t i; diff --git a/security/manager/ssl/PublicKeyPinningService.cpp b/security/manager/ssl/PublicKeyPinningService.cpp index f0b34a43f3..d9098f1768 100644 --- a/security/manager/ssl/PublicKeyPinningService.cpp +++ b/security/manager/ssl/PublicKeyPinningService.cpp @@ -30,12 +30,11 @@ LazyLogModule gPublicKeyPinningLog("PublicKeyPinningService"); of the DER Encoded subject Public Key Info for the given cert */ static nsresult -GetBase64HashSPKI(const CERTCertificate* cert, SECOidTag hashType, - nsACString& hashSPKIDigest) +GetBase64HashSPKI(const CERTCertificate* cert, nsACString& hashSPKIDigest) { hashSPKIDigest.Truncate(); Digest digest; - nsresult rv = digest.DigestBuf(hashType, cert->derPublicKey.data, + nsresult rv = digest.DigestBuf(SEC_OID_SHA256, cert->derPublicKey.data, cert->derPublicKey.len); if (NS_FAILED(rv)) { return rv; @@ -47,55 +46,68 @@ GetBase64HashSPKI(const CERTCertificate* cert, SECOidTag hashType, } /* - * Returns true if a given cert matches any hashType fingerprints from the - * given pinset or the dynamicFingeprints array, false otherwise. + * Sets certMatchesPinset to true if a given cert matches any fingerprints from + * the given pinset or the dynamicFingerprints array, or to false otherwise. */ static nsresult -EvalCertWithHashType(const CERTCertificate* cert, SECOidTag hashType, - const nsTArray* dynamicFingerprints, - /*out*/ bool& certMatchesPinset) +EvalCert(const CERTCertificate* cert, const StaticFingerprints* fingerprints, + const nsTArray* dynamicFingerprints, + /*out*/ bool& certMatchesPinset) { certMatchesPinset = false; - if (!dynamicFingerprints) { + if (!fingerprints && !dynamicFingerprints) { MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, - ("pkpin: No hashes found for hash type: %d\n", hashType)); + ("pkpin: No hashes found\n")); return NS_ERROR_INVALID_ARG; } nsAutoCString base64Out; - nsresult rv = GetBase64HashSPKI(cert, hashType, base64Out); + nsresult rv = GetBase64HashSPKI(cert, base64Out); if (NS_FAILED(rv)) { MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, ("pkpin: GetBase64HashSPKI failed!\n")); return rv; } - for (size_t i = 0; i < dynamicFingerprints->Length(); i++) { - if (base64Out.Equals((*dynamicFingerprints)[i])) { + if (fingerprints) { + for (size_t i = 0; i < fingerprints->size; i++) { + if (base64Out.Equals(fingerprints->data[i])) { MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, - ("pkpin: found pin base_64 ='%s'\n", base64Out.get())); - certMatchesPinset = true; - return NS_OK; + ("pkpin: found pin base_64 ='%s'\n", base64Out.get())); + certMatchesPinset = true; + return NS_OK; + } + } + } + if (dynamicFingerprints) { + for (size_t i = 0; i < dynamicFingerprints->Length(); i++) { + if (base64Out.Equals((*dynamicFingerprints)[i])) { + MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, + ("pkpin: found pin base_64 ='%s'\n", base64Out.get())); + certMatchesPinset = true; + return NS_OK; + } } } - return NS_OK; } /* - * Returns true if a given chain matches any hashType fingerprints from the - * given pinset or the dynamicFingerprints array, false otherwise. + * Sets certListIntersectsPinset to true if a given chain matches any + * fingerprints from the given static fingerprints or the + * dynamicFingerprints array, or to false otherwise. */ static nsresult -EvalChainWithHashType(const CERTCertList* certList, SECOidTag hashType, - const nsTArray* dynamicFingerprints, - /*out*/ bool& certListIntersectsPinset) +EvalChain(const CERTCertList* certList, const StaticFingerprints* fingerprints, + const nsTArray* dynamicFingerprints, + /*out*/ bool& certListIntersectsPinset) { certListIntersectsPinset = false; CERTCertificate* currentCert; - if (!dynamicFingerprints) { - return NS_OK; + if (!fingerprints && !dynamicFingerprints) { + MOZ_ASSERT(false, "Must pass in at least one type of pinset"); + return NS_ERROR_FAILURE; } CERTCertListNode* node; @@ -106,9 +118,8 @@ EvalChainWithHashType(const CERTCertList* certList, SECOidTag hashType, ("pkpin: certArray subject: '%s'\n", currentCert->subjectName)); MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, ("pkpin: certArray issuer: '%s'\n", currentCert->issuerName)); - nsresult rv = EvalCertWithHashType(currentCert, hashType, - dynamicFingerprints, - certListIntersectsPinset); + nsresult rv = EvalCert(currentCert, fingerprints, dynamicFingerprints, + certListIntersectsPinset); if (NS_FAILED(rv)) { return rv; } @@ -120,38 +131,52 @@ EvalChainWithHashType(const CERTCertList* certList, SECOidTag hashType, return NS_OK; } +/** + Comparator for the is public key pinned host. +*/ +static int +TransportSecurityPreloadCompare(const void *key, const void *entry) { + const char *keyStr = reinterpret_cast(key); + const TransportSecurityPreload *preloadEntry = + reinterpret_cast(entry); + + return strcmp(keyStr, preloadEntry->mHost); +} + nsresult PublicKeyPinningService::ChainMatchesPinset(const CERTCertList* certList, const nsTArray& aSHA256keys, /*out*/ bool& chainMatchesPinset) { - return EvalChainWithHashType(certList, SEC_OID_SHA256, &aSHA256keys, - chainMatchesPinset); + return EvalChain(certList, nullptr, &aSHA256keys, chainMatchesPinset); } -// Returns via the output parameter the pinning information that is -// valid for the given host at the given time. +// Returns via one of the output parameters the most relevant pinning +// information that is valid for the given host at the given time. +// Dynamic pins are prioritized over static pins. static nsresult FindPinningInformation(const char* hostname, mozilla::pkix::Time time, - /*out*/ nsTArray& dynamicFingerprints) + /*out*/ nsTArray& dynamicFingerprints, + /*out*/ TransportSecurityPreload*& staticFingerprints) { if (!hostname || hostname[0] == 0) { return NS_ERROR_INVALID_ARG; } + staticFingerprints = nullptr; dynamicFingerprints.Clear(); nsCOMPtr sssService = do_GetService(NS_SSSERVICE_CONTRACTID); if (!sssService) { return NS_ERROR_FAILURE; } - SiteHPKPState dynamicEntry; - char *evalHost = const_cast(hostname); - char *evalPart; + TransportSecurityPreload* foundEntry = nullptr; + char* evalHost = const_cast(hostname); + char* evalPart; // Notice how the (xx = strchr) prevents pins for unqualified domain names. - while (evalPart = strchr(evalHost, '.')) { + while (!foundEntry && (evalPart = strchr(evalHost, '.'))) { MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, ("pkpin: Querying pinsets for host: '%s'\n", evalHost)); - // Look up dynamic pins + // Attempt dynamic pins first nsresult rv; bool found; bool includeSubdomains; @@ -166,6 +191,22 @@ FindPinningInformation(const char* hostname, mozilla::pkix::Time time, ("pkpin: Found dyn match for host: '%s'\n", evalHost)); dynamicFingerprints = pinArray; return NS_OK; + } + + foundEntry = (TransportSecurityPreload *)bsearch(evalHost, + kPublicKeyPinningPreloadList, + sizeof(kPublicKeyPinningPreloadList) / sizeof(TransportSecurityPreload), + sizeof(TransportSecurityPreload), + TransportSecurityPreloadCompare); + if (foundEntry) { + MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, + ("pkpin: Found pinset for host: '%s'\n", evalHost)); + if (evalHost != hostname) { + if (!foundEntry->mIncludeSubdomains) { + // Does not apply to this host, continue iterating + foundEntry = nullptr; + } + } } else { MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, ("pkpin: Didn't find pinset for host: '%s'\n", evalHost)); @@ -173,6 +214,14 @@ FindPinningInformation(const char* hostname, mozilla::pkix::Time time, // Add one for '.' evalHost = evalPart + 1; } + + if (foundEntry && foundEntry->pinset) { + if (time > TimeFromEpochInSeconds(kPreloadPKPinsExpirationTime / + PR_USEC_PER_SEC)) { + return NS_OK; + } + staticFingerprints = foundEntry; + } return NS_OK; } @@ -196,15 +245,76 @@ CheckPinsForHostname(const CERTCertList* certList, const char* hostname, } nsTArray dynamicFingerprints; - nsresult rv = FindPinningInformation(hostname, time, dynamicFingerprints); + TransportSecurityPreload* staticFingerprints = nullptr; + nsresult rv = FindPinningInformation(hostname, time, dynamicFingerprints, + staticFingerprints); // If we have no pinning information, the certificate chain trivially // validates with respect to pinning. - if (dynamicFingerprints.Length() == 0) { + if (dynamicFingerprints.Length() == 0 && !staticFingerprints) { chainHasValidPins = true; return NS_OK; } - return EvalChainWithHashType(certList, SEC_OID_SHA256, - &dynamicFingerprints, chainHasValidPins); + if (dynamicFingerprints.Length() > 0) { + return EvalChain(certList, nullptr, &dynamicFingerprints, chainHasValidPins); + } + if (staticFingerprints) { + bool enforceTestModeResult; + rv = EvalChain(certList, staticFingerprints->pinset, nullptr, + enforceTestModeResult); + if (NS_FAILED(rv)) { + return rv; + } + chainHasValidPins = enforceTestModeResult; + Telemetry::ID histogram = staticFingerprints->mIsMoz + ? Telemetry::CERT_PINNING_MOZ_RESULTS + : Telemetry::CERT_PINNING_RESULTS; + if (staticFingerprints->mTestMode) { + histogram = staticFingerprints->mIsMoz + ? Telemetry::CERT_PINNING_MOZ_TEST_RESULTS + : Telemetry::CERT_PINNING_TEST_RESULTS; + if (!enforceTestMode) { + chainHasValidPins = true; + } + } + // We can collect per-host pinning violations for this host because it is + // operationally critical to Firefox. + if (pinningTelemetryInfo) { + if (staticFingerprints->mId != kUnknownId) { + int32_t bucket = staticFingerprints->mId * 2 + + (enforceTestModeResult ? 1 : 0); + histogram = staticFingerprints->mTestMode + ? Telemetry::CERT_PINNING_MOZ_TEST_RESULTS_BY_HOST + : Telemetry::CERT_PINNING_MOZ_RESULTS_BY_HOST; + pinningTelemetryInfo->certPinningResultBucket = bucket; + } else { + pinningTelemetryInfo->certPinningResultBucket = + enforceTestModeResult ? 1 : 0; + } + pinningTelemetryInfo->accumulateResult = true; + pinningTelemetryInfo->certPinningResultHistogram = histogram; + } + + // We only collect per-CA pinning statistics upon failures. + CERTCertListNode* rootNode = CERT_LIST_TAIL(certList); + // Only log telemetry if the certificate list is non-empty. + if (!CERT_LIST_END(rootNode, certList)) { + if (!enforceTestModeResult && pinningTelemetryInfo) { + int32_t binNumber = RootCABinNumber(&rootNode->cert->derCert); + if (binNumber != ROOT_CERTIFICATE_UNKNOWN ) { + pinningTelemetryInfo->accumulateForRoot = true; + pinningTelemetryInfo->rootBucket = binNumber; + } + } + } + + MOZ_LOG(gPublicKeyPinningLog, LogLevel::Debug, + ("pkpin: Pin check %s for %s host '%s' (mode=%s)\n", + enforceTestModeResult ? "passed" : "failed", + staticFingerprints->mIsMoz ? "mozilla" : "non-mozilla", + hostname, staticFingerprints->mTestMode ? "test" : "production")); + } + + return NS_OK; } nsresult @@ -237,13 +347,16 @@ PublicKeyPinningService::HostHasPins(const char* hostname, hostHasPins = false; nsAutoCString canonicalizedHostname(CanonicalizeHostname(hostname)); nsTArray dynamicFingerprints; + TransportSecurityPreload* staticFingerprints = nullptr; nsresult rv = FindPinningInformation(canonicalizedHostname.get(), time, - dynamicFingerprints); + dynamicFingerprints, staticFingerprints); if (NS_FAILED(rv)) { return rv; } if (dynamicFingerprints.Length() > 0) { hostHasPins = true; + } else if (staticFingerprints) { + hostHasPins = !staticFingerprints->mTestMode || enforceTestMode; } return NS_OK; } diff --git a/security/manager/ssl/PublicKeyPinningService.h b/security/manager/ssl/PublicKeyPinningService.h index 9a02ab9120..601f624e58 100644 --- a/security/manager/ssl/PublicKeyPinningService.h +++ b/security/manager/ssl/PublicKeyPinningService.h @@ -18,13 +18,11 @@ class PublicKeyPinningService { public: /** - * Returns true if the given (host, certList) passes pinning checks, - * false otherwise. If the host is pinned, return true if one of the keys in - * the given certificate chain matches the pin set specified by the - * hostname. If the hostname is null or empty evaluate against all the - * possible names for the EE cert (Common Name (CN) plus all DNS Name: - * subject Alt Name entries). The certList's head is the EE cert and the - * tail is the trust anchor. + * Sets chainHasValidPins to true if the given (host, certList) passes pinning + * checks, or to false otherwise. If the host is pinned, returns true via + * chainHasValidPins if one of the keys in the given certificate chain matches + * the pin set specified by the hostname. The certList's head is the EE cert + * and the tail is the trust anchor. * Note: if an alt name is a wildcard, it won't necessarily find a pinset * that would otherwise be valid for it */ @@ -35,9 +33,9 @@ public: /*out*/ bool& chainHasValidPins, /*optional out*/ PinningTelemetryInfo* pinningTelemetryInfo); /** - * Returns true if there is any intersection between the certificate list - * and the pins specified in the aSHA256key array. Values passed in are - * assumed to be in base64 encoded form + * Sets chainMatchesPinset to true if there is any intersection between the + * certificate list and the pins specified in the aSHA256keys array. + * Values passed in are assumed to be in base64 encoded form. */ static nsresult ChainMatchesPinset(const CERTCertList* certList, const nsTArray& aSHA256keys, diff --git a/security/manager/ssl/nsICertificateDialogs.idl b/security/manager/ssl/nsICertificateDialogs.idl index d7e01aae29..a5f023ffdf 100644 --- a/security/manager/ssl/nsICertificateDialogs.idl +++ b/security/manager/ssl/nsICertificateDialogs.idl @@ -25,18 +25,9 @@ interface nsICertificateDialogs : nsISupports * * @return true if the user allows to import the certificate. */ - boolean confirmDownloadCACert(in nsIInterfaceRequestor ctx, - in nsIX509Cert cert, - out unsigned long trust); - - /** - * UI shown when a web site has delivered a CA certificate to - * be imported, but the certificate is already contained in the - * user's storage. - * - * @param ctx A user interface context. - */ - void notifyCACertExists(in nsIInterfaceRequestor ctx); + boolean confirmDownloadCACert(in nsIInterfaceRequestor ctx, + in nsIX509Cert cert, + out unsigned long trust); /** * UI shown when a user's personal certificate is going to be diff --git a/security/manager/ssl/nsNSSCallbacks.cpp b/security/manager/ssl/nsNSSCallbacks.cpp index 4cb4303b27..a401e83b97 100644 --- a/security/manager/ssl/nsNSSCallbacks.cpp +++ b/security/manager/ssl/nsNSSCallbacks.cpp @@ -84,8 +84,7 @@ nsHTTPDownloadEvent::Run() NS_ENSURE_STATE(chan); // Security operations scheduled through normal HTTP channels are given - // high priority to accommodate real time OCSP transactions. Background CRL - // fetches happen through a different path (CRLDownloadEvent). + // high priority to accommodate real time OCSP transactions. nsCOMPtr priorityChannel = do_QueryInterface(chan); if (priorityChannel) priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST); @@ -117,7 +116,7 @@ nsHTTPDownloadEvent::Run() // Do not use SPDY for internal security operations. It could result // in the silent upgrade to ssl, which in turn could require an SSL - // operation to fufill something like a CRL fetch, which is an + // operation to fulfill something like an OCSP fetch, which is an // endless loop. nsCOMPtr internalChannel = do_QueryInterface(chan); if (internalChannel) { @@ -171,42 +170,49 @@ struct nsCancelHTTPDownloadEvent : nsRunnable { } }; -SECStatus nsNSSHttpServerSession::createSessionFcn(const char *host, - uint16_t portnum, - SEC_HTTP_SERVER_SESSION *pSession) +Result +nsNSSHttpServerSession::createSessionFcn(const char* host, + uint16_t portnum, + SEC_HTTP_SERVER_SESSION* pSession) { - if (!host || !pSession) - return SECFailure; + if (!host || !pSession) { + return Result::FATAL_ERROR_INVALID_ARGS; + } - nsNSSHttpServerSession *hss = new nsNSSHttpServerSession; - if (!hss) - return SECFailure; + nsNSSHttpServerSession* hss = new nsNSSHttpServerSession; + if (!hss) { + return Result::FATAL_ERROR_NO_MEMORY; + } hss->mHost = host; hss->mPort = portnum; *pSession = hss; - return SECSuccess; + return Success; } -SECStatus nsNSSHttpRequestSession::createFcn(SEC_HTTP_SERVER_SESSION session, - const char *http_protocol_variant, - const char *path_and_query_string, - const char *http_request_method, - const PRIntervalTime timeout, - SEC_HTTP_REQUEST_SESSION *pRequest) +Result +nsNSSHttpRequestSession::createFcn(SEC_HTTP_SERVER_SESSION session, + const char* http_protocol_variant, + const char* path_and_query_string, + const char* http_request_method, + const PRIntervalTime timeout, + SEC_HTTP_REQUEST_SESSION* pRequest) { - if (!session || !http_protocol_variant || !path_and_query_string || - !http_request_method || !pRequest) - return SECFailure; + if (!session || !http_protocol_variant || !path_and_query_string || + !http_request_method || !pRequest) { + return Result::FATAL_ERROR_INVALID_ARGS; + } nsNSSHttpServerSession* hss = static_cast(session); - if (!hss) - return SECFailure; + if (!hss) { + return Result::FATAL_ERROR_INVALID_ARGS; + } - nsNSSHttpRequestSession *rs = new nsNSSHttpRequestSession; - if (!rs) - return SECFailure; + nsNSSHttpRequestSession* rs = new nsNSSHttpRequestSession; + if (!rs) { + return Result::FATAL_ERROR_NO_MEMORY; + } rs->mTimeoutInterval = timeout; @@ -227,42 +233,28 @@ SECStatus nsNSSHttpRequestSession::createFcn(SEC_HTTP_SERVER_SESSION session, rs->mRequestMethod = http_request_method; *pRequest = (void*)rs; - return SECSuccess; + return Success; } -SECStatus nsNSSHttpRequestSession::setPostDataFcn(const char *http_data, - const uint32_t http_data_len, - const char *http_content_type) +Result +nsNSSHttpRequestSession::setPostDataFcn(const char* http_data, + const uint32_t http_data_len, + const char* http_content_type) { mHasPostData = true; mPostData.Assign(http_data, http_data_len); mPostContentType.Assign(http_content_type); - return SECSuccess; + return Success; } -SECStatus nsNSSHttpRequestSession::addHeaderFcn(const char *http_header_name, - const char *http_header_value) -{ - return SECFailure; // not yet implemented - - // All http code needs to be postponed to the UI thread. - // Once this gets implemented, we need to add a string list member to - // nsNSSHttpRequestSession and queue up the headers, - // so they can be added in HandleHTTPDownloadPLEvent. - // - // The header will need to be set using - // mHttpChannel->SetRequestHeader(nsDependentCString(http_header_name), - // nsDependentCString(http_header_value), - // false))); -} - -SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, - uint16_t *http_response_code, - const char **http_response_content_type, - const char **http_response_headers, - const char **http_response_data, - uint32_t *http_response_data_len) +Result +nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc** pPollDesc, + uint16_t* http_response_code, + const char** http_response_content_type, + const char** http_response_headers, + const char** http_response_data, + uint32_t* http_response_data_len) { MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("nsNSSHttpRequestSession::trySendAndReceiveFcn to %s\n", mURL.get())); @@ -273,28 +265,25 @@ SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &nrv); if (NS_FAILED(nrv)) { NS_ERROR("Could not get STS service"); - PR_SetError(PR_INVALID_STATE_ERROR, 0); - return SECFailure; + return Result::FATAL_ERROR_INVALID_STATE; } nrv = sts->IsOnCurrentThread(&onSTSThread); if (NS_FAILED(nrv)) { NS_ERROR("IsOnCurrentThread failed"); - PR_SetError(PR_INVALID_STATE_ERROR, 0); - return SECFailure; + return Result::FATAL_ERROR_INVALID_STATE; } if (onSTSThread) { NS_ERROR("nsNSSHttpRequestSession::trySendAndReceiveFcn called on socket " "thread; this will not work."); - PR_SetError(PR_INVALID_STATE_ERROR, 0); - return SECFailure; + return Result::FATAL_ERROR_INVALID_STATE; } const int max_retries = 2; int retry_count = 0; bool retryable_error = false; - SECStatus result_sec_status = SECFailure; + Result rv = Result::ERROR_UNKNOWN_ERROR; do { @@ -313,7 +302,7 @@ SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, ++retry_count; retryable_error = false; - result_sec_status = + rv = internal_send_receive_attempt(retryable_error, pPollDesc, http_response_code, http_response_content_type, http_response_headers, http_response_data, http_response_data_len); @@ -332,7 +321,7 @@ SECStatus nsNSSHttpRequestSession::trySendAndReceiveFcn(PRPollDesc **pPollDesc, retry_count)); } - return result_sec_status; + return rv; } void @@ -350,7 +339,7 @@ nsNSSHttpRequestSession::Release() } } -SECStatus +Result nsNSSHttpRequestSession::internal_send_receive_attempt(bool &retryable_error, PRPollDesc **pPollDesc, uint16_t *http_response_code, @@ -372,9 +361,10 @@ nsNSSHttpRequestSession::internal_send_receive_attempt(bool &retryable_error, acceptableResultSize = *http_response_data_len; *http_response_data_len = 0; } - - if (!mListener) - return SECFailure; + + if (!mListener) { + return Result::FATAL_ERROR_INVALID_STATE; + } Mutex& waitLock = mListener->mLock; CondVar& waitCondition = mListener->mCondition; @@ -382,18 +372,18 @@ nsNSSHttpRequestSession::internal_send_receive_attempt(bool &retryable_error, waitFlag = true; RefPtr event(new nsHTTPDownloadEvent); - if (!event) - return SECFailure; + if (!event) { + return Result::FATAL_ERROR_NO_MEMORY; + } event->mListener = mListener; this->AddRef(); event->mRequestSession = this; nsresult rv = NS_DispatchToMainThread(event); - if (NS_FAILED(rv)) - { + if (NS_FAILED(rv)) { event->mResponsibleForDoneSignal = false; - return SECFailure; + return Result::FATAL_ERROR_LIBRARY_FAILURE; } bool request_canceled = false; @@ -465,37 +455,33 @@ nsNSSHttpRequestSession::internal_send_receive_attempt(bool &retryable_error, } } - if (request_canceled) - return SECFailure; + if (request_canceled) { + return Result::ERROR_OCSP_SERVER_ERROR; + } - if (NS_FAILED(mListener->mResultCode)) - { - if (mListener->mResultCode == NS_ERROR_CONNECTION_REFUSED - || - mListener->mResultCode == NS_ERROR_NET_RESET) - { + if (NS_FAILED(mListener->mResultCode)) { + if (mListener->mResultCode == NS_ERROR_CONNECTION_REFUSED || + mListener->mResultCode == NS_ERROR_NET_RESET) { retryable_error = true; } - return SECFailure; + return Result::ERROR_OCSP_SERVER_ERROR; } if (http_response_code) *http_response_code = mListener->mHttpResponseCode; - if (mListener->mHttpRequestSucceeded && http_response_data && http_response_data_len) { - + if (mListener->mHttpRequestSucceeded && http_response_data && + http_response_data_len) { *http_response_data_len = mListener->mResultLen; - + // acceptableResultSize == 0 means: any size is acceptable - if (acceptableResultSize != 0 - && - acceptableResultSize < mListener->mResultLen) - { - return SECFailure; + if (acceptableResultSize != 0 && + acceptableResultSize < mListener->mResultLen) { + return Result::ERROR_OCSP_SERVER_ERROR; } - // return data by reference, result data will be valid - // until "this" gets destroyed by NSS + // Return data by reference, result data will be valid until "this" gets + // destroyed. *http_response_data = (const char*)mListener->mResultData; } @@ -505,21 +491,7 @@ nsNSSHttpRequestSession::internal_send_receive_attempt(bool &retryable_error, } } - return SECSuccess; -} - -SECStatus nsNSSHttpRequestSession::cancelFcn() -{ - // As of today, only the blocking variant of the http interface - // has been implemented. Implementing cancelFcn will be necessary - // as soon as we implement the nonblocking variant. - return SECSuccess; -} - -SECStatus nsNSSHttpRequestSession::freeFcn() -{ - Release(); - return SECSuccess; + return Success; } nsNSSHttpRequestSession::nsNSSHttpRequestSession() @@ -534,23 +506,6 @@ nsNSSHttpRequestSession::~nsNSSHttpRequestSession() { } -SEC_HttpClientFcn nsNSSHttpInterface::sNSSInterfaceTable; - -void nsNSSHttpInterface::initTable() -{ - sNSSInterfaceTable.version = 1; - SEC_HttpClientFcnV1 &v1 = sNSSInterfaceTable.fcnTable.ftable1; - v1.createSessionFcn = createSessionFcn; - v1.keepAliveSessionFcn = keepAliveFcn; - v1.freeSessionFcn = freeSessionFcn; - v1.createFcn = createFcn; - v1.setPostDataFcn = setPostDataFcn; - v1.addHeaderFcn = addHeaderFcn; - v1.trySendAndReceiveFcn = trySendAndReceiveFcn; - v1.cancelFcn = cancelFcn; - v1.freeFcn = freeFcn; -} - nsHTTPListener::nsHTTPListener() : mResultData(nullptr), mResultLen(0), diff --git a/security/manager/ssl/nsNSSCallbacks.h b/security/manager/ssl/nsNSSCallbacks.h index 65735a80f5..8ec6f95d1d 100644 --- a/security/manager/ssl/nsNSSCallbacks.h +++ b/security/manager/ssl/nsNSSCallbacks.h @@ -4,19 +4,21 @@ * 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 _NSNSSCALLBACKS_H_ -#define _NSNSSCALLBACKS_H_ +#ifndef nsNSSCallbacks_h +#define nsNSSCallbacks_h -#include "nsAutoPtr.h" -#include "nsCOMPtr.h" -#include "pk11func.h" -#include "nspr.h" -#include "ocspt.h" -#include "nsIStreamLoader.h" +#include "mozilla/Attributes.h" #include "mozilla/CondVar.h" #include "mozilla/Mutex.h" -#include "mozilla/Attributes.h" +#include "nsAutoPtr.h" +#include "nsCOMPtr.h" +#include "nsIStreamLoader.h" +#include "nspr.h" #include "nsString.h" +#include "pk11func.h" +#include "pkix/pkixtypes.h" + +#include "ocspt.h" // Must be included after pk11func.h. class nsILoadGroup; @@ -55,11 +57,11 @@ public: const uint8_t* mResultData; // allocated in loader, but owned by listener uint32_t mResultLen; - + mozilla::Mutex mLock; mozilla::CondVar mCondition; volatile bool mWaitFlag; - + bool mResponsibleForDoneSignal; void send_done_signal(); @@ -75,12 +77,14 @@ public: class nsNSSHttpServerSession { public: - nsCString mHost; - uint16_t mPort; + typedef mozilla::pkix::Result Result; - static SECStatus createSessionFcn(const char *host, - uint16_t portnum, - SEC_HTTP_SERVER_SESSION *pSession); + nsCString mHost; + uint16_t mPort; + + static Result createSessionFcn(const char* host, + uint16_t portnum, + SEC_HTTP_SERVER_SESSION* pSession); }; class nsNSSHttpRequestSession @@ -89,137 +93,100 @@ protected: mozilla::ThreadSafeAutoRefCnt mRefCount; public: - static SECStatus createFcn(SEC_HTTP_SERVER_SESSION session, - const char *http_protocol_variant, - const char *path_and_query_string, - const char *http_request_method, - const PRIntervalTime timeout, - SEC_HTTP_REQUEST_SESSION *pRequest); + typedef mozilla::pkix::Result Result; - SECStatus setPostDataFcn(const char *http_data, - const uint32_t http_data_len, - const char *http_content_type); + static Result createFcn(SEC_HTTP_SERVER_SESSION session, + const char* httpProtocolVariant, + const char* pathAndQueryString, + const char* httpRequestMethod, + const PRIntervalTime timeout, + SEC_HTTP_REQUEST_SESSION* pRequest); - SECStatus addHeaderFcn(const char *http_header_name, - const char *http_header_value); + Result setPostDataFcn(const char* httpData, + const uint32_t httpDataLen, + const char* httpContentType); - SECStatus trySendAndReceiveFcn(PRPollDesc **pPollDesc, - uint16_t *http_response_code, - const char **http_response_content_type, - const char **http_response_headers, - const char **http_response_data, - uint32_t *http_response_data_len); - - SECStatus cancelFcn(); - SECStatus freeFcn(); + Result trySendAndReceiveFcn(PRPollDesc** pPollDesc, + uint16_t* httpResponseCode, + const char** httpResponseContentType, + const char** httpResponseHeaders, + const char** httpResponseData, + uint32_t* httpResponseDataLen); void AddRef(); void Release(); nsCString mURL; nsCString mRequestMethod; - + bool mHasPostData; nsCString mPostData; nsCString mPostContentType; - + PRIntervalTime mTimeoutInterval; - + RefPtr mListener; - + protected: nsNSSHttpRequestSession(); ~nsNSSHttpRequestSession(); - SECStatus internal_send_receive_attempt(bool &retryable_error, - PRPollDesc **pPollDesc, - uint16_t *http_response_code, - const char **http_response_content_type, - const char **http_response_headers, - const char **http_response_data, - uint32_t *http_response_data_len); + Result internal_send_receive_attempt(bool& retryableError, + PRPollDesc** pPollDesc, + uint16_t* httpResponseCode, + const char** httpResponseContentType, + const char** httpResponseHeaders, + const char** httpResponseData, + uint32_t* httpResponseDataLen); }; class nsNSSHttpInterface { public: - static SECStatus createSessionFcn(const char *host, - uint16_t portnum, - SEC_HTTP_SERVER_SESSION *pSession) + typedef mozilla::pkix::Result Result; + + static Result createSessionFcn(const char* host, + uint16_t portnum, + SEC_HTTP_SERVER_SESSION* pSession) { return nsNSSHttpServerSession::createSessionFcn(host, portnum, pSession); } - static SECStatus keepAliveFcn(SEC_HTTP_SERVER_SESSION session, - PRPollDesc **pPollDesc) + static Result createFcn(SEC_HTTP_SERVER_SESSION session, + const char* httpProtocolVariant, + const char* pathAndQueryString, + const char* httpRequestMethod, + const PRIntervalTime timeout, + SEC_HTTP_REQUEST_SESSION* pRequest) { - // Not yet implemented, however, Necko does transparent keep-alive - // anyway, when enabled in Necko's prefs. - return SECSuccess; + return nsNSSHttpRequestSession::createFcn(session, httpProtocolVariant, + pathAndQueryString, + httpRequestMethod, timeout, + pRequest); } - static SECStatus freeSessionFcn(SEC_HTTP_SERVER_SESSION session) - { - delete static_cast(session); - return SECSuccess; - } - - static SECStatus createFcn(SEC_HTTP_SERVER_SESSION session, - const char *http_protocol_variant, - const char *path_and_query_string, - const char *http_request_method, - const PRIntervalTime timeout, - SEC_HTTP_REQUEST_SESSION *pRequest) - { - return nsNSSHttpRequestSession::createFcn(session, http_protocol_variant, - path_and_query_string, http_request_method, - timeout, pRequest); - } - - static SECStatus setPostDataFcn(SEC_HTTP_REQUEST_SESSION request, - const char *http_data, - const uint32_t http_data_len, - const char *http_content_type) + static Result setPostDataFcn(SEC_HTTP_REQUEST_SESSION request, + const char* httpData, + const uint32_t httpDataLen, + const char* httpContentType) { return static_cast(request) - ->setPostDataFcn(http_data, http_data_len, http_content_type); + ->setPostDataFcn(httpData, httpDataLen, httpContentType); } - static SECStatus addHeaderFcn(SEC_HTTP_REQUEST_SESSION request, - const char *http_header_name, - const char *http_header_value) + static Result trySendAndReceiveFcn(SEC_HTTP_REQUEST_SESSION request, + PRPollDesc** pPollDesc, + uint16_t* httpResponseCode, + const char** httpResponseContentType, + const char** httpResponseHeaders, + const char** httpResponseData, + uint32_t* httpResponseDataLen) { return static_cast(request) - ->addHeaderFcn(http_header_name, http_header_value); + ->trySendAndReceiveFcn(pPollDesc, httpResponseCode, + httpResponseContentType, httpResponseHeaders, + httpResponseData, httpResponseDataLen); } - - static SECStatus trySendAndReceiveFcn(SEC_HTTP_REQUEST_SESSION request, - PRPollDesc **pPollDesc, - uint16_t *http_response_code, - const char **http_response_content_type, - const char **http_response_headers, - const char **http_response_data, - uint32_t *http_response_data_len) - { - return static_cast(request) - ->trySendAndReceiveFcn(pPollDesc, http_response_code, http_response_content_type, - http_response_headers, http_response_data, http_response_data_len); - } - - static SECStatus cancelFcn(SEC_HTTP_REQUEST_SESSION request) - { - return static_cast(request) - ->cancelFcn(); - } - - static SECStatus freeFcn(SEC_HTTP_REQUEST_SESSION request) - { - return static_cast(request) - ->freeFcn(); - } - - static void initTable(); - static SEC_HttpClientFcn sNSSInterfaceTable; }; -#endif // _NSNSSCALLBACKS_H_ +#endif // nsNSSCallbacks_h diff --git a/security/manager/ssl/nsNSSCertificateFakeTransport.cpp b/security/manager/ssl/nsNSSCertificateFakeTransport.cpp index 4e9f44ea60..81863c7c6e 100644 --- a/security/manager/ssl/nsNSSCertificateFakeTransport.cpp +++ b/security/manager/ssl/nsNSSCertificateFakeTransport.cpp @@ -487,7 +487,9 @@ nsNSSCertListFakeTransport::Read(nsIObjectInputStream* aStream) } nsCOMPtr cert = do_QueryInterface(certSupports); - mFakeCertList.append(cert); + if (!mFakeCertList.append(cert)) { + return NS_ERROR_OUT_OF_MEMORY; + } } return rv; diff --git a/security/manager/ssl/nsNSSComponent.cpp b/security/manager/ssl/nsNSSComponent.cpp index 4d3038871b..c4c0ad4a2d 100644 --- a/security/manager/ssl/nsNSSComponent.cpp +++ b/security/manager/ssl/nsNSSComponent.cpp @@ -134,7 +134,7 @@ bool EnsureNSSInitialized(EnsureNSSOperator op) case nssInitFailed: NS_ASSERTION(loading, "Bad call to EnsureNSSInitialized(nssInitFailed)"); loading = false; - // no break + MOZ_FALLTHROUGH; case nssShutdown: PR_AtomicSet(&haveLoaded, 0); @@ -1147,8 +1147,6 @@ nsNSSComponent::InitializeNSS() // dynamic options from prefs setValidationOptions(true, lock); - mHttpForNSS.initTable(); - #ifndef MOZ_NO_SMART_CARDS LaunchSmartCardThreads(); #endif diff --git a/security/manager/ssl/nsSecureBrowserUIImpl.cpp b/security/manager/ssl/nsSecureBrowserUIImpl.cpp index 7b61721661..b5ed3c854d 100644 --- a/security/manager/ssl/nsSecureBrowserUIImpl.cpp +++ b/security/manager/ssl/nsSecureBrowserUIImpl.cpp @@ -1320,7 +1320,7 @@ nsSecureBrowserUIImpl::GetSSLStatus(nsISSLStatus** _result) break; default: - NS_NOTREACHED("if this is reached you must add more entries to the switch"); + MOZ_FALLTHROUGH_ASSERT("if this is reached you must add more entries to the switch"); case lis_no_security: *_result = nullptr; return NS_OK; diff --git a/security/manager/tools/genHPKPStaticPins.js b/security/manager/tools/genHPKPStaticPins.js index 6e9735f85b..559ccb9709 100644 --- a/security/manager/tools/genHPKPStaticPins.js +++ b/security/manager/tools/genHPKPStaticPins.js @@ -53,17 +53,13 @@ const DOMAINHEADER = "/* Domainlist */\n" + " const bool mTestMode;\n" + " const bool mIsMoz;\n" + " const int32_t mId;\n" + - " const StaticPinset* pinset;\n" + + " const StaticFingerprints* pinset;\n" + "};\n\n"; const PINSETDEF = "/* Pinsets are each an ordered list by the actual value of the fingerprint */\n" + "struct StaticFingerprints {\n" + " const size_t size;\n" + " const char* const* data;\n" + - "};\n\n" + - "struct StaticPinset {\n" + - " const StaticFingerprints* sha1;\n" + - " const StaticFingerprints* sha256;\n" + "};\n\n"; // Command-line arguments @@ -460,13 +456,11 @@ function writeFullPinset(certNameToSKD, certSKDToName, pinset) { } writeFingerprints(certNameToSKD, certSKDToName, pinset.name, pinset.sha256_hashes); - writeString("static const StaticPinset " + prefix + " = {\n" + - " nullptr,\n &" + prefix + "_sha256\n};\n\n"); } function writeFingerprints(certNameToSKD, certSKDToName, name, hashes) { - let varPrefix = "kPinset_" + name + "_sha256"; - writeString("static const char* " + varPrefix + "_Data[] = {\n"); + let varPrefix = "kPinset_" + name; + writeString("static const char* const " + varPrefix + "_Data[] = {\n"); let SKDList = []; for (let certName of hashes) { if (!(certName in certNameToSKD)) { diff --git a/security/pkix/moz.build b/security/pkix/moz.build index 14f14a1a6a..04b5a75042 100644 --- a/security/pkix/moz.build +++ b/security/pkix/moz.build @@ -31,3 +31,8 @@ include('warnings.mozbuild') Library('mozillapkix') FINAL_LIBRARY = 'xul' + +if CONFIG['_MSC_VER']: + # This is intended as a temporary hack to support building with VS2015. + # declaration of '*' hides class member + CXXFLAGS += ['-wd4458'] \ No newline at end of file diff --git a/security/pkix/test/gtest/moz.build b/security/pkix/test/gtest/moz.build index 560c1e1db5..1de63256c4 100644 --- a/security/pkix/test/gtest/moz.build +++ b/security/pkix/test/gtest/moz.build @@ -53,4 +53,8 @@ elif CONFIG['_MSC_VER']: '-wd4625', # copy constructor could not be generated. '-wd4626', # assugment operator could not be generated. '-wd4640', # construction of local static object is not thread safe. + + # This is intended as a temporary hack to support building with VS2015. + # declaration of '*' hides class member + '-wd4458', ] diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp index e014158d00..2c01b565dd 100644 --- a/security/sandbox/linux/SandboxFilter.cpp +++ b/security/sandbox/linux/SandboxFilter.cpp @@ -32,6 +32,15 @@ using namespace sandbox::bpf_dsl; #define CASES SANDBOX_BPF_DSL_CASES +// Fill in defines in case of old headers. +// (Warning: these are wrong on PA-RISC.) +#ifndef MADV_NOHUGEPAGE +#define MADV_NOHUGEPAGE 15 +#endif +#ifndef MADV_DONTDUMP +#define MADV_DONTDUMP 16 +#endif + // To avoid visual confusion between "ifdef ANDROID" and "ifndef ANDROID": #ifndef ANDROID #define DESKTOP @@ -695,6 +704,10 @@ public: case __NR_madvise: { Arg advice(2); return If(advice == MADV_DONTNEED, Allow()) +#ifdef MOZ_ASAN + .ElseIf(advice == MADV_NOHUGEPAGE, Allow()) + .ElseIf(advice == MADV_DONTDUMP, Allow()) +#endif .Else(InvalidSyscall()); } diff --git a/services/crypto/component/nsSyncJPAKE.cpp b/services/crypto/component/nsSyncJPAKE.cpp index e72e908193..4246a1b8aa 100644 --- a/services/crypto/component/nsSyncJPAKE.cpp +++ b/services/crypto/component/nsSyncJPAKE.cpp @@ -132,6 +132,11 @@ NS_IMETHODIMP nsSyncJPAKE::Round1(const nsACString & aSignerID, nsACString & aGV2, nsACString & aR2) { + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return NS_ERROR_NOT_AVAILABLE; + } + NS_ENSURE_STATE(round == JPAKENotStarted); NS_ENSURE_STATE(key == nullptr); @@ -141,9 +146,9 @@ NS_IMETHODIMP nsSyncJPAKE::Round1(const nsACString & aSignerID, CKM_NSS_JPAKE_FINAL_SHA256 }; - PK11SlotInfo * slot = PK11_GetBestSlotMultiple(mechanisms, - NUM_ELEM(mechanisms), - nullptr); + ScopedPK11SlotInfo slot(PK11_GetBestSlotMultiple(mechanisms, + NUM_ELEM(mechanisms), + nullptr)); NS_ENSURE_STATE(slot != nullptr); CK_BYTE pBuf[(NUM_ELEM(p) - 1) / 2]; @@ -208,6 +213,11 @@ NS_IMETHODIMP nsSyncJPAKE::Round2(const nsACString & aPeerID, nsACString & aGVA, nsACString & aRA) { + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return NS_ERROR_NOT_AVAILABLE; + } + NS_ENSURE_STATE(round == JPAKEBeforeRound2); NS_ENSURE_STATE(key != nullptr); NS_ENSURE_ARG(!aPeerID.IsEmpty()); @@ -267,28 +277,27 @@ NS_IMETHODIMP nsSyncJPAKE::Round2(const nsACString & aPeerID, { CKA_NSS_JPAKE_PEERID, (CK_BYTE *) aPeerID.Data(), aPeerID.Length(), }, { CKA_KEY_TYPE, &keyType, sizeof keyType } }; - PK11SymKey * newKey = PK11_DeriveWithTemplate(key, - CKM_NSS_JPAKE_ROUND2_SHA256, - ¶msItem, - CKM_NSS_JPAKE_FINAL_SHA256, - CKA_DERIVE, 0, - keyTemplate, - NUM_ELEM(keyTemplate), - false); + ScopedPK11SymKey newKey(PK11_DeriveWithTemplate(key, + CKM_NSS_JPAKE_ROUND2_SHA256, + ¶msItem, + CKM_NSS_JPAKE_FINAL_SHA256, + CKA_DERIVE, 0, + keyTemplate, + NUM_ELEM(keyTemplate), + false)); if (newKey != nullptr) { if (toHexString(rp.A.pGX, rp.A.ulGXLen, aA) && toHexString(rp.A.pGV, rp.A.ulGVLen, aGVA) && toHexString(rp.A.pR, rp.A.ulRLen, aRA)) { round = JPAKEAfterRound2; - PK11_FreeSymKey(key); - key = newKey; + key = newKey.forget(); return NS_OK; } else { - PK11_FreeSymKey(newKey); rv = NS_ERROR_OUT_OF_MEMORY; } - } else + } else { rv = mapErrno(); + } return rv; } @@ -304,10 +313,10 @@ setBase64(const unsigned char * data, unsigned len, nsACString & out) if (out.SetCapacity(len, fallible)) { out.SetLength(0); out.Append(base64, len); - PORT_Free((void*) base64); } else { rv = NS_ERROR_OUT_OF_MEMORY; } + PORT_Free((void*) base64); } else { rv = NS_ERROR_OUT_OF_MEMORY; } @@ -355,6 +364,11 @@ NS_IMETHODIMP nsSyncJPAKE::Final(const nsACString & aB, nsACString & aAES256Key, nsACString & aHMAC256Key) { + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return NS_ERROR_NOT_AVAILABLE; + } + static const unsigned AES256_KEY_SIZE = 256 / 8; static const unsigned HMAC_SHA256_KEY_SIZE = 256 / 8; CK_EXTRACT_PARAMS aesBitPosition = 0; @@ -377,10 +391,10 @@ NS_IMETHODIMP nsSyncJPAKE::Final(const nsACString & aB, SECItem paramsItem; paramsItem.data = (unsigned char *) &rp; paramsItem.len = sizeof rp; - PK11SymKey * keyMaterial = PK11_Derive(key, CKM_NSS_JPAKE_FINAL_SHA256, - ¶msItem, CKM_NSS_HKDF_SHA256, - CKA_DERIVE, 0); - PK11SymKey * keyBlock = nullptr; + ScopedPK11SymKey keyMaterial(PK11_Derive(key, CKM_NSS_JPAKE_FINAL_SHA256, + ¶msItem, CKM_NSS_HKDF_SHA256, + CKA_DERIVE, 0)); + ScopedPK11SymKey keyBlock; if (keyMaterial == nullptr) rv = mapErrno(); @@ -413,16 +427,11 @@ NS_IMETHODIMP nsSyncJPAKE::Final(const nsACString & aB, if (rv == NS_OK) { SECStatus srv = PK11_ExtractKeyValue(keyMaterial); - NS_ENSURE_TRUE(srv == SECSuccess, NS_ERROR_UNEXPECTED); // XXX leaks + NS_ENSURE_TRUE(srv == SECSuccess, NS_ERROR_UNEXPECTED); SECItem * keyMaterialBytes = PK11_GetKeyData(keyMaterial); NS_ENSURE_TRUE(keyMaterialBytes != nullptr, NS_ERROR_UNEXPECTED); } - if (keyBlock != nullptr) - PK11_FreeSymKey(keyBlock); - if (keyMaterial != nullptr) - PK11_FreeSymKey(keyMaterial); - return rv; } @@ -433,8 +442,24 @@ nsSyncJPAKE::nsSyncJPAKE() : round(JPAKENotStarted), key(nullptr) { } nsSyncJPAKE::~nsSyncJPAKE() { - if (key != nullptr) - PK11_FreeSymKey(key); + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return; + } + destructorSafeDestroyNSSReference(); + shutdown(calledFromObject); +} + +void +nsSyncJPAKE::virtualDestroyNSSReference() +{ + destructorSafeDestroyNSSReference(); +} + +void +nsSyncJPAKE::destructorSafeDestroyNSSReference() +{ + key.dispose(); } static const mozilla::Module::CIDEntry kServicesCryptoCIDs[] = { diff --git a/services/crypto/component/nsSyncJPAKE.h b/services/crypto/component/nsSyncJPAKE.h index b8ba3dabdf..a8da534451 100644 --- a/services/crypto/component/nsSyncJPAKE.h +++ b/services/crypto/component/nsSyncJPAKE.h @@ -4,7 +4,9 @@ #ifndef nsSyncJPAKE_h__ #define nsSyncJPAKE_h__ +#include "ScopedNSSTypes.h" #include "nsISyncJPAKE.h" +#include "nsNSSShutDown.h" #define NS_SYNCJPAKE_CONTRACTID \ "@mozilla.org/services-crypto/sync-jpake;1" @@ -12,9 +14,10 @@ #define NS_SYNCJPAKE_CID \ {0x0b9721c0, 0x1805, 0x47c3, {0x86, 0xce, 0x68, 0x13, 0x79, 0x5a, 0x78, 0x3f}} -typedef struct PK11SymKeyStr PK11SymKey; +using namespace mozilla; class nsSyncJPAKE : public nsISyncJPAKE + , public nsNSSShutDownObject { public: NS_DECL_ISUPPORTS @@ -23,8 +26,11 @@ public: protected: virtual ~nsSyncJPAKE(); private: + virtual void virtualDestroyNSSReference() override; + void destructorSafeDestroyNSSReference(); + enum { JPAKENotStarted, JPAKEBeforeRound2, JPAKEAfterRound2 } round; - PK11SymKey * key; + ScopedPK11SymKey key; }; NS_IMPL_ISUPPORTS(nsSyncJPAKE, nsISyncJPAKE) diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 305715a134..f46e615e12 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -23,7 +23,7 @@ "A11Y_UPDATE_TIME": { "expires_in_version": "default", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "time spent updating accessibility (ms)" }, @@ -31,7 +31,7 @@ "expires_in_version": "never", "kind": "enumerated", "n_values": 15, - "keyed": "true", + "keyed": true, "description": "Reasons why add-on shims were used, keyed by add-on ID." }, "BROWSER_SHIM_USAGE_BLOCKED": { @@ -73,15 +73,15 @@ "AUDIOSTREAM_FIRST_OPEN_MS": { "expires_in_version": "50", "kind": "exponential", - "high": "10000", - "n_buckets": "50", + "high": 10000, + "n_buckets": 50, "description": "The length of time (in milliseconds) for the first open of AudioStream." }, "AUDIOSTREAM_LATER_OPEN_MS": { "expires_in_version": "50", "kind": "exponential", - "high": "10000", - "n_buckets": "50", + "high": 10000, + "n_buckets": 50, "description": "The length of time (in milliseconds) for the subsequent opens of AudioStream." }, "BACKGROUNDFILESAVER_THREAD_COUNT": { @@ -101,7 +101,7 @@ "bug_numbers": [1238040], "expires_in_version": "55", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 50, "description": "Duration of a checkerboard event in milliseconds" }, @@ -110,7 +110,7 @@ "bug_numbers": [1238040], "expires_in_version": "55", "kind": "exponential", - "high": "3840 * 2160 * 8", + "high": 66355200, "n_buckets": 50, "description": "Peak number of CSS pixels checkerboarded during a checkerboard event (the high value is the size of a 4k display with max APZ zooming)" }, @@ -119,7 +119,7 @@ "bug_numbers": [1238040], "expires_in_version": "55", "kind": "exponential", - "high": "1000000", + "high": 1000000, "n_buckets": 50, "description": "Duration of a chunk of time (in ms) that could reasonably have had checkerboarding" }, @@ -128,7 +128,7 @@ "bug_numbers": [1238040], "expires_in_version": "55", "kind": "exponential", - "high": "1073741824", + "high": 1073741824, "n_buckets": 50, "description": "Opaque measure of the severity of a checkerboard event" }, @@ -136,41 +136,41 @@ "expires_in_version": "never", "description": "Composite times in milliseconds", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50 }, "COMPOSITE_FRAME_ROUNDTRIP_TIME" : { "expires_in_version": "never", "description": "Time from vsync to finishing a composite in milliseconds.", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50 }, "CYCLE_COLLECTOR": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent on one cycle collection (ms)" }, "CYCLE_COLLECTOR_WORKER": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent on one cycle collection in a worker (ms)" }, "CYCLE_COLLECTOR_FULL": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Full pause time for one cycle collection, including preparation (ms)" }, "CYCLE_COLLECTOR_MAX_PAUSE": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Longest pause for an individual slice of one cycle collection, including preparation (ms)" }, @@ -187,42 +187,42 @@ "CYCLE_COLLECTOR_VISITED_REF_COUNTED": { "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 50, "description": "Number of ref counted objects visited by the cycle collector" }, "CYCLE_COLLECTOR_WORKER_VISITED_REF_COUNTED": { "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 50, "description": "Number of ref counted objects visited by the cycle collector in a worker" }, "CYCLE_COLLECTOR_VISITED_GCED": { "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 50, "description": "Number of JS objects visited by the cycle collector" }, "CYCLE_COLLECTOR_WORKER_VISITED_GCED": { "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 50, "description": "Number of JS objects visited by the cycle collector in a worker" }, "CYCLE_COLLECTOR_COLLECTED": { "expires_in_version": "never", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 50, "description": "Number of objects collected by the cycle collector" }, "CYCLE_COLLECTOR_WORKER_COLLECTED": { "expires_in_version": "never", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 50, "description": "Number of objects collected by the cycle collector in a worker" }, @@ -239,7 +239,7 @@ "CYCLE_COLLECTOR_TIME_BETWEEN": { "expires_in_version": "never", "kind": "exponential", - "high": "120", + "high": 120, "n_buckets": 50, "description": "Time spent in between cycle collections (seconds)" }, @@ -256,14 +256,14 @@ "CYCLE_COLLECTOR_ASYNC_SNOW_WHITE_FREEING": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent on one asynchronous SnowWhite freeing (ms)" }, "DEFERRED_FINALIZE_ASYNC": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Pause time for asynchronous deferred finalization (ms)" }, @@ -288,7 +288,7 @@ "FORGET_SKIPPABLE_MAX": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Max time spent on one forget skippable (ms)" }, @@ -306,7 +306,7 @@ "GC_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent running JS GC (ms)" }, @@ -314,7 +314,7 @@ "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"], "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 10, "description": "Requested GC slice budget (ms)" }, @@ -322,28 +322,28 @@ "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"], "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent running JS GC when animating (ms)" }, "GC_MAX_PAUSE_MS": { "expires_in_version": "never", "kind": "linear", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "Longest GC slice in a GC (ms)" }, "GC_MARK_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent running JS GC mark phase (ms)" }, "GC_SWEEP_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent running JS GC sweep phase (ms)" }, @@ -351,28 +351,28 @@ "alert_emails": ["dev-telemetry-gc-alerts@mozilla.org"], "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent running JS GC compact phase (ms)" }, "GC_MARK_ROOTS_MS": { "expires_in_version": "never", "kind": "linear", - "high": "200", + "high": 200, "n_buckets": 50, "description": "Time spent marking GC roots (ms)" }, "GC_MARK_GRAY_MS": { "expires_in_version": "never", "kind": "linear", - "high": "200", + "high": 200, "n_buckets": 50, "description": "Time spent marking gray GC objects (ms)" }, "GC_SLICE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent running a JS GC slice (ms)" }, @@ -386,7 +386,7 @@ "GC_MMU_50": { "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 20, "description": "Minimum percentage of time spent outside GC over any 50ms window" }, @@ -408,7 +408,7 @@ "GC_SCC_SWEEP_TOTAL_MS": { "expires_in_version": "never", "kind": "linear", - "high": "500", + "high": 500, "n_buckets": 50, "description": "Time spent sweeping compartment SCCs (ms)" }, @@ -512,8 +512,8 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "low": "32 * 1024", - "high": "16 * 1024 * 1024", + "low": 32768, + "high": 16777216, "n_buckets": 100, "bug_numbers": [1226196], "description": "Resident memory size (KB)" @@ -543,8 +543,8 @@ "bug_numbers": [1198209], "expires_in_version": "never", "kind": "exponential", - "low": "32 * 1024", - "high": "16 * 1024 * 1024", + "low": 32768, + "high": 16777216, "n_buckets": 100, "description": "Unique Set Size (KB)" }, @@ -552,8 +552,8 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "low": "32 * 1024", - "high": "16 * 1024 * 1024", + "low": 32768, + "high": 16777216, "n_buckets": 100, "description": "Virtual memory size (KB)" }, @@ -561,8 +561,8 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "low": "32 * 1024", - "high": "16 * 1024 * 1024", + "low": 32768, + "high": 16777216, "n_buckets": 100, "description": "Maximum-sized block of contiguous virtual memory (KB)" }, @@ -570,7 +570,7 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "Total JavaScript compartments used for add-ons and internals." }, @@ -578,7 +578,7 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "Total JavaScript compartments used for web pages" }, @@ -587,7 +587,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1024, - "high": "16 * 1024 * 1024", + "high": 16777216, "n_buckets": 200, "description": "Peak memory used by the main JSRuntime to store transient data (KB)" }, @@ -596,7 +596,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1024, - "high": "16 * 1024 * 1024", + "high": 16777216, "n_buckets": 200, "description": "Memory used by the garbage-collected JavaScript heap (KB)" }, @@ -605,7 +605,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1024, - "high": "512 * 1024", + "high": 524288, "n_buckets": 50, "description": "Memory used by SQLite (KB)" }, @@ -614,7 +614,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1024, - "high": "1024 * 1024", + "high": 1048576, "n_buckets": 50, "description": "Memory used for uncompressed, in-use content images (KB)" }, @@ -623,7 +623,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1024, - "high": "16 * 1024 * 1024", + "high": 16777216, "n_buckets": 200, "description": "Heap memory allocated (KB)" }, @@ -632,7 +632,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1024, - "high": "512 * 1024", + "high": 524288, "n_buckets": 50, "description": "Committed, unused heap memory (KB)" }, @@ -649,7 +649,7 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "128", + "high": 128, "n_buckets": 32, "description": "Number of ghost windows" }, @@ -657,7 +657,7 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "1024", + "high": 1024, "n_buckets": 10, "description": "Time(ms) to purge dirty heap pages." }, @@ -665,7 +665,7 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "1024", + "high": 1024, "n_buckets": 21, "description": "Number of low-virtual-memory events fired since last ping", "cpp_guard": "XP_WIN" @@ -674,7 +674,7 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "1024", + "high": 1024, "n_buckets": 21, "description": "Number of low-physical-memory events fired since last ping", "cpp_guard": "XP_WIN" @@ -683,7 +683,7 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "1024", + "high": 1024, "n_buckets": 21, "description": "Number of low-commit-space events fired since last ping", "cpp_guard": "XP_WIN" @@ -692,7 +692,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 12, "description": "ProcessIoCounters.ReadOperationCount before glue startup", "cpp_guard": "XP_WIN" @@ -701,7 +701,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "exponential", - "high": "50 * 1024", + "high": 51200, "n_buckets": 12, "description": "ProcessIoCounters.ReadTransferCount before glue startup (KB)", "cpp_guard": "XP_WIN" @@ -710,7 +710,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "default", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 12, "description": "ProcessIoCounters.ReadOperationCount after glue startup", "cpp_guard": "XP_WIN" @@ -719,7 +719,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "default", "kind": "exponential", - "high": "50 * 1024", + "high": 51200, "n_buckets": 12, "description": "ProcessIoCounters.ReadTransferCount after glue startup (KB)", "cpp_guard": "XP_WIN" @@ -728,7 +728,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 12, "description": "Hard faults count before glue startup", "cpp_guard": "XP_UNIX" @@ -737,7 +737,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 12, "description": "Hard faults count after glue startup", "cpp_guard": "XP_UNIX" @@ -746,7 +746,7 @@ "expires_in_version": "default", "kind": "exponential", "low": 8, - "high": "64 * 1024", + "high": 65536, "n_buckets": 13, "description": "Hard page faults (since last telemetry ping)", "cpp_guard": "XP_UNIX" @@ -754,21 +754,21 @@ "FONTLIST_INITOTHERFAMILYNAMES": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "Time(ms) spent on reading other family names from all fonts" }, "FONTLIST_INITFACENAMELISTS": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "Time(ms) spent on reading family names from all fonts" }, "DWRITEFONT_DELAYEDINITFONTLIST_TOTAL": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "gfxDWriteFontList::DelayedInitFontList Total (ms)", "cpp_guard": "XP_WIN" @@ -776,7 +776,7 @@ "DWRITEFONT_DELAYEDINITFONTLIST_COUNT": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "gfxDWriteFontList::DelayedInitFontList Font Family Count", "cpp_guard": "XP_WIN" @@ -784,7 +784,7 @@ "DWRITEFONT_DELAYEDINITFONTLIST_COLLECT": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "gfxDWriteFontList::DelayedInitFontList GetSystemFontCollection (ms)", "cpp_guard": "XP_WIN" @@ -799,7 +799,7 @@ "GDI_INITFONTLIST_TOTAL": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "gfxGDIFontList::InitFontList Total (ms)", "cpp_guard": "XP_WIN" @@ -807,7 +807,7 @@ "MAC_INITFONTLIST_TOTAL": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "gfxMacPlatformFontList::InitFontList Total (ms)", "cpp_guard": "XP_MACOSX" @@ -815,14 +815,14 @@ "SYSTEM_FONT_FALLBACK": { "expires_in_version": "never", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 50, "description": "System font fallback (us)" }, "SYSTEM_FONT_FALLBACK_FIRST": { "expires_in_version": "never", "kind": "exponential", - "high": "40000", + "high": 40000, "n_buckets": 20, "description": "System font fallback, first call (ms)" }, @@ -835,21 +835,21 @@ "GRADIENT_DURATION": { "expires_in_version": "default", "kind": "exponential", - "high": "50000000", + "high": 50000000, "n_buckets": 20, "description": "Gradient generation time (us)" }, "GRADIENT_RETENTION_TIME": { "expires_in_version": "never", "kind": "linear", - "high": "10000", + "high": 10000, "n_buckets": 20, "description": "Maximum retention time for the gradient cache. (ms)" }, "STARTUP_CACHE_AGE_HOURS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 20, "description": "Startup cache age (hours)" }, @@ -862,28 +862,28 @@ "WORD_CACHE_HITS_CONTENT": { "expires_in_version": "never", "kind": "exponential", - "high": "256", + "high": 256, "n_buckets": 30, "description": "Word cache hits, content text (chars)" }, "WORD_CACHE_HITS_CHROME": { "expires_in_version": "never", "kind": "exponential", - "high": "256", + "high": 256, "n_buckets": 30, "description": "Word cache hits, chrome text (chars)" }, "WORD_CACHE_MISSES_CONTENT": { "expires_in_version": "never", "kind": "exponential", - "high": "256", + "high": 256, "n_buckets": 30, "description": "Word cache misses, content text (chars)" }, "WORD_CACHE_MISSES_CHROME": { "expires_in_version": "never", "kind": "exponential", - "high": "256", + "high": 256, "n_buckets": 30, "description": "Word cache misses, chrome text (chars)" }, @@ -906,7 +906,7 @@ "expires_in_version": "40", "kind": "exponential", "low": 50, - "high": "5000000", + "high": 5000000, "n_buckets": 100, "description": "Time spent decoding an image chunk (us)" }, @@ -914,7 +914,7 @@ "expires_in_version": "default", "kind": "exponential", "low": 50, - "high": "50000000", + "high": 50000000, "n_buckets": 100, "description": "Time spent decoding an image (us)" }, @@ -922,28 +922,28 @@ "expires_in_version": "40", "kind": "exponential", "low": 50, - "high": "50000000", + "high": 50000000, "n_buckets": 100, "description": "Time from starting a decode to it showing up on the screen (us)" }, "IMAGE_DECODE_CHUNKS": { "expires_in_version": "40", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 50, "description": "Number of chunks per decode attempt" }, "IMAGE_DECODE_COUNT": { "expires_in_version": "40", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 50, "description": "Decode count" }, "IMAGE_MAX_DECODE_COUNT": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 100, "description": "Max decode count over all images" }, @@ -951,7 +951,7 @@ "expires_in_version": "default", "kind": "exponential", "low": 500, - "high": "50000000", + "high": 50000000, "n_buckets": 50, "description": "JPEG image decode speed (Kbytes/sec)" }, @@ -959,7 +959,7 @@ "expires_in_version": "40", "kind": "exponential", "low": 500, - "high": "50000000", + "high": 50000000, "n_buckets": 50, "description": "GIF image decode speed (Kbytes/sec)" }, @@ -967,7 +967,7 @@ "expires_in_version": "40", "kind": "exponential", "low": 500, - "high": "50000000", + "high": 50000000, "n_buckets": 50, "description": "PNG image decode speed (Kbytes/sec)" }, @@ -1000,28 +1000,28 @@ "expires_in_version": "40", "kind": "exponential", "low": 100, - "high": "30000", + "high": 30000, "n_buckets": 100, "description": "HTTP: Total page load time (ms)" }, "HTTP_SUBITEM_OPEN_LATENCY_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Page start -> subitem open() (ms)" }, "HTTP_SUBITEM_FIRST_BYTE_LATENCY_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Page start -> first byte received for subitem reply (ms)" }, "HTTP_REQUEST_PER_PAGE": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "HTTP: Requests per page (count)" }, @@ -1034,252 +1034,252 @@ "HTTP_REQUEST_PER_CONN": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "HTTP: requests per connection" }, "HTTP_KBREAD_PER_CONN": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 50, "description": "HTTP: KB read per connection" }, "HTTP_PAGE_DNS_ISSUE_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: open() -> DNS request issued (ms)" }, "HTTP_PAGE_DNS_LOOKUP_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: DNS lookup time (ms)" }, "HTTP_PAGE_TCP_CONNECTION": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: TCP connection setup (ms)" }, "HTTP_PAGE_OPEN_TO_FIRST_SENT": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Open -> first byte of request sent (ms)" }, "HTTP_PAGE_FIRST_SENT_TO_LAST_RECEIVED": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: First byte of request sent -> last byte of response received (ms)" }, "HTTP_PAGE_OPEN_TO_FIRST_RECEIVED": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Open -> first byte of reply received (ms)" }, "HTTP_PAGE_OPEN_TO_FIRST_FROM_CACHE": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Open -> cache read start (ms)" }, "HTTP_PAGE_OPEN_TO_FIRST_FROM_CACHE_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Open -> cache read start (ms), [cache2]" }, "HTTP_PAGE_CACHE_READ_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Cache read time (ms)" }, "HTTP_PAGE_CACHE_READ_TIME_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Cache read time (ms) [cache2]" }, "HTTP_PAGE_REVALIDATION": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Positive cache validation time (ms)" }, "HTTP_PAGE_COMPLETE_LOAD": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Overall load time - all (ms)" }, "HTTP_PAGE_COMPLETE_LOAD_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Overall load time - all (ms) [cache2]" }, "HTTP_PAGE_COMPLETE_LOAD_CACHED": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Overall load time - cache hits (ms)" }, "HTTP_PAGE_COMPLETE_LOAD_CACHED_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Overall load time - cache hits (ms) [cache2]" }, "HTTP_PAGE_COMPLETE_LOAD_NET": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Overall load time - network (ms)" }, "HTTP_PAGE_COMPLETE_LOAD_NET_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP page: Overall load time - network (ms) [cache2]" }, "HTTP_SUB_DNS_ISSUE_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: open() -> DNS request issued (ms)" }, "HTTP_SUB_DNS_LOOKUP_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: DNS lookup time (ms)" }, "HTTP_SUB_TCP_CONNECTION": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: TCP connection setup (ms)" }, "HTTP_SUB_OPEN_TO_FIRST_SENT": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Open -> first byte of request sent (ms)" }, "HTTP_SUB_FIRST_SENT_TO_LAST_RECEIVED": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: First byte of request sent -> last byte of response received (ms)" }, "HTTP_SUB_OPEN_TO_FIRST_RECEIVED": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Open -> first byte of reply received (ms)" }, "HTTP_SUB_OPEN_TO_FIRST_FROM_CACHE": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Open -> cache read start (ms)" }, "HTTP_SUB_OPEN_TO_FIRST_FROM_CACHE_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Open -> cache read start (ms) [cache2]" }, "HTTP_SUB_CACHE_READ_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Cache read time (ms)" }, "HTTP_SUB_CACHE_READ_TIME_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Cache read time (ms) [cache2]" }, "HTTP_SUB_REVALIDATION": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Positive cache validation time (ms)" }, "HTTP_SUB_COMPLETE_LOAD": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Overall load time - all (ms)" }, "HTTP_SUB_COMPLETE_LOAD_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Overall load time - all (ms) [cache2]" }, "HTTP_SUB_COMPLETE_LOAD_CACHED": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Overall load time - cache hits (ms)" }, "HTTP_SUB_COMPLETE_LOAD_CACHED_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Overall load time - cache hits (ms) [cache2]" }, "HTTP_SUB_COMPLETE_LOAD_NET": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Overall load time - network (ms)" }, "HTTP_SUB_COMPLETE_LOAD_NET_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50, "description": "HTTP subitem: Overall load time - network (ms) [cache2]" }, @@ -1330,21 +1330,21 @@ "SSL_TIME_UNTIL_READY": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 200, "description": "ms of SSL wait time including TCP and proxy tunneling" }, "SSL_TIME_UNTIL_HANDSHAKE_FINISHED": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 200, "description": "ms of SSL wait time for full handshake including TCP and proxy tunneling" }, "SSL_BYTES_BEFORE_CERT_CALLBACK": { "expires_in_version": "never", "kind": "exponential", - "high": "32000", + "high": 32000, "n_buckets": 64, "description": "plaintext bytes read before a server certificate authenticated" }, @@ -1368,21 +1368,21 @@ "CERT_VALIDATION_HTTP_REQUEST_CANCELED_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 200, "description": "ms elapsed time of OCSP etc.. that was canceled" }, "CERT_VALIDATION_HTTP_REQUEST_SUCCEEDED_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 200, "description": "ms elapsed time of OCSP etc.. that succeeded" }, "CERT_VALIDATION_HTTP_REQUEST_FAILED_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 200, "description": "ms elapsed time of OCSP etc.. that failed" }, @@ -1410,7 +1410,7 @@ "expires_in_version": "50", "alert_emails": ["seceng-telemetry@mozilla.com"], "kind": "count", - "keyed": "true", + "keyed": true, "releaseChannelCollection": "opt-out", "description": "The number of times we generate a key via keygen, keyed on algorithm and keysize. Keys include RSA with key size (512, 1024, 2048, possibly others), secp384r1, secp256r1, and 'other_ec'." }, @@ -1435,28 +1435,28 @@ "SPDY_PARALLEL_STREAMS": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "SPDY: Streams concurrent active per connection" }, "SPDY_REQUEST_PER_CONN": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "SPDY: Streams created per connection" }, "SPDY_SERVER_INITIATED_STREAMS": { "expires_in_version": "never", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 250, "description": "SPDY: Streams recevied per connection" }, "SPDY_CHUNK_RECVD": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 100, "description": "SPDY: Recvd Chunk Size (rounded to KB)" }, @@ -1464,14 +1464,14 @@ "expires_in_version": "never", "kind": "exponential", "low": 20, - "high": "20000", + "high": 20000, "n_buckets": 50, "description": "SPDY: SYN Frame Header Size" }, "SPDY_SYN_RATIO": { "expires_in_version": "never", "kind": "linear", - "high": "99", + "high": 99, "n_buckets": 20, "description": "SPDY: SYN Frame Header Ratio (lower better)" }, @@ -1479,14 +1479,14 @@ "expires_in_version": "never", "kind": "exponential", "low": 16, - "high": "20000", + "high": 20000, "n_buckets": 50, "description": "SPDY: SYN Reply Header Size" }, "SPDY_SYN_REPLY_RATIO": { "expires_in_version": "never", "kind": "linear", - "high": "99", + "high": 99, "n_buckets": 20, "description": "SPDY: SYN Reply Header Ratio (lower better)" }, @@ -1503,56 +1503,56 @@ "SPDY_KBREAD_PER_CONN": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 50, "description": "SPDY: KB read per connection" }, "SPDY_SETTINGS_UL_BW": { "expires_in_version": "42", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 100, "description": "SPDY: Settings Upload Bandwidth" }, "SPDY_SETTINGS_DL_BW": { "expires_in_version": "42", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 100, "description": "SPDY: Settings Download Bandwidth" }, "SPDY_SETTINGS_RTT": { "expires_in_version": "42", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 100, "description": "SPDY: Settings RTT" }, "SPDY_SETTINGS_MAX_STREAMS": { "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 100, "description": "H2: Settings Max Streams parameter" }, "SPDY_SETTINGS_CWND": { "expires_in_version": "42", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 50, "description": "SPDY: Settings CWND (packets)" }, "SPDY_SETTINGS_RETRANS": { "expires_in_version": "42", "kind": "exponential", - "high": "100", + "high": 100, "n_buckets": 50, "description": "SPDY: Retransmission Rate" }, "SPDY_SETTINGS_IW": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50, "description": "H2: Settings Initial Window (rounded to KB)" }, @@ -1632,21 +1632,21 @@ "HTTP_CACHE_ENTRY_RELOAD_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "900000", + "high": 900000, "n_buckets": 50, "description": "Time before we reload an HTTP cache entry again to memory" }, "HTTP_CACHE_ENTRY_ALIVE_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "7200000", + "high": 7200000, "n_buckets": 50, "description": "Time for which an HTTP cache entry is kept warmed in memory" }, "HTTP_CACHE_ENTRY_REUSE_COUNT": { "expires_in_version": "never", "kind": "linear", - "high": "20", + "high": 20, "n_buckets": 19, "description": "Reuse count of an HTTP cache entry warmed in memory" }, @@ -1670,35 +1670,35 @@ "CACHE_DEVICE_SEARCH_2": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time to search cache (ms)" }, "CACHE_MEMORY_SEARCH_2": { "expires_in_version": "default", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time to search memory cache (ms)" }, "CACHE_DISK_SEARCH_2": { "expires_in_version": "default", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time to search disk cache (ms)" }, "CACHE_OFFLINE_SEARCH_2": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time to search offline cache (ms)" }, "TRANSACTION_WAIT_TIME_HTTP": { "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 100, "description": "Time from submission to dispatch of HTTP transaction (ms)" }, @@ -1761,7 +1761,7 @@ "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSSETDISKSMARTSIZECALLBACK_NOTIFY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSSETDISKSMARTSIZECALLBACK_NOTIFY" }, @@ -1831,413 +1831,413 @@ "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSEVICTDISKCACHEENTRIESEVENT_RUN": { "expires_in_version": "40", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSEVICTDISKCACHEENTRIESEVENT_RUN" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSDOOMEVENT_RUN": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSDOOMEVENT_RUN" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSDISKCACHESTREAMIO_WRITE": { "expires_in_version": "40", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSDISKCACHESTREAMIO_WRITE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSDISKCACHESTREAMIO_CLOSEOUTPUTSTREAM": { "expires_in_version": "40", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSDISKCACHESTREAMIO_CLOSEOUTPUTSTREAM" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSDISKCACHEDEVICEDEACTIVATEENTRYEVENT_RUN": { "expires_in_version": "40", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSDISKCACHEDEVICEDEACTIVATEENTRYEVENT_RUN" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSDISKCACHEBINDING_DESTRUCTOR": { "expires_in_version": "40", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSDISKCACHEBINDING_DESTRUCTOR" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SHUTDOWN" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETOFFLINECACHEENABLED": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETOFFLINECACHEENABLED" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETOFFLINECACHECAPACITY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETOFFLINECACHECAPACITY" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETMEMORYCACHE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETMEMORYCACHE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETDISKSMARTSIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETDISKSMARTSIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETDISKCACHEMAXENTRYSIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETDISKCACHEMAXENTRYSIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETMEMORYCACHEMAXENTRYSIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETMEMORYCACHEMAXENTRYSIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETDISKCACHEENABLED": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETDISKCACHEENABLED" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_SETDISKCACHECAPACITY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_SETDISKCACHECAPACITY" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_OPENCACHEENTRY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_OPENCACHEENTRY" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_ONPROFILESHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_ONPROFILESHUTDOWN" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_ONPROFILECHANGED": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_ONPROFILECHANGED" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_ISSTORAGEENABLEDFORPOLICY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_ISSTORAGEENABLEDFORPOLICY" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_GETCACHEIOTARGET": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_GETCACHEIOTARGET" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_EVICTENTRIESFORCLIENT": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_EVICTENTRIESFORCLIENT" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_DISKDEVICEHEAPSIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_DISKDEVICEHEAPSIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_CLOSEALLSTREAMS": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_CLOSEALLSTREAMS" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_DOOM": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_DOOM" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_SETPREDICTEDDATASIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_SETPREDICTEDDATASIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETDATASIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETDATASIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETSTORAGEDATASIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETSTORAGEDATASIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_REQUESTDATASIZECHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_REQUESTDATASIZECHANGE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_SETDATASIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_SETDATASIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_OPENINPUTSTREAM": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_OPENINPUTSTREAM" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_OPENOUTPUTSTREAM": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_OPENOUTPUTSTREAM" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETCACHEELEMENT": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETCACHEELEMENT" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_SETCACHEELEMENT": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_SETCACHEELEMENT" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETSTORAGEPOLICY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETSTORAGEPOLICY" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_SETSTORAGEPOLICY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_SETSTORAGEPOLICY" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETFILE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETFILE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETSECURITYINFO": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETSECURITYINFO" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_SETSECURITYINFO": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_SETSECURITYINFO" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_DOOMANDFAILPENDINGREQUESTS": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_DOOMANDFAILPENDINGREQUESTS" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_MARKVALID": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_MARKVALID" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_CLOSE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_CLOSE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETMETADATAELEMENT": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETMETADATAELEMENT" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_SETMETADATAELEMENT": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_SETMETADATAELEMENT" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_VISITMETADATA": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_VISITMETADATA" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_SETEXPIRATIONTIME": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_SETEXPIRATIONTIME" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_ISSTREAMBASED": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_ISSTREAMBASED" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETLASTMODIFIED": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETLASTMODIFIED" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETEXPIRATIONTIME": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETEXPIRATIONTIME" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETKEY": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETKEY" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETFETCHCOUNT": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETFETCHCOUNT" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETDEVICEID": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETDEVICEID" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_PROCESSREQUEST": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_PROCESSREQUEST" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHESERVICE_VISITENTRIES": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHESERVICE_VISITENTRIES" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETPREDICTEDDATASIZE": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETPREDICTEDDATASIZE" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETLASTFETCHED": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETLASTFETCHED" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSCACHEENTRYDESCRIPTOR_GETCLIENTID": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSCACHEENTRYDESCRIPTOR_GETCLIENTID" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSBLOCKONCACHETHREADEVENT_RUN": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSBLOCKONCACHETHREADEVENT_RUN" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSDISKCACHEMAP_REVALIDATION": { "expires_in_version": "40", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSDISKCACHEMAP_REVALIDATION *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_NSASYNCDOOMEVENT_RUN": { "expires_in_version": "never", "kind": "exponential", - "high": "10 * 1000", + "high": 10000, "n_buckets": 50, "description": "Time spent waiting on the cache service lock (ms) on the main thread in NSASYNCDOOMEVENT_RUN" }, @@ -2284,7 +2284,7 @@ "DNS_FAILED_LOOKUP_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 50, "description": "Time for an unsuccessful DNS OS resolution (msec)" }, @@ -2299,160 +2299,160 @@ "expires_in_version": "never", "description": "Total time spent ticking the refresh driver in milliseconds", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50 }, "PAINT_BUILD_DISPLAYLIST_TIME" : { "expires_in_version": "never", "description": "Time spent in building displaylists in milliseconds", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50 }, "PAINT_RASTERIZE_TIME" : { "expires_in_version": "never", "description": "Time spent rasterizing each frame in milliseconds", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 50 }, "PREDICTOR_PREDICT_ATTEMPTS": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "Number of times nsINetworkPredictor::Predict is called and attempts to predict" }, "PREDICTOR_LEARN_ATTEMPTS": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "Number of times nsINetworkPredictor::Learn is called and attempts to learn" }, "PREDICTOR_PREDICT_FULL_QUEUE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 50, "description": "Number of times nsINetworkPredictor::Predict doesn't continue because the queue is full" }, "PREDICTOR_LEARN_FULL_QUEUE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 50, "description": "Number of times nsINetworkPredictor::Learn doesn't continue because the queue is full" }, "PREDICTOR_WAIT_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Amount of time a predictor event waits in the queue (ms)" }, "PREDICTOR_PREDICT_WORK_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Amount of time spent doing the work for predict (ms)" }, "PREDICTOR_LEARN_WORK_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Amount of time spent doing the work for learn (ms)" }, "PREDICTOR_TOTAL_PREDICTIONS": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many actual predictions (preresolves, preconnects, ...) happen" }, "PREDICTOR_TOTAL_PRECONNECTS": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many actual preconnects happen" }, "PREDICTOR_TOTAL_PRECONNECTS_CREATED": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many preconnects actually created a speculative socket" }, "PREDICTOR_TOTAL_PRECONNECTS_USED": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many preconnects actually created a used speculative socket" }, "PREDICTOR_TOTAL_PRECONNECTS_UNUSED": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many preconnects needlessly created a speculative socket" }, "PREDICTOR_TOTAL_PRERESOLVES": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many actual preresolves happen" }, "PREDICTOR_PREDICTIONS_CALCULATED": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many prediction calculations are performed" }, "PREDICTOR_GLOBAL_DEGRADATION": { "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 50, "description": "The global degradation calculated" }, "PREDICTOR_SUBRESOURCE_DEGRADATION": { "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 50, "description": "The degradation calculated for a subresource" }, "PREDICTOR_BASE_CONFIDENCE": { "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 50, "description": "The base confidence calculated for a subresource" }, "PREDICTOR_CONFIDENCE": { "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 50, "description": "The final confidence calculated for a subresource" }, "PREDICTOR_PREDICT_TIME_TO_ACTION": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "How long it takes from the time Predict() is called to the time we take action" }, "PREDICTOR_PREDICT_TIME_TO_INACTION": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "How long it takes from the time Predict() is called to the time we figure out there's nothing to do" }, @@ -2511,210 +2511,210 @@ "HTTPCONNMGR_TOTAL_SPECULATIVE_CONN": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many speculative http connections are created" }, "HTTPCONNMGR_USED_SPECULATIVE_CONN": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many speculative http connections are actually used" }, "HTTPCONNMGR_UNUSED_SPECULATIVE_CONN": { "expires_in_version": "never", "kind": "exponential", - "high": "1000 * 1000", + "high": 1000000, "n_buckets": 50, "description": "How many speculative connections are made needlessly" }, "STS_POLL_AND_EVENTS_CYCLE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "The duraion of a socketThread cycle, including polls and pending events. (ms)" }, "STS_NUMBER_OF_PENDING_EVENTS": { "expires_in_version": "never", "kind": "exponential", - "high": "2000", + "high": 2000, "n_buckets": 100, "description": "Number of pending events per SocketThread cycle." }, "STS_POLL_CYCLE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "The duration of poll. (ms)" }, "STS_POLL_AND_EVENT_THE_LAST_CYCLE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "The duraion of the socketThread cycle during shutdown, including polls and pending events. (ms)" }, "STS_NUMBER_OF_PENDING_EVENTS_IN_THE_LAST_CYCLE": { "expires_in_version": "never", "kind": "exponential", - "high": "2000", + "high": 2000, "n_buckets": 100, "description": "Number of pending events per SocketThread cycle during shutdown." }, "STS_NUMBER_OF_ONSOCKETREADY_CALLS": { "expires_in_version": "never", "kind": "exponential", - "high": "2000", + "high": 2000, "n_buckets": 100, "description": "Number of OnSocketReady calls during a single poll." }, "STS_POLL_BLOCK_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked on poll (ms)." }, "PRCONNECT_BLOCKING_TIME_NORMAL": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Connect when we are not shutting down and there has been niether a network nor an offline state change in the last 60s (ms)." }, "PRCONNECT_BLOCKING_TIME_SHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Connect during a shutdown (ms)." }, "PRCONNECT_BLOCKING_TIME_CONNECTIVITY_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Connect when there has been the connectiviy change in the last 60s (ms)." }, "PRCONNECT_BLOCKING_TIME_LINK_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Connect when there has been a link change in the last 60s (ms)." }, "PRCONNECT_BLOCKING_TIME_OFFLINE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Connect when the offline state has changed in the last 60s (ms)." }, "PRCONNECTCONTINUE_BLOCKING_TIME_NORMAL": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_ConnectContinue when we are not shutting down and there has been niether a network nor an offline state change in the last 60s (ms)." }, "PRCONNECTCONTINUE_BLOCKING_TIME_SHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_ConnectContinue during a shutdown (ms)." }, "PRCONNECTCONTINUE_BLOCKING_TIME_CONNECTIVITY_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_ConnectContinue when there has been the connectivity change in the last 60s (ms)." }, "PRCONNECTCONTINUE_BLOCKING_TIME_LINK_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_ConnectContinue when there has been a link change in the last 60s (ms)." }, "PRCONNECTCONTINUE_BLOCKING_TIME_OFFLINE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_ConnectContinue when the offline state has changed in the last 60s (ms)." }, "PRCLOSE_TCP_BLOCKING_TIME_NORMAL": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when we are not shutting down and there has been niether a network nor an offline state change in the last 60s (ms)." }, "PRCLOSE_TCP_BLOCKING_TIME_SHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close during a shutdown (ms)." }, "PRCLOSE_TCP_BLOCKING_TIME_CONNECTIVITY_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when there has been the connectivity change in the last 60s (ms)." }, "PRCLOSE_TCP_BLOCKING_TIME_LINK_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when there has been a link change in the last 60s (ms)." }, "PRCLOSE_TCP_BLOCKING_TIME_OFFLINE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when the offline state has changed in the last 60s (ms)." }, "PRCLOSE_UDP_BLOCKING_TIME_NORMAL": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when we are not shutting down and there has been niether a network nor an offline state change in the last 60s (ms)." }, "PRCLOSE_UDP_BLOCKING_TIME_SHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close during a shutdown (ms)." }, "PRCLOSE_UDP_BLOCKING_TIME_CONNECTIVITY_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when there has been the connectivity change in the last 60s (ms)." }, "PRCLOSE_UDP_BLOCKING_TIME_LINK_CHANGE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when there has been a link change in the last 60s (ms)." }, "PRCLOSE_UDP_BLOCKING_TIME_OFFLINE": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 1000, "description": "Time spent blocked in PR_Close when the offline state has changed in the last 60s (ms)." }, @@ -2743,14 +2743,14 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent scanning filesystem for plugins (ms)" }, "CHECK_JAVA_ENABLED": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent checking if Java is enabled (ms)" }, @@ -2768,21 +2768,21 @@ "PLUGIN_HANG_UI_RESPONSE_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 20, "description": "Time spent in Plugin Hang UI (ms)" }, "PLUGIN_HANG_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 20, "description": "Value of dom.ipc.plugins.hangUITimeoutSecs plus time spent in Plugin Hang UI (ms)" }, "PLUGIN_LOAD_METADATA": { "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 20, "description": "Time spent loading plugin DLL and obtaining metadata (ms)" }, @@ -2796,7 +2796,7 @@ "PLUGIN_SHUTDOWN_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 20, "description": "Time spent shutting down plugins (ms)" }, @@ -2814,24 +2814,24 @@ "FLASH_PLUGIN_AREA": { "expires_in_version": "50", "kind": "exponential", - "low": "256", - "high": "16777216", + "low": 256, + "high": 16777216, "n_buckets": 50, "description": "Flash object area (width * height)" }, "FLASH_PLUGIN_WIDTH": { "expires_in_version": "50", "kind": "linear", - "low": "1", - "high": "2000", + "low": 1, + "high": 2000, "n_buckets": 50, "description": "Flash object width" }, "FLASH_PLUGIN_HEIGHT": { "expires_in_version": "50", "kind": "linear", - "low": "1", - "high": "2000", + "low": 1, + "high": 2000, "n_buckets": 50, "description": "Flash object height" }, @@ -2844,259 +2844,259 @@ "MOZ_SQLITE_OPEN_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite open() (ms)" }, "MOZ_SQLITE_OPEN_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite open() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_TRUNCATE_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite truncate() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_TRUNCATE_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite truncate() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_OTHER_READ_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_OTHER_READ_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_PLACES_READ_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_PLACES_READ_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_COOKIES_OPEN_READAHEAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on cookie DB open with readahead (ms)" }, "MOZ_SQLITE_COOKIES_READ_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_COOKIES_READ_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_WEBAPPS_READ_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_WEBAPPS_READ_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_OTHER_WRITE_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms)" }, "MOZ_SQLITE_OTHER_WRITE_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms)" }, "MOZ_SQLITE_PLACES_WRITE_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms)" }, "MOZ_SQLITE_PLACES_WRITE_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_COOKIES_WRITE_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_COOKIES_WRITE_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_WEBAPPS_WRITE_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_WEBAPPS_WRITE_MAIN_THREAD_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite write() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "MOZ_SQLITE_OTHER_SYNC_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_OTHER_SYNC_MAIN_THREAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_PLACES_SYNC_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_PLACES_SYNC_MAIN_THREAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_COOKIES_SYNC_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_COOKIES_SYNC_MAIN_THREAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_WEBAPPS_SYNC_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_WEBAPPS_SYNC_MAIN_THREAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time spent on SQLite fsync() (ms)" }, "MOZ_SQLITE_OTHER_READ_B": { "expires_in_version": "default", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite read() (bytes)" }, "MOZ_SQLITE_PLACES_READ_B": { "expires_in_version": "40", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite read() (bytes)" }, "MOZ_SQLITE_COOKIES_READ_B": { "expires_in_version": "40", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite read() (bytes)" }, "MOZ_SQLITE_WEBAPPS_READ_B": { "expires_in_version": "40", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite read() (bytes)" }, "MOZ_SQLITE_PLACES_WRITE_B": { "expires_in_version": "40", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite write (bytes)" }, "MOZ_SQLITE_COOKIES_WRITE_B": { "expires_in_version": "40", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite write (bytes)" }, "MOZ_SQLITE_WEBAPPS_WRITE_B": { "expires_in_version": "40", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite write (bytes)" }, "MOZ_SQLITE_OTHER_WRITE_B": { "expires_in_version": "default", "kind": "linear", - "high": "32768", + "high": 32768, "n_buckets": 3, "description": "SQLite write (bytes)" }, @@ -3104,7 +3104,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "exponential", - "high": "32768", + "high": 32768, "n_buckets": 20, "description": "mozStorage async requests completion (ms)" }, @@ -3123,119 +3123,119 @@ "NETWORK_DISK_CACHE_OPEN": { "expires_in_version": "default", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent opening disk cache (ms)" }, "NETWORK_DISK_CACHE_TRASHRENAME": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent renaming bad Cache to Cache.Trash (ms)" }, "NETWORK_DISK_CACHE_DELETEDIR": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent deleting disk cache (ms)" }, "NETWORK_DISK_CACHE_DELETEDIR_SHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent during showdown stopping thread deleting old disk cache (ms)" }, "NETWORK_DISK_CACHE_SHUTDOWN": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Total Time spent (ms) during disk cache showdown" }, "NETWORK_DISK_CACHE_SHUTDOWN_V2": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Total Time spent (ms) during disk cache showdown [cache2]" }, "NETWORK_DISK_CACHE_SHUTDOWN_CLEAR_PRIVATE": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent (ms) during showdown deleting disk cache for 'clear private data' option" }, "NETWORK_DISK_CACHE2_SHUTDOWN_CLEAR_PRIVATE": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent (ms) during showdown deleting disk cache v2 for 'clear private data' option" }, "NETWORK_DISK_CACHE_REVALIDATION": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Total Time spent (ms) during disk cache revalidation" }, "NETWORK_DISK_CACHE_STREAMIO_CLOSE": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent in nsDiskCacheStreamIO::Close() on non-main thread (ms)" }, "NETWORK_DISK_CACHE_STREAMIO_CLOSE_MAIN_THREAD": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "Time spent in nsDiskCacheStreamIO::Close() on the main thread (ms)" }, "IDLE_NOTIFY_BACK_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 10, "description": "Time spent checking for and notifying listeners that the user is back (ms)" }, "IDLE_NOTIFY_BACK_LISTENERS": { "expires_in_version": "40", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 20, "description": "Number of listeners notified that the user is back" }, "IDLE_NOTIFY_IDLE_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 10, "description": "Time spent checking for and notifying listeners that the user is idle (ms)" }, "IDLE_NOTIFY_IDLE_LISTENERS": { "expires_in_version": "40", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 20, "description": "Number of listeners notified that the user is idle" }, "URLCLASSIFIER_LOOKUP_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 10, "description": "Time spent per dbservice lookup (ms)" }, "URLCLASSIFIER_CL_CHECK_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 10, "description": "Time spent per classifier lookup (ms)" }, @@ -3243,42 +3243,42 @@ "expires_in_version": "never", "kind": "exponential", "low": 20, - "high": "15000", + "high": 15000, "n_buckets": 15, "description": "Time spent per classifier update (ms)" }, "URLCLASSIFIER_PS_FILELOAD_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 10, "description": "Time spent loading PrefixSet from file (ms)" }, "URLCLASSIFIER_PS_FALLOCATE_TIME": { "expires_in_version": "40", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 10, "description": "Time spent fallocating PrefixSet (ms)" }, "URLCLASSIFIER_PS_CONSTRUCT_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 15, "description": "Time spent constructing PrefixSet from DB (ms)" }, "URLCLASSIFIER_LC_PREFIXES": { "expires_in_version": "never", "kind": "linear", - "high": "1500000", + "high": 1500000, "n_buckets": 15, "description": "Size of the prefix cache in entries" }, "URLCLASSIFIER_LC_COMPLETIONS": { "expires_in_version": "never", "kind": "exponential", - "high": "200", + "high": 200, "n_buckets": 10, "description": "Size of the completion cache in entries" }, @@ -3287,11 +3287,32 @@ "kind": "boolean", "description": "Did UrlClassifier fail to construct the PrefixSet?" }, + "CSP_DOCUMENTS_COUNT": { + "alert_emails": ["seceng@mozilla.com"], + "bug_numbers": [1252829], + "expires_in_version": "55", + "kind": "count", + "description": "Number of unique pages that contain a CSP" + }, + "CSP_UNSAFE_INLINE_DOCUMENTS_COUNT": { + "alert_emails": ["seceng@mozilla.com"], + "bug_numbers": [1252829], + "expires_in_version": "55", + "kind": "count", + "description": "Number of unique pages that contain an unsafe-inline CSP directive" + }, + "CSP_UNSAFE_EVAL_DOCUMENTS_COUNT": { + "alert_emails": ["seceng@mozilla.com"], + "bug_numbers": [1252829], + "expires_in_version": "55", + "kind": "count", + "description": "Number of unique pages that contain an unsafe-eval CSP directive" + }, "PLACES_PAGES_COUNT": { "expires_in_version": "never", "kind": "exponential", "low": 1000, - "high": "150000", + "high": 150000, "n_buckets": 20, "description": "PLACES: Number of unique pages" }, @@ -3299,21 +3320,21 @@ "expires_in_version": "never", "kind": "exponential", "low": 100, - "high": "8000", + "high": 8000, "n_buckets": 15, "description": "PLACES: Number of bookmarks" }, "PLACES_TAGS_COUNT": { "expires_in_version": "never", "kind": "exponential", - "high": "200", + "high": 200, "n_buckets": 10, "description": "PLACES: Number of tags" }, "PLACES_KEYWORDS_COUNT": { "expires_in_version": "never", "kind": "exponential", - "high": "200", + "high": 200, "n_buckets": 10, "description": "PLACES: Number of keywords" }, @@ -3426,7 +3447,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 100, - "high": "40000", + "high": 40000, "n_buckets": 30, "description": "Time taken to download a specified distribution file (msec)", "cpp_guard": "ANDROID" @@ -3472,7 +3493,7 @@ "FENNEC_READING_LIST_COUNT": { "expires_in_version": "40", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 10, "cpp_guard": "ANDROID", "description": "Number of reading list items stored in the browser DB" @@ -3480,14 +3501,14 @@ "PLACES_SORTED_BOOKMARKS_PERC": { "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 10, "description": "PLACES: Percentage of bookmarks organized in folders" }, "PLACES_TAGGED_BOOKMARKS_PERC": { "expires_in_version": "never", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 10, "description": "PLACES: Percentage of tagged bookmarks" }, @@ -3495,7 +3516,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 5, - "high": "200", + "high": 200, "n_buckets": 10, "description": "PLACES: Database filesize (MB)" }, @@ -3503,7 +3524,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1024, - "high": "32768", + "high": 32768, "n_buckets": 10, "description": "PLACES: Database page size (bytes)" }, @@ -3511,7 +3532,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 500, - "high": "10240", + "high": 10240, "n_buckets": 20, "description": "PLACES: Average size of a place in the database (bytes)" }, @@ -3525,7 +3546,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "500", + "high": 500, "n_buckets": 10, "description": "PLACES: Time for first autocomplete result if > 50ms (ms)" }, @@ -3533,7 +3554,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "1000", + "high": 1000, "n_buckets": 30, "description": "PLACES: Time for the 6 first autocomplete results (ms)" }, @@ -3541,7 +3562,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "2000", + "high": 2000, "n_buckets": 30, "description": "PLACES: Time to load the sidebar history tree sorted by last visit (ms)" }, @@ -3549,7 +3570,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "1000", + "high": 1000, "n_buckets": 30, "description": "PLACES: Time to search the history library (ms)" }, @@ -3565,7 +3586,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "10000", + "high": 10000, "n_buckets": 10, "description": "PLACES: Time to decay all frecencies values on idle (ms)" }, @@ -3573,7 +3594,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 1000, - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "PLACES: Time to execute maintenance tasks on idle (ms)" }, @@ -3581,7 +3602,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "5000", + "high": 5000, "n_buckets": 10, "description": "PLACES: Number of bookmarks annotations" }, @@ -3589,7 +3610,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "5000", + "high": 5000, "n_buckets": 10, "description": "PLACES: Number of pages annotations" }, @@ -3649,14 +3670,14 @@ "expires_in_version": "never", "kind": "exponential", "n_buckets": 60, - "high": "365", + "high": 365, "description": "Update: interval in days since the last background update check (externally initiated)" }, "UPDATE_LAST_NOTIFY_INTERVAL_DAYS_NOTIFY": { "expires_in_version": "never", "kind": "exponential", "n_buckets": 30, - "high": "180", + "high": 180, "description": "Update: interval in days since the last background update check (timer initiated)" }, "UPDATE_PING_COUNT_EXTERNAL": { @@ -3892,36 +3913,36 @@ "THUNDERBIRD_INDEXING_RATE_MSG_PER_S": { "expires_in_version": "40", "kind": "linear", - "high": "100", + "high": 100, "n_buckets": 20, "description": "Gloda: indexing rate (message/s)" }, "FX_GESTURE_TAKE_SNAPSHOT_OF_PAGE": { "expires_in_version": "40", "kind": "exponential", - "high": "1000", - "n_buckets": "30", + "high": 1000, + "n_buckets": 30, "description": "Firefox: Time taken to capture the page to a canvas, for reuse while swiping through history (ms)." }, "FX_GESTURE_INSTALL_SNAPSHOT_OF_PAGE": { "expires_in_version": "40", "kind": "exponential", - "high": "1000", - "n_buckets": "30", + "high": 1000, + "n_buckets": 30, "description": "Firefox: Time taken to store the image capture of the page to a canvas, for reuse while swiping through history (ms)." }, "FX_GESTURE_COMPRESS_SNAPSHOT_OF_PAGE": { "expires_in_version": "40", "kind": "exponential", - "high": "1000", - "n_buckets": "30", + "high": 1000, + "n_buckets": 30, "description": "Firefox: Time taken to kick off image compression of the canvas that will be used during swiping through history (ms)." }, "FX_TAB_ANIM_OPEN_MS": { "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Firefox: Time taken by the tab opening animation in milliseconds" }, @@ -3929,7 +3950,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Firefox: Time taken by the tab closing animation in milliseconds" }, @@ -3937,7 +3958,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 7, - "high": "500", + "high": 500, "n_buckets": 50, "description": "Average frame interval during tab open animation of about:newtab (preview=on), when other tabs are unaffected" }, @@ -3945,7 +3966,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 7, - "high": "500", + "high": 500, "n_buckets": 50, "description": "Average frame interval during tab open animation of about:newtab (preview=off), when other tabs are unaffected" }, @@ -3953,14 +3974,14 @@ "expires_in_version": "never", "kind": "exponential", "low": 7, - "high": "500", + "high": 500, "n_buckets": 50, "description": "Average frame interval during any tab open/close animation (excluding tabstrip scroll)" }, "FX_TAB_ANIM_ANY_FRAME_PAINT_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 30, "description": "Average paint duration during any tab open/close animation (excluding tabstrip scroll)" }, @@ -3968,7 +3989,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "bug_numbers": [1220699], "description": "Delay in ms between the target and the actual handling time of the frame at refresh driver in the chrome process." @@ -3977,7 +3998,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "bug_numbers": [1221674], "description": "Delay in ms between the target and the actual handling time of the frame at refresh driver in the content process." @@ -3986,7 +4007,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "bug_numbers": [1228147], "description": "Delay in ms between the target and the actual handling time of the frame at refresh driver while scrolling synchronously." @@ -3995,42 +4016,42 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "40", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 20, "description": "Firefox: Time in ms spent updating UI in response to a tab switch" }, "FX_TAB_SWITCH_TOTAL_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 20, "description": "Firefox: Time in ms till a tab switch is complete including the first paint" }, "FX_TAB_SWITCH_TOTAL_E10S_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 20, "description": "Firefox: Time in ms between tab selection and tab content paint." }, "FX_TAB_SWITCH_SPINNER_VISIBLE_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 20, "description": "Firefox: If the spinner interstitial displays during tab switching, records the time in ms the graphic is visible" }, "FX_TAB_CLICK_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 20, "description": "Firefox: Time in ms spent on switching tabs in response to a tab click" }, "FX_IDENTITY_POPUP_OPEN_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 10, "description": "Firefox: Time taken by the identity popup to open in milliseconds" }, @@ -4038,7 +4059,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 50, - "high": "5000", + "high": 5000, "n_buckets": 10, "description": "Firefox: Time to initialize the bookmarks toolbar view (ms)" }, @@ -4050,16 +4071,16 @@ "FX_NEW_WINDOW_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "description": "Firefox: Time taken to open a new browser window (ms)" }, "FX_PAGE_LOAD_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, - "description": "Firefox: Time taken to load a page (ms)" + "description": "Firefox: Time taken to load a page (ms). This includes all static contents, no dynamic content. Loading of about: pages is not counted." }, "FX_TOTAL_TOP_VISITS": { "expires_in_version": "default", @@ -4069,14 +4090,14 @@ "FX_THUMBNAILS_CAPTURE_TIME_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 15, "description": "THUMBNAILS: Time (ms) it takes to capture a thumbnail" }, "FX_THUMBNAILS_STORE_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "500", + "high": 500, "n_buckets": 15, "description": "THUMBNAILS: Time (ms) it takes to store a thumbnail in the cache" }, @@ -4102,7 +4123,7 @@ "FX_MIGRATION_ERRORS": { "expires_in_version": "49", "kind": "enumerated", - "keyed": "true", + "keyed": true, "n_values": 12, "releaseChannelCollection": "opt-out", "description": "Errors encountered during migration in buckets defined by the datatype, keyed by the string description of the browser." @@ -4110,7 +4131,7 @@ "FX_MIGRATION_USAGE": { "expires_in_version": "49", "kind": "enumerated", - "keyed": "true", + "keyed": true, "n_values": 12, "releaseChannelCollection": "opt-out", "description": "Usage of migration for each datatype when migration is run through the post-firstrun flow which allows individual datatypes, keyed by the string description of the browser." @@ -4118,7 +4139,7 @@ "FX_MIGRATION_HOMEPAGE_IMPORTED": { "expires_in_version": "49", "kind": "boolean", - "keyed": "true", + "keyed": true, "releaseChannelCollection": "opt-out", "description": "Whether the homepage was imported during browser migration. Only available on release builds during firstrun." }, @@ -4143,49 +4164,49 @@ "FX_SESSION_RESTORE_STARTUP_INIT_SESSION_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 20, "description": "Session restore: Time it takes to prepare the data structures for restoring a session (ms)" }, "FX_SESSION_RESTORE_STARTUP_ONLOAD_INITIAL_WINDOW_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 20, "description": "Session restore: Time it takes to finish restoration once we have first opened a window (ms)" }, "FX_SESSION_RESTORE_COLLECT_ALL_WINDOWS_DATA_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "Session restore: Time to collect all window data (ms)" }, "FX_SESSION_RESTORE_COLLECT_COOKIES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "Session restore: Time to collect cookies (ms)" }, "FX_SESSION_RESTORE_COLLECT_DATA_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "Session restore: Time to collect all window and tab data (ms)" }, "FX_SESSION_RESTORE_COLLECT_DATA_LONGEST_OP_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "Session restore: Duration of the longest uninterruptible operation while collecting all window and tab data (ms)" }, "FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_LONGEST_OP_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 10, "description": "Session restore: Duration of the longest uninterruptible operation while collecting data in the content process (ms)" }, @@ -4193,14 +4214,14 @@ "alert_emails": ["session-restore-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 10, "description": "Session restore: Time to JSON serialize session data (ms)" }, "FX_SESSION_RESTORE_READ_FILE_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Session restore: Time to read the session data from the file on disk (ms)" }, @@ -4214,7 +4235,7 @@ "FX_SESSION_RESTORE_WRITE_FILE_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Session restore: Time to write the session data to the file on disk (ms)" }, @@ -4238,7 +4259,7 @@ "FX_SESSION_RESTORE_RESTORE_WINDOW_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Session restore: Time spent blocking the main thread while restoring a window state (ms)" }, @@ -4251,7 +4272,7 @@ "FX_SESSION_RESTORE_DOM_STORAGE_SIZE_ESTIMATE_CHARS": { "expires_in_version": "default", "kind": "exponential", - "high": "30000000", + "high": 30000000, "n_buckets": 20, "description": "Session restore: Number of characters in DOM Storage for a tab. Pages without DOM Storage or with an empty DOM Storage are ignored." }, @@ -4259,8 +4280,8 @@ "alert_emails": ["session-restore-telemetry-alerts@mozilla.com"], "expires_in_version": "default", "kind": "exponential", - "low": "100", - "high": "100000", + "low": 100, + "high": 100000, "n_buckets": 20, "description": "Session restore: If the browser is setup to auto-restore tabs, this probe measures the time elapsed between the instant we start Session Restore and the instant we have finished restoring tabs eagerly. At this stage, the tabs that are restored on demand are not restored yet." }, @@ -4268,11 +4289,30 @@ "alert_emails": ["session-restore-telemetry-alerts@mozilla.com"], "expires_in_version": "default", "kind": "exponential", - "low": "100", - "high": "100000", + "low": 100, + "high": 100000, "n_buckets": 20, "description": "Session restore: If a session is restored by the user clicking on 'Restore Session', this probe measures the time elapsed between the instant the user has clicked and the instant we have finished restoring tabs eagerly. At this stage, the tabs that are restored on demand are not restored yet." }, + "FX_SESSION_RESTORE_NUMBER_OF_TABS_RESTORED": { + "expires_in_version": "default", + "kind": "exponential", + "high": 500, + "n_buckets": 20, + "description": "Session restore: Number of tabs in the session that has just been restored." + }, + "FX_SESSION_RESTORE_NUMBER_OF_WINDOWS_RESTORED": { + "expires_in_version": "default", + "kind": "enumerated", + "n_values": 50, + "description": "Session restore: Number of windows in the session that has just been restored." + }, + "FX_SESSION_RESTORE_NUMBER_OF_EAGER_TABS_RESTORED": { + "expires_in_version": "default", + "kind": "enumerated", + "n_values": 50, + "description": "Session restore: Number of tabs restored eagerly in the session that has just been restored." + }, "FX_TABLETMODE_PAGE_LOAD": { "expires_in_version": "47", "kind": "exponential", @@ -4407,28 +4447,28 @@ "XUL_FOREGROUND_REFLOW_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "XUL reflows in foreground windows (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "XUL_BACKGROUND_REFLOW_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "XUL reflows in background windows (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "HTML_FOREGROUND_REFLOW_MS_2": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "description": "HTML reflows in foreground windows (ms)" }, "HTML_BACKGROUND_REFLOW_MS_2": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "description": "HTML reflows in background windows (ms)" }, @@ -4440,7 +4480,7 @@ "XUL_INITIAL_FRAME_CONSTRUCTION": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "initial xul frame construction" }, @@ -4452,14 +4492,14 @@ "DOM_TIMERS_FIRED_PER_NATIVE_TIMEOUT": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "DOM: Timer handlers called per native timer expiration" }, "DOM_TIMERS_RECENTLY_SET": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "DOM: setTimeout/setInterval calls recently (last 30s or more)" }, @@ -4476,14 +4516,14 @@ "LOCALDOMSTORAGE_INIT_DATABASE_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to open the localStorage database (ms)" }, "LOCALDOMSTORAGE_SHUTDOWN_DATABASE_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to flush and close the localStorage database (ms)" }, @@ -4495,63 +4535,63 @@ "LOCALDOMSTORAGE_GETALLKEYS_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to block before we return a list of all keys in domain's LocalStorage (ms)" }, "LOCALDOMSTORAGE_GETKEY_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to block before we return a key name in domain's LocalStorage (ms)" }, "LOCALDOMSTORAGE_GETLENGTH_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to block before we return number of keys in domain's LocalStorage (ms)" }, "LOCALDOMSTORAGE_GETVALUE_BLOCKING_MS": { "expires_in_version": "default", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to block before we return a value for a key in LocalStorage (ms)" }, "LOCALDOMSTORAGE_SETVALUE_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to block before we set a single key's value in LocalStorage (ms)" }, "LOCALDOMSTORAGE_REMOVEKEY_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to block before we remove a single key from LocalStorage (ms)" }, "LOCALDOMSTORAGE_CLEAR_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to block before we clear LocalStorage for all domains (ms)" }, "LOCALDOMSTORAGE_UNLOAD_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to fetch LocalStorage data before we can clean the cache (ms)" }, "LOCALDOMSTORAGE_SESSIONONLY_PRELOAD_BLOCKING_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to fetch LocalStorage data before we can expose them as session only data (ms)" }, @@ -4559,7 +4599,7 @@ "expires_in_version": "40", "kind": "exponential", "low": 1024, - "high": "32768", + "high": 32768, "n_buckets": 10, "description": "DOM storage: size of keys stored in localStorage" }, @@ -4567,7 +4607,7 @@ "expires_in_version": "40", "kind": "exponential", "low": 1024, - "high": "32768", + "high": 32768, "n_buckets": 10, "description": "DOM storage: size of values stored in localStorage" }, @@ -4575,7 +4615,7 @@ "expires_in_version": "40", "kind": "exponential", "low": 1024, - "high": "32768", + "high": 32768, "n_buckets": 10, "description": "DOM storage: size of keys stored in sessionStorage" }, @@ -4583,7 +4623,7 @@ "expires_in_version": "40", "kind": "exponential", "low": 1024, - "high": "32768", + "high": 32768, "n_buckets": 10, "description": "DOM storage: size of values stored in sessionStorage" }, @@ -4591,7 +4631,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Number of histograms with range checksum errors" }, @@ -4599,7 +4639,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Number of histograms with bucket order errors" }, @@ -4607,7 +4647,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Number of histograms with total count high errors" }, @@ -4615,7 +4655,7 @@ "alert_emails": ["perf-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Number of histograms with total count low errors" }, @@ -4623,7 +4663,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "13", + "high": 13, "n_buckets": 12, "bug_numbers": [1162538], "description": "Number of directories in the archive at scan" @@ -4632,7 +4672,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "13", + "high": 13, "n_buckets": 12, "bug_numbers": [1162538], "description": "The age of the oldest Telemetry archive directory in months" @@ -4641,7 +4681,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 100, "bug_numbers": [1162538], "description": "Number of Telemetry pings in the archive at scan" @@ -4657,7 +4697,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "300", + "high": 300, "n_buckets": 60, "bug_numbers": [1162538], "description": "The size of the Telemetry archive (MB)" @@ -4666,7 +4706,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 100, "bug_numbers": [1162538], "description": "Number of Telemetry pings evicted from the archive during cleanup, because they were over the quota" @@ -4675,7 +4715,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "13", + "high": 13, "n_buckets": 12, "bug_numbers": [1162538], "description": "Number of Telemetry directories evicted from the archive during cleanup, because they were too old" @@ -4684,7 +4724,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 20, "bug_numbers": [1162538], "description": "Time (ms) it takes for evicting old directories" @@ -4693,7 +4733,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 20, "bug_numbers": [1162538], "description": "Time (ms) it takes for checking if the archive is over-quota" @@ -4702,7 +4742,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 20, "bug_numbers": [1162538], "description": "Time (ms) it takes for evicting over-quota pings" @@ -4723,7 +4763,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "17", + "high": 17, "n_buckets": 16, "description": "The size of the Telemetry pending pings directory (MB). The special value 17 is used to indicate over quota pings." }, @@ -4731,7 +4771,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "365", + "high": 365, "n_buckets": 30, "description": "The age, in days, of the pending pings." }, @@ -4739,7 +4779,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "100000", + "high": 100000, "n_buckets": 100, "description": "Number of Telemetry pings evicted from the pending pings directory during cleanup, because they were over the quota" }, @@ -4747,7 +4787,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 20, "description": "Time (ms) it takes for evicting over-quota pending pings" }, @@ -4755,7 +4795,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "300000", + "high": 300000, "n_buckets": 20, "description": "Time (ms) it takes for checking if the pending pings are over-quota" }, @@ -4781,7 +4821,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "30", + "high": 30, "n_buckets": 29, "description": "The size (MB) of the Telemetry pending pings exceeding the maximum file size" }, @@ -4789,7 +4829,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "30", + "high": 30, "n_buckets": 29, "description": "The size (MB) of the Telemetry archived, compressed, pings exceeding the maximum file size" }, @@ -4797,7 +4837,7 @@ "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", "kind": "linear", - "high": "30", + "high": 30, "n_buckets": 29, "description": "The size (MB) of the ping data submitted to Telemetry exceeding the maximum size" }, @@ -4810,28 +4850,28 @@ "TELEMETRY_COMPRESS": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time taken to compress telemetry object (ms)" }, "TELEMETRY_PING": { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time taken to submit telemetry info (ms)" }, "TELEMETRY_SEND" : { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to send the compressed string to the Telemetry servers and get a reply back (ms)" }, "TELEMETRY_STRINGIFY" : { "expires_in_version": "never", "kind": "exponential", - "high": "3000", + "high": 3000, "n_buckets": 10, "description": "Time to stringify telemetry object (ms)" }, @@ -4847,6 +4887,12 @@ "keyed": true, "description": "Count of individual invalid ping types that were submitted to Telemetry." }, + "TELEMETRY_PING_EVICTED_FOR_SERVER_ERRORS": { + "alert_emails": ["telemetry-client-dev@mozilla.com"], + "expires_in_version": "never", + "kind": "count", + "description": "Number of Telemetry ping files evicted due to server errors (4XX HTTP code received)" + }, "TELEMETRY_SESSIONDATA_FAILED_LOAD": { "alert_emails": ["telemetry-client-dev@mozilla.com"], "expires_in_version": "never", @@ -4871,12 +4917,6 @@ "kind": "flag", "description": "Set if Telemetry failed to save the session data to disk." }, - "TELEMETRY_PING_EVICTED_FOR_SERVER_ERRORS": { - "alert_emails": ["telemetry-client-dev@mozilla.com"], - "expires_in_version": "never", - "kind": "count", - "description": "Number of Telemetry ping files evicted due to server errors (4XX HTTP code received)" - }, "TELEMETRY_TEST_FLAG": { "expires_in_version": "never", "kind": "flag", @@ -4960,14 +5000,14 @@ "NEWTAB_PAGE_LIFE_SPAN": { "expires_in_version": "default", "kind": "exponential", - "high": "1200", + "high": 1200, "n_buckets": 100, "description": "Life-span of a new tab without suggested tile: time delta between first-visible and unload events (half-seconds)." }, "NEWTAB_PAGE_LIFE_SPAN_SUGGESTED": { "expires_in_version": "default", "kind": "exponential", - "high": "1200", + "high": 1200, "n_buckets": 100, "description": "Life-span of a new tab with suggested tile: time delta between first-visible and unload events (half-seconds)." }, @@ -4980,7 +5020,7 @@ "NEWTAB_PAGE_BLOCKED_SITES_COUNT": { "expires_in_version": "default", "kind": "exponential", - "high": "100", + "high": 100, "n_buckets": 10, "description": "Number of sites blocked from the new tab page." }, @@ -4995,39 +5035,11 @@ "n_values": 10, "description": "Track click count on about:newtab tiles per index (0-8). For non-default row or column configurations all clicks into the '9' bucket." }, - "PANORAMA_INITIALIZATION_TIME_MS": { - "expires_in_version": "40", - "kind": "exponential", - "high": "10000", - "n_buckets": 15, - "description": "Time it takes to initialize Panorama (ms)" - }, - "PANORAMA_GROUPS_COUNT": { - "expires_in_version": "40", - "kind": "exponential", - "high": "25", - "n_buckets": 15, - "description": "Number of groups in Panorama" - }, - "PANORAMA_STACKED_GROUPS_COUNT": { - "expires_in_version": "40", - "kind": "exponential", - "high": "25", - "n_buckets": 15, - "description": "Number of stacked groups in Panorama" - }, - "PANORAMA_MEDIAN_TABS_IN_GROUPS_COUNT": { - "expires_in_version": "40", - "kind": "exponential", - "high": "100", - "n_buckets": 15, - "description": "Median of tabs in groups in Panorama" - }, "BROWSERPROVIDER_XUL_IMPORT_TIME": { "expires_in_version": "40", "kind": "exponential", "low": 20, - "high": "600000", + "high": 600000, "n_buckets": 20, "description": "Time for the initial conversion of a XUL places database (ms)", "cpp_guard": "ANDROID" @@ -5035,7 +5047,7 @@ "BROWSERPROVIDER_XUL_IMPORT_BOOKMARKS": { "expires_in_version": "default", "kind": "exponential", - "high": "50000", + "high": 50000, "n_buckets": 20, "description": "Number of bookmarks in the original XUL places database", "cpp_guard": "ANDROID" @@ -5043,7 +5055,7 @@ "BROWSERPROVIDER_XUL_IMPORT_HISTORY": { "expires_in_version": "40", "kind": "exponential", - "high": "1000000", + "high": 1000000, "n_buckets": 20, "description": "Number of history entries in the original XUL places database", "cpp_guard": "ANDROID" @@ -5052,7 +5064,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 10, - "high": "20000", + "high": 20000, "n_buckets": 20, "description": "Time for a record to be added to history (ms)", "cpp_guard": "ANDROID" @@ -5061,7 +5073,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 10, - "high": "20000", + "high": 20000, "n_buckets": 20, "description": "Time for a record to be updated in history (ms)", "cpp_guard": "ANDROID" @@ -5070,7 +5082,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 10, - "high": "20000", + "high": 20000, "n_buckets": 20, "description": "Time to update the visited link set (ms)", "cpp_guard": "ANDROID" @@ -5085,7 +5097,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 10, - "high": "20000", + "high": 20000, "n_buckets": 20, "description": "Time for a URL bar DB search to return (ms)", "cpp_guard": "ANDROID" @@ -5101,7 +5113,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 500, - "high": "20000", + "high": 20000, "n_buckets": 20, "description": "Time for the Gecko:Ready message to arrive (ms)", "cpp_guard": "ANDROID" @@ -5110,7 +5122,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 100, - "high": "5000", + "high": 5000, "n_buckets": 20, "description": "Time for the Java UI to load (ms)", "cpp_guard": "ANDROID" @@ -5119,7 +5131,7 @@ "expires_in_version": "never", "kind": "exponential", "low": 10, - "high": "20000", + "high": 20000, "n_buckets": 20, "description": "Time for the home screen Top Sites query to return with no filter set (ms)", "cpp_guard": "ANDROID" @@ -5173,7 +5185,7 @@ "SLOW_ADDON_WARNING_RESPONSE_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "86400000", + "high": 86400000, "n_buckets": 30, "description": "Time elapsed between before responding to Slow Add-on Warning UI (ms). Not updated if the user doesn't respond at all." }, @@ -5186,7 +5198,7 @@ "SEARCH_SERVICE_INIT_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 15, "description": "Time (ms) it takes to initialize the search service" }, @@ -5199,7 +5211,7 @@ "SEARCH_SERVICE_BUILD_CACHE_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "1000", + "high": 1000, "n_buckets": 15, "description": "Time (ms) it takes to build the cache of the search service" }, @@ -5290,7 +5302,7 @@ "CHECK_ADDONS_MODIFIED_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 15, "description": "Time (ms) it takes to figure out extension last modified time" }, @@ -5298,21 +5310,21 @@ "alert_emails": ["memshrink-telemetry-alerts@mozilla.com"], "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 10, "description": "Time (ms) it takes to run memory reporters when sending a telemetry ping" }, "SSL_SUCCESFUL_CERT_VALIDATION_TIME_MOZILLAPKIX" : { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 50, "description": "Time spent on a successful cert verification in mozilla::pkix mode (ms)" }, "SSL_INITIAL_FAILED_CERT_VALIDATION_TIME_MOZILLAPKIX" : { "expires_in_version": "never", "kind": "exponential", - "high": "60000", + "high": 60000, "n_buckets": 50, "description": "Time spent on an initially failed cert verification in mozilla::pkix mode (ms)" }, @@ -5477,509 +5489,509 @@ "DEVTOOLS_DEBUGGER_RDP_LOCAL_RELOAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'reload' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_RELOAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'reload' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_NAVIGATETO_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'navigateTo' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_NAVIGATETO_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'navigateTo' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_EVENTLISTENERS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took an 'eventListeners' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_EVENTLISTENERS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took an 'eventListeners' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_DETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_DETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_RESUME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'resume' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_RESUME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'resume' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_INTERRUPT_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took an 'interrupt' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_INTERRUPT_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took an 'interrupt' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_CLIENTEVALUATE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'clientEvaluate' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_CLIENTEVALUATE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'clientEvaluate' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_RELEASEMANY_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'releaseMany' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_RELEASEMANY_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'releaseMany' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_THREADGRIPS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'threadGrips' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_THREADGRIPS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'threadGrips' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_SOURCES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'sources' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_SOURCES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'sources' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_FRAMES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'frames' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_FRAMES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'frames' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_PARAMETERNAMES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'parameterNames' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_PARAMETERNAMES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'parameterNames' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_OWNPROPERTYNAMES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'ownPropertyNames' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_OWNPROPERTYNAMES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'ownPropertyNames' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_PROTOTYPEANDPROPERTIES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'prototypeAndProperties' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_PROTOTYPEANDPROPERTIES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'prototypeAndProperties' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_ENUMPROPERTIES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'enumProperties' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_ENUMPROPERTIES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'enumProperties' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_PROTOTYPESANDPROPERTIES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'prototypesAndProperties' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_PROTOTYPESANDPROPERTIES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'prototypesAndProperties' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_PROPERTY_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'property' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_PROPERTY_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'property' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_PROTOTYPE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'prototype' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_PROTOTYPE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'prototype' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_DISPLAYSTRING_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'displayString' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_DISPLAYSTRING_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'displayString' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_SUBSTRING_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'substring' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_SUBSTRING_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'substring' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_RELEASE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'release' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_RELEASE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'release' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_LISTTABS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listTabs' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_LISTTABS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listTabs' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_LISTSERVICEWORKERREGISTRATIONS_MS": { "alert_emails": ["dev-developer-tools@lists.mozilla.org", "ejpbruel@mozilla.com"], "expires_in_version": "50", "kind": "exponential", - "high": "10000", - "n_buckets": "100", + "high": 10000, + "n_buckets": 100, "description": "The time (in milliseconds) that it took a 'listServiceWorkerRegistrations' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_LISTSERVICEWORKERREGISTRATIONS_MS": { "alert_emails": ["dev-developer-tools@lists.mozilla.org", "ejpbruel@mozilla.com"], "expires_in_version": "50", "kind": "exponential", - "high": "10000", - "n_buckets": "100", + "high": 10000, + "n_buckets": 100, "description": "The time (in milliseconds) that it took a 'listServiceWorkerRegistrations' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_PROTOCOLDESCRIPTION_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'protocolDescription' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_PROTOCOLDESCRIPTION_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'protocolDescription' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_LISTADDONS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listAddons' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_LISTADDONS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listAddons' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_LISTWORKERS_MS": { "alert_emails": ["dev-developer-tools@lists.mozilla.org", "jan@mozilla.com"], "expires_in_version": "55", "kind": "exponential", - "high": "10000", - "n_buckets": "50", + "high": 10000, + "n_buckets": 50, "description": "The time (in milliseconds) that it took a 'listWorkers' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_LISTWORKERS_MS": { "alert_emails": ["dev-developer-tools@lists.mozilla.org", "jan@mozilla.com"], "expires_in_version": "55", "kind": "exponential", - "high": "10000", - "n_buckets": "50", + "high": 10000, + "n_buckets": 50, "description": "The time (in milliseconds) that it took a 'listWorkers' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_LISTPROCESSES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listProcesses' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_LISTPROCESSES_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listProcesses' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_DELETE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'delete' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_DELETE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'delete' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_THREADDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_THREADDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_ADDONDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_ADDONDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_TABDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_TABDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_WORKERDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_WORKERDETACH_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'detach' request to go round trip." }, "DEVTOOLS_DEBUGGER_DISPLAY_SOURCE_LOCAL_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took to display a selected source to the user." }, "DEVTOOLS_DEBUGGER_DISPLAY_SOURCE_REMOTE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took to display a selected source to the user." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_RECONFIGURETAB_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'reconfigure tab' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_RECONFIGURETAB_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'reconfigure tab' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_LISTWORKERS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listWorkers' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_LISTWORKERS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'listWorkers' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_RECONFIGURETHREAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'reconfigure thread' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_RECONFIGURETHREAD_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'reconfigure thread' request to go round trip." }, "MEDIA_RUST_MP4PARSE_SUCCESS": { @@ -6028,26 +6040,41 @@ "description": "Whether Ogg audio/video encountered are chained or not.", "bug_numbers": [1230295] }, + "VIDEO_MFT_OUTPUT_NULL_SAMPLES": { + "alert_emails": ["cpearce@mozilla.com"], + "expires_in_version": "53", + "kind": "enumerated", + "n_values": 10, + "description": "Does the WMF video decoder return success but null output? 0 = playback successful, 1 = excessive null output but able to decode some frames, 2 = excessive null output and gave up, 3 = null output but recovered, 4 = non-excessive null output without being able to decode frames.", + "bug_numbers": [1176071] + }, + "AUDIO_MFT_OUTPUT_NULL_SAMPLES": { + "alert_emails": ["cpearce@mozilla.com"], + "expires_in_version": "53", + "kind": "count", + "description": "How many times the audio MFT decoder returns success but output nothing.", + "bug_numbers": [1176071] + }, "VIDEO_CANPLAYTYPE_H264_CONSTRAINT_SET_FLAG": { - "expires_in_version": "40", + "expires_in_version": "50", "kind": "enumerated", "n_values": 128, "description": "The H.264 constraint set flag as extracted from the codecs parameter passed to HTMLMediaElement.canPlayType, with the addition of 0 for unknown values." }, "VIDEO_CANPLAYTYPE_H264_LEVEL": { - "expires_in_version": "40", + "expires_in_version": "50", "kind": "enumerated", "n_values": 51, "description": "The H.264 level (level_idc) as extracted from the codecs parameter passed to HTMLMediaElement.canPlayType, from levels 1 (10) to 5.2 (51), with the addition of 0 for unknown values." }, "VIDEO_CANPLAYTYPE_H264_PROFILE": { - "expires_in_version": "40", + "expires_in_version": "50", "kind": "enumerated", "n_values": 244, "description": "The H.264 profile number (profile_idc) as extracted from the codecs parameter passed to HTMLMediaElement.canPlayType." }, "VIDEO_DECODED_H264_SPS_CONSTRAINT_SET_FLAG": { - "expires_in_version": "40", + "expires_in_version": "50", "kind": "enumerated", "n_values": 128, "description": "A bit pattern to collect H.264 constraint set flag from the decoded SPS. Bits 0 through 5 represent constraint_set0_flag through constraint_set5_flag, respectively." @@ -6321,15 +6348,15 @@ "WEBRTC_VIDEO_DECODER_FRAMERATE_AVG_PER_CALL": { "expires_in_version": "never", "kind": "exponential", - "high": "200", - "n_buckets": "50", + "high": 200, + "n_buckets": 50, "description": "Video decoder's average framerate (in fps) over an entire call" }, "WEBRTC_VIDEO_DECODER_FRAMERATE_10X_STD_DEV_PER_CALL": { "expires_in_version": "never", "kind": "exponential", - "high": "200", - "n_buckets": "50", + "high": 200, + "n_buckets": 50, "description": "Standard deviation from video decoder's average framerate (in 1/10 fps) over an entire call" }, "WEBRTC_VIDEO_DECODER_DISCARDED_PACKETS_PER_CALL_PPM": { @@ -6524,25 +6551,25 @@ "COOKIES_3RDPARTY_NUM_SITES_BLOCKED": { "expires_in_version": "40", "kind": "linear", - "low": "5", - "high": "145", - "n_buckets": "30", - "description": "The number of distinct pairs (first-party site, third-party site attempting to set cookie) for which the third-party cookie has been rejected. Sites are considered identical if they have the same eTLD + 1. Measures are normalized per 24h." + "low": 5, + "high": 145, + "n_buckets": 30, + "description": "The number of distinct pairs (first-party site, third-party site attempting to set cookie) for which the third-party cookie has been rejected. Sites are considered identical if they have the same eTLD + 1. Measures are normalized per 24h. *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "COOKIES_3RDPARTY_NUM_ATTEMPTS_ACCEPTED": { "expires_in_version": "40", "kind": "linear", - "low": "10", - "high": "500", - "n_buckets": "50", - "description": "The total number of distinct attempts by third-party sites to place cookies which have been accepted. Measures are normalized per 24h." + "low": 10, + "high": 500, + "n_buckets": 50, + "description": "The total number of distinct attempts by third-party sites to place cookies which have been accepted. Measures are normalized per 24h. *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "COOKIES_3RDPARTY_NUM_ATTEMPTS_BLOCKED": { "expires_in_version": "default", "kind": "linear", - "low": "10", - "high": "500", - "n_buckets": "50", + "low": 10, + "high": 500, + "n_buckets": 50, "description": "The total number of distinct attempts by third-party sites to place cookies which have been rejected. Measures are normalized per 24h. *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_GET_EXECUTABLE_LINES_MS": { @@ -6590,279 +6617,411 @@ "DEVTOOLS_DEBUGGER_RDP_LOCAL_SCOPE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'scope' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_SCOPE_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'scope' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_BINDINGS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'bindings' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_BINDINGS_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took a 'bindings' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_LOCAL_ASSIGN_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took an 'assign' request to go round trip." }, "DEVTOOLS_DEBUGGER_RDP_REMOTE_ASSIGN_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "1000", + "high": 10000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took an 'assign' request to go round trip." }, - "DEVTOOLS_TOOLBOX_OPENED_BOOLEAN": { + "DEVTOOLS_TOOLBOX_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's toolbox been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools toolbox has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_OPTIONS_OPENED_BOOLEAN": { + "DEVTOOLS_OPTIONS_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Options panel been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools options panel has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_WEBCONSOLE_OPENED_BOOLEAN": { + "DEVTOOLS_WEBCONSOLE_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Web Console been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Web Console has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_BROWSERCONSOLE_OPENED_BOOLEAN": { + "DEVTOOLS_BROWSERCONSOLE_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Browser Console been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Browser Console has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_INSPECTOR_OPENED_BOOLEAN": { + "DEVTOOLS_INSPECTOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Inspector been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Inspector has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_RULEVIEW_OPENED_BOOLEAN": { + "DEVTOOLS_RULEVIEW_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Rule View been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Rule View has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_COMPUTEDVIEW_OPENED_BOOLEAN": { + "DEVTOOLS_COMPUTEDVIEW_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Computed View been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Computed View has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_LAYOUTVIEW_OPENED_BOOLEAN": { + "DEVTOOLS_LAYOUTVIEW_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Layout View been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Layout View has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_FONTINSPECTOR_OPENED_BOOLEAN": { + "DEVTOOLS_FONTINSPECTOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Font Inspector been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Font Inspector has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_BOOLEAN": { + "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Animation Inspector been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Animation Inspector has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_JSDEBUGGER_OPENED_BOOLEAN": { + "DEVTOOLS_JSDEBUGGER_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Debugger been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Debugger has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_JSBROWSERDEBUGGER_OPENED_BOOLEAN": { + "DEVTOOLS_JSBROWSERDEBUGGER_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Browser Debugger been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Browser Debugger has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_STYLEEDITOR_OPENED_BOOLEAN": { + "DEVTOOLS_STYLEEDITOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Style Editor been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Style Editor has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_SHADEREDITOR_OPENED_BOOLEAN": { + "DEVTOOLS_SHADEREDITOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Shader Editor been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Shader Editor has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_WEBAUDIOEDITOR_OPENED_BOOLEAN": { + "DEVTOOLS_WEBAUDIOEDITOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Web Audio Editor been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Web Audio Editor has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_CANVASDEBUGGER_OPENED_BOOLEAN": { + "DEVTOOLS_CANVASDEBUGGER_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Canvas Debugger been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Canvas Debugger has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_JSPROFILER_OPENED_BOOLEAN": { + "DEVTOOLS_JSPROFILER_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's JS Profiler been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools JS Profiler has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_MEMORY_OPENED_BOOLEAN": { + "DEVTOOLS_MEMORY_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Memory Tool been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Memory Tool has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_NETMONITOR_OPENED_BOOLEAN": { + "DEVTOOLS_NETMONITOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Network Monitor been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Network Monitor has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_STORAGE_OPENED_BOOLEAN": { + "DEVTOOLS_STORAGE_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the Storage Inspector been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Storage Inspector has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_PAINTFLASHING_OPENED_BOOLEAN": { + "DEVTOOLS_PAINTFLASHING_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Paint Flashing been opened via the toolbox button?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Paint Flashing has been opened via the toolbox button.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_TILT_OPENED_BOOLEAN": { + "DEVTOOLS_TILT_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Tilt been opened via the toolbox button?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Tilt has been opened via the toolbox button.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_SCRATCHPAD_OPENED_BOOLEAN": { + "DEVTOOLS_SCRATCHPAD_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Scratchpad been opened via the toolbox button?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Scratchpad toolbox panel has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_RESPONSIVE_OPENED_BOOLEAN": { + "DEVTOOLS_SCRATCHPAD_WINDOW_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Responsive View been opened via the toolbox button?" + "kind": "count", + "bug_numbers": [1214352, 1247985], + "description": "Number of times the DevTools Scratchpad standalone window has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_EYEDROPPER_OPENED_BOOLEAN": { + "DEVTOOLS_RESPONSIVE_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Eyedropper tool been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Responsive Design Mode tool has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_MENU_EYEDROPPER_OPENED_BOOLEAN": { + "DEVTOOLS_EYEDROPPER_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's eyedropper been opened via the devtools menu?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Eyedropper tool has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_PICKER_EYEDROPPER_OPENED_BOOLEAN": { + "DEVTOOLS_MENU_EYEDROPPER_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's eyedropper been opened via the color picker?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Eyedropper has been opened via the DevTools menu.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_DEVELOPERTOOLBAR_OPENED_BOOLEAN": { + "DEVTOOLS_PICKER_EYEDROPPER_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the devtool's Developer Toolbar been opened via the toolbox button?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Eyedropper has been opened via the color picker.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_WEBIDE_OPENED_BOOLEAN": { + "DEVTOOLS_DEVELOPERTOOLBAR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the DevTools WebIDE been opened?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools Developer Toolbar / GCLI has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_WEBIDE_PROJECT_EDITOR_OPENED_BOOLEAN": { + "DEVTOOLS_ABOUTDEBUGGING_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org", "jan@mozilla.com"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has the DevTools WebIDE project editor been opened?" + "kind": "count", + "bug_numbers": [1247985, 1204601], + "description": "Number of times about:debugging has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_WEBIDE_PROJECT_EDITOR_SAVE_BOOLEAN": { + "DEVTOOLS_WEBIDE_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has a file been saved in the DevTools WebIDE project editor?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools WebIDE has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_WEBIDE_NEW_PROJECT_BOOLEAN": { + "DEVTOOLS_WEBIDE_PROJECT_EDITOR_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has a new project been created in the DevTools WebIDE?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times the DevTools WebIDE project editor has been opened.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_WEBIDE_IMPORT_PROJECT_BOOLEAN": { + "DEVTOOLS_WEBIDE_PROJECT_EDITOR_SAVE_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has a project been imported into the DevTools WebIDE?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times a file has been saved in the DevTools WebIDE project editor.", + "releaseChannelCollection": "opt-out" }, - "DEVTOOLS_CUSTOM_OPENED_BOOLEAN": { + "DEVTOOLS_WEBIDE_NEW_PROJECT_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], "expires_in_version": "never", - "kind": "boolean", - "description": "How many times has a custom developer tool been opened via the toolbox button?" + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times a new project has been created in the DevTools WebIDE.", + "releaseChannelCollection": "opt-out" + }, + "DEVTOOLS_WEBIDE_IMPORT_PROJECT_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], + "expires_in_version": "never", + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times a project has been imported into the DevTools WebIDE.", + "releaseChannelCollection": "opt-out" + }, + "DEVTOOLS_CUSTOM_OPENED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], + "expires_in_version": "never", + "kind": "count", + "bug_numbers": [1247985], + "description": "Number of times a custom developer tool has been opened.", + "releaseChannelCollection": "opt-out" + }, + "DEVTOOLS_RELOAD_ADDON_INSTALLED_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], + "expires_in_version": "55", + "kind": "count", + "description": "Number of times the reload addon has been installed.", + "bug_numbers": [1248435] + }, + "DEVTOOLS_RELOAD_ADDON_RELOAD_COUNT": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], + "expires_in_version": "55", + "kind": "count", + "description": "Number of times the tools have been reloaded by the reload addon.", + "bug_numbers": [1248435] }, "DEVTOOLS_TOOLBOX_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many times has the devtool's toolbox been opened?" + "description": "Number of users that have opened the DevTools toolbox." }, "DEVTOOLS_OPTIONS_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many times has the devtool's Options panel been opened?" + "description": "Number of users that have opened the DevTools Options panel." }, "DEVTOOLS_WEBCONSOLE_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Web Console?" + "description": "Number of users that have opened the DevTools Web Console." }, "DEVTOOLS_BROWSERCONSOLE_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Browser Console?" + "description": "Number of users that have opened the DevTools Browser Console." }, "DEVTOOLS_INSPECTOR_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Inspector?" + "description": "Number of users that have opened the DevTools Inspector." }, "DEVTOOLS_RULEVIEW_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Rule View?" + "description": "Number of users that have opened the DevTools Rule View." }, "DEVTOOLS_COMPUTEDVIEW_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Computed View?" + "description": "Number of users that have opened the DevTools Computed View." }, "DEVTOOLS_LAYOUTVIEW_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Layout View?" + "description": "Number of users that have opened the DevTools Layout View." }, "DEVTOOLS_FONTINSPECTOR_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Font Inspector?" + "description": "Number of users that have opened the DevTools Font Inspector." }, "DEVTOOLS_ANIMATIONINSPECTOR_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Animation Inspector?" + "description": "Number of users that have opened the DevTools Animation Inspector." }, "DEVTOOLS_JSDEBUGGER_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Debugger?" + "description": "Number of users that have opened the DevTools Debugger." }, "DEVTOOLS_JSBROWSERDEBUGGER_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Browser Debugger?" + "description": "Number of users that have opened the DevTools Browser Debugger." }, "DEVTOOLS_STYLEEDITOR_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", - "description": "How many users have opened the devtool's Style Editor?" + "description": "Number of users that have opened the DevTools Style Editor." }, "DEVTOOLS_SHADEREDITOR_OPENED_PER_USER_FLAG": { "expires_in_version": "never", @@ -6914,6 +7073,13 @@ "kind": "flag", "description": "How many users have opened the devtool's Scratchpad been opened via the toolbox button?" }, + "DEVTOOLS_SCRATCHPAD_WINDOW_OPENED_PER_USER_FLAG": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], + "expires_in_version": "50", + "kind": "flag", + "description": "How many users have opened the devtool's Scratchpad standalone window been opened?", + "bug_numbers": [1214352] + }, "DEVTOOLS_RESPONSIVE_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", @@ -6939,6 +7105,12 @@ "kind": "flag", "description": "How many users have opened the devtool's Developer Toolbar been opened via the toolbox button?" }, + "DEVTOOLS_ABOUTDEBUGGING_OPENED_PER_USER_FLAG": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org", "jan@mozilla.com"], + "expires_in_version": "55", + "kind": "flag", + "description": "How many users have opened about:debugging? (bug 1204601)" + }, "DEVTOOLS_WEBIDE_OPENED_PER_USER_FLAG": { "expires_in_version": "never", "kind": "flag", @@ -7105,63 +7277,80 @@ "DEVTOOLS_STORAGE_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has the storage inspector been active (seconds)" }, "DEVTOOLS_PAINTFLASHING_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has paint flashing been active (seconds)" }, "DEVTOOLS_TILT_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has Tilt been active (seconds)" }, "DEVTOOLS_SCRATCHPAD_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has Scratchpad been active (seconds)" }, + "DEVTOOLS_SCRATCHPAD_WINDOW_TIME_ACTIVE_SECONDS": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org"], + "expires_in_version": "50", + "kind": "exponential", + "high": 10000000, + "n_buckets": 100, + "description": "How long has Scratchpad standalone window been active (seconds)", + "bug_numbers": [1214352] + }, "DEVTOOLS_RESPONSIVE_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has the responsive view been active (seconds)" }, "DEVTOOLS_DEVELOPERTOOLBAR_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has the developer toolbar been active (seconds)" }, + "DEVTOOLS_ABOUTDEBUGGING_TIME_ACTIVE_SECONDS": { + "alert_emails": ["dev-developer-tools@lists.mozilla.org", "jan@mozilla.com"], + "expires_in_version": "55", + "kind": "exponential", + "high": 10000000, + "n_buckets": 100, + "description": "How long has about:debugging been active? (seconds) (bug 1204601)" + }, "DEVTOOLS_WEBIDE_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has WebIDE been active (seconds)" }, "DEVTOOLS_WEBIDE_PROJECT_EDITOR_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has WebIDE's project editor been active (seconds)" }, "DEVTOOLS_CUSTOM_TIME_ACTIVE_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long has a custom developer tool been active (seconds)" }, @@ -7198,7 +7387,7 @@ "DEVTOOLS_WEBIDE_CONNECTION_TIME_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 100, "description": "How long was WebIDE connected to a runtime (seconds)?" }, @@ -7275,57 +7464,57 @@ "DEVTOOLS_TABS_OPEN_PEAK_LINEAR": { "expires_in_version": "never", "kind": "linear", - "high": "101", + "high": 101, "n_buckets": 100, "description": "The peak number of open tabs in all windows for a session for devtools users." }, "DEVTOOLS_TABS_OPEN_AVERAGE_LINEAR": { "expires_in_version": "never", "kind": "linear", - "high": "101", - "n_buckets": "100", + "high": 101, + "n_buckets": 100, "description": "The mean number of open tabs in all windows for a session for devtools users." }, "DEVTOOLS_TABS_PINNED_PEAK_LINEAR": { "expires_in_version": "never", "kind": "linear", - "high": "101", - "n_buckets": "100", + "high": 101, + "n_buckets": 100, "description": "The peak number of pinned tabs (app tabs) in all windows for a session for devtools users." }, "DEVTOOLS_TABS_PINNED_AVERAGE_LINEAR": { "expires_in_version": "never", "kind": "linear", - "high": "101", - "n_buckets": "100", + "high": 101, + "n_buckets": 100, "description": "The mean number of pinned tabs (app tabs) in all windows for a session for devtools users." }, "DEVTOOLS_SAVE_HEAP_SNAPSHOT_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "100000", - "n_buckets": "1000", + "high": 100000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took to save a heap snapshot in mozilla::devtools::ChromeUtils::SaveHeapSnapshot." }, "DEVTOOLS_READ_HEAP_SNAPSHOT_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "100000", - "n_buckets": "1000", + "high": 100000, + "n_buckets": 1000, "description": "The time (in milliseconds) that it took to read a heap snapshot in mozilla::devtools::ChromeUtils::ReadHeapSnapshot." }, "DEVTOOLS_HEAP_SNAPSHOT_NODE_COUNT": { "expires_in_version": "never", "kind": "linear", - "high": "10000000", - "n_buckets": "10000", + "high": 10000000, + "n_buckets": 10000, "description": "The number of nodes serialized into a heap snapshot." }, "DEVTOOLS_HEAP_SNAPSHOT_EDGE_COUNT": { "expires_in_version": "never", "kind": "linear", - "high": "10000000", - "n_buckets": "10000", + "high": 10000000, + "n_buckets": 10000, "description": "The number of edges serialized into a heap snapshot." }, "DEVTOOLS_PERFTOOLS_RECORDING_COUNT": { @@ -7357,7 +7546,7 @@ "DEVTOOLS_PERFTOOLS_RECORDING_DURATION_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "600000", + "high": 600000, "n_buckets": 20, "description": "The length of a duration in MS of a performance tool recording." }, @@ -7365,7 +7554,7 @@ "expires_in_version": "never", "kind": "exponential", "keyed": true, - "high": "600000", + "high": 600000, "n_buckets": 20, "description": "The amount of time spent in a specific performance tool view, keyed by view name (waterfall, js-calltree, js-flamegraph, etc)." }, @@ -7402,8 +7591,8 @@ "BROWSER_SET_DEFAULT_DIALOG_PROMPT_RAWCOUNT": { "expires_in_version": "never", "kind": "exponential", - "high": "250", - "n_buckets": "15", + "high": 250, + "n_buckets": 15, "releaseChannelCollection": "opt-out", "description": "The number of times that a profile has seen the 'Set Default Browser' dialog." }, @@ -7416,7 +7605,7 @@ "BROWSER_SET_DEFAULT_RESULT": { "expires_in_version": "never", "kind": "enumerated", - "n_values": "4", + "n_values": 4, "releaseChannelCollection": "opt-out", "description": "Result of the Set Default Browser dialog (0=Use Firefox + 'Always perform check' unchecked, 1=Use Firefox + 'Always perform check' checked, 2=Not Now + 'Always perform check' unchecked, 3=Not Now + 'Always perform check' checked)" }, @@ -7429,8 +7618,8 @@ "BROWSER_SET_DEFAULT_TIME_TO_COMPLETION_SECONDS": { "expires_in_version": "never", "kind": "exponential", - "high": "500", - "n_buckets": "15", + "high": 500, + "n_buckets": 15, "releaseChannelCollection": "opt-out", "description": "Time to successfully set Firefox as the default browser after clicking 'Set Firefox as Default'. Should be near-instant in some environments, others require user interaction. Measured in seconds." }, @@ -7458,6 +7647,14 @@ "n_values": 10, "description": "How often would blocked mixed content be allowed if HSTS upgrades were allowed? 0=display/no-HSTS, 1=display/HSTS, 2=active/no-HSTS, 3=active/HSTS" }, + "MIXED_CONTENT_OBJECT_SUBREQUEST": { + "alert_emails": ["seceng@mozilla.org"], + "bug_numbers": [1244116], + "expires_in_version": "55", + "kind": "enumerated", + "n_values": 10, + "description": "How often objects load insecure content on secure pages (counting pages, not objects). 0=pages with no mixed object subrequests, 1=pages with mixed object subrequests" + }, "COOKIE_SCHEME_SECURITY": { "alert_emails": ["seceng@mozilla.org"], "expires_in_version": "50", @@ -7516,60 +7713,60 @@ "NETWORK_CACHE_V2_MISS_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent to find out a cache entry file is missing" }, "NETWORK_CACHE_V2_HIT_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent to open an existing file" }, "NETWORK_CACHE_V1_TRUNCATE_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent to reopen an entry with OPEN_TRUNCATE" }, "NETWORK_CACHE_V1_MISS_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent to find out a cache entry is missing" }, "NETWORK_CACHE_V1_HIT_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent to open an existing cache entry" }, "NETWORK_CACHE_V2_OUTPUT_STREAM_STATUS": { "expires_in_version": "never", "kind": "enumerated", - "n_values": "7", + "n_values": 7, "description": "Final status of the CacheFileOutputStream (0=ok, 1=other error, 2=out of memory, 3=disk full, 4=file corrupted, 5=file not found, 6=binding aborted)" }, "NETWORK_CACHE_V2_INPUT_STREAM_STATUS": { "expires_in_version": "never", "kind": "enumerated", - "n_values": "7", + "n_values": 7, "description": "Final status of the CacheFileInputStream (0=ok, 1=other error, 2=out of memory, 3=disk full, 4=file corrupted, 5=file not found, 6=binding aborted)" }, "NETWORK_CACHE_FS_TYPE": { "expires_in_version": "42", "kind": "enumerated", - "n_values": "5", + "n_values": 5, "description": "Type of FS that the cache is stored on (0=NTFS (Win), 1=FAT32 (Win), 2=FAT (Win), 3=other FS (Win), 4=other OS)" }, "NETWORK_CACHE_SIZE_FULL_FAT": { "expires_in_version": "42", "kind": "linear", - "high": "500", + "high": 500, "n_buckets": 50, "description": "Size (in MB) of a cache that reached a file count limit" }, @@ -7588,65 +7785,65 @@ "NETWORK_CACHE_METADATA_FIRST_READ_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent to read the first part of the metadata from the cache entry file." }, "NETWORK_CACHE_METADATA_SECOND_READ_TIME_MS": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 50, "description": "Time spent to read the missing part of the metadata from the cache entry file." }, "NETWORK_CACHE_METADATA_FIRST_READ_SIZE": { "expires_in_version": "never", "kind": "linear", - "high": "5119", + "high": 5119, "n_buckets": 256, "description": "Guessed size of the metadata that we read from the cache file as the first part." }, "NETWORK_CACHE_METADATA_SIZE": { "expires_in_version": "never", "kind": "linear", - "high": "5119", + "high": 5119, "n_buckets": 256, "description": "Actual size of the metadata parsed from the disk." }, "NETWORK_CACHE_HASH_STATS": { "expires_in_version": "46", "kind": "enumerated", - "n_values": "160", + "n_values": 160, "description": "The longest hash match between a newly added entry and all the existing entries." }, "DATABASE_LOCKED_EXCEPTION": { "expires_in_version": "42", "kind": "enumerated", "description": "Record database locks when opening one of Fennec's databases. The index corresponds to how many attempts, beginning with 0.", - "n_values": "5" + "n_values": 5 }, "DATABASE_SUCCESSFUL_UNLOCK": { "expires_in_version": "42", "kind": "enumerated", "description": "Record on which attempt we successfully unlocked a database. See DATABASE_LOCKED_EXCEPTION.", - "n_values": "5" + "n_values": 5 }, "SQLITEBRIDGE_PROVIDER_PASSWORDS_LOCKED": { "expires_in_version": "40", "kind": "enumerated", - "n_values": "10", - "description": "The number of errors using the PasswordsProvider due to a locked DB." + "n_values": 10, + "description": "The number of errors using the PasswordsProvider due to a locked DB. *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "SQLITEBRIDGE_PROVIDER_FORMS_LOCKED": { "expires_in_version": "40", "kind": "enumerated", - "n_values": "10", - "description": "The number of errors using the FormHistoryProvider due to a locked DB." + "n_values": 10, + "description": "The number of errors using the FormHistoryProvider due to a locked DB. *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***" }, "SQLITEBRIDGE_PROVIDER_HOME_LOCKED": { "expires_in_version": "40", "kind": "enumerated", - "n_values": "10", + "n_values": 10, "description": "The number of errors using the HomeProvider due to a locked DB." }, "SSL_TLS13_INTOLERANCE_REASON_PRE": { @@ -7742,7 +7939,7 @@ "SSL_KEA_ECDHE_CURVE_FULL": { "expires_in_version": "never", "kind": "enumerated", - "n_values": "36", + "n_values": 36, "description": "ECDHE KEA (TLS_ECDHE_*) curve (23=P-256, 24=P-384, 25=P-521) in full handshake" }, "SSL_AUTH_ALGORITHM_FULL": { @@ -7766,7 +7963,7 @@ "SSL_AUTH_ECDSA_CURVE_FULL": { "expires_in_version": "never", "kind": "enumerated", - "n_values": "36", + "n_values": 36, "description": "ECDSA signature curve for TLS_*_ECDSA_* in full handshake (23=P-256, 24=P-384, 25=P-521)" }, "SSL_SYMMETRIC_CIPHER_FULL": { @@ -7857,21 +8054,21 @@ "expires_in_version": "default", "kind": "exponential", "description": "The duration between the instant the first message is sent to OS.File and the moment the OS.File worker starts executing JavaScript, in milliseconds", - "high": "5000", + "high": 5000, "n_buckets": 10 }, "OSFILE_WORKER_READY_MS": { "expires_in_version": "default", "kind": "exponential", "description": "The duration between the instant the first message is sent to OS.File and the moment the OS.File worker has finished executing its startup JavaScript and is ready to receive requests, in milliseconds", - "high": "5000", + "high": 5000, "n_buckets": 10 }, "OSFILE_WRITEATOMIC_JANK_MS": { "expires_in_version": "default", "kind": "exponential", "description": "The duration during which the main thread is blocked during a call to OS.File.writeAtomic, in milliseconds", - "high": "5000", + "high": 5000, "n_buckets": 10 }, "CERT_VALIDATION_SUCCESS_BY_CA": { @@ -8069,7 +8266,7 @@ "SOCIAL_SIDEBAR_OPEN_DURATION": { "expires_in_version": "40", "kind": "exponential", - "high": "10000000", + "high": 10000000, "n_buckets": 10, "description": "Sidebar showing: seconds that the sidebar has been opened" }, @@ -8133,7 +8330,7 @@ "SERVICE_WORKER_REGISTRATION_LOADING": { "expires_in_version": "never", "kind": "exponential", - "high": "5000", + "high": 5000, "n_buckets": 20, "description": "Tracking how ServiceWorkerRegistrar loads data before the first content is shown. File bugs in Core::DOM in case of a Telemetry regression." }, @@ -8175,19 +8372,19 @@ "description": "Whether a browser window is set as an e10s window" }, "E10S_STILL_ACCEPTED_FROM_PROMPT": { - "expires_in_version": "40", + "expires_in_version": "never", "kind": "boolean", "description": "Whether a user who accepted e10s from the prompt is still using e10s" }, "E10S_BLOCKED_FROM_RUNNING": { - "expires_in_version": "40", + "expires_in_version": "never", "kind": "boolean", "description": "Whether the e10s pref was set but it was blocked from running due to blacklisted conditions" }, "BLOCKED_ON_PLUGIN_MODULE_INIT_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "keyed": true, "description": "Time (ms) that the main thread has been blocked on LoadModule and NP_Initialize in PluginModuleParent" @@ -8195,7 +8392,7 @@ "BLOCKED_ON_PLUGIN_INSTANCE_INIT_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "keyed": true, "description": "Time (ms) that the main thread has been blocked on NPP_New in an IPC plugin" @@ -8203,7 +8400,7 @@ "BLOCKED_ON_PLUGIN_STREAM_INIT_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "keyed": true, "description": "Time (ms) that the main thread has been blocked on NPP_NewStream in an IPC plugin" @@ -8211,7 +8408,7 @@ "BLOCKED_ON_PLUGINASYNCSURROGATE_WAITFORINIT_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "keyed": true, "description": "Time (ms) that the main thread has been blocked on PluginAsyncSurrogate::WaitForInit in an IPC plugin" @@ -8219,7 +8416,7 @@ "BLOCKED_ON_PLUGIN_INSTANCE_DESTROY_MS": { "expires_in_version": "40", "kind": "exponential", - "high": "10000", + "high": 10000, "n_buckets": 20, "keyed": true, "description": "Time (ms) that the main thread has been blocked on NPP_Destroy in an IPC plugin" @@ -8327,7 +8524,7 @@ "DATA_STORAGE_ENTRIES": { "expires_in_version": "default", "kind": "linear", - "high": "1024", + "high": 1024, "n_buckets": 16, "description": "The number of entries in persistent DataStorage (HSTS and HPKP data, basically)" }, @@ -8340,14 +8537,14 @@ "expires_in_version": "45", "description": "Time in MS between MSE video load and playback", "kind": "exponential", - "high": "30000", + "high": 30000, "n_buckets": 50 }, "VIDEO_MSE_PLAY_TIME_MS" : { "expires_in_version": "45", "description": "Total time spent playing MSE video", "kind": "exponential", - "high": "7200000", + "high": 7200000, "n_buckets": 100 }, "VIDEO_MSE_BUFFERING_COUNT" : { @@ -8441,6 +8638,16 @@ "n_buckets": 20, "description": "Sanitize: Time it takes to sanitize the open windows list (ms)" }, + "VIDEO_VP9_BENCHMARK_FPS": { + "alert_emails": ["ajones@mozilla.com"], + "expires_in_version": "50", + "bug_numbers": [1230265], + "kind": "linear", + "high": 1000, + "n_buckets": 100, + "description": "720p VP9 decode benchmark measurement in frames per second", + "releaseChannelCollection": "opt-out" + }, "MEDIA_CODEC_USED": { "alert_emails": ["cpearce@mozilla.com"], "expires_in_version": "never", @@ -8763,7 +8970,7 @@ "SERVICE_WORKER_LIFE_TIME": { "expires_in_version": "50", "kind": "exponential", - "high": "120000", + "high": 120000, "n_buckets": 20, "description": "Tracking how long a ServiceWorker stays alive after it is spawned. File bugs in Core::DOM in case of a Telemetry regression." }, @@ -8794,6 +9001,11 @@ "kind": "count", "description": "Record the permissions.sqlite init failure" }, + "DEFECTIVE_PERMISSIONS_SQL_REMOVED": { + "expires_in_version": "never", + "kind": "count", + "description": "Record the removal of defective permissions.sqlite" + }, "GRAPHICS_DRIVER_STARTUP_TEST": { "alert_emails": ["danderson@mozilla.com"], "expires_in_version": "never", @@ -8813,163 +9025,219 @@ "DEVTOOLS_HUD_JANK": { "expires_in_version": "never", "kind": "exponential", - "keyed": "true", + "keyed": true, "description": "The duration which a thread is blocked in ms, keyed by appName.", - "high": "5000", + "high": 5000, "n_buckets": 10 }, "DEVTOOLS_HUD_REFLOW_DURATION": { "expires_in_version": "never", "kind": "exponential", - "keyed": "true", + "keyed": true, "description": "The duration a reflow takes in ms, keyed by appName.", - "high": "1000", + "high": 1000, "n_buckets": 10 }, "DEVTOOLS_HUD_REFLOWS": { "expires_in_version": "never", "kind": "count", - "keyed": "true", + "keyed": true, "description": "A count of the number of reflows, keyed by appName." }, "DEVTOOLS_HUD_SECURITY_CATEGORY": { "expires_in_version": "never", "kind": "enumerated", - "keyed": "true", + "keyed": true, "description": "The security error enums, keyed by appName.", "n_values": 8 }, "DEVTOOLS_HUD_ERRORS": { "expires_in_version": "never", "kind": "count", - "keyed": "true", + "keyed": true, "description": "Number of errors, keyed by appName." }, "DEVTOOLS_HUD_WARNINGS": { "expires_in_version": "never", "kind": "count", - "keyed": "true", + "keyed": true, "description": "Number of warnings, keyed by appName." }, "DEVTOOLS_HUD_APP_STARTUP_TIME_CONTENTINTERACTIVE": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The duration in ms between application launch and the 'contentInteractive' performance mark, keyed by appName.", - "high": "2000", + "high": 2000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_STARTUP_TIME_NAVIGATIONINTERACTIVE": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The duration in ms between application launch and the 'navigationInteractive' performance mark, keyed by appName.", - "high": "3000", + "high": 3000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_STARTUP_TIME_NAVIGATIONLOADED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The duration in ms between application launch and the 'navigationLoaded' performance mark, keyed by appName.", - "high": "4000", + "high": 4000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_STARTUP_TIME_VISUALLYLOADED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The duration in ms between application launch and the 'visuallyLoaded' performance mark, keyed by appName.", - "high": "5000", + "high": 5000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_STARTUP_TIME_MEDIAENUMERATED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The duration in ms between application launch and the 'mediaEnumerated' performance mark, keyed by appName.", - "high": "5000", + "high": 5000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_STARTUP_TIME_FULLYLOADED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The duration in ms between application launch and the 'fullyLoaded' performance mark, keyed by appName.", - "high": "30000", + "high": 30000, "n_buckets": 30 }, "DEVTOOLS_HUD_APP_STARTUP_TIME_SCANEND": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The duration in ms between application launch and the 'scanEnd' performance mark, keyed by appName.", - "high": "30000", + "high": 30000, "n_buckets": 30 }, "DEVTOOLS_HUD_APP_MEMORY_CONTENTINTERACTIVE": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The USS memory consumed by an application at the time of the 'contentInteractive' performance mark, keyed by appName.", - "low": "2000000", - "high": "3000000", + "low": 20000000, + "high": 30000000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_MEMORY_NAVIGATIONINTERACTIVE": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The USS memory consumed by an application at the time of the 'navigationInteractive' performance mark, keyed by appName.", - "low": "2000000", - "high": "3000000", + "low": 20000000, + "high": 30000000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_MEMORY_NAVIGATIONLOADED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The USS memory consumed by an application at the time of the 'navigationLoaded' performance mark, keyed by appName.", - "low": "2000000", - "high": "3000000", + "low": 20000000, + "high": 30000000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_MEMORY_VISUALLYLOADED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The USS memory consumed by an application at the time of the 'visuallyLoaded' performance mark, keyed by appName.", - "low": "2000000", - "high": "3000000", + "low": 20000000, + "high": 30000000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_MEMORY_MEDIAENUMERATED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The USS memory consumed by an application at the time of the 'mediaEnumerated' performance mark, keyed by appName.", - "low": "2000000", - "high": "3000000", + "low": 20000000, + "high": 40000000, "n_buckets": 10 }, "DEVTOOLS_HUD_APP_MEMORY_FULLYLOADED": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The USS memory consumed by an application at the time of the 'fullyLoaded' performance mark, keyed by appName.", - "low": "2000000", - "high": "4000000", + "low": 20000000, + "high": 40000000, "n_buckets": 20 }, "DEVTOOLS_HUD_APP_MEMORY_SCANEND": { "expires_in_version": "never", "kind": "linear", - "keyed": "true", + "keyed": true, "description": "The USS memory consumed by an application at the time of the 'scanEnd' performance mark, keyed by appName.", - "low": "2000000", - "high": "4000000", + "low": 20000000, + "high": 40000000, "n_buckets": 20 }, + "DEVTOOLS_MEMORY_TAKE_SNAPSHOT_COUNT": { + "expires_in_version": "56", + "kind": "count", + "bug_numbers": [1221619], + "description": "The number of heap snapshots taken by a user" + }, + "DEVTOOLS_MEMORY_IMPORT_SNAPSHOT_COUNT": { + "expires_in_version": "56", + "kind": "count", + "bug_numbers": [1221619], + "description": "The number of heap snapshots imported by a user" + }, + "DEVTOOLS_MEMORY_EXPORT_SNAPSHOT_COUNT": { + "expires_in_version": "56", + "kind": "count", + "bug_numbers": [1221619], + "description": "The number of heap snapshots exported by a user" + }, + "DEVTOOLS_MEMORY_FILTER_CENSUS": { + "expires_in_version": "56", + "kind": "boolean", + "bug_numbers": [1221619], + "description": "Whether a census tree was filtered or not" + }, + "DEVTOOLS_MEMORY_DIFF_CENSUS": { + "expires_in_version": "56", + "kind": "boolean", + "bug_numbers": [1221619], + "description": "Whether a census was the result of diffing or not" + }, + "DEVTOOLS_MEMORY_INVERTED_CENSUS": { + "expires_in_version": "56", + "kind": "boolean", + "bug_numbers": [1221619], + "description": "Whether a census tree was inverted or not" + }, + "DEVTOOLS_MEMORY_BREAKDOWN_CENSUS_COUNT": { + "expires_in_version": "56", + "kind": "count", + "bug_numbers": [1221619], + "keyed": true, + "description": "The number of times a given type of breakdown was used for a census" + }, + "DEVTOOLS_MEMORY_DOMINATOR_TREE_COUNT": { + "expires_in_version": "56", + "kind": "count", + "bug_numbers": [1221619], + "description": "The number of times a user requested a dominator tree be computed" + }, + "DEVTOOLS_MEMORY_BREAKDOWN_DOMINATOR_TREE_COUNT": { + "expires_in_version": "56", + "kind": "count", + "bug_numbers": [1221619], + "keyed": true, + "description": "The number of times a given type of breakdown was used for a dominator tree" + }, "GRAPHICS_SANITY_TEST_REASON": { "alert_emails": ["danderson@mozilla.com"], "expires_in_version": "43", @@ -8978,11 +9246,6 @@ "releaseChannelCollection": "opt-out", "description": "Reports why a graphics sanity test was run. 0=First Run, 1=App Updated, 2=Device Change, 3=Driver Change." }, - "DEFECTIVE_PERMISSIONS_SQL_REMOVED": { - "expires_in_version": "never", - "kind": "count", - "description": "Record the removal of defective permissions.sqlite" - }, "DENIED_TRANSLATION_OFFERS": { "expires_in_version": "default", "kind": "count", @@ -9040,15 +9303,15 @@ "LOOP_ICE_ON_TIME_TRICKLE_ARRIVAL_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "20", + "high": 10000, + "n_buckets": 20, "description": "The length of time (in milliseconds) that a trickle candidate took to arrive after the start of ICE, given that it arrived when ICE was not in a failure state (ie; a candidate that we could do something with, hence 'on time')" }, "LOOP_ICE_LATE_TRICKLE_ARRIVAL_TIME": { "expires_in_version": "never", "kind": "exponential", - "high": "10000", - "n_buckets": "20", + "high": 10000, + "n_buckets": 20, "description": "The length of time (in milliseconds) that a trickle candidate took to arrive after the start of ICE, given that it arrived after ICE failed." }, "LOOP_ICE_SUCCESS_TIME": { @@ -9483,7 +9746,7 @@ "alert_emails": ["push@mozilla.com"], "expires_in_version": "55", "kind": "exponential", - "high": "15000", + "high": 15000, "n_buckets": 10, "description": "Time taken to subscribe over WebSocket (ms)." }, @@ -9712,6 +9975,20 @@ "kind": "count", "description": "Number of origins that have shown a web notification. Excludes system alerts like update reminders and add-ons." }, + "YOUTUBE_REWRITABLE_EMBED_SEEN": { + "alert_emails": ["cpeterson@mozilla.com"], + "expires_in_version": "48", + "kind": "flag", + "bug_numbers": [1229971], + "description": "Flag activated whenever a rewritable youtube flash embed is seen during a session." + }, + "YOUTUBE_NONREWRITABLE_EMBED_SEEN": { + "alert_emails": ["cpeterson@mozilla.com"], + "expires_in_version": "48", + "kind": "flag", + "bug_numbers": [1237401], + "description": "Flag activated whenever a non-rewritable (enablejsapi=1) youtube flash embed is seen during a session." + }, "PLUGIN_DRAWING_MODEL": { "alert_emails": ["danderson@mozilla.com"], "expires_in_version": "never", @@ -9742,5 +10019,23 @@ "n_buckets": 50, "bug_numbers": [1238433], "description": "Percentage of frames decoded frames dropped in an HTMLVideoElement" + }, + "VIDEO_DETAILED_DROPPED_FRAMES_PROPORTION" : { + "alert_emails": ["lchristie@mozilla.com", "cpearce@mozilla.com"], + "expires_in_version": "55", + "kind": "linear", + "high": 100, + "n_buckets": 50, + "keyed": true, + "bug_numbers": [1238433], + "description": "Percentage of frames decoded frames dropped in an HTMLVideoElement, keyed by MimeType, Resolution and Hardware Accelerated Decoding" + }, + "TAB_SWITCH_CACHE_POSITION": { + "expires_in_version": "55", + "bug_numbers": [1242013], + "kind": "linear", + "high": 100, + "n_buckets": 50, + "description": "Position in (theoretical) tab cache of tab being switched to" } } diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index c5aea454a8..0fde6ab8c8 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -353,29 +353,6 @@ PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus) nsEventStatus PuppetWidget::DispatchInputEvent(WidgetInputEvent* aEvent) -{ - if (!mTabChild) { - return nsEventStatus_eIgnore; - } - - switch (aEvent->mClass) { - case eMouseEventClass: - Unused << - mTabChild->SendDispatchMouseEvent(*aEvent->AsMouseEvent()); - break; - case eKeyboardEventClass: - Unused << - mTabChild->SendDispatchKeyboardEvent(*aEvent->AsKeyboardEvent()); - break; - default: - MOZ_ASSERT_UNREACHABLE("unsupported event type"); - } - - return nsEventStatus_eIgnore; -} - -nsEventStatus -PuppetWidget::DispatchAPZAwareEvent(WidgetInputEvent* aEvent) { if (!AsyncPanZoomEnabled()) { nsEventStatus status = nsEventStatus_eIgnore; @@ -392,6 +369,14 @@ PuppetWidget::DispatchAPZAwareEvent(WidgetInputEvent* aEvent) Unused << mTabChild->SendDispatchWheelEvent(*aEvent->AsWheelEvent()); break; + case eMouseEventClass: + Unused << + mTabChild->SendDispatchMouseEvent(*aEvent->AsMouseEvent()); + break; + case eKeyboardEventClass: + Unused << + mTabChild->SendDispatchKeyboardEvent(*aEvent->AsKeyboardEvent()); + break; default: MOZ_ASSERT_UNREACHABLE("unsupported event type"); } diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index bca266879c..9fa16885d6 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -132,7 +132,6 @@ public: LayoutDeviceIntPoint* aPoint = nullptr); NS_IMETHOD DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override; - nsEventStatus DispatchAPZAwareEvent(WidgetInputEvent* aEvent) override; nsEventStatus DispatchInputEvent(WidgetInputEvent* aEvent) override; void SetConfirmedTargetAPZC(uint64_t aInputBlockId, const nsTArray& aTargets) const override; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index ab50df760d..7754993c69 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -4531,7 +4531,7 @@ NSEvent* gLastDragMouseDownEvent = nil; else geckoEvent.button = WidgetMouseEvent::eLeftButton; - mGeckoChild->DispatchAPZAwareEvent(&geckoEvent); + mGeckoChild->DispatchInputEvent(&geckoEvent); mBlockedLastMouseDown = NO; // XXX maybe call markedTextSelectionChanged:client: here? @@ -4558,7 +4558,7 @@ NSEvent* gLastDragMouseDownEvent = nil; // This might destroy our widget (and null out mGeckoChild). bool defaultPrevented = - (mGeckoChild->DispatchAPZAwareEvent(&geckoEvent) == nsEventStatus_eConsumeNoDefault); + (mGeckoChild->DispatchInputEvent(&geckoEvent) == nsEventStatus_eConsumeNoDefault); // Check to see if we are double-clicking in the titlebar. CGFloat locationInTitlebar = [[self window] frame].size.height - [theEvent locationInWindow].y; @@ -4679,7 +4679,7 @@ NewCGSRegionFromRegion(const LayoutDeviceIntRegion& aRegion, WidgetMouseEvent::eReal); [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - mGeckoChild->DispatchAPZAwareEvent(&geckoEvent); + mGeckoChild->DispatchInputEvent(&geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -4725,7 +4725,7 @@ NewCGSRegionFromRegion(const LayoutDeviceIntRegion& aRegion, geckoEvent.button = WidgetMouseEvent::eRightButton; geckoEvent.clickCount = [theEvent clickCount]; - mGeckoChild->DispatchAPZAwareEvent(&geckoEvent); + mGeckoChild->DispatchInputEvent(&geckoEvent); if (!mGeckoChild) return; @@ -4749,7 +4749,7 @@ NewCGSRegionFromRegion(const LayoutDeviceIntRegion& aRegion, geckoEvent.clickCount = [theEvent clickCount]; nsAutoRetainCocoaObject kungFuDeathGrip(self); - mGeckoChild->DispatchAPZAwareEvent(&geckoEvent); + mGeckoChild->DispatchInputEvent(&geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -4833,7 +4833,7 @@ static int32_t RoundUp(double aDouble) WidgetWheelEvent wheelEvent(true, msg, mGeckoChild); [self convertCocoaMouseWheelEvent:theEvent toGeckoEvent:&wheelEvent]; mExpectingWheelStop = (msg == eWheelOperationStart); - mGeckoChild->DispatchAPZAwareEvent(wheelEvent.AsInputEvent()); + mGeckoChild->DispatchInputEvent(wheelEvent.AsInputEvent()); } - (void)sendWheelCondition:(BOOL)condition diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index f5671a6cbc..abfcd54d8a 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -2234,22 +2234,21 @@ nsWindow::OnExposeEvent(cairo_t *cr) return FALSE; } RefPtr ctx; + IntRect boundsRect = region.GetBounds().ToUnknownRect(); + IntPoint offset(0, 0); + if (dt->GetSize() == boundsRect.Size()) { + offset = boundsRect.TopLeft(); + dt->SetTransform(Matrix::Translation(-offset)); + } #ifdef MOZ_X11 - nsIntRect boundsRect; // for shaped only - if (shaped) { // Collapse update area to the bounding box. This is so we only have to // call UpdateTranslucentWindowAlpha once. After we have dropped // support for non-Thebes graphics, UpdateTranslucentWindowAlpha will be // our private interface so we can rework things to avoid this. - boundsRect = region.GetBounds().ToUnknownRect(); dt->PushClipRect(Rect(boundsRect)); - } else { - gfxUtils::ClipToRegion(dt, region.ToUnknownRegion()); - } - if (shaped) { // The double buffering is done here to extract the shape mask. // (The shape mask won't be necessary when a visual with an alpha // channel is used on compositing window managers.) @@ -2257,7 +2256,9 @@ nsWindow::OnExposeEvent(cairo_t *cr) RefPtr destDT = dt->CreateSimilarDrawTarget(boundsRect.Size(), SurfaceFormat::B8G8R8A8); ctx = new gfxContext(destDT, boundsRect.TopLeft()); } else { - ctx = new gfxContext(dt); + gfxUtils::ClipToRegion(dt, region.ToUnknownRegion()); + + ctx = new gfxContext(dt, offset); } #if 0 @@ -2302,7 +2303,7 @@ nsWindow::OnExposeEvent(cairo_t *cr) # ifdef MOZ_HAVE_SHMIMAGE if (mShmImage && MOZ_LIKELY(!mIsDestroyed)) { - mShmImage->Put(mXDisplay, mXWindow, region); + mShmImage->Put(region); } # endif // MOZ_HAVE_SHMIMAGE #endif // MOZ_X11 @@ -2688,7 +2689,7 @@ nsWindow::DispatchMissedButtonReleases(GdkEventCrossing *aGdkEvent) WidgetMouseEvent synthEvent(true, eMouseUp, this, WidgetMouseEvent::eSynthesized); synthEvent.button = buttonType; - DispatchAPZAwareEvent(&synthEvent); + DispatchInputEvent(&synthEvent); } } } @@ -2810,7 +2811,7 @@ nsWindow::OnButtonPressEvent(GdkEventButton *aEvent) InitButtonEvent(event, aEvent); event.pressure = mLastMotionPressure; - DispatchAPZAwareEvent(&event); + DispatchInputEvent(&event); // right menu click on linux should also pop up a context menu if (domButton == WidgetMouseEvent::eRightButton && @@ -2853,7 +2854,7 @@ nsWindow::OnButtonReleaseEvent(GdkEventButton *aEvent) gdk_event_get_axis ((GdkEvent*)aEvent, GDK_AXIS_PRESSURE, &pressure); event.pressure = pressure ? pressure : mLastMotionPressure; - DispatchAPZAwareEvent(&event); + DispatchInputEvent(&event); mLastMotionPressure = pressure; } @@ -3221,7 +3222,7 @@ nsWindow::OnScrollEvent(GdkEventScroll *aEvent) wheelEvent.time = aEvent->time; wheelEvent.timeStamp = GetEventTimeStamp(aEvent->time); - DispatchAPZAwareEvent(&wheelEvent); + DispatchInputEvent(&wheelEvent); } void @@ -3438,7 +3439,7 @@ nsWindow::OnTouchEvent(GdkEventTouch* aEvent) *event.touches.AppendElement() = touch.forget(); } - DispatchAPZAwareEvent(&event); + DispatchInputEvent(&event); return TRUE; } #endif @@ -6332,13 +6333,7 @@ nsWindow::GetSurfaceForGdkDrawable(GdkDrawable* aDrawable, already_AddRefed nsWindow::GetDrawTarget(const LayoutDeviceIntRegion& aRegion, BufferMode* aBufferMode) { - if (!mGdkWindow) { - return nullptr; - } - - LayoutDeviceIntRect bounds = aRegion.GetBounds(); - LayoutDeviceIntSize size(bounds.XMost(), bounds.YMost()); - if (size.width <= 0 || size.height <= 0) { + if (!mGdkWindow || aRegion.IsEmpty()) { return nullptr; } @@ -6347,12 +6342,19 @@ nsWindow::GetDrawTarget(const LayoutDeviceIntRegion& aRegion, BufferMode* aBuffe #ifdef MOZ_X11 # ifdef MOZ_HAVE_SHMIMAGE if (nsShmImage::UseShm()) { - dt = nsShmImage::EnsureShmImage(size, - mXDisplay, mXVisual, mXDepth, mShmImage); + if (!mShmImage) { + mShmImage = new nsShmImage(mXDisplay, mXWindow, mXVisual, mXDepth); + } + dt = mShmImage->CreateDrawTarget(aRegion); *aBufferMode = BufferMode::BUFFER_NONE; + if (!dt) { + mShmImage = nullptr; + } } # endif // MOZ_HAVE_SHMIMAGE if (!dt) { + LayoutDeviceIntRect bounds = aRegion.GetBounds(); + LayoutDeviceIntSize size(bounds.XMost(), bounds.YMost()); RefPtr surf = new gfxXlibSurface(mXDisplay, mXWindow, mXVisual, size.ToUnknownSize()); if (!surf->CairoStatus()) { dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf.get(), surf->GetSize()); @@ -6380,7 +6382,7 @@ nsWindow::EndRemoteDrawingInRegion(DrawTarget* aDrawTarget, return; } - mShmImage->Put(mXDisplay, mXWindow, aInvalidRegion); + mShmImage->Put(aInvalidRegion); # endif // MOZ_HAVE_SHMIMAGE #endif // MOZ_X11 } diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index cd5bdf3f99..1b1e1f9b13 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1106,12 +1106,6 @@ nsBaseWidget::ProcessUntransformedAPZEvent(WidgetInputEvent* aEvent, return status; } -nsEventStatus -nsBaseWidget::DispatchInputEvent(WidgetInputEvent* aEvent) -{ - return DispatchAPZAwareEvent(aEvent); -} - class DispatchWheelEventOnMainThread : public Task { public: @@ -1179,7 +1173,7 @@ private: }; nsEventStatus -nsBaseWidget::DispatchAPZAwareEvent(WidgetInputEvent* aEvent) +nsBaseWidget::DispatchInputEvent(WidgetInputEvent* aEvent) { MOZ_ASSERT(NS_IsMainThread()); if (mAPZC) { @@ -1366,6 +1360,15 @@ already_AddRefed nsBaseWidget::StartRemoteDrawing() return nullptr; } +already_AddRefed +nsBaseWidget::CreateBackBufferDrawTarget(mozilla::gfx::DrawTarget* aScreenTarget, + const LayoutDeviceIntRect& aRect) +{ + MOZ_ASSERT(aScreenTarget); + gfx::SurfaceFormat format = aScreenTarget->GetFormat() == gfx::SurfaceFormat::B8G8R8X8 ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8; + return aScreenTarget->CreateSimilarDrawTarget(aRect.ToUnknownRect().Size(), format); +} + //------------------------------------------------------------------------- // // Destroy the window diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index d755b58ad9..e9f1aa2b69 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -167,6 +167,8 @@ public: virtual already_AddRefed StartRemoteDrawing() override; virtual void EndRemoteDrawing() override { }; virtual void CleanupRemoteDrawing() override { }; + virtual already_AddRefed CreateBackBufferDrawTarget(mozilla::gfx::DrawTarget* aScreenTarget, + const LayoutDeviceIntRect& aRect) override; virtual void UpdateThemeGeometries(const nsTArray& aThemeGeometries) override {} NS_IMETHOD SetModal(bool aModal) override; virtual uint32_t GetMaxTouchPoints() const override; @@ -250,12 +252,8 @@ public: const FrameMetrics::ViewID& aViewId, const CSSRect& aRect, const uint32_t& aFlags) override; - // Helper function for dispatching events which are not processed by APZ, - // but need to be transformed by APZ. - nsEventStatus DispatchInputEvent(mozilla::WidgetInputEvent* aEvent) override; - // Dispatch an event that must be first be routed through APZ. - nsEventStatus DispatchAPZAwareEvent(mozilla::WidgetInputEvent* aEvent) override; + nsEventStatus DispatchInputEvent(mozilla::WidgetInputEvent* aEvent) override; void SetConfirmedTargetAPZC(uint64_t aInputBlockId, const nsTArray& aTargets) const override; diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 440e7f9f0d..af87a50a39 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1284,6 +1284,20 @@ class nsIWidget : public nsISupports { EndRemoteDrawing(); } + /** + * Clean up any resources used by Start/EndRemoteDrawing. + * + * Called by BasicCompositor on the compositor thread for OMTC drawing + * when the compositor is destroyed. + */ + virtual void CleanupRemoteDrawing() = 0; + + /** + * Create DrawTarget used as BackBuffer of the screen + */ + virtual already_AddRefed CreateBackBufferDrawTarget(mozilla::gfx::DrawTarget* aScreenTarget, + const LayoutDeviceIntRect& aRect) = 0; + /** * A hook for the widget to prepare a Compositor, during the latter's initialization. * @@ -1294,14 +1308,6 @@ class nsIWidget : public nsISupports { */ virtual bool InitCompositor(mozilla::layers::Compositor*) { return true; } - /** - * Clean up any resources used by Start/EndRemoteDrawing. - * - * Called by BasicCompositor on the compositor thread for OMTC drawing - * when the compositor is destroyed. - */ - virtual void CleanupRemoteDrawing() = 0; - /** * Called when Gecko knows which themed widgets exist in this window. * The passed array contains an entry for every themed widget of the right @@ -1394,13 +1400,6 @@ class nsIWidget : public nsISupports { * enabled. If invoked in the child process, it is forwarded to the * parent process synchronously. */ - virtual nsEventStatus DispatchAPZAwareEvent(mozilla::WidgetInputEvent* aEvent) = 0; - - /** - * Dispatches an event that must be transformed by APZ first, but is not - * actually handled by APZ. If invoked in the child process, it is - * forwarded to the parent process synchronously. - */ virtual nsEventStatus DispatchInputEvent(mozilla::WidgetInputEvent* aEvent) = 0; /** diff --git a/widget/nsShmImage.cpp b/widget/nsShmImage.cpp index 47e91cf27a..a2a1312766 100644 --- a/widget/nsShmImage.cpp +++ b/widget/nsShmImage.cpp @@ -4,13 +4,6 @@ * 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/. */ -#if defined(MOZ_WIDGET_GTK) -#include -#include -#elif defined(MOZ_WIDGET_QT) -#include -#endif - #include "nsShmImage.h" #ifdef MOZ_WIDGET_GTK #include "gfxPlatformGtk.h" @@ -35,9 +28,9 @@ static bool gShmAvailable = true; bool nsShmImage::UseShm() { #ifdef MOZ_WIDGET_GTK - return (gShmAvailable && !gfxPlatformGtk::GetPlatform()->UseXRender()); + return (gShmAvailable && !gfxPlatformGtk::GetPlatform()->UseXRender()); #else - return gShmAvailable; + return gShmAvailable; #endif } @@ -47,9 +40,9 @@ static int gShmError = 0; static int TrapShmError(Display* aDisplay, XErrorEvent* aEvent) { - // store the error code and ignore the error - gShmError = aEvent->error_code; - return 0; + // store the error code and ignore the error + gShmError = aEvent->error_code; + return 0; } #endif @@ -68,16 +61,19 @@ nsShmImage::CreateShmSegment() } mInfo.shmaddr = (char *)shmat(mInfo.shmid, nullptr, 0); + + // Mark the handle removed so that it will destroy the segment when unmapped. + shmctl(mInfo.shmid, IPC_RMID, nullptr); + if (mInfo.shmaddr == (void *)-1) { + // Since mapping failed, the segment is already destroyed. + mInfo.shmid = -1; + nsPrintfCString warning("shmat(): %s (%d)\n", strerror(errno), errno); NS_WARNING(warning.get()); return false; } - // Mark the handle as deleted so that, should this process go away, the - // segment is cleaned up. - shmctl(mInfo.shmid, IPC_RMID, 0); - #ifdef DEBUG struct shmid_ds info; if (shmctl(mInfo.shmid, IPC_STAT, &info) < 0) { @@ -105,55 +101,25 @@ nsShmImage::DestroyShmSegment() } bool -nsShmImage::CreateImage(const LayoutDeviceIntSize& aSize, - Display* aDisplay, Visual* aVisual, unsigned int aDepth) +nsShmImage::CreateImage(const IntSize& aSize) { - mDisplay = aDisplay; - mImage = XShmCreateImage(aDisplay, aVisual, aDepth, - ZPixmap, nullptr, - &mInfo, - aSize.width, aSize.height); - if (!mImage || !CreateShmSegment()) { - return false; - } + MOZ_ASSERT(mDisplay && mVisual); -#if defined(MOZ_WIDGET_GTK) - gShmError = 0; - XErrorHandler previousHandler = XSetErrorHandler(TrapShmError); - Status attachOk = XShmAttach(aDisplay, &mInfo); - XSync(aDisplay, False); - XSetErrorHandler(previousHandler); - if (gShmError) { - attachOk = 0; - } -#elif defined(MOZ_WIDGET_QT) - Status attachOk = XShmAttach(aDisplay, &mInfo); -#endif - - if (!attachOk) { - // Assume XShm isn't available, and don't attempt to use it - // again. - gShmAvailable = false; - return false; - } - - mXAttached = true; - mSize = aSize; mFormat = SurfaceFormat::UNKNOWN; - switch (mImage->depth) { + switch (mDepth) { case 32: - if ((mImage->red_mask == 0xff0000) && - (mImage->green_mask == 0xff00) && - (mImage->blue_mask == 0xff)) { + if (mVisual->red_mask == 0xff0000 && + mVisual->green_mask == 0xff00 && + mVisual->blue_mask == 0xff) { mFormat = SurfaceFormat::B8G8R8A8; } break; case 24: // Only support the BGRX layout, and report it as BGRA to the compositor. // The alpha channel will be discarded when we put the image. - if ((mImage->red_mask == 0xff0000) && - (mImage->green_mask == 0xff00) && - (mImage->blue_mask == 0xff)) { + if (mVisual->red_mask == 0xff0000 && + mVisual->green_mask == 0xff00 && + mVisual->blue_mask == 0xff) { mFormat = SurfaceFormat::B8G8R8A8; } break; @@ -168,96 +134,108 @@ nsShmImage::CreateImage(const LayoutDeviceIntSize& aSize, return false; } + mImage = XShmCreateImage(mDisplay, mVisual, mDepth, + ZPixmap, nullptr, + &mInfo, + aSize.width, aSize.height); + if (!mImage || !CreateShmSegment()) { + DestroyImage(); + return false; + } + +#ifdef MOZ_WIDGET_GTK + gShmError = 0; + XErrorHandler previousHandler = XSetErrorHandler(TrapShmError); + Status attachOk = XShmAttach(mDisplay, &mInfo); + XSync(mDisplay, False); + XSetErrorHandler(previousHandler); + if (gShmError) { + attachOk = 0; + } +#else + Status attachOk = XShmAttach(mDisplay, &mInfo); +#endif + + if (!attachOk) { + DestroyShmSegment(); + DestroyImage(); + + // Assume XShm isn't available, and don't attempt to use it + // again. + gShmAvailable = false; + return false; + } + return true; } -nsShmImage::~nsShmImage() +void +nsShmImage::DestroyImage() { if (mImage) { mozilla::FinishX(mDisplay); - if (mXAttached) { + if (mInfo.shmid != -1) { XShmDetach(mDisplay, &mInfo); } XDestroyImage(mImage); + mImage = nullptr; } DestroyShmSegment(); } already_AddRefed -nsShmImage::CreateDrawTarget() +nsShmImage::CreateDrawTarget(const LayoutDeviceIntRegion& aRegion) { + // Due to bug 1205045, we must avoid making GTK calls off the main thread to query window size. + // Instead we just track the largest offset within the image we are drawing to and grow the image + // to accomodate it. Since usually the entire window is invalidated on the first paint to it, + // this should grow the image to the necessary size quickly without many intermediate reallocations. + IntRect bounds = aRegion.GetBounds().ToUnknownRect(); + IntSize size(bounds.XMost(), bounds.YMost()); + if (!mImage || size.width > mImage->width || size.height > mImage->height) { + DestroyImage(); + if (!CreateImage(size)) { + return nullptr; + } + } + return gfxPlatform::GetPlatform()->CreateDrawTargetForData( - reinterpret_cast(mImage->data), - mSize.ToUnknownSize(), + reinterpret_cast(mImage->data) + + bounds.y * mImage->bytes_per_line + bounds.x * BytesPerPixel(mFormat), + bounds.Size(), mImage->bytes_per_line, mFormat); } -#ifdef MOZ_WIDGET_GTK void -nsShmImage::Put(Display* aDisplay, Drawable aWindow, - const LayoutDeviceIntRegion& aRegion) +nsShmImage::Put(const LayoutDeviceIntRegion& aRegion) { - GC gc = XCreateGC(aDisplay, aWindow, 0, nullptr); - LayoutDeviceIntRegion bounded; - bounded.And(aRegion, - LayoutDeviceIntRect(0, 0, mImage->width, mImage->height)); - for (auto iter = bounded.RectIter(); !iter.Done(); iter.Next()) { - const LayoutDeviceIntRect& r = iter.Get(); - XShmPutImage(aDisplay, aWindow, gc, mImage, - r.x, r.y, - r.x, r.y, - r.width, r.height, - False); - } - - XFreeGC(aDisplay, gc); - - // FIXME/bug 597336: we need to ensure that the shm image isn't - // scribbled over before all its pending XShmPutImage()s complete. - // However, XSync() is an unnecessarily heavyweight - // synchronization mechanism; other options are possible. If this - // XSync is shown to hurt responsiveness, we need to explore the - // other options. - XSync(aDisplay, False); -} - -#elif defined(MOZ_WIDGET_QT) -void -nsShmImage::Put(QWindow* aWindow, QRect& aRect) -{ - Display* dpy = gfxQtPlatform::GetXDisplay(aWindow); - Drawable d = aWindow->winId(); - - GC gc = XCreateGC(dpy, d, 0, nullptr); - // Avoid out of bounds painting - QRect inter = aRect.intersected(aWindow->geometry()); - XShmPutImage(dpy, d, gc, mImage, - inter.x(), inter.y(), - inter.x(), inter.y(), - inter.width(), inter.height(), - False); - XFreeGC(dpy, gc); -} -#endif - -already_AddRefed -nsShmImage::EnsureShmImage(const LayoutDeviceIntSize& aSize, - Display* aDisplay, Visual* aVisual, unsigned int aDepth, - RefPtr& aImage) -{ - if (!aImage || aImage->Size() != aSize) { - // Because we XSync() after XShmAttach() to trap errors, we - // know that the X server has the old image's memory mapped - // into its address space, so it's OK to destroy the old image - // here even if there are outstanding Puts. The Detach is - // ordered after the Puts. - aImage = new nsShmImage; - if (!aImage->CreateImage(aSize, aDisplay, aVisual, aDepth)) { - aImage = nullptr; - } + if (!mImage) { + return; } - return !aImage ? nullptr : aImage->CreateDrawTarget(); + + GC gc = XCreateGC(mDisplay, mWindow, 0, nullptr); + LayoutDeviceIntRegion bounded; + bounded.And(aRegion, + LayoutDeviceIntRect(0, 0, mImage->width, mImage->height)); + for (auto iter = bounded.RectIter(); !iter.Done(); iter.Next()) { + const LayoutDeviceIntRect& r = iter.Get(); + XShmPutImage(mDisplay, mWindow, gc, mImage, + r.x, r.y, + r.x, r.y, + r.width, r.height, + False); + } + + XFreeGC(mDisplay, gc); + + // FIXME/bug 597336: we need to ensure that the shm image isn't + // scribbled over before all its pending XShmPutImage()s complete. + // However, XSync() is an unnecessarily heavyweight + // synchronization mechanism; other options are possible. If this + // XSync is shown to hurt responsiveness, we need to explore the + // other options. + XSync(mDisplay, False); } #endif // MOZ_HAVE_SHMIMAGE diff --git a/widget/nsShmImage.h b/widget/nsShmImage.h index 27c9d23f55..c9e3e02834 100644 --- a/widget/nsShmImage.h +++ b/widget/nsShmImage.h @@ -20,55 +20,51 @@ #include #include -#ifdef MOZ_WIDGET_QT -class QRect; -class QWindow; -#endif - class nsShmImage { - // bug 1168843, compositor thread may create shared memory instances that are destroyed by main thread on shutdown, so this must use thread-safe RC to avoid hitting assertion - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsShmImage) + // bug 1168843, compositor thread may create shared memory instances that are destroyed by main thread on shutdown, so this must use thread-safe RC to avoid hitting assertion + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsShmImage) public: - static bool UseShm(); - static already_AddRefed - EnsureShmImage(const mozilla::LayoutDeviceIntSize& aSize, - Display* aDisplay, Visual* aVisual, unsigned int aDepth, - RefPtr& aImage); + static bool UseShm(); - already_AddRefed CreateDrawTarget(); + already_AddRefed + CreateDrawTarget(const mozilla::LayoutDeviceIntRegion& aRegion); -#ifdef MOZ_WIDGET_GTK - void Put(Display* aDisplay, Drawable aWindow, - const mozilla::LayoutDeviceIntRegion& aRegion); -#elif defined(MOZ_WIDGET_QT) - void Put(QWindow* aWindow, QRect& aRect); -#endif + void Put(const mozilla::LayoutDeviceIntRegion& aRegion); - mozilla::LayoutDeviceIntSize Size() const { return mSize; } + nsShmImage(Display* aDisplay, + Drawable aWindow, + Visual* aVisual, + unsigned int aDepth) + : mImage(nullptr) + , mDisplay(aDisplay) + , mWindow(aWindow) + , mVisual(aVisual) + , mDepth(aDepth) + , mFormat(mozilla::gfx::SurfaceFormat::UNKNOWN) + { + mInfo.shmid = -1; + } private: - nsShmImage() - : mImage(nullptr) - , mDisplay(nullptr) - , mFormat(mozilla::gfx::SurfaceFormat::UNKNOWN) - , mXAttached(false) - { mInfo.shmid = -1; } + ~nsShmImage() + { + DestroyImage(); + } - ~nsShmImage(); + bool CreateShmSegment(); + void DestroyShmSegment(); - bool CreateShmSegment(); - void DestroyShmSegment(); + bool CreateImage(const mozilla::gfx::IntSize& aSize); + void DestroyImage(); - bool CreateImage(const mozilla::LayoutDeviceIntSize& aSize, - Display* aDisplay, Visual* aVisual, unsigned int aDepth); - - XImage* mImage; - Display* mDisplay; - XShmSegmentInfo mInfo; - mozilla::LayoutDeviceIntSize mSize; - mozilla::gfx::SurfaceFormat mFormat; - bool mXAttached; + XImage* mImage; + Display* mDisplay; + Drawable mWindow; + Visual* mVisual; + unsigned int mDepth; + XShmSegmentInfo mInfo; + mozilla::gfx::SurfaceFormat mFormat; }; #endif // MOZ_HAVE_SHMIMAGE diff --git a/widget/uikit/nsWindow.mm b/widget/uikit/nsWindow.mm index d1fa115af9..5412fee505 100644 --- a/widget/uikit/nsWindow.mm +++ b/widget/uikit/nsWindow.mm @@ -185,7 +185,7 @@ private: event.refPoint = loc; event.touches.AppendElement(t); } - aWindow->DispatchAPZAwareEvent(&event); + aWindow->DispatchInputEvent(&event); } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event diff --git a/widget/windows/IMMHandler.cpp b/widget/windows/IMMHandler.cpp index 7652c105b0..73b6871b40 100644 --- a/widget/windows/IMMHandler.cpp +++ b/widget/windows/IMMHandler.cpp @@ -1266,7 +1266,7 @@ TextEventDispatcher* IMMHandler::GetTextEventDispatcherFor(nsWindow* aWindow) { return aWindow == mComposingWindow && mDispatcher ? - mDispatcher : aWindow->GetTextEventDispatcher(); + mDispatcher.get() : aWindow->GetTextEventDispatcher(); } void @@ -1802,7 +1802,7 @@ IMMHandler::HandleDocumentFeed(nsWindow* aWindow, // Get the focused paragraph, we decide that it starts from the previous CRLF // (or start of the editor) to the next one (or the end of the editor). - int32_t paragraphStart = str.RFind("", false, targetOffset, -1) + 1; + int32_t paragraphStart = str.RFind("\n", false, targetOffset, -1) + 1; int32_t paragraphEnd = str.Find("\r", false, targetOffset + targetLength, -1); if (paragraphEnd < 0) { @@ -2802,7 +2802,7 @@ IMMHandler::SetCandidateWindow(nsWindow* aWindow, CANDIDATEFORM* aForm) { // Hack for ATOK. ATOK (Japanese IME) refers native caret position at // deciding candidate window position. - if (aForm->dwStyle == CFS_CANDIDATEPOS && aWindow->PluginHasFocus()) { + if (aWindow->PluginHasFocus()) { // We cannot retrieve proper character height from plugin. Therefore, // we should assume that the caret height is always 20px since if less than // this height, candidate window may overlap with composition string when diff --git a/widget/windows/KeyboardLayout.cpp b/widget/windows/KeyboardLayout.cpp index 55b625d901..b3a64601dc 100644 --- a/widget/windows/KeyboardLayout.cpp +++ b/widget/windows/KeyboardLayout.cpp @@ -1300,6 +1300,14 @@ NativeKey::HandleAppCommandMessage() const // This allow web applications to provide better UX for multimedia keyboard // users. bool dispatchKeyEvent = (GET_DEVICE_LPARAM(mMsg.lParam) == FAPPCOMMAND_KEY); + if (dispatchKeyEvent) { + // If a plug-in window has focus but it didn't consume the message, our + // window receive WM_APPCOMMAND message. In this case, we shouldn't + // dispatch KeyboardEvents because an event handler may access the + // plug-in process synchronously. + dispatchKeyEvent = + WinUtils::IsOurProcessWindow(reinterpret_cast(mMsg.wParam)); + } bool consumed = false; diff --git a/widget/windows/WindowsUIUtils.cpp b/widget/windows/WindowsUIUtils.cpp index de6b9b355f..39422f233d 100644 --- a/widget/windows/WindowsUIUtils.cpp +++ b/widget/windows/WindowsUIUtils.cpp @@ -11,7 +11,7 @@ #include "nsIObserverService.h" #include "nsIBaseWindow.h" -#include "nsIDocshell.h" +#include "nsIDocShell.h" #include "nsIAppShellService.h" #include "nsAppShellCID.h" #include "nsIXULWindow.h" @@ -33,7 +33,7 @@ using namespace ABI::Windows::Foundation; /* All of this is win10 stuff and we're compiling against win81 headers * for now, so we may need to do some legwork: */ -#ifndef UserInteractionMode +#if MOZ_WINSDK_MAXVER < 0x0A000000 namespace ABI { namespace Windows { namespace UI { @@ -53,7 +53,7 @@ namespace ABI { #define RuntimeClass_Windows_UI_ViewManagement_UIViewSettings L"Windows.UI.ViewManagement.UIViewSettings" #endif -#ifndef IUIViewSettings +#if MOZ_WINSDK_MAXVER < 0x0A000000 namespace ABI { namespace Windows { namespace UI { diff --git a/widget/windows/nsBidiKeyboard.cpp b/widget/windows/nsBidiKeyboard.cpp index bb8407b553..c186679d93 100644 --- a/widget/windows/nsBidiKeyboard.cpp +++ b/widget/windows/nsBidiKeyboard.cpp @@ -7,6 +7,10 @@ #include #include "nsBidiKeyboard.h" #include "prmem.h" +#include "nsServiceManagerUtils.h" +#include "nsTArray.h" +#include "nsContentUtils.h" +#include "mozilla/dom/ContentParent.h" #include NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard) @@ -177,3 +181,24 @@ bool nsBidiKeyboard::IsRTLLanguage(HKL aLocale) (sizeof(localesig)/sizeof(WCHAR))) && (localesig.lsUsb[3] & 0x08000000)); } + +//static +void +nsBidiKeyboard::OnLayoutChange() +{ + nsCOMPtr bidiKeyboard = nsContentUtils::GetBidiKeyboard(); + if (!bidiKeyboard) { + return; + } + + bool rtl; + if (NS_FAILED(bidiKeyboard->IsLangRTL(&rtl))) { + return; + } + + nsTArray children; + mozilla::dom::ContentParent::GetAll(children); + for (uint32_t i = 0; i < children.Length(); i++) { + children[i]->SendBidiKeyboardNotify(rtl); + } +} diff --git a/widget/windows/nsBidiKeyboard.h b/widget/windows/nsBidiKeyboard.h index 378e760773..b3b56f48f6 100644 --- a/widget/windows/nsBidiKeyboard.h +++ b/widget/windows/nsBidiKeyboard.h @@ -19,6 +19,8 @@ public: nsBidiKeyboard(); + static void OnLayoutChange(); + protected: nsresult SetupBidiKeyboards(); diff --git a/widget/windows/nsDeviceContextSpecWin.cpp b/widget/windows/nsDeviceContextSpecWin.cpp index 5eb15fe5a3..6fbfaf3761 100644 --- a/widget/windows/nsDeviceContextSpecWin.cpp +++ b/widget/windows/nsDeviceContextSpecWin.cpp @@ -181,10 +181,11 @@ NS_IMETHODIMP nsDeviceContextSpecWin::Init(nsIWidget* aWidget, PR_PL(("***** nsDeviceContextSpecWin::Init - aPrintSettingswas NULL!\n")); } - // Get the Print Name to be used + // Get the Printer Name to be used and output format. char16_t * printerName = nullptr; if (mPrintSettings) { mPrintSettings->GetPrinterName(&printerName); + mPrintSettings->GetOutputFormat(&mOutputFormat); } // If there is no name then use the default printer @@ -225,12 +226,7 @@ NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface *surface = nullptr; RefPtr newSurface; - int16_t outputFormat = 0; - if (mPrintSettings) { - mPrintSettings->GetOutputFormat(&outputFormat); - } - - if (outputFormat == nsIPrintSettings::kOutputFormatPDF) { + if (mOutputFormat == nsIPrintSettings::kOutputFormatPDF) { nsXPIDLString filename; mPrintSettings->GetToFileName(getter_Copies(filename)); @@ -277,11 +273,25 @@ NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface return NS_OK; } +float +nsDeviceContextSpecWin::GetDPI() +{ + // To match the previous printing code we need to return 72 when printing to + // PDF and 144 when printing to a Windows surface. + return mOutputFormat == nsIPrintSettings::kOutputFormatPDF ? 72.0f : 144.0f; +} + float nsDeviceContextSpecWin::GetPrintingScale() { MOZ_ASSERT(mPrintSettings); + // To match the previous printing code there is no scaling for PDF. + if (mOutputFormat == nsIPrintSettings::kOutputFormatPDF) { + return 1.0f; + } + + // The print settings will have the resolution stored from the real device. int32_t resolution; mPrintSettings->GetResolution(&resolution); return float(resolution) / GetDPI(); @@ -444,7 +454,8 @@ nsPrinterEnumeratorWin::InitPrintSettingsFromPrinter(const char16_t *aPrinterNam aPrintSettings->SetPrinterName(aPrinterName); // We need to get information from the device as well. - HDC dc = ::CreateICW(kDriverName, aPrinterName, nullptr, devmode); + char16ptr_t printerName = aPrinterName; + HDC dc = ::CreateICW(kDriverName, printerName, nullptr, devmode); if (NS_WARN_IF(!dc)) { return NS_ERROR_FAILURE; } diff --git a/widget/windows/nsDeviceContextSpecWin.h b/widget/windows/nsDeviceContextSpecWin.h index 43cf08c87c..19aa3ff236 100644 --- a/widget/windows/nsDeviceContextSpecWin.h +++ b/widget/windows/nsDeviceContextSpecWin.h @@ -35,7 +35,7 @@ public: NS_IMETHOD Init(nsIWidget* aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override; - float GetDPI() final { return 144.0f; } + float GetDPI() final; float GetPrintingScale() final; @@ -64,6 +64,7 @@ protected: LPDEVMODEW mDevMode; nsCOMPtr mPrintSettings; + int16_t mOutputFormat = nsIPrintSettings::kOutputFormatNative; }; diff --git a/widget/windows/nsUXThemeData.cpp b/widget/windows/nsUXThemeData.cpp index c5c7c3f02a..fed516915f 100644 --- a/widget/windows/nsUXThemeData.cpp +++ b/widget/windows/nsUXThemeData.cpp @@ -30,7 +30,8 @@ nsUXThemeData::sFlatMenus = false; bool nsUXThemeData::sTitlebarInfoPopulatedAero = false; bool nsUXThemeData::sTitlebarInfoPopulatedThemed = false; -SIZE nsUXThemeData::sCommandButtons[4]; +const int NUM_COMMAND_BUTTONS = 4; +SIZE nsUXThemeData::sCommandButtons[NUM_COMMAND_BUTTONS]; void nsUXThemeData::Teardown() { @@ -219,6 +220,15 @@ nsUXThemeData::UpdateTitlebarInfo(HWND aWnd) sCommandButtons[2].cx = info.rgrect[5].right - info.rgrect[5].left; sCommandButtons[2].cy = info.rgrect[5].bottom - info.rgrect[5].top; +#ifdef DEBUG + // Verify that all values for the command buttons are positive values + // otherwise we have cached bad values for the caption buttons + for (int i = 0; i < NUM_COMMAND_BUTTONS; i++) { + MOZ_ASSERT(sCommandButtons[i].cx > 0); + MOZ_ASSERT(sCommandButtons[i].cy > 0); + } +#endif + sTitlebarInfoPopulatedThemed = true; } diff --git a/widget/windows/nsWidgetFactory.cpp b/widget/windows/nsWidgetFactory.cpp index 196d228b8b..9e8f052bc8 100644 --- a/widget/windows/nsWidgetFactory.cpp +++ b/widget/windows/nsWidgetFactory.cpp @@ -194,7 +194,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_WIN_JUMPLISTSHORTCUT_CID, false, nullptr, JumpListShortcutConstructor }, { &kNS_WINDOWS_UIUTILS_CID, false, nullptr, WindowsUIUtilsConstructor }, { &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY }, - { &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor }, + { &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor, Module::MAIN_PROCESS_ONLY }, { &kNS_TASKBARPREVIEWCALLBACK_CID, false, nullptr, TaskbarPreviewCallbackConstructor }, #ifdef NS_PRINTING { &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintOptionsWinConstructor }, @@ -228,7 +228,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { { "@mozilla.org/windows-jumplistshortcut;1", &kNS_WIN_JUMPLISTSHORTCUT_CID }, { "@mozilla.org/windows-ui-utils;1", &kNS_WINDOWS_UIUTILS_CID }, { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::MAIN_PROCESS_ONLY }, - { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID }, + { "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID, Module::MAIN_PROCESS_ONLY }, { "@mozilla.org/widget/taskbar-preview-callback;1", &kNS_TASKBARPREVIEWCALLBACK_CID }, #ifdef NS_PRINTING { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID }, diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 0da7b22663..e21e99115f 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -134,6 +134,7 @@ #include "mozilla/TextEvents.h" // For WidgetKeyboardEvent #include "mozilla/TextEventDispatcherListener.h" #include "nsThemeConstants.h" +#include "nsBidiKeyboard.h" #include "nsIFrame.h" #include "nsIGfxInfo.h" @@ -191,6 +192,7 @@ #include "mozilla/layers/APZCTreeManager.h" #include "mozilla/layers/InputAPZContext.h" +#include "mozilla/layers/ScrollInputMethods.h" #include "ClientLayerManager.h" #include "InputData.h" @@ -469,11 +471,10 @@ nsWindow::~nsWindow() mInDtor = true; // If the widget was released without calling Destroy() then the native window still - // exists, and we need to destroy it. This will also result in a call to OnDestroy. - // - // XXX How could this happen??? - if (nullptr != mWnd) - Destroy(); + // exists, and we need to destroy it. + // Destroy() will early-return if it was already called. In any case it is important + // to call it before destroying mPresentLock (cf. 1156182). + Destroy(); // Free app icon resources. This must happen after `OnDestroy` (see bug 708033). if (mIconSmall) @@ -517,6 +518,16 @@ int32_t nsWindow::GetHeight(int32_t aProposedHeight) return aProposedHeight; } +static bool +ShouldCacheTitleBarInfo(nsWindowType aWindowType, nsBorderStyle aBorderStyle) +{ + return (aWindowType == eWindowType_toplevel) && + (aBorderStyle == eBorderStyle_default || + aBorderStyle == eBorderStyle_all) && + (!nsUXThemeData::sTitlebarInfoPopulatedThemed || + !nsUXThemeData::sTitlebarInfoPopulatedAero); +} + // Create the proper widget nsresult nsWindow::Create(nsIWidget* aParent, @@ -705,10 +716,8 @@ nsWindow::Create(nsIWidget* aParent, } // Query for command button metric data for rendering the titlebar. We - // only do this once on the first window. - if (mWindowType == eWindowType_toplevel && - (!nsUXThemeData::sTitlebarInfoPopulatedThemed || - !nsUXThemeData::sTitlebarInfoPopulatedAero)) { + // only do this once on the first window that has an actual titlebar + if (ShouldCacheTitleBarInfo(mWindowType, mBorderStyle)) { nsUXThemeData::UpdateTitlebarInfo(mWnd); } @@ -1427,16 +1436,16 @@ nsWindow::GetSizeConstraints() } scale /= mSizeConstraintsScale; SizeConstraints c = mSizeConstraints; - if (c.mMinSize.width != NS_UNCONSTRAINEDSIZE) { + if (c.mMinSize.width != NS_MAXSIZE) { c.mMinSize.width = NSToIntRound(c.mMinSize.width * scale); } - if (c.mMinSize.height != NS_UNCONSTRAINEDSIZE) { + if (c.mMinSize.height != NS_MAXSIZE) { c.mMinSize.height = NSToIntRound(c.mMinSize.height * scale); } - if (c.mMaxSize.width != NS_UNCONSTRAINEDSIZE) { + if (c.mMaxSize.width != NS_MAXSIZE) { c.mMaxSize.width = NSToIntRound(c.mMaxSize.width * scale); } - if (c.mMaxSize.height != NS_UNCONSTRAINEDSIZE) { + if (c.mMaxSize.height != NS_MAXSIZE) { c.mMaxSize.height = NSToIntRound(c.mMaxSize.height * scale); } return c; @@ -1817,42 +1826,31 @@ NS_METHOD nsWindow::ConstrainPosition(bool aAllowSlop, RECT screenRect; nsCOMPtr screenmgr = do_GetService(sScreenManagerContractID); - if (screenmgr) { - nsCOMPtr screen; - int32_t left, top, width, height; + if (!screenmgr) { + return NS_ERROR_NOT_AVAILABLE; + } + nsCOMPtr screen; + int32_t left, top, width, height; - screenmgr->ScreenForRect(*aX, *aY, logWidth, logHeight, - getter_AddRefs(screen)); - if (screen) { - if (mSizeMode != nsSizeMode_Fullscreen) { - // For normalized windows, use the desktop work area. - screen->GetAvailRectDisplayPix(&left, &top, &width, &height); - } else { - // For full screen windows, use the desktop. - screen->GetRectDisplayPix(&left, &top, &width, &height); - } - screenRect.left = left; - screenRect.right = left + width; - screenRect.top = top; - screenRect.bottom = top + height; + screenmgr->ScreenForRect(*aX, *aY, logWidth, logHeight, + getter_AddRefs(screen)); + if (mSizeMode != nsSizeMode_Fullscreen) { + // For normalized windows, use the desktop work area. + nsresult rv = screen->GetAvailRectDisplayPix(&left, &top, &width, &height); + if (NS_FAILED(rv)) { + return rv; } } else { - if (mWnd) { - HDC dc = ::GetDC(mWnd); - if (dc) { - if (::GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) { - if (mSizeMode != nsSizeMode_Fullscreen) { - ::SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0); - } else { - screenRect.left = screenRect.top = 0; - screenRect.right = GetSystemMetrics(SM_CXFULLSCREEN); - screenRect.bottom = GetSystemMetrics(SM_CYFULLSCREEN); - } - } - ::ReleaseDC(mWnd, dc); - } + // For full screen windows, use the desktop. + nsresult rv = screen->GetRectDisplayPix(&left, &top, &width, &height); + if (NS_FAILED(rv)) { + return rv; } } + screenRect.left = left; + screenRect.right = left + width; + screenRect.top = top; + screenRect.bottom = top + height; if (aAllowSlop) { if (*aX < screenRect.left - logWidth + kWindowPositionSlop) @@ -2201,7 +2199,7 @@ nsWindow::UpdateGetWindowInfoCaptionStatus(bool aActiveCaption) } // Update our internally tracked caption status SetPropW(mWnd, kManageWindowInfoProperty, - reinterpret_cast(static_cast(aActiveCaption) + 1)); + reinterpret_cast(static_cast(aActiveCaption) + 1)); } /** @@ -3736,7 +3734,7 @@ bool nsWindow::DispatchContentCommandEvent(WidgetContentCommandEvent* aEvent) bool nsWindow::DispatchWheelEvent(WidgetWheelEvent* aEvent) { - nsEventStatus status = DispatchAPZAwareEvent(aEvent->AsInputEvent()); + nsEventStatus status = DispatchInputEvent(aEvent->AsInputEvent()); return ConvertStatus(status); } @@ -4074,7 +4072,7 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam, } } - result = ConvertStatus(DispatchAPZAwareEvent(&event)); + result = ConvertStatus(DispatchInputEvent(&event)); // Release the widget with NS_IF_RELEASE() just in case // the context menu key code in EventListenerManager::HandleEvent() @@ -5317,6 +5315,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam, case WM_INPUTLANGCHANGE: KeyboardLayout::GetInstance()-> OnLayoutChange(reinterpret_cast(lParam)); + nsBidiKeyboard::OnLayoutChange(); result = false; // always pass to child window break; @@ -5351,6 +5350,7 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam, } } } + break; #endif case WM_SYSCOMMAND: @@ -6282,13 +6282,13 @@ bool nsWindow::OnTouch(WPARAM wParam, LPARAM lParam) if (!touchInput.mTimeStamp.IsNull()) { // Convert MultiTouchInput to WidgetTouchEvent interface. WidgetTouchEvent widgetTouchEvent = touchInput.ToWidgetTouchEvent(this); - DispatchAPZAwareEvent(&widgetTouchEvent); + DispatchInputEvent(&widgetTouchEvent); } // Dispatch touch end event if we have one. if (!touchEndInput.mTimeStamp.IsNull()) { // Convert MultiTouchInput to WidgetTouchEvent interface. WidgetTouchEvent widgetTouchEvent = touchEndInput.ToWidgetTouchEvent(this); - DispatchAPZAwareEvent(&widgetTouchEvent); + DispatchInputEvent(&widgetTouchEvent); } } @@ -6320,6 +6320,8 @@ bool nsWindow::OnGesture(WPARAM wParam, LPARAM lParam) bool endFeedback = true; if (mGesture.PanDeltaToPixelScroll(wheelEvent)) { + mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, + (uint32_t) ScrollInputMethod::MainThreadTouch); DispatchEvent(&wheelEvent, status); } @@ -6675,6 +6677,11 @@ nsWindow::OnSysColorChanged() void nsWindow::OnDPIChanged(int32_t x, int32_t y, int32_t width, int32_t height) { + // Don't try to handle WM_DPICHANGED for popup windows (see bug 1239353); + // they remain tied to their original parent's resolution. + if (mWindowType == eWindowType_popup) { + return; + } if (DefaultScaleOverride() > 0.0) { return; } @@ -6698,6 +6705,22 @@ nsWindow::OnDPIChanged(int32_t x, int32_t y, int32_t width, int32_t height) width = w; height = h; } + + // Limit the position & size, if it would overflow the destination screen + nsCOMPtr sm = do_GetService(sScreenManagerContractID); + if (sm) { + nsCOMPtr screen; + sm->ScreenForRect(x, y, width, height, getter_AddRefs(screen)); + if (screen) { + int32_t availLeft, availTop, availWidth, availHeight; + screen->GetAvailRect(&availLeft, &availTop, &availWidth, &availHeight); + x = std::max(x, availLeft); + y = std::max(y, availTop); + width = std::min(width, availWidth); + height = std::min(height, availHeight); + } + } + Resize(x, y, width, height, true); } ChangedDPI(); diff --git a/xpcom/build/IOInterposer.h b/xpcom/build/IOInterposer.h index 2a1fb8d6cc..e5abc51a55 100644 --- a/xpcom/build/IOInterposer.h +++ b/xpcom/build/IOInterposer.h @@ -253,10 +253,16 @@ class IOInterposerInit public: IOInterposerInit() { +#if !defined(RELEASE_BUILD) + IOInterposer::Init(); +#endif } ~IOInterposerInit() { +#if !defined(RELEASE_BUILD) + IOInterposer::Clear(); +#endif } }; diff --git a/xpcom/build/PoisonIOInterposerMac.cpp b/xpcom/build/PoisonIOInterposerMac.cpp index 7064a41218..913145cfe8 100644 --- a/xpcom/build/PoisonIOInterposerMac.cpp +++ b/xpcom/build/PoisonIOInterposerMac.cpp @@ -13,7 +13,7 @@ #include "mozilla/IOInterposer.h" #include "mozilla/Mutex.h" #include "mozilla/ProcessedStack.h" -#include "mozilla/Scoped.h" +#include "mozilla/UniquePtrExtensions.h" #include "nsPrintfCString.h" #include "mozilla/StackWalk.h" #include "nsTraceRefcnt.h" @@ -180,7 +180,7 @@ IsValidWrite(int aFd, const void* aWbuf, size_t aCount) // content. This is needed because dbm doesn't keep track of dirty bits // and can end up writing the same data to disk twice. Once when the // user (nss) asks it to sync and once when closing the database. - ScopedFreePtr wbuf2(malloc(aCount)); + auto wbuf2 = MakeUniqueFallible(aCount); if (!wbuf2) { return true; } @@ -188,11 +188,11 @@ IsValidWrite(int aFd, const void* aWbuf, size_t aCount) if (pos == -1) { return true; } - ssize_t r = read(aFd, wbuf2, aCount); + ssize_t r = read(aFd, wbuf2.get(), aCount); if (r < 0 || (size_t)r != aCount) { return true; } - int cmp = memcmp(aWbuf, wbuf2, aCount); + int cmp = memcmp(aWbuf, wbuf2.get(), aCount); if (cmp != 0) { return true; } diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index aa9e56152b..ea4a45b052 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -679,6 +679,14 @@ NS_InitXPCOM2(nsIServiceManager** aResult, memmove); #endif +#ifdef MOZ_WEBM + // And for libnestegg. + // libnestegg expects that its realloc implementation will free + // the pointer argument when a size of 0 is passed in, so we need + // the special version of the counting realloc. + nestegg_set_halloc_func(NesteggReporter::CountingFreeingRealloc); +#endif + // Initialize the JS engine. if (!JS_Init()) { NS_RUNTIMEABORT("JS_Init failed"); diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h index e7ccbd2353..81bc53de9a 100644 --- a/xpcom/build/nsXULAppAPI.h +++ b/xpcom/build/nsXULAppAPI.h @@ -382,6 +382,17 @@ XRE_API(const char*, XRE_API(void, XRE_SetProcessType, (const char* aProcessTypeString)) +#if defined(MOZ_CRASHREPORTER) +// Used in the "master" parent process hosting the crash server +XRE_API(bool, + XRE_TakeMinidumpForChild, (uint32_t aChildPid, nsIFile** aDump, + uint32_t* aSequence)) + +// Used in child processes. +XRE_API(bool, + XRE_SetRemoteExceptionHandler, (const char* aPipe)) +#endif + namespace mozilla { namespace gmp { class GMPLoader; diff --git a/xpcom/ds/nsAtomTable.cpp b/xpcom/ds/nsAtomTable.cpp index 333e2f8226..a909a311f1 100644 --- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -574,7 +574,7 @@ class CheckStaticAtomSizes } }; -nsresult +void RegisterStaticAtoms(const nsStaticAtom* aAtoms, uint32_t aAtomCount) { if (!gStaticAtomTable && !gStaticAtomTableSealed) { @@ -612,7 +612,6 @@ RegisterStaticAtoms(const nsStaticAtom* aAtoms, uint32_t aAtomCount) entry->mAtom = atom; } } - return NS_OK; } already_AddRefed diff --git a/xpcom/ds/nsIAtom.idl b/xpcom/ds/nsIAtom.idl index ef10363491..a214397163 100644 --- a/xpcom/ds/nsIAtom.idl +++ b/xpcom/ds/nsIAtom.idl @@ -53,10 +53,12 @@ interface nsIAtom : nsISupports } inline void ToString(nsAString& aBuf) { + // See the comment on |mString|'s declaration. nsStringBuffer::FromData(mString)->ToString(mLength, aBuf); } inline nsStringBuffer* GetStringBuffer() const { + // See the comment on |mString|'s declaration. return nsStringBuffer::FromData(mString); } @@ -72,6 +74,11 @@ interface nsIAtom : nsISupports protected: uint32_t mLength; uint32_t mHash; + /** + * WARNING! There is an invisible constraint on |mString|: the chars it + * points to must belong to an nsStringBuffer. This is so that the + * nsStringBuffer::FromData() calls above are valid. + */ char16_t* mString; %} }; diff --git a/xpcom/ds/nsStaticAtom.h b/xpcom/ds/nsStaticAtom.h index 2bf96531d2..56c127be05 100644 --- a/xpcom/ds/nsStaticAtom.h +++ b/xpcom/ds/nsStaticAtom.h @@ -9,12 +9,13 @@ #include "nsIAtom.h" #include "nsStringBuffer.h" -#include "mozilla/Logging.h" -typedef char16_t nsStaticAtomStringType; +#define NS_STATIC_ATOM(buffer_name, atom_ptr) \ + { (nsStringBuffer*) &buffer_name, atom_ptr } -#define NS_STATIC_ATOM(buffer_name, atom_ptr) { (nsStringBuffer*) &buffer_name, atom_ptr } -#define NS_STATIC_ATOM_BUFFER(buffer_name, str_data) static nsFakeStringBuffer< sizeof(str_data) > buffer_name = { 1, sizeof(str_data) * sizeof(nsStaticAtomStringType), MOZ_UTF16(str_data) }; +#define NS_STATIC_ATOM_BUFFER(buffer_name, str_data) \ + static nsFakeStringBuffer buffer_name = \ + { 1, sizeof(str_data) * sizeof(char16_t), MOZ_UTF16(str_data) }; /** * Holds data used to initialize large number of atoms during startup. Use @@ -37,16 +38,16 @@ struct nsFakeStringBuffer { int32_t mRefCnt; uint32_t mSize; - nsStaticAtomStringType mStringData[size]; + char16_t mStringData[size]; }; // Register an array of static atoms with the atom table template -nsresult +void NS_RegisterStaticAtoms(const nsStaticAtom (&aAtoms)[N]) { - extern nsresult RegisterStaticAtoms(const nsStaticAtom*, uint32_t aAtomCount); - return RegisterStaticAtoms(aAtoms, N); + extern void RegisterStaticAtoms(const nsStaticAtom*, uint32_t aAtomCount); + RegisterStaticAtoms(aAtoms, N); } #endif diff --git a/xpcom/glue/nsID.h b/xpcom/glue/nsID.h index 9ea31609d7..1cbc27e0a0 100644 --- a/xpcom/glue/nsID.h +++ b/xpcom/glue/nsID.h @@ -97,7 +97,7 @@ typedef nsID nsCID; const nsCID _name = _cidspec #define NS_DEFINE_NAMED_CID(_name) \ - static nsCID k##_name = _name + static const nsCID k##_name = _name #define REFNSCID const nsCID& diff --git a/xpcom/threads/SharedThreadPool.h b/xpcom/threads/SharedThreadPool.h index 8a90dbcd38..d3d5976a43 100644 --- a/xpcom/threads/SharedThreadPool.h +++ b/xpcom/threads/SharedThreadPool.h @@ -54,6 +54,11 @@ public: // Forward behaviour to wrapped thread pool implementation. NS_FORWARD_SAFE_NSITHREADPOOL(mPool); + // Call this when dispatching from an event on the same + // threadpool that is about to complete. We should not create a new thread + // in that case since a thread is about to become idle. + nsresult TailDispatch(nsIRunnable *event) { return Dispatch(event, NS_DISPATCH_TAIL); } + NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override { return Dispatch(event, flags); } diff --git a/xpcom/threads/TaskQueue.cpp b/xpcom/threads/TaskQueue.cpp index e44c072f94..bfad502953 100644 --- a/xpcom/threads/TaskQueue.cpp +++ b/xpcom/threads/TaskQueue.cpp @@ -193,7 +193,7 @@ TaskQueue::Runner::Run() // run in a loop here so that we don't hog the thread pool. This means we may // run on another thread next time, but we rely on the memory fences from // mQueueMonitor for thread safety of non-threadsafe tasks. - nsresult rv = mQueue->mPool->Dispatch(this, NS_DISPATCH_NORMAL); + nsresult rv = mQueue->mPool->TailDispatch(this); if (NS_FAILED(rv)) { // Failed to dispatch, shutdown! MonitorAutoLock mon(mQueue->mQueueMonitor); diff --git a/xpcom/threads/nsIEventTarget.idl b/xpcom/threads/nsIEventTarget.idl index db71ac7bf6..52a023cf0c 100644 --- a/xpcom/threads/nsIEventTarget.idl +++ b/xpcom/threads/nsIEventTarget.idl @@ -40,6 +40,18 @@ interface nsIEventTarget : nsISupports */ const unsigned long DISPATCH_SYNC = 1; + /** + * This flag specifies that the dispatch is occurring from a running event + * that was dispatched to the same event target, and that event is about to + * finish. + * + * A thread pool can use this as an optimization hint to not spin up + * another thread, since the current thread is about to become idle. + * + * These events are always async. + */ + const unsigned long DISPATCH_TAIL = 2; + /** * Check to see if this event target is associated with the current thread. * @@ -91,4 +103,5 @@ interface nsIEventTarget : nsISupports // convenient aliases: #define NS_DISPATCH_NORMAL nsIEventTarget::DISPATCH_NORMAL #define NS_DISPATCH_SYNC nsIEventTarget::DISPATCH_SYNC +#define NS_DISPATCH_TAIL nsIEventTarget::DISPATCH_TAIL %} diff --git a/xpcom/threads/nsThreadPool.cpp b/xpcom/threads/nsThreadPool.cpp index 173afbdd02..65ade4f60e 100644 --- a/xpcom/threads/nsThreadPool.cpp +++ b/xpcom/threads/nsThreadPool.cpp @@ -64,11 +64,11 @@ nsresult nsThreadPool::PutEvent(nsIRunnable* aEvent) { nsCOMPtr event(aEvent); - return PutEvent(event.forget()); + return PutEvent(event.forget(), 0); } nsresult -nsThreadPool::PutEvent(already_AddRefed&& aEvent) +nsThreadPool::PutEvent(already_AddRefed&& aEvent, uint32_t aFlags) { // Avoid spawning a new thread while holding the event queue lock... @@ -86,6 +86,7 @@ nsThreadPool::PutEvent(already_AddRefed&& aEvent) // Make sure we have a thread to service this event. if (mThreads.Count() < (int32_t)mThreadLimit && + !(aFlags & NS_DISPATCH_TAIL) && // Spawn a new thread if we don't have enough idle threads to serve // pending events immediately. mEvents.Count(lock) >= mIdleCount) { @@ -272,7 +273,7 @@ nsThreadPool::Dispatch(already_AddRefed&& aEvent, uint32_t aFlags) } } else { NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "unexpected dispatch flags"); - PutEvent(Move(aEvent)); + PutEvent(Move(aEvent), aFlags); } return NS_OK; } diff --git a/xpcom/threads/nsThreadPool.h b/xpcom/threads/nsThreadPool.h index 9552738b36..e95c07359e 100644 --- a/xpcom/threads/nsThreadPool.h +++ b/xpcom/threads/nsThreadPool.h @@ -37,7 +37,7 @@ private: void ShutdownThread(nsIThread* aThread); nsresult PutEvent(nsIRunnable* aEvent); - nsresult PutEvent(already_AddRefed&& aEvent); + nsresult PutEvent(already_AddRefed&& aEvent, uint32_t aFlags); nsCOMArray mThreads; mozilla::Mutex mMutex;