summaryrefslogtreecommitdiffstats
path: root/gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp b/gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp
new file mode 100644
index 0000000000..5cca7b111f
--- /dev/null
+++ b/gfx/layers/d3d11/DeviceAttachmentsD3D11.cpp
@@ -0,0 +1,342 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DeviceAttachmentsD3D11.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/layers/Compositor.h"
+#include "CompositorD3D11Shaders.h"
+#include "Layers.h"
+#include "ShaderDefinitionsD3D11.h"
+
+namespace mozilla {
+namespace layers {
+
+using namespace gfx;
+
+static const size_t kInitialMaximumTriangles = 64;
+
+DeviceAttachmentsD3D11::DeviceAttachmentsD3D11(ID3D11Device* device)
+ : mMaximumTriangles(kInitialMaximumTriangles),
+ mDevice(device),
+ mContinueInit(true),
+ mInitialized(false),
+ mDeviceReset(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 (LayerManager::LayersComponentAlphaEnabled()) {
+ 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;
+ }
+
+ MOZ_ASSERT(!mSyncObject);
+ MOZ_ASSERT(mDevice);
+
+ mSyncObject = SyncObjectHost::CreateSyncObjectHost(mDevice);
+ MOZ_ASSERT(mSyncObject);
+
+ return mSyncObject->Init();
+}
+
+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 (LayerManager::LayersComponentAlphaEnabled()) {
+ 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