diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index 6ad229bc1578..4e227e43b3c3 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -1058,8 +1058,9 @@ nsFocusManager::FireDelayedEvents(nsIDocument* aDocument) nsCOMPtr presShell = mDelayedBlurFocusEvents[i].mPresShell; nsCOMPtr relatedTarget = mDelayedBlurFocusEvents[i].mRelatedTarget; mDelayedBlurFocusEvents.RemoveElementAt(i); - SendFocusOrBlurEvent(message, presShell, aDocument, target, 0, - false, false, relatedTarget); + + FireFocusOrBlurEvent(message, presShell, target, false, false, + relatedTarget); --i; } } @@ -2081,7 +2082,7 @@ GetDocumentHelper(EventTarget* aTarget) return node->OwnerDoc(); } -void nsFocusManager::SendFocusInOrOutEvent(EventMessage aEventMessage, +void nsFocusManager::FireFocusInOrOutEvent(EventMessage aEventMessage, nsIPresShell* aPresShell, nsISupports* aTarget, nsPIDOMWindowOuter* aCurrentFocusedWindow, @@ -2089,7 +2090,7 @@ void nsFocusManager::SendFocusInOrOutEvent(EventMessage aEventMessage, EventTarget* aRelatedTarget) { NS_ASSERTION(aEventMessage == eFocusIn || aEventMessage == eFocusOut, - "Wrong event type for SendFocusInOrOutEvent"); + "Wrong event type for FireFocusInOrOutEvent"); nsContentUtils::AddScriptRunner( new FocusInOutEvent( @@ -2117,11 +2118,6 @@ nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage, nsCOMPtr eventTarget = do_QueryInterface(aTarget); nsCOMPtr eventTargetDoc = GetDocumentHelper(eventTarget); nsCOMPtr relatedTargetDoc = GetDocumentHelper(aRelatedTarget); - nsCOMPtr currentWindow = mFocusedWindow; - nsCOMPtr targetWindow = do_QueryInterface(aTarget); - nsCOMPtr targetDocument = do_QueryInterface(aTarget); - nsCOMPtr currentFocusedContent = currentWindow ? - currentWindow->GetFocusedNode() : nullptr; // set aRelatedTarget to null if it's not in the same document as eventTarget if (eventTargetDoc != relatedTargetDoc) { @@ -2149,6 +2145,36 @@ nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage, return; } + // If mDelayedBlurFocusEvents queue is not empty, check if there are events + // that belongs to this doc, if yes, fire them first. + if (aDocument && !aDocument->EventHandlingSuppressed() && + mDelayedBlurFocusEvents.Length()) { + FireDelayedEvents(aDocument); + } + + FireFocusOrBlurEvent(aEventMessage, aPresShell, aTarget, aWindowRaised, + aIsRefocus, aRelatedTarget); +} + +void +nsFocusManager::FireFocusOrBlurEvent(EventMessage aEventMessage, + nsIPresShell* aPresShell, + nsISupports* aTarget, + bool aWindowRaised, + bool aIsRefocus, + EventTarget* aRelatedTarget) +{ + nsCOMPtr eventTarget = do_QueryInterface(aTarget); + nsCOMPtr eventTargetDoc = GetDocumentHelper(eventTarget); + nsCOMPtr currentWindow = mFocusedWindow; + nsCOMPtr targetWindow = do_QueryInterface(aTarget); + nsCOMPtr targetDocument = do_QueryInterface(aTarget); + nsCOMPtr currentFocusedContent = currentWindow ? + currentWindow->GetFocusedNode() : nullptr; + + bool dontDispatchEvent = + eventTargetDoc && nsContentUtils::IsUserFocusIgnored(eventTargetDoc); + #ifdef ACCESSIBILITY nsAccessibilityService* accService = GetAccService(); if (accService) { @@ -2174,7 +2200,7 @@ nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage, // resolved. if (!targetWindow && !targetDocument) { EventMessage focusInOrOutMessage = aEventMessage == eFocus ? eFocusIn : eFocusOut; - SendFocusInOrOutEvent(focusInOrOutMessage, aPresShell, aTarget, + FireFocusInOrOutEvent(focusInOrOutMessage, aPresShell, aTarget, currentWindow, currentFocusedContent, aRelatedTarget); } } diff --git a/dom/base/nsFocusManager.h b/dom/base/nsFocusManager.h index ffb38359b701..ddbb741da5fb 100644 --- a/dom/base/nsFocusManager.h +++ b/dom/base/nsFocusManager.h @@ -280,7 +280,8 @@ protected: nsIContent* aContentLostFocus = nullptr); /** - * Fires a focus or blur event at aTarget. + * Send a focus or blur event at aTarget. It may be added to the delayed + * event queue if the document is suppressing events. * * aEventMessage should be either eFocus or eBlur. * For blur events, aFocusMethod should normally be non-zero. @@ -297,7 +298,22 @@ protected: mozilla::dom::EventTarget* aRelatedTarget = nullptr); /** - * Send a focusin or focusout event + * Fire a focus or blur event at aTarget. + * + * aEventMessage should be either eFocus or eBlur. + * For blur events, aFocusMethod should normally be non-zero. + * + * aWindowRaised should only be true if called from WindowRaised. + */ + void FireFocusOrBlurEvent(mozilla::EventMessage aEventMessage, + nsIPresShell* aPresShell, + nsISupports* aTarget, + bool aWindowRaised, + bool aIsRefocus = false, + mozilla::dom::EventTarget* aRelatedTarget = nullptr); + + /** + * Fire a focusin or focusout event * * aEventMessage should be either eFocusIn or eFocusOut. * @@ -313,7 +329,7 @@ protected: * aRelatedTarget is the content related to the event (the object * losing focus for focusin, the object getting focus for focusout). */ - void SendFocusInOrOutEvent(mozilla::EventMessage aEventMessage, + void FireFocusInOrOutEvent(mozilla::EventMessage aEventMessage, nsIPresShell* aPresShell, nsISupports* aTarget, nsPIDOMWindowOuter* aCurrentFocusedWindow, diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index f07a7d75a2d3..7ba38f83b62d 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -34,7 +34,7 @@ #include "EventListenerService.h" #include "GeckoProfiler.h" #ifdef MOZ_GECKO_PROFILER -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #endif #include "nsCOMArray.h" #include "nsCOMPtr.h" diff --git a/dom/performance/Performance.cpp b/dom/performance/Performance.cpp index f1d55b3fb72d..823e62fb3c43 100644 --- a/dom/performance/Performance.cpp +++ b/dom/performance/Performance.cpp @@ -8,7 +8,7 @@ #include "GeckoProfiler.h" #ifdef MOZ_GECKO_PROFILER -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #endif #include "PerformanceEntry.h" #include "PerformanceMainThread.h" diff --git a/gfx/ipc/GPUParent.cpp b/gfx/ipc/GPUParent.cpp index fc5f31857086..e6144fa3e263 100644 --- a/gfx/ipc/GPUParent.cpp +++ b/gfx/ipc/GPUParent.cpp @@ -208,6 +208,10 @@ GPUParent::RecvInit(nsTArray&& prefs, RecvGetDeviceStatus(&data); Unused << SendInitComplete(data); +#ifdef XP_WIN + DeviceManagerDx::PreloadAttachmentsOnCompositorThread(); +#endif + Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS, mLaunchTime); return IPC_OK(); } diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index cbff00a6b4c4..83a187a8295d 100755 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -36,7 +36,7 @@ #include #include "GeckoProfiler.h" // for GeckoProfiler #ifdef MOZ_GECKO_PROFILER -#include "ProfilerMarkers.h" // for ProfilerMarkers +#include "ProfilerMarkerPayload.h" // for LayerTranslationPayload #endif #define CULLING_LOG(...) diff --git a/gfx/layers/d3d11/CompositorD3D11.cpp b/gfx/layers/d3d11/CompositorD3D11.cpp index f5f53f43f3ff..4bab4f83a568 100644 --- a/gfx/layers/d3d11/CompositorD3D11.cpp +++ b/gfx/layers/d3d11/CompositorD3D11.cpp @@ -6,7 +6,6 @@ #include "CompositorD3D11.h" #include "TextureD3D11.h" -#include "CompositorD3D11Shaders.h" #include "gfxWindowsPlatform.h" #include "nsIWidget.h" @@ -33,6 +32,7 @@ #include "BlendShaderConstants.h" #include "D3D11ShareHandleImage.h" +#include "DeviceAttachmentsD3D11.h" #include // For IsWindows8OrGreater #include @@ -45,22 +45,8 @@ namespace layers { static bool CanUsePartialPresents(ID3D11Device* aDevice); -struct Vertex -{ - float position[2]; -}; - -// {1E4D7BEB-D8EC-4A0B-BF0A-63E6DE129425} -static const GUID sDeviceAttachmentsD3D11 = -{ 0x1e4d7beb, 0xd8ec, 0x4a0b, { 0xbf, 0xa, 0x63, 0xe6, 0xde, 0x12, 0x94, 0x25 } }; -// {88041664-C835-4AA8-ACB8-7EC832357ED8} -static const GUID sLayerManagerCount = -{ 0x88041664, 0xc835, 0x4aa8, { 0xac, 0xb8, 0x7e, 0xc8, 0x32, 0x35, 0x7e, 0xd8 } }; - const FLOAT sBlendFactor[] = { 0, 0, 0, 0 }; -static const size_t kInitialMaximumTriangles = 64; - namespace TexSlot { static const int RGB = 0; static const int Y = 1; @@ -71,92 +57,6 @@ namespace TexSlot { static const int Backdrop = 6; } -struct DeviceAttachmentsD3D11 -{ - explicit DeviceAttachmentsD3D11(ID3D11Device* device) - : mSyncHandle(0), - mDevice(device), - mInitOkay(true) - {} - - bool CreateShaders(); - bool InitBlendShaders(); - bool InitSyncObject(); - - typedef EnumeratedArray> - VertexShaderArray; - typedef EnumeratedArray> - PixelShaderArray; - - RefPtr mInputLayout; - RefPtr mDynamicInputLayout; - - RefPtr mVertexBuffer; - RefPtr mDynamicVertexBuffer; - - VertexShaderArray mVSQuadShader; - VertexShaderArray mVSQuadBlendShader; - - VertexShaderArray mVSDynamicShader; - VertexShaderArray mVSDynamicBlendShader; - - PixelShaderArray mSolidColorShader; - PixelShaderArray mRGBAShader; - PixelShaderArray mRGBShader; - PixelShaderArray mYCbCrShader; - PixelShaderArray mNV12Shader; - PixelShaderArray mComponentAlphaShader; - PixelShaderArray mBlendShader; - RefPtr mPSConstantBuffer; - RefPtr mVSConstantBuffer; - RefPtr mRasterizerState; - RefPtr mLinearSamplerState; - RefPtr mPointSamplerState; - - RefPtr mPremulBlendState; - RefPtr mNonPremulBlendState; - RefPtr mComponentBlendState; - RefPtr mDisabledBlendState; - RefPtr mSyncTexture; - HANDLE mSyncHandle; - -private: - void InitVertexShader(const ShaderBytes& aShader, VertexShaderArray& aArray, MaskType aMaskType) { - InitVertexShader(aShader, getter_AddRefs(aArray[aMaskType])); - } - void InitPixelShader(const ShaderBytes& aShader, PixelShaderArray& aArray, MaskType aMaskType) { - InitPixelShader(aShader, getter_AddRefs(aArray[aMaskType])); - } - void InitVertexShader(const ShaderBytes& aShader, ID3D11VertexShader** aOut) { - if (!mInitOkay) { - return; - } - if (Failed(mDevice->CreateVertexShader(aShader.mData, aShader.mLength, nullptr, aOut), "create vs")) { - mInitOkay = false; - } - } - void InitPixelShader(const ShaderBytes& aShader, ID3D11PixelShader** aOut) { - if (!mInitOkay) { - return; - } - if (Failed(mDevice->CreatePixelShader(aShader.mData, aShader.mLength, nullptr, aOut), "create ps")) { - mInitOkay = false; - } - } - - bool Failed(HRESULT hr, const char* aContext) { - if (SUCCEEDED(hr)) - return false; - - gfxCriticalNote << "[D3D11] " << aContext << " failed: " << hexa(hr); - return true; - } - - // Only used during initialization. - RefPtr mDevice; - bool mInitOkay; -}; - CompositorD3D11::CompositorD3D11(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget) : Compositor(aWidget, aParent) , mAttachments(nullptr) @@ -165,36 +65,13 @@ CompositorD3D11::CompositorD3D11(CompositorBridgeParent* aParent, widget::Compos , mAllowPartialPresents(false) , mVerifyBuffersFailed(false) , mIsDoubleBuffered(false) - , mMaximumTriangles(kInitialMaximumTriangles) { } CompositorD3D11::~CompositorD3D11() { - if (mDevice) { - int referenceCount = 0; - UINT size = sizeof(referenceCount); - HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount); - NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device."); - referenceCount--; - mDevice->SetPrivateData(sLayerManagerCount, - sizeof(referenceCount), - &referenceCount); - - if (!referenceCount) { - DeviceAttachmentsD3D11 *attachments; - size = sizeof(attachments); - mDevice->GetPrivateData(sDeviceAttachmentsD3D11, &size, &attachments); - // No LayerManagers left for this device. Clear out interfaces stored - // which hold a reference to the device. - mDevice->SetPrivateData(sDeviceAttachmentsD3D11, 0, nullptr); - - delete attachments; - } - } } - template void CompositorD3D11::SetVertexBuffer(ID3D11Buffer* aBuffer) @@ -216,24 +93,10 @@ CompositorD3D11::UpdateDynamicVertexBuffer(const nsTArray HRESULT hr; // Resize the dynamic vertex buffer if needed. - if (aTriangles.Length() > mMaximumTriangles) { - CD3D11_BUFFER_DESC bufferDesc(sizeof(TexturedVertex) * aTriangles.Length() * 3, - D3D11_BIND_VERTEX_BUFFER, - D3D11_USAGE_DYNAMIC, - D3D11_CPU_ACCESS_WRITE); - - hr = mDevice->CreateBuffer(&bufferDesc, nullptr, - getter_AddRefs(mAttachments->mDynamicVertexBuffer)); - - if (Failed(hr, "resize dynamic vertex buffer")) { - return false; - } - - mMaximumTriangles = aTriangles.Length(); + if (!mAttachments->EnsureTriangleBuffer(aTriangles.Length())) { + return false; } - MOZ_ASSERT(mMaximumTriangles >= aTriangles.Length()); - D3D11_MAPPED_SUBRESOURCE resource {}; hr = mContext->Map(mAttachments->mDynamicVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource); @@ -260,12 +123,19 @@ CompositorD3D11::Initialize(nsCString* const out_failureReason) HRESULT hr; - mDevice = DeviceManagerDx::Get()->GetCompositorDevice(); + DeviceManagerDx::Get()->GetCompositorDevices(&mDevice, &mAttachments); if (!mDevice) { gfxCriticalNote << "[D3D11] failed to get compositor device."; *out_failureReason = "FEATURE_FAILURE_D3D11_NO_DEVICE"; return false; } + if (!mAttachments || !mAttachments->IsValid()) { + gfxCriticalNote << "[D3D11] failed to get compositor device attachments"; + *out_failureReason = mAttachments + ? mAttachments->GetFailureId() + : NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_ATTACHMENTS"); + return false; + } mDevice->GetImmediateContext(getter_AddRefs(mContext)); if (!mContext) { @@ -281,193 +151,6 @@ CompositorD3D11::Initialize(nsCString* const out_failureReason) memset(&mVSConstants, 0, sizeof(VertexShaderConstants)); - int referenceCount = 0; - UINT size = sizeof(referenceCount); - // If this isn't there yet it'll fail, count will remain 0, which is correct. - mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount); - referenceCount++; - mDevice->SetPrivateData(sLayerManagerCount, - sizeof(referenceCount), - &referenceCount); - - size = sizeof(DeviceAttachmentsD3D11*); - if (FAILED(mDevice->GetPrivateData(sDeviceAttachmentsD3D11, - &size, - &mAttachments))) { - mAttachments = new DeviceAttachmentsD3D11(mDevice); - mDevice->SetPrivateData(sDeviceAttachmentsD3D11, - sizeof(mAttachments), - &mAttachments); - - D3D11_INPUT_ELEMENT_DESC layout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - hr = mDevice->CreateInputLayout(layout, - sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC), - LayerQuadVS, - sizeof(LayerQuadVS), - getter_AddRefs(mAttachments->mInputLayout)); - - if (Failed(hr, "CreateInputLayout")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_INPUT_LAYOUT"; - return false; - } - - Vertex vertices[] = { {{0.0, 0.0}}, {{1.0, 0.0}}, {{0.0, 1.0}}, {{1.0, 1.0}} }; - CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER); - D3D11_SUBRESOURCE_DATA data; - data.pSysMem = (void*)vertices; - - hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mAttachments->mVertexBuffer)); - if (Failed(hr, "create vertex buffer")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_VERTEX_BUFFER"; - return false; - } - - // Create a second input layout for layers with dynamic geometry. - D3D11_INPUT_ELEMENT_DESC dynamicLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - hr = mDevice->CreateInputLayout(dynamicLayout, - sizeof(dynamicLayout) / sizeof(D3D11_INPUT_ELEMENT_DESC), - LayerDynamicVS, - sizeof(LayerDynamicVS), - getter_AddRefs(mAttachments->mDynamicInputLayout)); - - if (Failed(hr, "CreateInputLayout")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_INPUT_LAYOUT"; - return false; - } - - // Allocate memory for the dynamic vertex buffer. - bufferDesc = CD3D11_BUFFER_DESC(sizeof(TexturedVertex) * mMaximumTriangles * 3, - D3D11_BIND_VERTEX_BUFFER, - D3D11_USAGE_DYNAMIC, - D3D11_CPU_ACCESS_WRITE); - - hr = mDevice->CreateBuffer(&bufferDesc, nullptr, getter_AddRefs(mAttachments->mDynamicVertexBuffer)); - if (Failed(hr, "create dynamic vertex buffer")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_VERTEX_BUFFER"; - return false; - } - - if (!mAttachments->CreateShaders()) { - *out_failureReason = "FEATURE_FAILURE_D3D11_CREATE_SHADERS"; - return false; - } - - CD3D11_BUFFER_DESC cBufferDesc(sizeof(VertexShaderConstants), - D3D11_BIND_CONSTANT_BUFFER, - D3D11_USAGE_DYNAMIC, - D3D11_CPU_ACCESS_WRITE); - - hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mAttachments->mVSConstantBuffer)); - if (Failed(hr, "create vs buffer")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_VS_BUFFER"; - return false; - } - - cBufferDesc.ByteWidth = sizeof(PixelShaderConstants); - hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mAttachments->mPSConstantBuffer)); - if (Failed(hr, "create ps buffer")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_PS_BUFFER"; - return false; - } - - CD3D11_RASTERIZER_DESC rastDesc(D3D11_DEFAULT); - rastDesc.CullMode = D3D11_CULL_NONE; - rastDesc.ScissorEnable = TRUE; - - hr = mDevice->CreateRasterizerState(&rastDesc, getter_AddRefs(mAttachments->mRasterizerState)); - if (Failed(hr, "create rasterizer")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_RASTERIZER"; - return false; - } - - CD3D11_SAMPLER_DESC samplerDesc(D3D11_DEFAULT); - hr = mDevice->CreateSamplerState(&samplerDesc, getter_AddRefs(mAttachments->mLinearSamplerState)); - if (Failed(hr, "create linear sampler")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_LINEAR_SAMPLER"; - return false; - } - - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; - hr = mDevice->CreateSamplerState(&samplerDesc, getter_AddRefs(mAttachments->mPointSamplerState)); - if (Failed(hr, "create point sampler")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_POINT_SAMPLER"; - return false; - } - - CD3D11_BLEND_DESC blendDesc(D3D11_DEFAULT); - D3D11_RENDER_TARGET_BLEND_DESC rtBlendPremul = { - TRUE, - D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, - D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, - D3D11_COLOR_WRITE_ENABLE_ALL - }; - blendDesc.RenderTarget[0] = rtBlendPremul; - hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mAttachments->mPremulBlendState)); - if (Failed(hr, "create pm blender")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_PM_BLENDER"; - return false; - } - - D3D11_RENDER_TARGET_BLEND_DESC rtBlendNonPremul = { - TRUE, - D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, - D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, - D3D11_COLOR_WRITE_ENABLE_ALL - }; - blendDesc.RenderTarget[0] = rtBlendNonPremul; - hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mAttachments->mNonPremulBlendState)); - if (Failed(hr, "create npm blender")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_NPM_BLENDER"; - return false; - } - - if (gfxPrefs::ComponentAlphaEnabled()) { - D3D11_RENDER_TARGET_BLEND_DESC rtBlendComponent = { - TRUE, - D3D11_BLEND_ONE, - D3D11_BLEND_INV_SRC1_COLOR, - D3D11_BLEND_OP_ADD, - D3D11_BLEND_ONE, - D3D11_BLEND_INV_SRC_ALPHA, - D3D11_BLEND_OP_ADD, - D3D11_COLOR_WRITE_ENABLE_ALL - }; - blendDesc.RenderTarget[0] = rtBlendComponent; - hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mAttachments->mComponentBlendState)); - if (Failed(hr, "create component blender")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_COMP_BLENDER"; - return false; - } - } - - D3D11_RENDER_TARGET_BLEND_DESC rtBlendDisabled = { - FALSE, - D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, - D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, - D3D11_COLOR_WRITE_ENABLE_ALL - }; - blendDesc.RenderTarget[0] = rtBlendDisabled; - hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mAttachments->mDisabledBlendState)); - if (Failed(hr, "create null blender")) { - *out_failureReason = "FEATURE_FAILURE_D3D11_NULL_BLENDER"; - return false; - } - - if (!mAttachments->InitSyncObject()) { - *out_failureReason = "FEATURE_FAILURE_D3D11_OBJ_SYNC"; - return false; - } - } - RefPtr dxgiDevice; RefPtr dxgiAdapter; @@ -1715,91 +1398,6 @@ CompositorD3D11::UpdateRenderTarget() return true; } -bool -DeviceAttachmentsD3D11::InitSyncObject() -{ - // Sync object is not supported on WARP. - if (DeviceManagerDx::Get()->IsWARP()) { - return true; - } - - // It's okay to do this on Windows 8. But for now we'll just bail - // whenever we're using WARP. - CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1, - D3D11_BIND_SHADER_RESOURCE | - D3D11_BIND_RENDER_TARGET); - desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; - - RefPtr texture; - HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)); - if (Failed(hr, "create sync texture")) { - return false; - } - - hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture)); - if (Failed(hr, "QI sync texture")) { - return false; - } - - hr = mSyncTexture->GetSharedHandle(&mSyncHandle); - if (FAILED(hr) || !mSyncHandle) { - gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: " - << hexa(hr); - NS_DispatchToMainThread(NS_NewRunnableFunction([] () -> void { - Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1); - })); - return false; - } - - return true; -} - -bool -DeviceAttachmentsD3D11::InitBlendShaders() -{ - if (!mVSQuadBlendShader[MaskType::MaskNone]) { - InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone); - InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask); - } - - if (!mVSDynamicBlendShader[MaskType::MaskNone]) { - InitVertexShader(sLayerDynamicBlendVS, mVSDynamicBlendShader, MaskType::MaskNone); - InitVertexShader(sLayerDynamicBlendMaskVS, mVSDynamicBlendShader, MaskType::Mask); - } - - if (!mBlendShader[MaskType::MaskNone]) { - InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone); - } - return mInitOkay; -} - -bool -DeviceAttachmentsD3D11::CreateShaders() -{ - InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone); - InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask); - - InitVertexShader(sLayerDynamicVS, mVSDynamicShader, MaskType::MaskNone); - InitVertexShader(sLayerDynamicMaskVS, mVSDynamicShader, MaskType::Mask); - - InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone); - InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask); - InitPixelShader(sRGBShader, mRGBShader, MaskType::MaskNone); - InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask); - InitPixelShader(sRGBAShader, mRGBAShader, MaskType::MaskNone); - InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask); - InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone); - InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask); - InitPixelShader(sNV12Shader, mNV12Shader, MaskType::MaskNone); - InitPixelShader(sNV12ShaderMask, mNV12Shader, MaskType::Mask); - if (gfxPrefs::ComponentAlphaEnabled()) { - InitPixelShader(sComponentAlphaShader, mComponentAlphaShader, MaskType::MaskNone); - InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask); - } - - return mInitOkay; -} - bool CompositorD3D11::UpdateConstantBuffers() { diff --git a/gfx/layers/d3d11/CompositorD3D11.h b/gfx/layers/d3d11/CompositorD3D11.h index 17e578d37104..a44e68886fea 100644 --- a/gfx/layers/d3d11/CompositorD3D11.h +++ b/gfx/layers/d3d11/CompositorD3D11.h @@ -12,6 +12,7 @@ #include "TextureD3D11.h" #include #include +#include "ShaderDefinitionsD3D11.h" class nsWidget; @@ -20,26 +21,7 @@ namespace layers { #define LOGD3D11(param) -struct VertexShaderConstants -{ - float layerTransform[4][4]; - float projection[4][4]; - float renderTargetOffset[4]; - gfx::Rect textureCoords; - gfx::Rect layerQuad; - float maskTransform[4][4]; - float backdropTransform[4][4]; -}; - -struct PixelShaderConstants -{ - float layerColor[4]; - float layerOpacity[4]; - int blendConfig[4]; - float yuvColorMatrix[3][4]; -}; - -struct DeviceAttachmentsD3D11; +class DeviceAttachmentsD3D11; class DiagnosticsD3D11; class CompositorD3D11 : public Compositor @@ -233,7 +215,7 @@ private: RefPtr mQuery; - DeviceAttachmentsD3D11* mAttachments; + RefPtr mAttachments; UniquePtr mDiagnostics; LayoutDeviceIntSize mSize; @@ -254,8 +236,6 @@ private: gfx::IntRect mCurrentClip; bool mVerifyBuffersFailed; - - size_t mMaximumTriangles; }; } diff --git a/gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp b/gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp new file mode 100644 index 000000000000..50a77b0c2966 --- /dev/null +++ b/gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp @@ -0,0 +1,361 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DeviceAttachmentsD3D11.h" +#include "mozilla/Telemetry.h" +#include "mozilla/layers/Compositor.h" +#include "CompositorD3D11Shaders.h" +#include "gfxPrefs.h" +#include "ShaderDefinitionsD3D11.h" + +namespace mozilla { +namespace layers { + +using namespace gfx; + +static const size_t kInitialMaximumTriangles = 64; + +DeviceAttachmentsD3D11::DeviceAttachmentsD3D11(ID3D11Device* device) + : mSyncHandle(0), + mMaximumTriangles(kInitialMaximumTriangles), + mDevice(device), + mContinueInit(true), + mInitialized(false) +{ +} + +DeviceAttachmentsD3D11::~DeviceAttachmentsD3D11() +{ +} + +/* static */ RefPtr +DeviceAttachmentsD3D11::Create(ID3D11Device* aDevice) +{ + // We don't return null even if the attachments object even if it fails to + // initialize, so the compositor can grab the failure ID. + RefPtr attachments = new DeviceAttachmentsD3D11(aDevice); + attachments->Initialize(); + return attachments.forget(); +} + +bool +DeviceAttachmentsD3D11::Initialize() +{ + D3D11_INPUT_ELEMENT_DESC layout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + HRESULT hr; + hr = mDevice->CreateInputLayout(layout, + sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC), + LayerQuadVS, + sizeof(LayerQuadVS), + getter_AddRefs(mInputLayout)); + + if (Failed(hr, "CreateInputLayout")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_INPUT_LAYOUT"; + return false; + } + + Vertex vertices[] = { {{0.0, 0.0}}, {{1.0, 0.0}}, {{0.0, 1.0}}, {{1.0, 1.0}} }; + CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER); + D3D11_SUBRESOURCE_DATA data; + data.pSysMem = (void*)vertices; + + hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer)); + if (Failed(hr, "create vertex buffer")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_VERTEX_BUFFER"; + return false; + } + + // Create a second input layout for layers with dynamic geometry. + D3D11_INPUT_ELEMENT_DESC dynamicLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + hr = mDevice->CreateInputLayout(dynamicLayout, + sizeof(dynamicLayout) / sizeof(D3D11_INPUT_ELEMENT_DESC), + LayerDynamicVS, + sizeof(LayerDynamicVS), + getter_AddRefs(mDynamicInputLayout)); + + if (Failed(hr, "CreateInputLayout")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_INPUT_LAYOUT"; + return false; + } + + // Allocate memory for the dynamic vertex buffer. + bufferDesc = CD3D11_BUFFER_DESC(sizeof(TexturedVertex) * mMaximumTriangles * 3, + D3D11_BIND_VERTEX_BUFFER, + D3D11_USAGE_DYNAMIC, + D3D11_CPU_ACCESS_WRITE); + + hr = mDevice->CreateBuffer(&bufferDesc, nullptr, getter_AddRefs(mDynamicVertexBuffer)); + if (Failed(hr, "create dynamic vertex buffer")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_VERTEX_BUFFER"; + return false; + } + + if (!CreateShaders()) { + mInitFailureId = "FEATURE_FAILURE_D3D11_CREATE_SHADERS"; + return false; + } + + CD3D11_BUFFER_DESC cBufferDesc(sizeof(VertexShaderConstants), + D3D11_BIND_CONSTANT_BUFFER, + D3D11_USAGE_DYNAMIC, + D3D11_CPU_ACCESS_WRITE); + + hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mVSConstantBuffer)); + if (Failed(hr, "create vs buffer")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_VS_BUFFER"; + return false; + } + + cBufferDesc.ByteWidth = sizeof(PixelShaderConstants); + hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, getter_AddRefs(mPSConstantBuffer)); + if (Failed(hr, "create ps buffer")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_PS_BUFFER"; + return false; + } + + CD3D11_RASTERIZER_DESC rastDesc(D3D11_DEFAULT); + rastDesc.CullMode = D3D11_CULL_NONE; + rastDesc.ScissorEnable = TRUE; + + hr = mDevice->CreateRasterizerState(&rastDesc, getter_AddRefs(mRasterizerState)); + if (Failed(hr, "create rasterizer")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_RASTERIZER"; + return false; + } + + CD3D11_SAMPLER_DESC samplerDesc(D3D11_DEFAULT); + hr = mDevice->CreateSamplerState(&samplerDesc, getter_AddRefs(mLinearSamplerState)); + if (Failed(hr, "create linear sampler")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_LINEAR_SAMPLER"; + return false; + } + + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + hr = mDevice->CreateSamplerState(&samplerDesc, getter_AddRefs(mPointSamplerState)); + if (Failed(hr, "create point sampler")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_POINT_SAMPLER"; + return false; + } + + CD3D11_BLEND_DESC blendDesc(D3D11_DEFAULT); + D3D11_RENDER_TARGET_BLEND_DESC rtBlendPremul = { + TRUE, + D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_COLOR_WRITE_ENABLE_ALL + }; + blendDesc.RenderTarget[0] = rtBlendPremul; + hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mPremulBlendState)); + if (Failed(hr, "create pm blender")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_PM_BLENDER"; + return false; + } + + D3D11_RENDER_TARGET_BLEND_DESC rtBlendNonPremul = { + TRUE, + D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_COLOR_WRITE_ENABLE_ALL + }; + blendDesc.RenderTarget[0] = rtBlendNonPremul; + hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mNonPremulBlendState)); + if (Failed(hr, "create npm blender")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_NPM_BLENDER"; + return false; + } + + if (gfxPrefs::ComponentAlphaEnabled()) { + D3D11_RENDER_TARGET_BLEND_DESC rtBlendComponent = { + TRUE, + D3D11_BLEND_ONE, + D3D11_BLEND_INV_SRC1_COLOR, + D3D11_BLEND_OP_ADD, + D3D11_BLEND_ONE, + D3D11_BLEND_INV_SRC_ALPHA, + D3D11_BLEND_OP_ADD, + D3D11_COLOR_WRITE_ENABLE_ALL + }; + blendDesc.RenderTarget[0] = rtBlendComponent; + hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mComponentBlendState)); + if (Failed(hr, "create component blender")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_COMP_BLENDER"; + return false; + } + } + + D3D11_RENDER_TARGET_BLEND_DESC rtBlendDisabled = { + FALSE, + D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD, + D3D11_COLOR_WRITE_ENABLE_ALL + }; + blendDesc.RenderTarget[0] = rtBlendDisabled; + hr = mDevice->CreateBlendState(&blendDesc, getter_AddRefs(mDisabledBlendState)); + if (Failed(hr, "create null blender")) { + mInitFailureId = "FEATURE_FAILURE_D3D11_NULL_BLENDER"; + return false; + } + + if (!InitSyncObject()) { + mInitFailureId = "FEATURE_FAILURE_D3D11_OBJ_SYNC"; + return false; + } + + mInitialized = true; + return true; +} + +bool +DeviceAttachmentsD3D11::InitSyncObject() +{ + // Sync object is not supported on WARP. + if (DeviceManagerDx::Get()->IsWARP()) { + return true; + } + + // It's okay to do this on Windows 8. But for now we'll just bail + // whenever we're using WARP. + CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1, + D3D11_BIND_SHADER_RESOURCE | + D3D11_BIND_RENDER_TARGET); + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + + RefPtr texture; + HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)); + if (Failed(hr, "create sync texture")) { + return false; + } + + hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture)); + if (Failed(hr, "QI sync texture")) { + return false; + } + + hr = mSyncTexture->GetSharedHandle(&mSyncHandle); + if (FAILED(hr) || !mSyncHandle) { + gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: " + << hexa(hr); + NS_DispatchToMainThread(NS_NewRunnableFunction([] () -> void { + Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1); + })); + return false; + } + + return true; +} + +bool +DeviceAttachmentsD3D11::InitBlendShaders() +{ + if (!mVSQuadBlendShader[MaskType::MaskNone]) { + InitVertexShader(sLayerQuadBlendVS, mVSQuadBlendShader, MaskType::MaskNone); + InitVertexShader(sLayerQuadBlendMaskVS, mVSQuadBlendShader, MaskType::Mask); + } + + if (!mVSDynamicBlendShader[MaskType::MaskNone]) { + InitVertexShader(sLayerDynamicBlendVS, mVSDynamicBlendShader, MaskType::MaskNone); + InitVertexShader(sLayerDynamicBlendMaskVS, mVSDynamicBlendShader, MaskType::Mask); + } + + if (!mBlendShader[MaskType::MaskNone]) { + InitPixelShader(sBlendShader, mBlendShader, MaskType::MaskNone); + } + return mContinueInit; +} + +bool +DeviceAttachmentsD3D11::CreateShaders() +{ + InitVertexShader(sLayerQuadVS, mVSQuadShader, MaskType::MaskNone); + InitVertexShader(sLayerQuadMaskVS, mVSQuadShader, MaskType::Mask); + + InitVertexShader(sLayerDynamicVS, mVSDynamicShader, MaskType::MaskNone); + InitVertexShader(sLayerDynamicMaskVS, mVSDynamicShader, MaskType::Mask); + + InitPixelShader(sSolidColorShader, mSolidColorShader, MaskType::MaskNone); + InitPixelShader(sSolidColorShaderMask, mSolidColorShader, MaskType::Mask); + InitPixelShader(sRGBShader, mRGBShader, MaskType::MaskNone); + InitPixelShader(sRGBShaderMask, mRGBShader, MaskType::Mask); + InitPixelShader(sRGBAShader, mRGBAShader, MaskType::MaskNone); + InitPixelShader(sRGBAShaderMask, mRGBAShader, MaskType::Mask); + InitPixelShader(sYCbCrShader, mYCbCrShader, MaskType::MaskNone); + InitPixelShader(sYCbCrShaderMask, mYCbCrShader, MaskType::Mask); + InitPixelShader(sNV12Shader, mNV12Shader, MaskType::MaskNone); + InitPixelShader(sNV12ShaderMask, mNV12Shader, MaskType::Mask); + if (gfxPrefs::ComponentAlphaEnabled()) { + InitPixelShader(sComponentAlphaShader, mComponentAlphaShader, MaskType::MaskNone); + InitPixelShader(sComponentAlphaShaderMask, mComponentAlphaShader, MaskType::Mask); + } + + return mContinueInit; +} + +void +DeviceAttachmentsD3D11::InitVertexShader(const ShaderBytes& aShader, ID3D11VertexShader** aOut) +{ + if (!mContinueInit) { + return; + } + if (Failed(mDevice->CreateVertexShader(aShader.mData, aShader.mLength, nullptr, aOut), "create vs")) { + mContinueInit = false; + } +} + +void +DeviceAttachmentsD3D11::InitPixelShader(const ShaderBytes& aShader, ID3D11PixelShader** aOut) +{ + if (!mContinueInit) { + return; + } + if (Failed(mDevice->CreatePixelShader(aShader.mData, aShader.mLength, nullptr, aOut), "create ps")) { + mContinueInit = false; + } +} + +bool +DeviceAttachmentsD3D11::Failed(HRESULT hr, const char* aContext) +{ + if (SUCCEEDED(hr)) { + return false; + } + + gfxCriticalNote << "[D3D11] " << aContext << " failed: " << hexa(hr); + return true; +} + +bool +DeviceAttachmentsD3D11::EnsureTriangleBuffer(size_t aNumTriangles) +{ + if (aNumTriangles > mMaximumTriangles) { + CD3D11_BUFFER_DESC bufferDesc(sizeof(TexturedVertex) * aNumTriangles * 3, + D3D11_BIND_VERTEX_BUFFER, + D3D11_USAGE_DYNAMIC, + D3D11_CPU_ACCESS_WRITE); + + HRESULT hr = + mDevice->CreateBuffer(&bufferDesc, nullptr, getter_AddRefs(mDynamicVertexBuffer)); + + if (Failed(hr, "resize dynamic vertex buffer")) { + return false; + } + + mMaximumTriangles = aNumTriangles; + } + + MOZ_ASSERT(mMaximumTriangles >= aNumTriangles); + return true; +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/d3d11/DeviceAttachmentsD3D11.h b/gfx/layers/d3d11/DeviceAttachmentsD3D11.h new file mode 100644 index 000000000000..5310af643205 --- /dev/null +++ b/gfx/layers/d3d11/DeviceAttachmentsD3D11.h @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_gfx_layers_d3d11_DeviceAttachmentsD3D11_h +#define mozilla_gfx_layers_d3d11_DeviceAttachmentsD3D11_h + +#include "mozilla/EnumeratedArray.h" +#include "mozilla/RefPtr.h" +#include "mozilla/gfx/DeviceManagerDx.h" +#include "mozilla/layers/CompositorTypes.h" +#include +#include + +struct ShaderBytes; + +namespace mozilla { +namespace layers { + +class DeviceAttachmentsD3D11 +{ + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceAttachmentsD3D11); + +public: + static RefPtr Create(ID3D11Device* aDevice); + + bool InitBlendShaders(); + bool EnsureTriangleBuffer(size_t aNumTriangles); + + bool IsValid() const { + return mInitialized; + } + const nsCString& GetFailureId() const { + MOZ_ASSERT(!IsValid()); + return mInitFailureId; + } + + typedef EnumeratedArray> + VertexShaderArray; + typedef EnumeratedArray> + PixelShaderArray; + + RefPtr mInputLayout; + RefPtr mDynamicInputLayout; + + RefPtr mVertexBuffer; + RefPtr mDynamicVertexBuffer; + + VertexShaderArray mVSQuadShader; + VertexShaderArray mVSQuadBlendShader; + + VertexShaderArray mVSDynamicShader; + VertexShaderArray mVSDynamicBlendShader; + + PixelShaderArray mSolidColorShader; + PixelShaderArray mRGBAShader; + PixelShaderArray mRGBShader; + PixelShaderArray mYCbCrShader; + PixelShaderArray mNV12Shader; + PixelShaderArray mComponentAlphaShader; + PixelShaderArray mBlendShader; + RefPtr mPSConstantBuffer; + RefPtr mVSConstantBuffer; + RefPtr mRasterizerState; + RefPtr mLinearSamplerState; + RefPtr mPointSamplerState; + + RefPtr mPremulBlendState; + RefPtr mNonPremulBlendState; + RefPtr mComponentBlendState; + RefPtr mDisabledBlendState; + RefPtr mSyncTexture; + HANDLE mSyncHandle; + +private: + explicit DeviceAttachmentsD3D11(ID3D11Device* device); + ~DeviceAttachmentsD3D11(); + + bool Initialize(); + bool CreateShaders(); + bool InitSyncObject(); + + void InitVertexShader(const ShaderBytes& aShader, VertexShaderArray& aArray, MaskType aMaskType) { + InitVertexShader(aShader, getter_AddRefs(aArray[aMaskType])); + } + void InitPixelShader(const ShaderBytes& aShader, PixelShaderArray& aArray, MaskType aMaskType) { + InitPixelShader(aShader, getter_AddRefs(aArray[aMaskType])); + } + + void InitVertexShader(const ShaderBytes& aShader, ID3D11VertexShader** aOut); + void InitPixelShader(const ShaderBytes& aShader, ID3D11PixelShader** aOut); + + bool Failed(HRESULT hr, const char* aContext); + +private: + size_t mMaximumTriangles; + + // Only used during initialization. + RefPtr mDevice; + bool mContinueInit; + bool mInitialized; + nsCString mInitFailureId; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_gfx_layers_d3d11_DeviceAttachmentsD3D11_h diff --git a/gfx/layers/d3d11/ShaderDefinitionsD3D11.h b/gfx/layers/d3d11/ShaderDefinitionsD3D11.h new file mode 100644 index 000000000000..b06fff2c6981 --- /dev/null +++ b/gfx/layers/d3d11/ShaderDefinitionsD3D11.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_gfx_layers_d3d11_ShaderDefinitionsD3D11_h +#define mozilla_gfx_layers_d3d11_ShaderDefinitionsD3D11_h + +#include "mozilla/gfx/Rect.h" + +namespace mozilla { +namespace layers { + +struct VertexShaderConstants +{ + float layerTransform[4][4]; + float projection[4][4]; + float renderTargetOffset[4]; + gfx::Rect textureCoords; + gfx::Rect layerQuad; + float maskTransform[4][4]; + float backdropTransform[4][4]; +}; + +struct PixelShaderConstants +{ + float layerColor[4]; + float layerOpacity[4]; + int blendConfig[4]; + float yuvColorMatrix[3][4]; +}; + +struct Vertex +{ + float position[2]; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_gfx_layers_d3d11_ShaderDefinitionsD3D11_h diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index 7dd80c964612..212fb14a7358 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -82,7 +82,7 @@ #include "mozilla/StaticPtr.h" #include "mozilla/Telemetry.h" #ifdef MOZ_GECKO_PROFILER -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #endif #include "mozilla/VsyncDispatcher.h" #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 9798c2a1106c..a2bba7bcbe99 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -62,9 +62,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': if CONFIG['MOZ_ENABLE_D3D10_LAYER']: EXPORTS.mozilla.layers += [ 'd3d11/CompositorD3D11.h', + 'd3d11/DeviceAttachmentsD3D11.h', 'd3d11/DiagnosticsD3D11.h', 'd3d11/HelpersD3D11.h', 'd3d11/ReadbackManagerD3D11.h', + 'd3d11/ShaderDefinitionsD3D11.h', 'd3d11/TextureD3D11.h', ] UNIFIED_SOURCES += [ @@ -73,6 +75,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': ] SOURCES += [ 'd3d11/CompositorD3D11.cpp', + 'd3d11/DeviceAttachmentsD3D11.cpp', 'd3d11/ReadbackManagerD3D11.cpp', ] diff --git a/gfx/thebes/ContextStateTracker.cpp b/gfx/thebes/ContextStateTracker.cpp index ef7c2b6de148..d8f06f8b4001 100644 --- a/gfx/thebes/ContextStateTracker.cpp +++ b/gfx/thebes/ContextStateTracker.cpp @@ -6,7 +6,7 @@ #include "ContextStateTracker.h" #include "GLContext.h" #ifdef MOZ_GECKO_PROFILER -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #endif namespace mozilla { diff --git a/gfx/thebes/DeviceManagerDx.cpp b/gfx/thebes/DeviceManagerDx.cpp index c7bc4bb760ec..de2664e2c165 100644 --- a/gfx/thebes/DeviceManagerDx.cpp +++ b/gfx/thebes/DeviceManagerDx.cpp @@ -15,6 +15,7 @@ #include "mozilla/gfx/GraphicsMessages.h" #include "mozilla/gfx/Logging.h" #include "mozilla/layers/CompositorThread.h" +#include "mozilla/layers/DeviceAttachmentsD3D11.h" #include "nsIGfxInfo.h" #include #include @@ -602,6 +603,7 @@ DeviceManagerDx::ResetDevices() MutexAutoLock lock(mDeviceLock); mAdapter = nullptr; + mCompositorAttachments = nullptr; mCompositorDevice = nullptr; mContentDevice = nullptr; mDeviceStatus = Nothing(); @@ -900,5 +902,61 @@ DeviceManagerDx::GetDirectDraw() return mDirectDraw; } +void +DeviceManagerDx::GetCompositorDevices(RefPtr* aOutDevice, + RefPtr* aOutAttachments) +{ + MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread()); + + RefPtr device; + { + MutexAutoLock lock(mDeviceLock); + if (!mCompositorDevice) { + return; + } + if (mCompositorAttachments) { + *aOutDevice = mCompositorDevice; + *aOutAttachments = mCompositorAttachments; + return; + } + + // Otherwise, we'll try to create attachments outside the lock. + device = mCompositorDevice; + } + + // We save the attachments object even if it fails to initialize, so the + // compositor can grab the failure ID. + RefPtr attachments = + layers::DeviceAttachmentsD3D11::Create(device); + { + MutexAutoLock lock(mDeviceLock); + if (device != mCompositorDevice) { + return; + } + mCompositorAttachments = attachments; + } + + *aOutDevice = device; + *aOutAttachments = attachments; +} + +/* static */ void +DeviceManagerDx::PreloadAttachmentsOnCompositorThread() +{ + MessageLoop* loop = layers::CompositorThreadHolder::Loop(); + if (!loop) { + return; + } + + RefPtr task = NS_NewRunnableFunction([]() -> void { + if (DeviceManagerDx* dm = DeviceManagerDx::Get()) { + RefPtr device; + RefPtr attachments; + dm->GetCompositorDevices(&device, &attachments); + } + }); + loop->PostTask(task.forget()); +} + } // namespace gfx } // namespace mozilla diff --git a/gfx/thebes/DeviceManagerDx.h b/gfx/thebes/DeviceManagerDx.h index ea6dd4846a2f..1507b0c74924 100644 --- a/gfx/thebes/DeviceManagerDx.h +++ b/gfx/thebes/DeviceManagerDx.h @@ -35,6 +35,9 @@ struct IDirectDraw7; namespace mozilla { class ScopedGfxFeatureReporter; +namespace layers { +class DeviceAttachmentsD3D11; +} // namespace layers namespace gfx { class FeatureState; @@ -70,6 +73,9 @@ public: bool CreateCompositorDevices(); void CreateContentDevices(); + void GetCompositorDevices(RefPtr* aOutDevice, + RefPtr* aOutAttachments); + void ImportDeviceInfo(const D3D11DeviceStatus& aDeviceStatus); void ExportDeviceInfo(D3D11DeviceStatus* aOut); @@ -93,6 +99,10 @@ public: void ForceDeviceReset(ForcedDeviceResetReason aReason); void NotifyD3D9DeviceReset(); + // Pre-load any compositor resources that are expensive, and are needed when we + // attempt to create a compositor. + static void PreloadAttachmentsOnCompositorThread(); + private: IDXGIAdapter1 *GetDXGIAdapter(); @@ -138,6 +148,7 @@ private: RefPtr mCompositorDevice; RefPtr mContentDevice; RefPtr mDecoderDevice; + RefPtr mCompositorAttachments; bool mCompositorDeviceSupportsVideo; Maybe mDeviceStatus; diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 934a6e326af2..f521ac3497d8 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -51,6 +51,7 @@ #ifdef XP_WIN #include "mozilla/WindowsVersion.h" +#include "mozilla/gfx/DeviceManagerDx.h" #endif #include "nsGkAtoms.h" @@ -964,6 +965,9 @@ gfxPlatform::InitLayersIPC() wr::RenderThread::Start(); } layers::CompositorThreadHolder::Start(); +#ifdef XP_WIN + gfx::DeviceManagerDx::PreloadAttachmentsOnCompositorThread(); +#endif } } diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 92341fb668b8..90b2f6240c56 100755 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -71,6 +71,7 @@ #include "DriverCrashGuard.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/gfx/DeviceManagerDx.h" +#include "mozilla/layers/DeviceAttachmentsD3D11.h" #include "D3D11Checks.h" using namespace mozilla; diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json index 05bdb48790ab..36a96514f38a 100644 --- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -166252,7 +166252,7 @@ "testharness" ], "dom/nodes/Element-classlist.html": [ - "612d218e8252405070a6c075d6eb5aa5f36772c1", + "7e3b68e65468fba0708f4084a9b2f6af93edde90", "testharness" ], "dom/nodes/Element-closest.html": [ @@ -166396,7 +166396,7 @@ "testharness" ], "dom/nodes/MutationObserver-attributes.html": [ - "f0695f2e137e34f015d9831d68b89c669d515c75", + "0a224c3dc64de0c4cf1fdc895a2c52667be2134f", "testharness" ], "dom/nodes/MutationObserver-characterData.html": [ @@ -211708,7 +211708,7 @@ "support" ], "web-animations/animation-model/animation-types/property-types.js": [ - "564158b80368dc7ff9aa8fa0140343289762c413", + "d62c58c9dfb52b7147008c1080c8a5d4f4d72a93", "support" ], "web-animations/animation-model/animation-types/spacing-keyframes-filters.html": [ diff --git a/testing/web-platform/meta/web-animations/animation-model/animation-types/interpolation-per-property.html.ini b/testing/web-platform/meta/web-animations/animation-model/animation-types/interpolation-per-property.html.ini index c686f5666fbc..9e05e96bdb66 100644 --- a/testing/web-platform/meta/web-animations/animation-model/animation-types/interpolation-per-property.html.ini +++ b/testing/web-platform/meta/web-animations/animation-model/animation-types/interpolation-per-property.html.ini @@ -1,25 +1,9 @@ prefs: [layout.css.contain.enabled:true, layout.css.initial-letter.enabled:true, layout.css.overflow-clip-box.enabled:true, layout.css.shape-outside.enabled:true] [interpolation-per-property.html] type: testharness - [flex-basis supports animating as combination units "px" and "%"] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1291187 - - [flex-basis supports animating as combination units "%" and "em"] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1291187 - [filterList has testInterpolation function] expected: FAIL [filter (type: filterList) has testInterpolation function] expected: FAIL - [word-spacing supports animating as combination units "px" and "%"] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1291187 - - [word-spacing supports animating as combination units "%" and "em"] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1291187 - diff --git a/testing/web-platform/mozilla/meta/MANIFEST.json b/testing/web-platform/mozilla/meta/MANIFEST.json index 8b2aa6581a52..c24f1e797875 100644 --- a/testing/web-platform/mozilla/meta/MANIFEST.json +++ b/testing/web-platform/mozilla/meta/MANIFEST.json @@ -838,7 +838,7 @@ "support" ], "dom/classList.html": [ - "6d9b7f24be9c7e2ccf504c8fe05e93bbc01fd7c6", + "f289334e7b3486259b9aae54b4282a7211b8813e", "testharness" ], "fetch/api/redirect/redirect-referrer-mixed-content.js": [ diff --git a/testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js index a95924f45fab..7e1d5f6d327f 100644 --- a/testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js +++ b/testing/web-platform/tests/web-animations/animation-model/animation-types/property-types.js @@ -85,9 +85,7 @@ const lengthType = { var animation = target.animate({ [idlName]: ['10px', '50px'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10px' }, - { time: 500, expected: '30px' }, - { time: 1000, expected: '50px' }]); + [{ time: 500, expected: '30px' }]); }, property + ' supports animating as a length'); test(function(t) { @@ -96,9 +94,7 @@ const lengthType = { var animation = target.animate({ [idlName]: ['1rem', '5rem'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10px' }, - { time: 500, expected: '30px' }, - { time: 1000, expected: '50px' }]); + [{ time: 500, expected: '30px' }]); }, property + ' supports animating as a length of rem'); }, @@ -175,9 +171,7 @@ const percentageType = { var animation = target.animate({ [idlName]: ['10%', '50%'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10%' }, - { time: 500, expected: '30%' }, - { time: 1000, expected: '50%' }]); + [{ time: 500, expected: '30%' }]); }, property + ' supports animating as a percentage'); }, @@ -202,9 +196,7 @@ const integerType = { var animation = target.animate({ [idlName]: [-2, 2] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '-2' }, - { time: 500, expected: '0' }, - { time: 1000, expected: '2' }]); + [{ time: 500, expected: '0' }]); }, property + ' supports animating as an integer'); }, @@ -233,9 +225,7 @@ const lengthPercentageOrCalcType = { var animation = target.animate({ [idlName]: ['10px', '20%'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10px' }, - { time: 500, expected: 'calc(5px + 10%)' }, - { time: 1000, expected: '20%' }]); + [{ time: 500, expected: 'calc(5px + 10%)' }]); }, property + ' supports animating as combination units "px" and "%"'); test(function(t) { @@ -244,9 +234,7 @@ const lengthPercentageOrCalcType = { var animation = target.animate({ [idlName]: ['10%', '2em'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10%' }, - { time: 500, expected: 'calc(10px + 5%)' }, - { time: 1000, expected: '20px' }]); + [{ time: 500, expected: 'calc(10px + 5%)' }]); }, property + ' supports animating as combination units "%" and "em"'); test(function(t) { @@ -255,9 +243,7 @@ const lengthPercentageOrCalcType = { var animation = target.animate({ [idlName]: ['1em', '2rem'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10px' }, - { time: 500, expected: '15px' }, - { time: 1000, expected: '20px' }]); + [{ time: 500, expected: '15px' }]); }, property + ' supports animating as combination units "em" and "rem"'); test(function(t) { @@ -266,9 +252,7 @@ const lengthPercentageOrCalcType = { var animation = target.animate({ [idlName]: ['10px', 'calc(1em + 20%)'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10px' }, - { time: 500, expected: 'calc(10px + 10%)' }, - { time: 1000, expected: 'calc(10px + 20%)' }]); + [{ time: 500, expected: 'calc(10px + 10%)' }]); }, property + ' supports animating as combination units "px" and "calc"'); test(function(t) { @@ -278,12 +262,8 @@ const lengthPercentageOrCalcType = { { [idlName]: ['calc(10px + 10%)', 'calc(1em + 1rem + 20%)'] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, - expected: 'calc(10px + 10%)' }, - { time: 500, - expected: 'calc(15px + 15%)' }, - { time: 1000, - expected: 'calc(20px + 20%)' }]); + [{ time: 500, + expected: 'calc(15px + 15%)' }]); }, property + ' supports animating as a calc'); }, @@ -382,9 +362,7 @@ const positiveNumberType = { var animation = target.animate({ [idlName]: [1.1, 1.5] }, { duration: 1000, fill: 'both' }); testAnimationSamples(animation, idlName, - [{ time: 0, expected: '1.1' }, - { time: 500, expected: '1.3' }, - { time: 1000, expected: '1.5' }]); + [{ time: 500, expected: '1.3' }]); }, property + ' supports animating as a positive number'); }, @@ -1154,27 +1132,7 @@ const boxShadowListType = { const positionType = { testInterpolation: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['10px 10px', '50px 50px'] }, - { duration: 1000, fill: 'both' }); - testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10px 10px' }, - { time: 500, expected: '30px 30px' }, - { time: 1000, expected: '50px 50px' }]); - }, property + ' supports animating as a position'); - - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - var animation = target.animate({ [idlName]: ['1rem 1rem', '5rem 5rem'] }, - { duration: 1000, fill: 'both' }); - testAnimationSamples(animation, idlName, - [{ time: 0, expected: '10px 10px' }, - { time: 500, expected: '30px 30px' }, - { time: 1000, expected: '50px 50px' }]); - }, property + ' supports animating as a position of rem'); + lengthPairType.testInterpolation(property, setup); test(function(t) { var idlName = propertyToIDL(property); @@ -1183,30 +1141,12 @@ const positionType = { { duration: 1000, fill: 'both' }); testAnimationSamples( animation, idlName, - [{ time: 0, expected: calcFromPercentage(idlName, '10% 10%') }, - { time: 500, expected: calcFromPercentage(idlName, '30% 30%') }, - { time: 1000, expected: calcFromPercentage(idlName, '50% 50%') }]); + [{ time: 500, expected: calcFromPercentage(idlName, '30% 30%') }]); }, property + ' supports animating as a position of percent'); }, testAddition: function(property, setup) { - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - target.style[idlName] = '10px 10px'; - var animation = target.animate({ [idlName]: ['10px 10px', '50px 50px'] }, - { duration: 1000, composite: 'add' }); - testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px 20px' }]); - }, property + ': position'); - - test(function(t) { - var idlName = propertyToIDL(property); - var target = createTestElement(t, setup); - target.style[idlName] = '1rem 1rem'; - var animation = target.animate({ [idlName]: ['1rem 1rem', '5rem 5rem'] }, - { duration: 1000, composite: 'add' }); - testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px 20px' }]); - }, property + ': position of rem'); + lengthPairType.testAddition(property, setup); test(function(t) { var idlName = propertyToIDL(property); diff --git a/tools/profiler/core/ProfileBuffer.cpp b/tools/profiler/core/ProfileBuffer.cpp index 43df07344edf..8567fbbee305 100644 --- a/tools/profiler/core/ProfileBuffer.cpp +++ b/tools/profiler/core/ProfileBuffer.cpp @@ -6,6 +6,8 @@ #include "ProfileBuffer.h" +#include "ProfilerMarker.h" + ProfileBuffer::ProfileBuffer(int aEntrySize) : mEntries(mozilla::MakeUnique(aEntrySize)) , mWritePos(0) diff --git a/tools/profiler/core/ProfileBuffer.h b/tools/profiler/core/ProfileBuffer.h index 6e4b11d4b0fb..45ba3d590fff 100644 --- a/tools/profiler/core/ProfileBuffer.h +++ b/tools/profiler/core/ProfileBuffer.h @@ -6,8 +6,9 @@ #ifndef MOZ_PROFILE_BUFFER_H #define MOZ_PROFILE_BUFFER_H -#include "ProfileBufferEntry.h" #include "platform.h" +#include "ProfileBufferEntry.h" +#include "ProfilerMarker.h" #include "ProfileJSONWriter.h" #include "mozilla/RefPtr.h" #include "mozilla/RefCounted.h" diff --git a/tools/profiler/core/ProfileBufferEntry.h b/tools/profiler/core/ProfileBufferEntry.h index 5bd2d9667591..a0bcd77703fe 100644 --- a/tools/profiler/core/ProfileBufferEntry.h +++ b/tools/profiler/core/ProfileBufferEntry.h @@ -12,7 +12,6 @@ #include "platform.h" #include "ProfileJSONWriter.h" #include "ProfilerBacktrace.h" -#include "PseudoStack.h" #include "mozilla/RefPtr.h" #include #include @@ -26,6 +25,8 @@ #include "mozilla/HashFunctions.h" #include "mozilla/UniquePtr.h" +class ProfilerMarker; + #define PROFILE_BUFFER_ENTRY_KIND_LIST(_) \ _(Category, int) \ _(CodeLocation, const char *) \ diff --git a/tools/profiler/core/ProfilerMarker.h b/tools/profiler/core/ProfilerMarker.h new file mode 100644 index 000000000000..54a7a0018067 --- /dev/null +++ b/tools/profiler/core/ProfilerMarker.h @@ -0,0 +1,177 @@ +/* -*- 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 ProfilerMarker_h +#define ProfilerMarker_h + +#include "mozilla/UniquePtrExtensions.h" + +#include "ProfilerMarkerPayload.h" +#include "StoreSequencer.h" + +template +class ProfilerLinkedList; +class SpliceableJSONWriter; +class UniqueStacks; + +class ProfilerMarker +{ + friend class ProfilerLinkedList; + +public: + explicit ProfilerMarker(const char* aMarkerName, + ProfilerMarkerPayload* aPayload = nullptr, + double aTime = 0) + : mMarkerName(strdup(aMarkerName)) + , mPayload(aPayload) + , mTime(aTime) + {} + + void SetGeneration(uint32_t aGenID) { mGenID = aGenID; } + + bool HasExpired(uint32_t aGenID) const { return mGenID + 2 <= aGenID; } + + double GetTime() const { return mTime; } + + void StreamJSON(SpliceableJSONWriter& aWriter, + const mozilla::TimeStamp& aStartTime, + UniqueStacks& aUniqueStacks) const + { + // Schema: + // [name, time, data] + + aWriter.StartArrayElement(); + { + aUniqueStacks.mUniqueStrings.WriteElement(aWriter, mMarkerName.get()); + aWriter.DoubleElement(mTime); + // TODO: Store the callsite for this marker if available: + // if have location data + // b.NameValue(marker, "location", ...); + if (mPayload) { + aWriter.StartObjectElement(); + { + mPayload->StreamPayload(aWriter, aStartTime, aUniqueStacks); + } + aWriter.EndObject(); + } + } + aWriter.EndArray(); + } + +private: + mozilla::UniqueFreePtr mMarkerName; + mozilla::UniquePtr mPayload; + ProfilerMarker* mNext; + double mTime; + uint32_t mGenID; +}; + +template +class ProfilerLinkedList +{ +public: + ProfilerLinkedList() + : mHead(nullptr) + , mTail(nullptr) + {} + + void insert(T* aElem) + { + if (!mTail) { + mHead = aElem; + mTail = aElem; + } else { + mTail->mNext = aElem; + mTail = aElem; + } + aElem->mNext = nullptr; + } + + T* popHead() + { + if (!mHead) { + MOZ_ASSERT(false); + return nullptr; + } + + T* head = mHead; + + mHead = head->mNext; + if (!mHead) { + mTail = nullptr; + } + + return head; + } + + const T* peek() { + return mHead; + } + +private: + T* mHead; + T* mTail; +}; + +typedef ProfilerLinkedList ProfilerMarkerLinkedList; + +template +class ProfilerSignalSafeLinkedList +{ +public: + ProfilerSignalSafeLinkedList() + : mSignalLock(false) + {} + + ~ProfilerSignalSafeLinkedList() + { + if (mSignalLock) { + // Some thread is modifying the list. We should only be released on that + // thread. + abort(); + } + + while (mList.peek()) { + delete mList.popHead(); + } + } + + // Insert an item into the list. Must only be called from the owning thread. + // Must not be called while the list from accessList() is being accessed. + // In the profiler, we ensure that by interrupting the profiled thread + // (which is the one that owns this list and calls insert() on it) until + // we're done reading the list from the signal handler. + void insert(T* aElement) + { + MOZ_ASSERT(aElement); + + mSignalLock = true; + STORE_SEQUENCER(); + + mList.insert(aElement); + + STORE_SEQUENCER(); + mSignalLock = false; + } + + // Called within signal, from any thread, possibly while insert() is in the + // middle of modifying the list (on the owning thread). Will return null if + // that is the case. + // Function must be reentrant. + ProfilerLinkedList* accessList() + { + return mSignalLock ? nullptr : &mList; + } + +private: + ProfilerLinkedList mList; + + // If this is set, then it's not safe to read the list because its contents + // are being changed. + volatile bool mSignalLock; +}; + +#endif // ProfilerMarker_h diff --git a/tools/profiler/core/ProfilerMarkers.cpp b/tools/profiler/core/ProfilerMarkerPayload.cpp similarity index 99% rename from tools/profiler/core/ProfilerMarkers.cpp rename to tools/profiler/core/ProfilerMarkerPayload.cpp index 6cf8e6ce69eb..9d11ca6c2691 100644 --- a/tools/profiler/core/ProfilerMarkers.cpp +++ b/tools/profiler/core/ProfilerMarkerPayload.cpp @@ -5,7 +5,7 @@ #include "GeckoProfiler.h" #include "ProfilerBacktrace.h" -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #include "gfxASurface.h" #include "Layers.h" #include "mozilla/Sprintf.h" diff --git a/tools/profiler/core/ThreadInfo.h b/tools/profiler/core/ThreadInfo.h index dcc6add9851d..f771ca32c1d7 100644 --- a/tools/profiler/core/ThreadInfo.h +++ b/tools/profiler/core/ThreadInfo.h @@ -10,8 +10,9 @@ #include "mozilla/NotNull.h" #include "mozilla/UniquePtrExtensions.h" -#include "ProfileBuffer.h" #include "platform.h" +#include "ProfileBuffer.h" +#include "PseudoStack.h" // Stub eventMarker function for js-engine event generation. void ProfilerJSEventMarker(const char* aEvent); diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp index 9f67e8093473..7df0ed915315 100644 --- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -37,7 +37,7 @@ #include "nsProfilerStartParams.h" #include "mozilla/Services.h" #include "nsThreadUtils.h" -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #include "shared-libraries.h" #include "prtime.h" @@ -1578,8 +1578,6 @@ locked_profiler_stream_json_for_this_process(PSLockRef aLock, // Lists the samples for each thread profile aWriter.StartArrayProperty("threads"); { - ActivePS::SetIsPaused(aLock, true); - const CorePS::ThreadVector& liveThreads = CorePS::LiveThreads(aLock); for (size_t i = 0; i < liveThreads.size(); i++) { ThreadInfo* info = liveThreads.at(i); @@ -1611,8 +1609,6 @@ locked_profiler_stream_json_for_this_process(PSLockRef aLock, java::GeckoJavaSampler::Unpause(); } #endif - - ActivePS::SetIsPaused(aLock, false); } aWriter.EndArray(); } @@ -1638,55 +1634,6 @@ profiler_stream_json_for_this_process(SpliceableJSONWriter& aWriter, double aSin // END saving/streaming code //////////////////////////////////////////////////////////////////////// -ProfilerMarker::ProfilerMarker(const char* aMarkerName, - ProfilerMarkerPayload* aPayload, - double aTime) - : mMarkerName(strdup(aMarkerName)) - , mPayload(aPayload) - , mTime(aTime) -{ -} - -ProfilerMarker::~ProfilerMarker() { - free(mMarkerName); - delete mPayload; -} - -void -ProfilerMarker::SetGeneration(uint32_t aGenID) { - mGenID = aGenID; -} - -double -ProfilerMarker::GetTime() const { - return mTime; -} - -void ProfilerMarker::StreamJSON(SpliceableJSONWriter& aWriter, - const TimeStamp& aProcessStartTime, - UniqueStacks& aUniqueStacks) const -{ - // Schema: - // [name, time, data] - - aWriter.StartArrayElement(); - { - aUniqueStacks.mUniqueStrings.WriteElement(aWriter, GetMarkerName()); - aWriter.DoubleElement(mTime); - // TODO: Store the callsite for this marker if available: - // if have location data - // b.NameValue(marker, "location", ...); - if (mPayload) { - aWriter.StartObjectElement(); - { - mPayload->StreamPayload(aWriter, aProcessStartTime, aUniqueStacks); - } - aWriter.EndObject(); - } - } - aWriter.EndArray(); -} - static void PrintUsageThenExit(int aExitCode) { @@ -3070,15 +3017,11 @@ profiler_clear_js_context() // requires a live JSContext. if (ActivePS::Exists(lock)) { - ActivePS::SetIsPaused(lock, true); - // Flush this thread's ThreadInfo, if it is being profiled. if (info->IsBeingProfiled()) { info->FlushSamplesAndMarkers(ActivePS::Buffer(lock), CorePS::ProcessStartTime(lock)); } - - ActivePS::SetIsPaused(lock, false); } // We don't call info->StopJSSampling() here; there's no point doing that for diff --git a/tools/profiler/gecko/ProfilerIOInterposeObserver.cpp b/tools/profiler/gecko/ProfilerIOInterposeObserver.cpp index 51a29873ece0..c26452751236 100644 --- a/tools/profiler/gecko/ProfilerIOInterposeObserver.cpp +++ b/tools/profiler/gecko/ProfilerIOInterposeObserver.cpp @@ -4,7 +4,7 @@ #include "GeckoProfiler.h" #include "ProfilerIOInterposeObserver.h" -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" using namespace mozilla; diff --git a/tools/profiler/moz.build b/tools/profiler/moz.build index 8485390fa4c2..0578dd439c4c 100644 --- a/tools/profiler/moz.build +++ b/tools/profiler/moz.build @@ -11,9 +11,10 @@ if CONFIG['MOZ_GECKO_PROFILER']: ] EXPORTS += [ 'public/CrossProcessProfilerController.h', - 'public/ProfilerMarkers.h', + 'public/ProfilerMarkerPayload.h', 'public/PseudoStack.h', 'public/shared-libraries.h', + 'public/StoreSequencer.h', ] EXTRA_JS_MODULES += [ 'gecko/Profiler.jsm', @@ -24,7 +25,7 @@ if CONFIG['MOZ_GECKO_PROFILER']: 'core/ProfileBufferEntry.cpp', 'core/ProfileJSONWriter.cpp', 'core/ProfilerBacktrace.cpp', - 'core/ProfilerMarkers.cpp', + 'core/ProfilerMarkerPayload.cpp', 'core/StackTop.cpp', 'core/ThreadInfo.cpp', 'gecko/CrossProcessProfilerController.cpp', diff --git a/tools/profiler/public/ProfilerMarkers.h b/tools/profiler/public/ProfilerMarkerPayload.h similarity index 100% rename from tools/profiler/public/ProfilerMarkers.h rename to tools/profiler/public/ProfilerMarkerPayload.h diff --git a/tools/profiler/public/PseudoStack.h b/tools/profiler/public/PseudoStack.h index 870a2c9f4cc8..3f14139fb794 100644 --- a/tools/profiler/public/PseudoStack.h +++ b/tools/profiler/public/PseudoStack.h @@ -9,185 +9,13 @@ #include "mozilla/ArrayUtils.h" #include "js/ProfilingStack.h" -#include "nsISupportsImpl.h" +#include "StoreSequencer.h" #include #include #include -// STORE_SEQUENCER: Because signals can interrupt our profile modification -// we need to make stores are not re-ordered by the compiler -// or hardware to make sure the profile is consistent at -// every point the signal can fire. -#if defined(__arm__) -// TODO Is there something cheaper that will prevent memory stores from being -// reordered? - -typedef void (*LinuxKernelMemoryBarrierFunc)(void); -LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = - (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; - -# define STORE_SEQUENCER() pLinuxKernelMemoryBarrier() - -#elif defined(__i386__) || defined(__x86_64__) || \ - defined(_M_IX86) || defined(_M_X64) -# if defined(_MSC_VER) -# include -# define STORE_SEQUENCER() _ReadWriteBarrier(); -# elif defined(__INTEL_COMPILER) -# define STORE_SEQUENCER() __memory_barrier(); -# elif __GNUC__ -# define STORE_SEQUENCER() asm volatile("" ::: "memory"); -# else -# error "Memory clobber not supported for your compiler." -# endif - -#else -# error "Memory clobber not supported for your platform." -#endif - -class ProfilerMarkerPayload; -template -class ProfilerLinkedList; -class SpliceableJSONWriter; -class UniqueStacks; - -class ProfilerMarker -{ - friend class ProfilerLinkedList; - -public: - explicit ProfilerMarker(const char* aMarkerName, - ProfilerMarkerPayload* aPayload = nullptr, - double aTime = 0); - ~ProfilerMarker(); - - const char* GetMarkerName() const { return mMarkerName; } - - void StreamJSON(SpliceableJSONWriter& aWriter, - const mozilla::TimeStamp& aStartTime, - UniqueStacks& aUniqueStacks) const; - - void SetGeneration(uint32_t aGenID); - - bool HasExpired(uint32_t aGenID) const { return mGenID + 2 <= aGenID; } - - double GetTime() const; - -private: - char* mMarkerName; - ProfilerMarkerPayload* mPayload; - ProfilerMarker* mNext; - double mTime; - uint32_t mGenID; -}; - -template -class ProfilerLinkedList -{ -public: - ProfilerLinkedList() - : mHead(nullptr) - , mTail(nullptr) - {} - - void insert(T* aElem) - { - if (!mTail) { - mHead = aElem; - mTail = aElem; - } else { - mTail->mNext = aElem; - mTail = aElem; - } - aElem->mNext = nullptr; - } - - T* popHead() - { - if (!mHead) { - MOZ_ASSERT(false); - return nullptr; - } - - T* head = mHead; - - mHead = head->mNext; - if (!mHead) { - mTail = nullptr; - } - - return head; - } - - const T* peek() { - return mHead; - } - -private: - T* mHead; - T* mTail; -}; - -typedef ProfilerLinkedList ProfilerMarkerLinkedList; - -template -class ProfilerSignalSafeLinkedList -{ -public: - ProfilerSignalSafeLinkedList() - : mSignalLock(false) - {} - - ~ProfilerSignalSafeLinkedList() - { - if (mSignalLock) { - // Some thread is modifying the list. We should only be released on that - // thread. - abort(); - } - - while (mList.peek()) { - delete mList.popHead(); - } - } - - // Insert an item into the list. Must only be called from the owning thread. - // Must not be called while the list from accessList() is being accessed. - // In the profiler, we ensure that by interrupting the profiled thread - // (which is the one that owns this list and calls insert() on it) until - // we're done reading the list from the signal handler. - void insert(T* aElement) - { - MOZ_ASSERT(aElement); - - mSignalLock = true; - STORE_SEQUENCER(); - - mList.insert(aElement); - - STORE_SEQUENCER(); - mSignalLock = false; - } - - // Called within signal, from any thread, possibly while insert() is in the - // middle of modifying the list (on the owning thread). Will return null if - // that is the case. - // Function must be reentrant. - ProfilerLinkedList* accessList() - { - return mSignalLock ? nullptr : &mList; - } - -private: - ProfilerLinkedList mList; - - // If this is set, then it's not safe to read the list because its contents - // are being changed. - volatile bool mSignalLock; -}; - // The PseudoStack members are read by signal handlers, so the mutation of them // needs to be signal-safe. class PseudoStack diff --git a/tools/profiler/public/StoreSequencer.h b/tools/profiler/public/StoreSequencer.h new file mode 100644 index 000000000000..6044999a9dde --- /dev/null +++ b/tools/profiler/public/StoreSequencer.h @@ -0,0 +1,41 @@ +/* -*- 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 StoreSequencer_h +#define StoreSequencer_h + +// STORE_SEQUENCER is a memory barrier used to ensure profiles are updated +// safely. + +#if defined(__arm__) +// TODO Is there something cheaper that will prevent memory stores from being +// reordered? + +typedef void (*LinuxKernelMemoryBarrierFunc)(void); +LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = + (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; + +# define STORE_SEQUENCER() pLinuxKernelMemoryBarrier() + +#elif defined(__i386__) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_X64) + +# if defined(_MSC_VER) +# include +# define STORE_SEQUENCER() _ReadWriteBarrier(); +# elif defined(__INTEL_COMPILER) +# define STORE_SEQUENCER() __memory_barrier(); +# elif __GNUC__ +# define STORE_SEQUENCER() asm volatile("" ::: "memory"); +# else +# error "STORE_SEQUENCER not supported for your compiler." +# endif + +#else +# error "STORE_SEQUENCER not supported for your platform." +#endif + +#endif // StoreSequencer_h diff --git a/tools/profiler/tests/gtest/GeckoProfiler.cpp b/tools/profiler/tests/gtest/GeckoProfiler.cpp index 675d2c34236e..eb4ebd0a5696 100644 --- a/tools/profiler/tests/gtest/GeckoProfiler.cpp +++ b/tools/profiler/tests/gtest/GeckoProfiler.cpp @@ -12,7 +12,7 @@ #include "gtest/gtest.h" #include "GeckoProfiler.h" -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #include "jsapi.h" #include "js/Initialization.h" #include "mozilla/UniquePtrExtensions.h" diff --git a/widget/VsyncDispatcher.cpp b/widget/VsyncDispatcher.cpp index eb3e716f547c..d184b6d94e2f 100644 --- a/widget/VsyncDispatcher.cpp +++ b/widget/VsyncDispatcher.cpp @@ -13,7 +13,7 @@ #ifdef MOZ_GECKO_PROFILER #include "GeckoProfiler.h" -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #endif using namespace mozilla::layers; diff --git a/widget/gonk/GeckoTouchDispatcher.cpp b/widget/gonk/GeckoTouchDispatcher.cpp index 0b18c91a13fe..5ae095783639 100644 --- a/widget/gonk/GeckoTouchDispatcher.cpp +++ b/widget/gonk/GeckoTouchDispatcher.cpp @@ -19,7 +19,7 @@ #include "GeckoProfiler.h" #include "GeckoTouchDispatcher.h" #include "InputData.h" -#include "ProfilerMarkers.h" +#include "ProfilerMarkerPayload.h" #include "base/basictypes.h" #include "gfxPrefs.h" #include "libui/Input.h" @@ -350,8 +350,10 @@ GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput aMultiTouch) } const ScreenIntPoint& touchPoint = aMultiTouch.mTouches[0].mScreenPoint; +#ifdef MOZ_GECKO_PROFILER TouchDataPayload* payload = new TouchDataPayload(touchPoint); PROFILER_MARKER_PAYLOAD(touchAction, payload); +#endif } }