merge mozilla-central to autoland. r=merge a=merge

This commit is contained in:
Sebastian Hengst 2017-05-01 11:22:50 +02:00
commit d08bc7fba3
37 changed files with 922 additions and 789 deletions

View File

@ -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);
}
}

View File

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

View File

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

View File

@ -8,7 +8,7 @@
#include "GeckoProfiler.h"
#ifdef MOZ_GECKO_PROFILER
#include "ProfilerMarkers.h"
#include "ProfilerMarkerPayload.h"
#endif
#include "PerformanceEntry.h"
#include "PerformanceMainThread.h"

View File

@ -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();
}

View File

@ -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(...)

View File

@ -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,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<typename VertexType>
void
CompositorD3D11::SetVertexBuffer(ID3D11Buffer* aBuffer)
@ -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")) {
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<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()
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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',
]

View File

@ -6,7 +6,7 @@
#include "ContextStateTracker.h"
#include "GLContext.h"
#ifdef MOZ_GECKO_PROFILER
#include "ProfilerMarkers.h"
#include "ProfilerMarkerPayload.h"
#endif
namespace mozilla {

View File

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

View File

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

View File

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

View File

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

View File

@ -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": [

View File

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

View File

@ -838,7 +838,7 @@
"support"
],
"dom/classList.html": [
"6d9b7f24be9c7e2ccf504c8fe05e93bbc01fd7c6",
"f289334e7b3486259b9aae54b4282a7211b8813e",
"testharness"
],
"fetch/api/redirect/redirect-referrer-mixed-content.js": [

View File

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

View File

@ -6,6 +6,8 @@
#include "ProfileBuffer.h"
#include "ProfilerMarker.h"
ProfileBuffer::ProfileBuffer(int aEntrySize)
: mEntries(mozilla::MakeUnique<ProfileBufferEntry[]>(aEntrySize))
, mWritePos(0)

View File

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

View File

@ -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 *) \

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@
#include "GeckoProfiler.h"
#include "ProfilerIOInterposeObserver.h"
#include "ProfilerMarkers.h"
#include "ProfilerMarkerPayload.h"
using namespace mozilla;

View File

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

View File

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

View File

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

View File

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

View File

@ -13,7 +13,7 @@
#ifdef MOZ_GECKO_PROFILER
#include "GeckoProfiler.h"
#include "ProfilerMarkers.h"
#include "ProfilerMarkerPayload.h"
#endif
using namespace mozilla::layers;

View File

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