mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
265e672179
# ignore-this-changeset --HG-- extra : amend_source : 4d301d3b0b8711c4692392aa76088ba7fd7d1022
342 lines
12 KiB
C++
342 lines
12 KiB
C++
/* -*- 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 "gfxPrefs.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 (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;
|
|
}
|
|
|
|
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 (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
|