зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central. r=merge a=merge
MozReview-Commit-ID: 4QFAkv28IPJ
This commit is contained in:
Коммит
71ca1d9609
|
@ -1058,8 +1058,9 @@ nsFocusManager::FireDelayedEvents(nsIDocument* aDocument)
|
|||
nsCOMPtr<nsIPresShell> presShell = mDelayedBlurFocusEvents[i].mPresShell;
|
||||
nsCOMPtr<EventTarget> 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> eventTarget = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsIDocument> eventTargetDoc = GetDocumentHelper(eventTarget);
|
||||
nsCOMPtr<nsIDocument> relatedTargetDoc = GetDocumentHelper(aRelatedTarget);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> currentWindow = mFocusedWindow;
|
||||
nsCOMPtr<nsPIDOMWindowInner> targetWindow = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsIDocument> targetDocument = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsIContent> 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> eventTarget = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsIDocument> eventTargetDoc = GetDocumentHelper(eventTarget);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> currentWindow = mFocusedWindow;
|
||||
nsCOMPtr<nsPIDOMWindowInner> targetWindow = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsIDocument> targetDocument = do_QueryInterface(aTarget);
|
||||
nsCOMPtr<nsIContent> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "GeckoProfiler.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkers.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#endif
|
||||
#include "PerformanceEntry.h"
|
||||
#include "PerformanceMainThread.h"
|
||||
|
|
|
@ -208,6 +208,10 @@ GPUParent::RecvInit(nsTArray<GfxPrefSetting>&& prefs,
|
|||
RecvGetDeviceStatus(&data);
|
||||
Unused << SendInitComplete(data);
|
||||
|
||||
#ifdef XP_WIN
|
||||
DeviceManagerDx::PreloadAttachmentsOnCompositorThread();
|
||||
#endif
|
||||
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS, mLaunchTime);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <vector>
|
||||
#include "GeckoProfiler.h" // for GeckoProfiler
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkers.h" // for ProfilerMarkers
|
||||
#include "ProfilerMarkerPayload.h" // for LayerTranslationPayload
|
||||
#endif
|
||||
|
||||
#define CULLING_LOG(...)
|
||||
|
|
|
@ -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 <VersionHelpers.h> // For IsWindows8OrGreater
|
||||
#include <winsdkver.h>
|
||||
|
@ -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<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11VertexShader>>
|
||||
VertexShaderArray;
|
||||
typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11PixelShader>>
|
||||
PixelShaderArray;
|
||||
|
||||
RefPtr<ID3D11InputLayout> mInputLayout;
|
||||
RefPtr<ID3D11InputLayout> mDynamicInputLayout;
|
||||
|
||||
RefPtr<ID3D11Buffer> mVertexBuffer;
|
||||
RefPtr<ID3D11Buffer> mDynamicVertexBuffer;
|
||||
|
||||
VertexShaderArray mVSQuadShader;
|
||||
VertexShaderArray mVSQuadBlendShader;
|
||||
|
||||
VertexShaderArray mVSDynamicShader;
|
||||
VertexShaderArray mVSDynamicBlendShader;
|
||||
|
||||
PixelShaderArray mSolidColorShader;
|
||||
PixelShaderArray mRGBAShader;
|
||||
PixelShaderArray mRGBShader;
|
||||
PixelShaderArray mYCbCrShader;
|
||||
PixelShaderArray mNV12Shader;
|
||||
PixelShaderArray mComponentAlphaShader;
|
||||
PixelShaderArray mBlendShader;
|
||||
RefPtr<ID3D11Buffer> mPSConstantBuffer;
|
||||
RefPtr<ID3D11Buffer> mVSConstantBuffer;
|
||||
RefPtr<ID3D11RasterizerState> mRasterizerState;
|
||||
RefPtr<ID3D11SamplerState> mLinearSamplerState;
|
||||
RefPtr<ID3D11SamplerState> mPointSamplerState;
|
||||
|
||||
RefPtr<ID3D11BlendState> mPremulBlendState;
|
||||
RefPtr<ID3D11BlendState> mNonPremulBlendState;
|
||||
RefPtr<ID3D11BlendState> mComponentBlendState;
|
||||
RefPtr<ID3D11BlendState> mDisabledBlendState;
|
||||
RefPtr<IDXGIResource> 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<ID3D11Device> mDevice;
|
||||
bool mInitOkay;
|
||||
};
|
||||
|
||||
CompositorD3D11::CompositorD3D11(CompositorBridgeParent* aParent, widget::CompositorWidget* aWidget)
|
||||
: Compositor(aWidget, aParent)
|
||||
, mAttachments(nullptr)
|
||||
|
@ -165,35 +65,12 @@ 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<typename VertexType>
|
||||
void
|
||||
|
@ -216,24 +93,10 @@ CompositorD3D11::UpdateDynamicVertexBuffer(const nsTArray<gfx::TexturedTriangle>
|
|||
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")) {
|
||||
if (!mAttachments->EnsureTriangleBuffer(aTriangles.Length())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mMaximumTriangles = aTriangles.Length();
|
||||
}
|
||||
|
||||
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<IDXGIDevice> dxgiDevice;
|
||||
RefPtr<IDXGIAdapter> 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<ID3D11Texture2D> 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()
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "TextureD3D11.h"
|
||||
#include <d3d11.h>
|
||||
#include <dxgi1_2.h>
|
||||
#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<ID3D11Query> mQuery;
|
||||
|
||||
DeviceAttachmentsD3D11* mAttachments;
|
||||
RefPtr<DeviceAttachmentsD3D11> mAttachments;
|
||||
UniquePtr<DiagnosticsD3D11> mDiagnostics;
|
||||
|
||||
LayoutDeviceIntSize mSize;
|
||||
|
@ -254,8 +236,6 @@ private:
|
|||
gfx::IntRect mCurrentClip;
|
||||
|
||||
bool mVerifyBuffersFailed;
|
||||
|
||||
size_t mMaximumTriangles;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
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<DeviceAttachmentsD3D11> 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<ID3D11Texture2D> 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
|
|
@ -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 <d3d11.h>
|
||||
#include <dxgi1_2.h>
|
||||
|
||||
struct ShaderBytes;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class DeviceAttachmentsD3D11
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceAttachmentsD3D11);
|
||||
|
||||
public:
|
||||
static RefPtr<DeviceAttachmentsD3D11> 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<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11VertexShader>>
|
||||
VertexShaderArray;
|
||||
typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11PixelShader>>
|
||||
PixelShaderArray;
|
||||
|
||||
RefPtr<ID3D11InputLayout> mInputLayout;
|
||||
RefPtr<ID3D11InputLayout> mDynamicInputLayout;
|
||||
|
||||
RefPtr<ID3D11Buffer> mVertexBuffer;
|
||||
RefPtr<ID3D11Buffer> mDynamicVertexBuffer;
|
||||
|
||||
VertexShaderArray mVSQuadShader;
|
||||
VertexShaderArray mVSQuadBlendShader;
|
||||
|
||||
VertexShaderArray mVSDynamicShader;
|
||||
VertexShaderArray mVSDynamicBlendShader;
|
||||
|
||||
PixelShaderArray mSolidColorShader;
|
||||
PixelShaderArray mRGBAShader;
|
||||
PixelShaderArray mRGBShader;
|
||||
PixelShaderArray mYCbCrShader;
|
||||
PixelShaderArray mNV12Shader;
|
||||
PixelShaderArray mComponentAlphaShader;
|
||||
PixelShaderArray mBlendShader;
|
||||
RefPtr<ID3D11Buffer> mPSConstantBuffer;
|
||||
RefPtr<ID3D11Buffer> mVSConstantBuffer;
|
||||
RefPtr<ID3D11RasterizerState> mRasterizerState;
|
||||
RefPtr<ID3D11SamplerState> mLinearSamplerState;
|
||||
RefPtr<ID3D11SamplerState> mPointSamplerState;
|
||||
|
||||
RefPtr<ID3D11BlendState> mPremulBlendState;
|
||||
RefPtr<ID3D11BlendState> mNonPremulBlendState;
|
||||
RefPtr<ID3D11BlendState> mComponentBlendState;
|
||||
RefPtr<ID3D11BlendState> mDisabledBlendState;
|
||||
RefPtr<IDXGIResource> 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<ID3D11Device> mDevice;
|
||||
bool mContinueInit;
|
||||
bool mInitialized;
|
||||
nsCString mInitFailureId;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_gfx_layers_d3d11_DeviceAttachmentsD3D11_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
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
]
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "ContextStateTracker.h"
|
||||
#include "GLContext.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ProfilerMarkers.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
@ -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 <d3d11.h>
|
||||
#include <ddraw.h>
|
||||
|
@ -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<ID3D11Device>* aOutDevice,
|
||||
RefPtr<layers::DeviceAttachmentsD3D11>* aOutAttachments)
|
||||
{
|
||||
MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
|
||||
|
||||
RefPtr<ID3D11Device> 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<layers::DeviceAttachmentsD3D11> 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<Runnable> task = NS_NewRunnableFunction([]() -> void {
|
||||
if (DeviceManagerDx* dm = DeviceManagerDx::Get()) {
|
||||
RefPtr<ID3D11Device> device;
|
||||
RefPtr<layers::DeviceAttachmentsD3D11> attachments;
|
||||
dm->GetCompositorDevices(&device, &attachments);
|
||||
}
|
||||
});
|
||||
loop->PostTask(task.forget());
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -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<ID3D11Device>* aOutDevice,
|
||||
RefPtr<layers::DeviceAttachmentsD3D11>* 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<ID3D11Device> mCompositorDevice;
|
||||
RefPtr<ID3D11Device> mContentDevice;
|
||||
RefPtr<ID3D11Device> mDecoderDevice;
|
||||
RefPtr<layers::DeviceAttachmentsD3D11> mCompositorAttachments;
|
||||
bool mCompositorDeviceSupportsVideo;
|
||||
|
||||
Maybe<D3D11DeviceStatus> mDeviceStatus;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -838,7 +838,7 @@
|
|||
"support"
|
||||
],
|
||||
"dom/classList.html": [
|
||||
"6d9b7f24be9c7e2ccf504c8fe05e93bbc01fd7c6",
|
||||
"f289334e7b3486259b9aae54b4282a7211b8813e",
|
||||
"testharness"
|
||||
],
|
||||
"fetch/api/redirect/redirect-referrer-mixed-content.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);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "ProfileBuffer.h"
|
||||
|
||||
#include "ProfilerMarker.h"
|
||||
|
||||
ProfileBuffer::ProfileBuffer(int aEntrySize)
|
||||
: mEntries(mozilla::MakeUnique<ProfileBufferEntry[]>(aEntrySize))
|
||||
, mWritePos(0)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "platform.h"
|
||||
#include "ProfileJSONWriter.h"
|
||||
#include "ProfilerBacktrace.h"
|
||||
#include "PseudoStack.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -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 *) \
|
||||
|
|
|
@ -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<typename T>
|
||||
class ProfilerLinkedList;
|
||||
class SpliceableJSONWriter;
|
||||
class UniqueStacks;
|
||||
|
||||
class ProfilerMarker
|
||||
{
|
||||
friend class ProfilerLinkedList<ProfilerMarker>;
|
||||
|
||||
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<char> mMarkerName;
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> mPayload;
|
||||
ProfilerMarker* mNext;
|
||||
double mTime;
|
||||
uint32_t mGenID;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
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<ProfilerMarker> ProfilerMarkerLinkedList;
|
||||
|
||||
template<typename T>
|
||||
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<T>* accessList()
|
||||
{
|
||||
return mSignalLock ? nullptr : &mList;
|
||||
}
|
||||
|
||||
private:
|
||||
ProfilerLinkedList<T> 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
|
|
@ -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"
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "ProfilerIOInterposeObserver.h"
|
||||
#include "ProfilerMarkers.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -9,185 +9,13 @@
|
|||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "js/ProfilingStack.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "StoreSequencer.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// 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 <intrin.h>
|
||||
# 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<typename T>
|
||||
class ProfilerLinkedList;
|
||||
class SpliceableJSONWriter;
|
||||
class UniqueStacks;
|
||||
|
||||
class ProfilerMarker
|
||||
{
|
||||
friend class ProfilerLinkedList<ProfilerMarker>;
|
||||
|
||||
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<typename T>
|
||||
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<ProfilerMarker> ProfilerMarkerLinkedList;
|
||||
|
||||
template<typename T>
|
||||
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<T>* accessList()
|
||||
{
|
||||
return mSignalLock ? nullptr : &mList;
|
||||
}
|
||||
|
||||
private:
|
||||
ProfilerLinkedList<T> 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
|
||||
|
|
|
@ -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 <intrin.h>
|
||||
# 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
|
|
@ -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"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "GeckoProfiler.h"
|
||||
#include "ProfilerMarkers.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче