Bug 830347 - Part 2: Add the code for CompositorD3D11. r=jrmuizel

This commit is contained in:
Bas Schouten 2013-05-03 19:34:29 +02:00
Родитель 34f8ad7af9
Коммит 745964b1cd
17 изменённых файлов: 6507 добавлений и 41 удалений

Просмотреть файл

@ -37,6 +37,7 @@ enum LayersBackend {
LAYERS_OPENGL,
LAYERS_D3D9,
LAYERS_D3D10,
LAYERS_D3D11,
LAYERS_CLIENT,
LAYERS_LAST
};

Просмотреть файл

@ -14,6 +14,7 @@ VPATH = \
$(srcdir)/opengl \
$(srcdir)/d3d9 \
$(srcdir)/d3d10 \
$(srcdir)/d3d11 \
$(srcdir)/ipc \
$(NULL)
@ -97,11 +98,13 @@ ifdef MOZ_ENABLE_D3D10_LAYER
CPPSRCS += \
CanvasLayerD3D10.cpp \
ColorLayerD3D10.cpp \
CompositorD3D11.cpp \
ContainerLayerD3D10.cpp \
ImageLayerD3D10.cpp \
LayerManagerD3D10.cpp \
ReadbackManagerD3D10.cpp \
ShadowLayerUtilsD3D10.cpp \
TextureD3D11.cpp \
ThebesLayerD3D10.cpp \
$(NULL)
endif

Просмотреть файл

@ -8,6 +8,10 @@
#include "mozilla/layers/TextureClientOGL.h"
#include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/CompositableForwarder.h"
#ifdef XP_WIN
#include "mozilla/layers/TextureD3D11.h"
#include "gfxWindowsPlatform.h"
#endif
namespace mozilla {
namespace layers {
@ -96,17 +100,20 @@ CompositableClient::CreateTextureClient(TextureClientType aTextureClientType)
}
break;
case TEXTURE_YCBCR:
if (parentBackend == LAYERS_OPENGL) {
if (parentBackend == LAYERS_OPENGL || parentBackend == LAYERS_D3D11) {
result = new TextureClientShmemYCbCr(GetForwarder(), GetTextureInfo());
}
break;
case TEXTURE_CONTENT:
#ifdef XP_WIN
if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice()) {
result = new TextureClientD3D11(GetForwarder(), GetTextureInfo());
break;
}
#endif
// fall through to TEXTURE_SHMEM
case TEXTURE_SHMEM:
if (parentBackend == LAYERS_OPENGL ||
parentBackend == LAYERS_BASIC) {
result = new TextureClientShmem(GetForwarder(), GetTextureInfo());
}
result = new TextureClientShmem(GetForwarder(), GetTextureInfo());
break;
default:
MOZ_ASSERT(false, "Unhandled texture client type");

Просмотреть файл

@ -10,6 +10,9 @@
#include "gfxUtils.h"
#include "gfxPlatform.h"
#include "mozilla/layers/LayerManagerComposite.h"
#ifdef XP_WIN
#include "gfxWindowsPlatform.h"
#endif
namespace mozilla {
@ -21,11 +24,23 @@ namespace layers {
ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
{
if (aForwarder->GetCompositorBackendType() != LAYERS_OPENGL &&
aForwarder->GetCompositorBackendType() != LAYERS_D3D11 &&
aForwarder->GetCompositorBackendType() != LAYERS_BASIC) {
return nullptr;
return nullptr;
}
if (LayerManagerComposite::SupportsDirectTexturing() ||
PR_GetEnv("MOZ_FORCE_DOUBLE_BUFFERING")) {
bool useDoubleBuffering = false;
#ifdef XP_WIN
if (aForwarder->GetCompositorBackendType() == LAYERS_D3D11) {
useDoubleBuffering = !!gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
} else
#endif
{
useDoubleBuffering = LayerManagerComposite::SupportsDirectTexturing();
}
if (useDoubleBuffering || PR_GetEnv("MOZ_FORCE_DOUBLE_BUFFERING")) {
return new ContentClientDoubleBuffered(aForwarder);
}
return new ContentClientSingleBuffered(aForwarder);

Просмотреть файл

@ -28,19 +28,13 @@ ImageClient::CreateImageClient(CompositableType aCompositableHostType,
RefPtr<ImageClient> result = nullptr;
switch (aCompositableHostType) {
case BUFFER_IMAGE_SINGLE:
if (ImageClientSingle::SupportsBackend(aForwarder->GetCompositorBackendType())) {
result = new ImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_SINGLE);
}
result = new ImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_SINGLE);
break;
case BUFFER_IMAGE_BUFFERED:
if (ImageClientSingle::SupportsBackend(aForwarder->GetCompositorBackendType())) {
result = new ImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_BUFFERED);
}
result = new ImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_BUFFERED);
break;
case BUFFER_BRIDGE:
if (ImageClientBridge::SupportsBackend(aForwarder->GetCompositorBackendType())) {
result = new ImageClientBridge(aForwarder, aFlags);
}
result = new ImageClientBridge(aForwarder, aFlags);
break;
case BUFFER_UNKNOWN:
result = nullptr;
@ -224,26 +218,6 @@ ImageClientSingle::Updated()
mForwarder->UpdateTexture(this, 1, mTextureClient->GetDescriptor());
}
bool
ImageClientSingle::SupportsBackend(LayersBackend aBackend)
{
if (aBackend == LAYERS_OPENGL ||
aBackend == LAYERS_BASIC) {
return true;
}
return false;
}
bool
ImageClientBridge::SupportsBackend(LayersBackend aBackend)
{
if (aBackend == LAYERS_OPENGL ||
aBackend == LAYERS_BASIC) {
return true;
}
return false;
}
ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
TextureFlags aFlags)
: ImageClient(aFwd, BUFFER_BRIDGE)

Просмотреть файл

@ -102,8 +102,6 @@ public:
return mTextureInfo;
}
static bool SupportsBackend(LayersBackend aBackend);
private:
RefPtr<TextureClient> mTextureClient;
TextureInfo mTextureInfo;
@ -133,8 +131,6 @@ public:
return TextureInfo(mType);
}
static bool SupportsBackend(LayersBackend aBackend);
protected:
uint64_t mAsyncContainerID;
ShadowableLayer* mLayer;

Просмотреть файл

@ -28,6 +28,12 @@ TemporaryRef<TextureHost> CreateTextureHostD3D9(SurfaceDescriptorType aDescripto
return nullptr;
}
#ifdef XP_WIN
TemporaryRef<TextureHost> CreateTextureHostD3D11(SurfaceDescriptorType aDescriptorType,
uint32_t aTextureHostFlags,
uint32_t aTextureFlags);
#endif
/* static */ TemporaryRef<TextureHost>
TextureHost::CreateTextureHost(SurfaceDescriptorType aDescriptorType,
uint32_t aTextureHostFlags,
@ -42,6 +48,12 @@ TextureHost::CreateTextureHost(SurfaceDescriptorType aDescriptorType,
return CreateTextureHostD3D9(aDescriptorType,
aTextureHostFlags,
aTextureFlags);
#ifdef XP_WIN
case LAYERS_D3D11:
return CreateTextureHostD3D11(aDescriptorType,
aTextureHostFlags,
aTextureFlags);
#endif
case LAYERS_BASIC:
return CreateBasicTextureHost(aDescriptorType,
aTextureHostFlags,

Просмотреть файл

@ -25,6 +25,7 @@ class Compositor;
class SurfaceDescriptor;
class ISurfaceAllocator;
class TextureSourceOGL;
class TextureSourceD3D11;
class TextureSourceBasic;
class TextureParent;
@ -78,6 +79,11 @@ public:
*/
virtual TextureSourceOGL* AsSourceOGL() { return nullptr; }
/**
* Cast to an TextureSource for the D3D11 backend.
*/
virtual TextureSourceD3D11* AsSourceD3D11() { return nullptr; }
virtual TextureSourceBasic* AsSourceBasic() { return nullptr; }
/**

Просмотреть файл

@ -0,0 +1,782 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 "CompositorD3D11.h"
#include "TextureD3D11.h"
#include "CompositorD3D11Shaders.h"
#include "gfxWindowsPlatform.h"
#include "nsIWidget.h"
#include "mozilla/layers/ImageHost.h"
#include "mozilla/layers/ContentHost.h"
#include "mozilla/layers/Effects.h"
#include "nsWindowsHelpers.h"
#ifdef MOZ_METRO
#include <DXGI1_2.h>
#endif
namespace mozilla {
using namespace gfx;
namespace layers {
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 };
struct DeviceAttachmentsD3D11
{
RefPtr<ID3D11InputLayout> mInputLayout;
RefPtr<ID3D11Buffer> mVertexBuffer;
RefPtr<ID3D11VertexShader> mVSQuadShader[3];
RefPtr<ID3D11PixelShader> mSolidColorShader[2];
RefPtr<ID3D11PixelShader> mRGBAShader[3];
RefPtr<ID3D11PixelShader> mRGBShader[2];
RefPtr<ID3D11PixelShader> mYCbCrShader[2];
RefPtr<ID3D11Buffer> mPSConstantBuffer;
RefPtr<ID3D11Buffer> mVSConstantBuffer;
RefPtr<ID3D11RasterizerState> mRasterizerState;
RefPtr<ID3D11SamplerState> mLinearSamplerState;
RefPtr<ID3D11SamplerState> mPointSamplerState;
RefPtr<ID3D11BlendState> mPremulBlendState;
RefPtr<ID3D11BlendState> mNonPremulBlendState;
};
CompositorD3D11::CompositorD3D11(nsIWidget *aWidget)
: mWidget(aWidget)
, mAttachments(nullptr)
{
sBackend = LAYERS_D3D11;
}
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, NULL);
delete attachments;
}
}
}
bool
CompositorD3D11::Initialize()
{
HRESULT hr;
mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
if (!mDevice) {
return false;
}
mDevice->GetImmediateContext(byRef(mContext));
if (!mContext) {
return false;
}
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->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),
byRef(mAttachments->mInputLayout));
if (FAILED(hr)) {
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, byRef(mAttachments->mVertexBuffer));
if (FAILED(hr)) {
return false;
}
if (!CreateShaders()) {
return false;
}
CD3D11_BUFFER_DESC cBufferDesc(sizeof(VertexShaderConstants), D3D11_BIND_CONSTANT_BUFFER,
D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mVSConstantBuffer));
if (FAILED(hr)) {
return false;
}
cBufferDesc.ByteWidth = sizeof(PixelShaderConstants);
hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mPSConstantBuffer));
if (FAILED(hr)) {
return false;
}
CD3D11_RASTERIZER_DESC rastDesc(D3D11_DEFAULT);
rastDesc.CullMode = D3D11_CULL_NONE;
rastDesc.ScissorEnable = TRUE;
hr = mDevice->CreateRasterizerState(&rastDesc, byRef(mAttachments->mRasterizerState));
if (FAILED(hr)) {
return false;
}
CD3D11_SAMPLER_DESC samplerDesc(D3D11_DEFAULT);
samplerDesc.AddressU = samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
hr = mDevice->CreateSamplerState(&samplerDesc, byRef(mAttachments->mLinearSamplerState));
if (FAILED(hr)) {
return false;
}
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
hr = mDevice->CreateSamplerState(&samplerDesc, byRef(mAttachments->mPointSamplerState));
if (FAILED(hr)) {
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, byRef(mAttachments->mPremulBlendState));
if (FAILED(hr)) {
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, byRef(mAttachments->mNonPremulBlendState));
if (FAILED(hr)) {
return false;
}
}
nsRefPtr<IDXGIDevice> dxgiDevice;
nsRefPtr<IDXGIAdapter> dxgiAdapter;
mDevice->QueryInterface(dxgiDevice.StartAssignment());
dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
#ifdef MOZ_METRO
if (IsRunningInWindowsMetro()) {
nsRefPtr<IDXGIFactory2> dxgiFactory;
dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
nsIntRect rect;
mWidget->GetClientBounds(rect);
DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 };
// Automatically detect the width and the height from the winrt CoreWindow
swapDesc.Width = rect.width;
swapDesc.Height = rect.height;
// This is the most common swapchain format
swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapDesc.Stereo = false;
// Don't use multi-sampling
swapDesc.SampleDesc.Count = 1;
swapDesc.SampleDesc.Quality = 0;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
// Use double buffering to enable flip
swapDesc.BufferCount = 2;
swapDesc.Scaling = DXGI_SCALING_STRETCH;
// All Metro style apps must use this SwapEffect
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapDesc.Flags = 0;
/**
* Create a swap chain, this swap chain will contain the backbuffer for
* the window we draw to. The front buffer is the full screen front
* buffer.
*/
nsRefPtr<IDXGISwapChain1> swapChain1;
hr = dxgiFactory->CreateSwapChainForCoreWindow(
dxgiDevice, (IUnknown *)mWidget->GetNativeData(NS_NATIVE_ICOREWINDOW),
&swapDesc, nullptr, getter_AddRefs(swapChain1));
if (FAILED(hr)) {
return false;
}
mSwapChain = swapChain1;
} else
#endif
{
nsRefPtr<IDXGIFactory> dxgiFactory;
dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
DXGI_SWAP_CHAIN_DESC swapDesc;
::ZeroMemory(&swapDesc, sizeof(swapDesc));
swapDesc.BufferDesc.Width = 0;
swapDesc.BufferDesc.Height = 0;
swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapDesc.BufferDesc.RefreshRate.Numerator = 60;
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
swapDesc.SampleDesc.Count = 1;
swapDesc.SampleDesc.Quality = 0;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapDesc.BufferCount = 1;
swapDesc.OutputWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
swapDesc.Windowed = TRUE;
// We don't really need this flag, however it seems on some NVidia hardware
// smaller area windows do not present properly without this flag. This flag
// should have no negative consequences by itself. See bug 613790. This flag
// is broken on optimus devices. As a temporary solution we don't set it
// there, the only way of reliably detecting we're on optimus is looking for
// the DLL. See Bug 623807.
if (gfxWindowsPlatform::IsOptimus()) {
swapDesc.Flags = 0;
} else {
swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
}
/**
* Create a swap chain, this swap chain will contain the backbuffer for
* the window we draw to. The front buffer is the full screen front
* buffer.
*/
hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, byRef(mSwapChain));
if (FAILED(hr)) {
return false;
}
// We need this because we don't want DXGI to respond to Alt+Enter.
dxgiFactory->MakeWindowAssociation(swapDesc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES);
}
return true;
}
TextureFactoryIdentifier
CompositorD3D11::GetTextureFactoryIdentifier()
{
TextureFactoryIdentifier ident;
ident.mMaxTextureSize = GetMaxTextureSize();
ident.mParentBackend = LAYERS_D3D11;
return ident;
}
bool
CompositorD3D11::CanUseCanvasLayerForSize(const gfxIntSize &aSize)
{
int32_t maxTextureSize = GetMaxTextureSize();
if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
return false;
}
return true;
}
int32_t
CompositorD3D11::GetMaxTextureSize() const
{
return GetMaxTextureSizeForFeatureLevel(mFeatureLevel);
}
TemporaryRef<CompositingRenderTarget>
CompositorD3D11::CreateRenderTarget(const gfx::IntRect &aRect,
SurfaceInitMode aInit)
{
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aRect.width, aRect.height, 1, 1,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
RefPtr<ID3D11Texture2D> texture;
mDevice->CreateTexture2D(&desc, NULL, byRef(texture));
RefPtr<CompositingRenderTargetD3D11> rt = new CompositingRenderTargetD3D11(texture);
rt->SetSize(IntSize(aRect.width, aRect.height));
if (aInit == INIT_MODE_CLEAR) {
FLOAT clear[] = { 0, 0, 0, 0 };
mContext->ClearRenderTargetView(rt->mRTView, clear);
}
return rt;
}
// TODO[Bas] this method doesn't actually use aSource
TemporaryRef<CompositingRenderTarget>
CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect,
const CompositingRenderTarget *aSource)
{
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aRect.width, aRect.height, 1, 1,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
RefPtr<ID3D11Texture2D> texture;
mDevice->CreateTexture2D(&desc, NULL, byRef(texture));
RefPtr<CompositingRenderTargetD3D11> rt = new CompositingRenderTargetD3D11(texture);
rt->SetSize(IntSize(aRect.width, aRect.height));
return rt;
}
void
CompositorD3D11::SetRenderTarget(CompositingRenderTarget *aRenderTarget)
{
MOZ_ASSERT(aRenderTarget);
CompositingRenderTargetD3D11 *newRT =
static_cast<CompositingRenderTargetD3D11*>(aRenderTarget);
ID3D11RenderTargetView *view = newRT->mRTView;
mCurrentRT = newRT;
mContext->OMSetRenderTargets(1, &view, nullptr);
PrepareViewport(newRT->GetSize(), gfxMatrix());
}
void
CompositorD3D11::SetPSForEffect(Effect *aEffect, MaskMode aMaskMode)
{
switch (aEffect->mType) {
case EFFECT_SOLID_COLOR:
mContext->PSSetShader(mAttachments->mSolidColorShader[aMaskMode], nullptr, 0);
return;
case EFFECT_BGRA:
case EFFECT_RENDER_TARGET:
mContext->PSSetShader(mAttachments->mRGBAShader[aMaskMode], nullptr, 0);
return;
case EFFECT_BGRX:
mContext->PSSetShader(mAttachments->mRGBShader[aMaskMode], nullptr, 0);
return;
case EFFECT_YCBCR:
mContext->PSSetShader(mAttachments->mYCbCrShader[aMaskMode], nullptr, 0);
return;
}
}
void
CompositorD3D11::DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect,
const EffectChain &aEffectChain,
gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform,
const gfx::Point &aOffset)
{
MOZ_ASSERT(mCurrentRT, "No render target");
memcpy(&mVSConstants.layerTransform, &aTransform._11, 64);
mVSConstants.renderTargetOffset[0] = aOffset.x;
mVSConstants.renderTargetOffset[1] = aOffset.y;
mVSConstants.layerQuad = aRect;
mPSConstants.layerOpacity[0] = aOpacity;
bool isPremultiplied = true;
MaskMode maskMode = UNMASKED;
if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
if (aTransform.Is2D()) {
maskMode = MASKED;
} else {
MOZ_ASSERT(aEffectChain.mPrimaryEffect->mType == EFFECT_BGRA);
maskMode = MASKED3D;
}
EffectMask *maskEffect = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
TextureSourceD3D11 *source = maskEffect->mMaskTexture->AsSourceD3D11();
RefPtr<ID3D11ShaderResourceView> view;
mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
ID3D11ShaderResourceView *srView = view;
mContext->PSSetShaderResources(3, 1, &srView);
const gfx::Matrix4x4& maskTransform = maskEffect->mMaskTransform;
NS_ASSERTION(maskTransform.Is2D(), "How did we end up with a 3D transform here?!");
Rect bounds = Rect(Point(), Size(maskEffect->mSize));
mVSConstants.maskQuad = maskTransform.As2D().TransformBounds(bounds);
}
D3D11_RECT scissor;
scissor.left = aClipRect.x;
scissor.right = aClipRect.XMost();
scissor.top = aClipRect.y;
scissor.bottom = aClipRect.YMost();
mContext->RSSetScissorRects(1, &scissor);
mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
mContext->VSSetShader(mAttachments->mVSQuadShader[maskMode], nullptr, 0);
SetPSForEffect(aEffectChain.mPrimaryEffect, maskMode);
switch (aEffectChain.mPrimaryEffect->mType) {
case EFFECT_SOLID_COLOR: {
Color color =
static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
mPSConstants.layerColor[0] = color.r * color.a * aOpacity;
mPSConstants.layerColor[1] = color.g * color.a * aOpacity;
mPSConstants.layerColor[2] = color.b * color.a * aOpacity;
mPSConstants.layerColor[3] = color.a * aOpacity;
}
break;
case EFFECT_BGRX:
case EFFECT_BGRA:
case EFFECT_RENDER_TARGET:
{
TexturedEffect *texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
mVSConstants.textureCoords = texturedEffect->mTextureCoords;
TextureSourceD3D11 *source = texturedEffect->mTexture->AsSourceD3D11();
RefPtr<ID3D11ShaderResourceView> view;
mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
ID3D11ShaderResourceView *srView = view;
mContext->PSSetShaderResources(0, 1, &srView);
isPremultiplied = texturedEffect->mPremultiplied;
SetSamplerForFilter(texturedEffect->mFilter);
}
break;
case EFFECT_YCBCR: {
EffectYCbCr *ycbcrEffect = static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
SetSamplerForFilter(FILTER_LINEAR);
mVSConstants.textureCoords = ycbcrEffect->mTextureCoords;
TextureSourceD3D11 *source = ycbcrEffect->mTexture->AsSourceD3D11();
TextureSourceD3D11::YCbCrTextures textures = source->GetYCbCrTextures();
RefPtr<ID3D11ShaderResourceView> views[3];
mDevice->CreateShaderResourceView(textures.mY, nullptr, byRef(views[0]));
mDevice->CreateShaderResourceView(textures.mCb, nullptr, byRef(views[1]));
mDevice->CreateShaderResourceView(textures.mCr, nullptr, byRef(views[2]));
ID3D11ShaderResourceView *srViews[3] = { views[0], views[1], views[2] };
mContext->PSSetShaderResources(0, 3, srViews);
}
break;
default:
return;
}
UpdateConstantBuffers();
if (!isPremultiplied) {
mContext->OMSetBlendState(mAttachments->mNonPremulBlendState, sBlendFactor, 0xFFFFFFFF);
}
mContext->Draw(4, 0);
if (!isPremultiplied) {
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
}
}
void
CompositorD3D11::BeginFrame(const Rect *aClipRectIn,
const gfxMatrix& aTransform,
const Rect& aRenderBounds,
Rect *aClipRectOut,
Rect *aRenderBoundsOut)
{
VerifyBufferSize();
UpdateRenderTarget();
nsIntRect rect;
mWidget->GetClientBounds(rect);
if (rect.IsEmpty()) {
*aRenderBoundsOut = Rect();
return;
}
mDefaultRT->SetSize(IntSize(rect.width, rect.height));
mContext->IASetInputLayout(mAttachments->mInputLayout);
ID3D11Buffer *buffer = mAttachments->mVertexBuffer;
UINT size = sizeof(Vertex);
UINT offset = 0;
mContext->IASetVertexBuffers(0, 1, &buffer, &size, &offset);
SetRenderTarget(mDefaultRT);
if (aClipRectOut) {
*aClipRectOut = Rect(0, 0, rect.width, rect.height);
}
if (aRenderBoundsOut) {
*aRenderBoundsOut = Rect(0, 0, rect.width, rect.height);
}
FLOAT black[] = { 0, 0, 0, 0 };
mContext->ClearRenderTargetView(mDefaultRT->mRTView, black);
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
mContext->RSSetState(mAttachments->mRasterizerState);
}
void
CompositorD3D11::EndFrame()
{
mContext->Flush();
mSwapChain->Present(0, 0);
if (mTarget) {
PaintToTarget();
}
mCurrentRT = nullptr;
}
void
CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize,
const gfxMatrix &aWorldTransform)
{
D3D11_VIEWPORT viewport;
viewport.MaxDepth = 1.0f;
viewport.MinDepth = 0;
viewport.Width = aSize.width;
viewport.Height = aSize.height;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
mContext->RSSetViewports(1, &viewport);
gfxMatrix viewMatrix;
viewMatrix.Translate(-gfxPoint(1.0, -1.0));
viewMatrix.Scale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
viewMatrix.Scale(1.0f, -1.0f);
viewMatrix = aWorldTransform * viewMatrix;
gfx3DMatrix projection = gfx3DMatrix::From2D(viewMatrix);
projection._33 = 0.0f;
memcpy(&mVSConstants.projection, &projection, sizeof(mVSConstants.projection));
}
const nsIntSize&
CompositorD3D11::GetWidgetSize()
{
nsIntRect rect;
mWidget->GetClientBounds(rect);
mSize = rect.Size();
return mSize;
}
void
CompositorD3D11::VerifyBufferSize()
{
nsIntRect rect;
mWidget->GetClientBounds(rect);
DXGI_SWAP_CHAIN_DESC swapDesc;
mSwapChain->GetDesc(&swapDesc);
if ((swapDesc.BufferDesc.Width == rect.width &&
swapDesc.BufferDesc.Height == rect.height) || rect.IsEmpty()) {
return;
}
mDefaultRT = nullptr;
if (gfxWindowsPlatform::IsOptimus()) {
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
DXGI_FORMAT_B8G8R8A8_UNORM,
0);
} else if (IsRunningInWindowsMetro()) {
mSwapChain->ResizeBuffers(2, rect.width, rect.height,
DXGI_FORMAT_B8G8R8A8_UNORM,
0);
} else {
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
}
}
void
CompositorD3D11::UpdateRenderTarget()
{
if (mDefaultRT) {
return;
}
HRESULT hr;
nsRefPtr<ID3D11Texture2D> backBuf;
hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
if (FAILED(hr)) {
return;
}
mDefaultRT = new CompositingRenderTargetD3D11(nullptr);
mDevice->CreateRenderTargetView(backBuf, NULL, byRef(mDefaultRT->mRTView));
}
bool
CompositorD3D11::CreateShaders()
{
HRESULT hr;
hr = mDevice->CreateVertexShader(LayerQuadVS, sizeof(LayerQuadVS), nullptr, byRef(mAttachments->mVSQuadShader[UNMASKED]));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreateVertexShader(LayerQuadMaskVS, sizeof(LayerQuadMaskVS), nullptr, byRef(mAttachments->mVSQuadShader[MASKED]));
if (FAILED(hr)) {
return false;
}
hr = mDevice->CreateVertexShader(LayerQuadMask3DVS, sizeof(LayerQuadMask3DVS), nullptr, byRef(mAttachments->mVSQuadShader[MASKED3D]));
if (FAILED(hr)) {
return false;
}
#define LOAD_PIXEL_SHADER(x) hr = mDevice->CreatePixelShader(x, sizeof(x), nullptr, byRef(mAttachments->m##x[UNMASKED])); \
if (FAILED(hr)) { \
return false; \
} \
hr = mDevice->CreatePixelShader(x##Mask, sizeof(x##Mask), nullptr, byRef(mAttachments->m##x[MASKED])); \
if (FAILED(hr)) { \
return false; \
}
LOAD_PIXEL_SHADER(SolidColorShader);
LOAD_PIXEL_SHADER(RGBShader);
LOAD_PIXEL_SHADER(RGBAShader);
LOAD_PIXEL_SHADER(YCbCrShader);
#undef LOAD_PIXEL_SHADER
hr = mDevice->CreatePixelShader(RGBAShaderMask3D, sizeof(RGBAShaderMask3D), nullptr, byRef(mAttachments->mRGBAShader[MASKED3D]));
if (FAILED(hr)) {
return false;
}
return true;
}
void
CompositorD3D11::UpdateConstantBuffers()
{
D3D11_MAPPED_SUBRESOURCE resource;
mContext->Map(mAttachments->mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
*(VertexShaderConstants*)resource.pData = mVSConstants;
mContext->Unmap(mAttachments->mVSConstantBuffer, 0);
mContext->Map(mAttachments->mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
*(PixelShaderConstants*)resource.pData = mPSConstants;
mContext->Unmap(mAttachments->mPSConstantBuffer, 0);
ID3D11Buffer *buffer = mAttachments->mVSConstantBuffer;
mContext->VSSetConstantBuffers(0, 1, &buffer);
buffer = mAttachments->mPSConstantBuffer;
mContext->PSSetConstantBuffers(0, 1, &buffer);
}
void
CompositorD3D11::SetSamplerForFilter(Filter aFilter)
{
ID3D11SamplerState *sampler;
switch (aFilter) {
case FILTER_LINEAR:
sampler = mAttachments->mLinearSamplerState;
break;
case FILTER_POINT:
sampler = mAttachments->mPointSamplerState;
break;
}
mContext->PSSetSamplers(0, 1, &sampler);
}
void
CompositorD3D11::PaintToTarget()
{
nsRefPtr<ID3D11Texture2D> backBuf;
mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
D3D11_TEXTURE2D_DESC bbDesc;
backBuf->GetDesc(&bbDesc);
CD3D11_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height);
softDesc.MipLevels = 1;
softDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
softDesc.Usage = D3D11_USAGE_STAGING;
softDesc.BindFlags = 0;
nsRefPtr<ID3D11Texture2D> readTexture;
HRESULT hr = mDevice->CreateTexture2D(&softDesc, NULL, getter_AddRefs(readTexture));
mContext->CopyResource(readTexture, backBuf);
D3D11_MAPPED_SUBRESOURCE map;
mContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &map);
nsRefPtr<gfxImageSurface> tmpSurface =
new gfxImageSurface((unsigned char*)map.pData,
gfxIntSize(bbDesc.Width, bbDesc.Height),
map.RowPitch,
gfxASurface::ImageFormatARGB32);
mTarget->SetSource(tmpSurface);
mTarget->SetOperator(gfxContext::OPERATOR_OVER);
mTarget->Paint();
mContext->Unmap(readTexture, 0);
}
}
}

Просмотреть файл

@ -0,0 +1,303 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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/. */
typedef float4 rect;
float4x4 mLayerTransform : register(vs, c0);
float4x4 mProjection : register(vs, c4);
float4 vRenderTargetOffset : register(vs, c8);
rect vTextureCoords : register(vs, c9);
rect vLayerQuad : register(vs, c10);
rect vMaskQuad : register(vs, c11);
float4 fLayerColor : register(ps, c0);
float fLayerOpacity : register(ps, c1);
sampler sSampler : register(ps, s0);
BlendState NoBlendDual
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = FALSE;
BlendEnable[1] = FALSE;
RenderTargetWriteMask[0] = 0x0F; // All
RenderTargetWriteMask[1] = 0x0F; // All
};
BlendState ComponentAlphaBlend
{
AlphaToCoverageEnable = FALSE;
BlendEnable[0] = TRUE;
SrcBlend = One;
DestBlend = Inv_Src1_Color;
BlendOp = Add;
SrcBlendAlpha = One;
DestBlendAlpha = Inv_Src_Alpha;
BlendOpAlpha = Add;
RenderTargetWriteMask[0] = 0x0F; // All
};
Texture2D tRGB;
Texture2D tY;
Texture2D tCb;
Texture2D tCr;
Texture2D tRGBWhite;
// Always bind this to slot 3 since this is always available!
Texture2D tMask : register(ps, t3);
struct VS_INPUT {
float2 vPosition : POSITION;
};
struct VS_OUTPUT {
float4 vPosition : SV_Position;
float2 vTexCoords : TEXCOORD0;
};
struct VS_MASK_OUTPUT {
float4 vPosition : SV_Position;
float2 vTexCoords : TEXCOORD0;
float2 vMaskCoords : TEXCOORD1;
};
struct VS_MASK_3D_OUTPUT {
float4 vPosition : SV_Position;
float2 vTexCoords : TEXCOORD0;
float3 vMaskCoords : TEXCOORD1;
};
struct PS_OUTPUT {
float4 vSrc;
float4 vAlpha;
};
struct PS_DUAL_OUTPUT {
float4 vOutput1 : SV_Target0;
float4 vOutput2 : SV_Target1;
};
float2 TexCoords(const float2 aPosition)
{
float2 result;
const float2 size = vTextureCoords.zw;
result.x = vTextureCoords.x + aPosition.x * size.x;
result.y = vTextureCoords.y + aPosition.y * size.y;
return result;
}
SamplerState LayerTextureSamplerLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};
float4 TransformedPosition(float2 aInPosition)
{
// the current vertex's position on the quad
float4 position = float4(0, 0, 0, 1);
// We use 4 component floats to uniquely describe a rectangle, by the structure
// of x, y, width, height. This allows us to easily generate the 4 corners
// of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the
// stream source for our LayerQuad vertex shader. We do this by doing:
// Xout = x + Xin * width
// Yout = y + Yin * height
float2 size = vLayerQuad.zw;
position.x = vLayerQuad.x + aInPosition.x * size.x;
position.y = vLayerQuad.y + aInPosition.y * size.y;
position = mul(mLayerTransform, position);
return position;
}
float4 VertexPosition(float4 aTransformedPosition)
{
float4 result;
result.w = aTransformedPosition.w;
result.xyz = aTransformedPosition.xyz / aTransformedPosition.w;
result -= vRenderTargetOffset;
result.xyz *= result.w;
result = mul(mProjection, result);
return result;
}
VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
{
VS_OUTPUT outp;
float4 position = TransformedPosition(aVertex.vPosition);
outp.vPosition = VertexPosition(position);
outp.vTexCoords = TexCoords(aVertex.vPosition.xy);
return outp;
}
VS_MASK_OUTPUT LayerQuadMaskVS(const VS_INPUT aVertex)
{
VS_MASK_OUTPUT outp;
float4 position = TransformedPosition(aVertex.vPosition);
outp.vPosition = VertexPosition(position);
// calculate the position on the mask texture
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
outp.vTexCoords = TexCoords(aVertex.vPosition.xy);
return outp;
}
VS_MASK_3D_OUTPUT LayerQuadMask3DVS(const VS_INPUT aVertex)
{
VS_MASK_3D_OUTPUT outp;
float4 position = TransformedPosition(aVertex.vPosition);
outp.vPosition = VertexPosition(position);
// calculate the position on the mask texture
position.xyz /= position.w;
outp.vMaskCoords.x = (position.x - vMaskQuad.x) / vMaskQuad.z;
outp.vMaskCoords.y = (position.y - vMaskQuad.y) / vMaskQuad.w;
// We use the w coord to do non-perspective correct interpolation:
// the quad might be transformed in 3D, in which case it will have some
// perspective. The graphics card will do perspective-correct interpolation
// of the texture, but our mask is already transformed and so we require
// linear interpolation. Therefore, we must correct the interpolation
// ourselves, we do this by multiplying all coords by w here, and dividing by
// w in the pixel shader (post-interpolation), we pass w in outp.vMaskCoords.z.
// See http://en.wikipedia.org/wiki/Texture_mapping#Perspective_correctness
outp.vMaskCoords.z = 1;
outp.vMaskCoords *= position.w;
outp.vTexCoords = TexCoords(aVertex.vPosition.xy);
return outp;
}
float4 RGBAShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords;
float mask = tMask.Sample(sSampler, maskCoords).a;
return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask;
}
float4 RGBAShaderMask3D(const VS_MASK_3D_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords.xy / aVertex.vMaskCoords.z;
float mask = tMask.Sample(LayerTextureSamplerLinear, maskCoords).a;
return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity * mask;
}
float4 RGBShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
float4 result;
result = tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity;
result.a = fLayerOpacity;
float2 maskCoords = aVertex.vMaskCoords;
float mask = tMask.Sample(sSampler, maskCoords).a;
return result * mask;
}
float4 CalculateYCbCrColor(const float2 aTexCoords)
{
float4 yuv;
float4 color;
yuv.r = tCr.Sample(sSampler, aTexCoords).r - 0.5;
yuv.g = tY.Sample(sSampler, aTexCoords).r - 0.0625;
yuv.b = tCb.Sample(sSampler, aTexCoords).r - 0.5;
color.r = yuv.g * 1.164 + yuv.r * 1.596;
color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b;
color.b = yuv.g * 1.164 + yuv.b * 2.018;
color.a = 1.0f;
return color;
}
float4 YCbCrShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords;
float mask = tMask.Sample(sSampler, maskCoords).a;
return CalculateYCbCrColor(aVertex.vTexCoords) * fLayerOpacity * mask;
}
PS_OUTPUT ComponentAlphaShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
PS_OUTPUT result;
result.vSrc = tRGB.Sample(sSampler, aVertex.vTexCoords);
result.vAlpha = 1.0 - tRGBWhite.Sample(sSampler, aVertex.vTexCoords) + result.vSrc;
result.vSrc.a = result.vAlpha.g;
float2 maskCoords = aVertex.vMaskCoords;
float mask = tMask.Sample(sSampler, maskCoords).a;
result.vSrc *= fLayerOpacity * mask;
result.vAlpha *= fLayerOpacity * mask;
return result;
}
float4 SolidColorShaderMask(const VS_MASK_OUTPUT aVertex) : SV_Target
{
float2 maskCoords = aVertex.vMaskCoords;
float mask = tMask.Sample(sSampler, maskCoords).a;
return fLayerColor * mask;
}
/*
* Un-masked versions
*************************************************************
*/
float4 RGBAShader(const VS_OUTPUT aVertex) : SV_Target
{
return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity;
}
float4 RGBShader(const VS_OUTPUT aVertex) : SV_Target
{
float4 result;
result = tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity;
result.a = fLayerOpacity;
return result;
}
float4 YCbCrShader(const VS_OUTPUT aVertex) : SV_Target
{
return CalculateYCbCrColor(aVertex.vTexCoords) * fLayerOpacity;
}
PS_OUTPUT ComponentAlphaShader(const VS_OUTPUT aVertex) : SV_Target
{
PS_OUTPUT result;
result.vSrc = tRGB.Sample(sSampler, aVertex.vTexCoords);
result.vAlpha = 1.0 - tRGBWhite.Sample(sSampler, aVertex.vTexCoords) + result.vSrc;
result.vSrc.a = result.vAlpha.g;
result.vSrc *= fLayerOpacity;
result.vAlpha *= fLayerOpacity;
return result;
}
float4 SolidColorShader(const VS_OUTPUT aVertex) : SV_Target
{
return fLayerColor;
}
PS_DUAL_OUTPUT AlphaExtractionPrepareShader(const VS_OUTPUT aVertex)
{
PS_DUAL_OUTPUT result;
result.vOutput1 = float4(0, 0, 0, 1);
result.vOutput2 = float4(1, 1, 1, 1);
return result;
}

Просмотреть файл

@ -0,0 +1,174 @@
/* -*- 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_COMPOSITORD3D11_H
#define MOZILLA_GFX_COMPOSITORD3D11_H
#include "mozilla/layers/Compositor.h"
#include "TextureD3D11.h"
#include <d3d11.h>
class nsWidget;
namespace mozilla {
namespace layers {
#define LOGD3D11(param)
struct VertexShaderConstants
{
float layerTransform[4][4];
float projection[4][4];
float renderTargetOffset[4];
gfx::Rect textureCoords;
gfx::Rect layerQuad;
gfx::Rect maskQuad;
};
struct PixelShaderConstants
{
float layerColor[4];
float layerOpacity[4];
};
struct DeviceAttachmentsD3D11;
class CompositorD3D11 : public Compositor
{
public:
CompositorD3D11(nsIWidget *aWidget);
~CompositorD3D11();
virtual bool Initialize();
virtual void Destroy() { }
virtual TextureFactoryIdentifier
GetTextureFactoryIdentifier() MOZ_OVERRIDE;
virtual bool CanUseCanvasLayerForSize(const gfxIntSize &aSize) MOZ_OVERRIDE;
virtual int32_t GetMaxTextureSize() const MOZ_FINAL;
virtual void SetTargetContext(gfxContext *aTarget) { mTarget = aTarget; }
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) { }
virtual TemporaryRef<CompositingRenderTarget>
CreateRenderTarget(const gfx::IntRect &aRect,
SurfaceInitMode aInit) MOZ_OVERRIDE;
virtual TemporaryRef<CompositingRenderTarget>
CreateRenderTargetFromSource(const gfx::IntRect &aRect,
const CompositingRenderTarget *aSource) MOZ_OVERRIDE;
virtual void SetRenderTarget(CompositingRenderTarget *aSurface) MOZ_OVERRIDE;
virtual CompositingRenderTarget* GetCurrentRenderTarget() MOZ_OVERRIDE
{
return mCurrentRT;
}
virtual void SetDestinationSurfaceSize(const gfx::IntSize& aSize) MOZ_OVERRIDE { }
/**
* Declare an offset to use when rendering layers. This will be ignored when
* rendering to a target instead of the screen.
*/
virtual void SetScreenRenderOffset(const gfx::Point& aOffset) MOZ_OVERRIDE {
if (aOffset.x || aOffset.y) {
NS_RUNTIMEABORT("SetScreenRenderOffset not supported by CompositorD3D11.");
}
// If the offset is 0, 0 that's okay.
}
virtual void DrawQuad(const gfx::Rect &aRect, const gfx::Rect &aClipRect,
const EffectChain &aEffectChain,
gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform,
const gfx::Point &aOffset) MOZ_OVERRIDE;
/**
* Start a new frame. If aClipRectIn is null, sets *aClipRectOut to the screen dimensions.
*/
virtual void BeginFrame(const gfx::Rect *aClipRectIn,
const gfxMatrix& aTransform,
const gfx::Rect& aRenderBounds,
gfx::Rect *aClipRectOut = nullptr,
gfx::Rect *aRenderBoundsOut = nullptr) MOZ_OVERRIDE;
/**
* Flush the current frame to the screen.
*/
virtual void EndFrame() MOZ_OVERRIDE;
/**
* Post rendering stuff if the rendering is outside of this Compositor
* e.g., by Composer2D
*/
virtual void EndFrameForExternalComposition(const gfxMatrix& aTransform) MOZ_OVERRIDE { }
/**
* Tidy up if BeginFrame has been called, but EndFrame won't be
*/
virtual void AbortFrame() MOZ_OVERRIDE { }
/**
* Setup the viewport and projection matrix for rendering
* to a window of the given dimensions.
*/
virtual void PrepareViewport(const gfx::IntSize& aSize,
const gfxMatrix& aWorldTransform) MOZ_OVERRIDE;
virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE { return true; }
#ifdef MOZ_DUMP_PAINTING
virtual const char* Name() const MOZ_OVERRIDE { return "Direct3D 11"; }
#endif
virtual void NotifyLayersTransaction() MOZ_OVERRIDE { }
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
virtual const nsIntSize& GetWidgetSize() MOZ_OVERRIDE;
ID3D11Device *GetDevice() { return mDevice; }
private:
enum MaskMode {
UNMASKED = 0,
MASKED = 1,
MASKED3D
};
void VerifyBufferSize();
void UpdateRenderTarget();
bool CreateShaders();
void UpdateConstantBuffers();
void SetSamplerForFilter(gfx::Filter aFilter);
void SetPSForEffect(Effect *aEffect, MaskMode aMaskMode);
void PaintToTarget();
RefPtr<ID3D11DeviceContext> mContext;
RefPtr<ID3D11Device> mDevice;
RefPtr<IDXGISwapChain> mSwapChain;
RefPtr<CompositingRenderTargetD3D11> mDefaultRT;
RefPtr<CompositingRenderTargetD3D11> mCurrentRT;
DeviceAttachmentsD3D11 *mAttachments;
nsRefPtr<gfxContext> mTarget;
nsIWidget *mWidget;
// XXX - Bas - wth?
nsIntSize mSize;
HWND mHwnd;
D3D_FEATURE_LEVEL mFeatureLevel;
VertexShaderConstants mVSConstants;
PixelShaderConstants mPSConstants;
};
}
}
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,487 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 "TextureD3D11.h"
#include "CompositorD3D11.h"
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "Effects.h"
#include "ipc/AutoOpenSurface.h"
#include "ShmemYCbCrImage.h"
#include "gfxWindowsPlatform.h"
#include "gfxD2DSurface.h"
namespace mozilla {
using namespace gfx;
namespace layers {
TemporaryRef<TextureHost>
CreateTextureHostD3D11(SurfaceDescriptorType aDescriptorType,
uint32_t aTextureHostFlags,
uint32_t aTextureFlags)
{
RefPtr<TextureHost> result;
if (aDescriptorType == SurfaceDescriptor::TYCbCrImage) {
result = new TextureHostYCbCrD3D11();
} else if (aDescriptorType == SurfaceDescriptor::TSurfaceDescriptorD3D10) {
result = new TextureHostDXGID3D11();
} else {
result = new TextureHostShmemD3D11();
}
result->SetFlags(aTextureFlags);
return result.forget();
}
CompositingRenderTargetD3D11::CompositingRenderTargetD3D11(ID3D11Texture2D *aTexture)
{
if (!aTexture) {
return;
}
mTextures[0] = aTexture;
RefPtr<ID3D11Device> device;
mTextures[0]->GetDevice(byRef(device));
HRESULT hr = device->CreateRenderTargetView(mTextures[0], NULL, byRef(mRTView));
if (FAILED(hr)) {
LOGD3D11("Failed to create RenderTargetView.");
}
}
IntSize
CompositingRenderTargetD3D11::GetSize() const
{
return TextureSourceD3D11::GetSize();
}
TextureClientD3D11::TextureClientD3D11(CompositableForwarder* aCompositableForwarder, const TextureInfo& aTextureInfo)
: TextureClient(aCompositableForwarder, aTextureInfo)
, mIsLocked(false)
{
mTextureInfo = aTextureInfo;
}
TextureClientD3D11::~TextureClientD3D11()
{
mDescriptor = SurfaceDescriptor();
ClearDT();
}
void
TextureClientD3D11::EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType)
{
D3D10_TEXTURE2D_DESC desc;
if (mTexture) {
mTexture->GetDesc(&desc);
if (desc.Width == aSize.width || desc.Height == aSize.height) {
return;
}
mTexture = nullptr;
mSurface = nullptr;
ClearDT();
}
mSize = aSize;
ID3D10Device *device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
aSize.width, aSize.height, 1, 1,
D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture));
if (FAILED(hr)) {
LOGD3D11("Error creating texture for client!");
return;
}
RefPtr<IDXGIResource> resource;
mTexture->QueryInterface((IDXGIResource**)byRef(resource));
HANDLE sharedHandle;
hr = resource->GetSharedHandle(&sharedHandle);
if (FAILED(hr)) {
LOGD3D11("Error getting shared handle for texture.");
}
mDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, aType == gfxASurface::CONTENT_COLOR_ALPHA);
mContentType = aType;
}
gfxASurface*
TextureClientD3D11::LockSurface()
{
EnsureSurface();
LockTexture();
return mSurface.get();
}
DrawTarget*
TextureClientD3D11::LockDrawTarget()
{
EnsureDrawTarget();
LockTexture();
return mDrawTarget.get();
}
void
TextureClientD3D11::Unlock()
{
// TODO - Things seem to believe they can hold on to our surface... well...
// They shouldn't!!
ReleaseTexture();
}
void
TextureClientD3D11::SetDescriptor(const SurfaceDescriptor& aDescriptor)
{
if (aDescriptor.type() == SurfaceDescriptor::Tnull_t) {
EnsureAllocated(mSize, mContentType);
return;
}
mDescriptor = aDescriptor;
mSurface = nullptr;
ClearDT();
if (aDescriptor.type() == SurfaceDescriptor::T__None) {
return;
}
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorD3D10);
ID3D10Device *device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
device->OpenSharedResource((HANDLE)aDescriptor.get_SurfaceDescriptorD3D10().handle(),
__uuidof(ID3D10Texture2D),
(void**)(ID3D10Texture2D**)byRef(mTexture));
}
void
TextureClientD3D11::EnsureSurface()
{
if (mSurface) {
return;
}
LockTexture();
mSurface = new gfxD2DSurface(mTexture, mContentType);
ReleaseTexture();
}
void
TextureClientD3D11::EnsureDrawTarget()
{
if (mDrawTarget) {
return;
}
LockTexture();
SurfaceFormat format;
switch (mContentType) {
case gfxASurface::CONTENT_ALPHA:
format = FORMAT_A8;
break;
case gfxASurface::CONTENT_COLOR:
format = FORMAT_B8G8R8X8;
break;
case gfxASurface::CONTENT_COLOR_ALPHA:
format = FORMAT_B8G8R8A8;
break;
default:
format = FORMAT_B8G8R8A8;
}
mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, format);
ReleaseTexture();
}
void
TextureClientD3D11::LockTexture()
{
RefPtr<IDXGIKeyedMutex> mutex;
mTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
mutex->AcquireSync(0, INFINITE);
mIsLocked = true;
}
void
TextureClientD3D11::ReleaseTexture()
{
// TODO - Bas - We seem to have places that unlock without ever having locked,
// that's kind of bad.
if (!mIsLocked) {
return;
}
if (mDrawTarget) {
mDrawTarget->Flush();
}
RefPtr<IDXGIKeyedMutex> mutex;
mTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
mutex->ReleaseSync(0);
mIsLocked = false;
}
void
TextureClientD3D11::ClearDT()
{
// An Azure DrawTarget needs to be locked when it gets NULL'ed as this is
// when it calls EndDraw. This EndDraw should not execute anything so it
// shouldn't -really- need the lock but the debug layer chokes on this.
//
// Perhaps this should be debug only.
if (mDrawTarget) {
LockTexture();
mDrawTarget = nullptr;
ReleaseTexture();
}
}
IntSize
TextureHostShmemD3D11::GetSize() const
{
if (mIterating) {
gfx::IntRect rect = GetTileRect(mCurrentTile);
return gfx::IntSize(rect.width, rect.height);
}
return TextureSourceD3D11::GetSize();
}
nsIntRect
TextureHostShmemD3D11::GetTileRect()
{
IntRect rect = GetTileRect(mCurrentTile);
return nsIntRect(rect.x, rect.y, rect.width, rect.height);
}
static uint32_t GetRequiredTiles(uint32_t aSize, uint32_t aMaxSize)
{
uint32_t requiredTiles = aSize / aMaxSize;
if (aSize % aMaxSize) {
requiredTiles++;
}
return requiredTiles;
}
void
TextureHostShmemD3D11::SetCompositor(Compositor* aCompositor)
{
CompositorD3D11 *d3dCompositor = static_cast<CompositorD3D11*>(aCompositor);
mDevice = d3dCompositor ? d3dCompositor->GetDevice() : nullptr;
}
void
TextureHostShmemD3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion *aRegion)
{
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TShmem);
AutoOpenSurface openSurf(OPEN_READ_ONLY, aImage);
nsRefPtr<gfxImageSurface> surf = openSurf.GetAsImage();
gfxIntSize size = surf->GetSize();
uint32_t bpp = 0;
DXGI_FORMAT dxgiFormat;
switch (surf->Format()) {
case gfxImageSurface::ImageFormatRGB24:
mFormat = FORMAT_B8G8R8X8;
dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
bpp = 4;
break;
case gfxImageSurface::ImageFormatARGB32:
mFormat = FORMAT_B8G8R8A8;
dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
bpp = 4;
break;
case gfxImageSurface::ImageFormatA8:
mFormat = FORMAT_A8;
dxgiFormat = DXGI_FORMAT_A8_UNORM;
bpp = 1;
break;
}
mSize = IntSize(size.width, size.height);
CD3D11_TEXTURE2D_DESC desc(dxgiFormat, size.width, size.height,
1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_IMMUTABLE);
int32_t maxSize = GetMaxTextureSizeForFeatureLevel(mDevice->GetFeatureLevel());
if (size.width <= maxSize && size.height <= maxSize) {
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = surf->Data();
initData.SysMemPitch = surf->Stride();
mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[0]));
mIsTiled = false;
} else {
mIsTiled = true;
uint32_t tileCount = GetRequiredTiles(size.width, maxSize) *
GetRequiredTiles(size.height, maxSize);
mTileTextures.resize(tileCount);
for (uint32_t i = 0; i < tileCount; i++) {
IntRect tileRect = GetTileRect(i);
desc.Width = tileRect.width;
desc.Height = tileRect.height;
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = surf->Data() + tileRect.y * surf->Stride() + tileRect.x * bpp;
initData.SysMemPitch = surf->Stride();
mDevice->CreateTexture2D(&desc, &initData, byRef(mTileTextures[i]));
}
}
}
IntRect
TextureHostShmemD3D11::GetTileRect(uint32_t aID) const
{
uint32_t maxSize = GetMaxTextureSizeForFeatureLevel(mDevice->GetFeatureLevel());
uint32_t horizontalTiles = GetRequiredTiles(mSize.width, maxSize);
uint32_t verticalTiles = GetRequiredTiles(mSize.height, maxSize);
uint32_t verticalTile = aID / horizontalTiles;
uint32_t horizontalTile = aID % horizontalTiles;
return IntRect(horizontalTile * maxSize,
verticalTile * maxSize,
horizontalTile < (horizontalTiles - 1) ? maxSize : mSize.width % maxSize,
verticalTile < (verticalTiles - 1) ? maxSize : mSize.height % maxSize);
}
void
TextureHostDXGID3D11::SetCompositor(Compositor* aCompositor)
{
CompositorD3D11 *d3dCompositor = static_cast<CompositorD3D11*>(aCompositor);
mDevice = d3dCompositor ? d3dCompositor->GetDevice() : nullptr;
}
IntSize
TextureHostDXGID3D11::GetSize() const
{
return TextureSourceD3D11::GetSize();
}
bool
TextureHostDXGID3D11::Lock()
{
LockTexture();
return true;
}
void
TextureHostDXGID3D11::Unlock()
{
ReleaseTexture();
}
void
TextureHostDXGID3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion *aRegion)
{
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorD3D10);
mDevice->OpenSharedResource((HANDLE)aImage.get_SurfaceDescriptorD3D10().handle(),
__uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)byRef(mTextures[0]));
mFormat = aImage.get_SurfaceDescriptorD3D10().hasAlpha() ? FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8;
D3D11_TEXTURE2D_DESC desc;
mTextures[0]->GetDesc(&desc);
mSize = IntSize(desc.Width, desc.Height);
}
void
TextureHostDXGID3D11::LockTexture()
{
RefPtr<IDXGIKeyedMutex> mutex;
mTextures[0]->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
mutex->AcquireSync(0, INFINITE);
}
void
TextureHostDXGID3D11::ReleaseTexture()
{
RefPtr<IDXGIKeyedMutex> mutex;
mTextures[0]->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
mutex->ReleaseSync(0);
}
void
TextureHostYCbCrD3D11::SetCompositor(Compositor* aCompositor)
{
CompositorD3D11 *d3dCompositor = static_cast<CompositorD3D11*>(aCompositor);
mDevice = d3dCompositor ? d3dCompositor->GetDevice() : nullptr;
}
IntSize
TextureHostYCbCrD3D11::GetSize() const
{
return TextureSourceD3D11::GetSize();
}
void
TextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion *aRegion)
{
MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
ShmemYCbCrImage shmemImage(aImage.get_YCbCrImage().data(),
aImage.get_YCbCrImage().offset());
gfxIntSize gfxCbCrSize = shmemImage.GetCbCrSize();
gfxIntSize size = shmemImage.GetYSize();
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = shmemImage.GetYData();
initData.SysMemPitch = shmemImage.GetYStride();
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8_UNORM, size.width, size.height,
1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_IMMUTABLE);
mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[0]));
initData.pSysMem = shmemImage.GetCbData();
initData.SysMemPitch = shmemImage.GetCbCrStride();
desc.Width = shmemImage.GetCbCrSize().width;
desc.Height = shmemImage.GetCbCrSize().height;
mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[1]));
initData.pSysMem = shmemImage.GetCrData();
mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[2]));
mSize = IntSize(size.width, size.height);
}
}
}

Просмотреть файл

@ -0,0 +1,246 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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_TEXTURED3D11_H
#define MOZILLA_GFX_TEXTURED3D11_H
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/TextureClient.h"
#include <d3d11.h>
#include <vector>
class gfxD2DSurface;
namespace mozilla {
namespace layers {
class TextureSourceD3D11
{
public:
TextureSourceD3D11()
{ }
virtual ID3D11Texture2D *GetD3D11Texture() { return mTextures[0]; }
virtual bool IsYCbCrSource() const { return false; }
struct YCbCrTextures
{
ID3D11Texture2D *mY;
ID3D11Texture2D *mCb;
ID3D11Texture2D *mCr;
};
virtual YCbCrTextures GetYCbCrTextures() {
YCbCrTextures textures = { mTextures[0], mTextures[1], mTextures[2] };
return textures;
}
protected:
virtual gfx::IntSize GetSize() const { return mSize; }
gfx::IntSize mSize;
RefPtr<ID3D11Texture2D> mTextures[3];
};
class CompositingRenderTargetD3D11 : public CompositingRenderTarget,
public TextureSourceD3D11
{
public:
// Use aTexture == nullptr for rendering to the window
CompositingRenderTargetD3D11(ID3D11Texture2D *aTexture);
virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE { return this; }
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
void SetSize(const gfx::IntSize& aSize) { mSize = aSize; }
private:
friend class CompositorD3D11;
RefPtr<ID3D11RenderTargetView> mRTView;
};
class TextureClientD3D11 : public TextureClient
{
public:
TextureClientD3D11(CompositableForwarder* aCompositableForwarder, const TextureInfo& aTextureInfo);
~TextureClientD3D11();
virtual bool SupportsType(TextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_CONTENT; }
virtual void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType) MOZ_OVERRIDE;
virtual gfxASurface* LockSurface() MOZ_OVERRIDE;
virtual gfx::DrawTarget* LockDrawTarget() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual void SetDescriptor(const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
virtual gfxASurface::gfxContentType GetContentType() MOZ_OVERRIDE { return mContentType; }
private:
void EnsureSurface();
void EnsureDrawTarget();
void LockTexture();
void ReleaseTexture();
void ClearDT();
RefPtr<ID3D10Texture2D> mTexture;
nsRefPtr<gfxD2DSurface> mSurface;
RefPtr<gfx::DrawTarget> mDrawTarget;
gfx::IntSize mSize;
bool mIsLocked;
gfxContentType mContentType;
};
class TextureHostShmemD3D11 : public TextureHost
, public TextureSourceD3D11
, public TileIterator
{
public:
TextureHostShmemD3D11()
: mDevice(nullptr)
, mIsTiled(false)
, mCurrentTile(0)
, mIterating(false)
{
}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE { return this; }
virtual ID3D11Texture2D *GetD3D11Texture() MOZ_OVERRIDE {
return mIsTiled ? mTileTextures[mCurrentTile] : TextureSourceD3D11::GetD3D11Texture();
}
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
virtual bool Lock() MOZ_OVERRIDE { return true; }
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() { return "TextureHostShmemD3D11"; }
#endif
virtual void BeginTileIteration() MOZ_OVERRIDE {
mIterating = true;
mCurrentTile = 0;
}
virtual void EndTileIteration() MOZ_OVERRIDE {
mIterating = false;
}
virtual nsIntRect GetTileRect() MOZ_OVERRIDE;
virtual size_t GetTileCount() MOZ_OVERRIDE { return mTileTextures.size(); }
virtual bool NextTile() MOZ_OVERRIDE {
return (++mCurrentTile < mTileTextures.size());
}
virtual TileIterator* AsTileIterator() MOZ_OVERRIDE {
return mIsTiled ? this : nullptr;
}
protected:
virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
nsIntRegion* aRegion) MOZ_OVERRIDE;
private:
gfx::IntRect GetTileRect(uint32_t aID) const;
RefPtr<ID3D11Device> mDevice;
bool mIsTiled;
std::vector< RefPtr<ID3D11Texture2D> > mTileTextures;
uint32_t mCurrentTile;
bool mIterating;
};
class TextureHostDXGID3D11 : public TextureHost
, public TextureSourceD3D11
{
public:
TextureHostDXGID3D11()
: mDevice(nullptr)
{
}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE { return this; }
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
virtual bool Lock() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() { return "TextureHostDXGID3D11"; }
#endif
protected:
virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
nsIntRegion* aRegion) MOZ_OVERRIDE;
private:
void LockTexture();
void ReleaseTexture();
gfx::IntRect GetTileRect(uint32_t aID) const; // TODO[Bas] not defined anywhere?
RefPtr<ID3D11Device> mDevice;
};
class TextureHostYCbCrD3D11 : public TextureHost
, public TextureSourceD3D11
{
public:
TextureHostYCbCrD3D11()
: mDevice(nullptr)
{
mFormat = gfx::FORMAT_YUV;
}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual TextureSourceD3D11* AsSourceD3D11() MOZ_OVERRIDE { return this; }
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
virtual bool IsYCbCrSource() const MOZ_OVERRIDE { return true; }
#ifdef MOZ_LAYERS_HAVE_LOG
virtual const char* Name() MOZ_OVERRIDE { return "TextureImageTextureHostD3D11"; }
#endif
protected:
virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
nsIntRegion* aRegion) MOZ_OVERRIDE;
private:
RefPtr<ID3D11Device> mDevice;
};
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)
{
int32_t maxTextureSize;
switch (aFeatureLevel) {
case D3D_FEATURE_LEVEL_11_1:
case D3D_FEATURE_LEVEL_11_0:
maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
break;
case D3D_FEATURE_LEVEL_10_1:
case D3D_FEATURE_LEVEL_10_0:
maxTextureSize = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
break;
case D3D_FEATURE_LEVEL_9_3:
maxTextureSize = D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
break;
default:
maxTextureSize = D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
}
return maxTextureSize;
}
}
}
#endif /* MOZILLA_GFX_TEXTURED3D11_H */

Просмотреть файл

@ -0,0 +1,30 @@
# 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/.
tempfile=tmpShaderHeader
rm CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ELayerQuadVS -nologo -Tvs_4_0_level_9_3 -Fh$tempfile -VnLayerQuadVS
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ESolidColorShader -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnSolidColorShader
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ERGBShader -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnRGBShader
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ERGBAShader -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnRGBAShader
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -EYCbCrShader -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnYCbCrShader
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ELayerQuadMaskVS -nologo -Tvs_4_0_level_9_3 -Fh$tempfile -VnLayerQuadMaskVS
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ELayerQuadMask3DVS -nologo -Tvs_4_0_level_9_3 -Fh$tempfile -VnLayerQuadMask3DVS
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ESolidColorShaderMask -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnSolidColorShaderMask
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ERGBShaderMask -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnRGBShaderMask
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ERGBAShaderMask -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnRGBAShaderMask
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -ERGBAShaderMask3D -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnRGBAShaderMask3D
cat $tempfile >> CompositorD3D11Shaders.h
fxc CompositorD3D11.fx -EYCbCrShaderMask -Tps_4_0_level_9_3 -nologo -Fh$tempfile -VnYCbCrShaderMask
cat $tempfile >> CompositorD3D11Shaders.h

Просмотреть файл

@ -13,6 +13,9 @@
#include "CompositorParent.h"
#include "mozilla/layers/CompositorOGL.h"
#include "mozilla/layers/BasicCompositor.h"
#ifdef XP_WIN
#include "mozilla/layers/CompositorD3D11.h"
#endif
#include "LayerTransactionParent.h"
#include "nsIWidget.h"
#include "nsGkAtoms.h"
@ -568,6 +571,11 @@ CompositorParent::AllocPLayerTransaction(const LayersBackend& aBackendHint,
} else if (aBackendHint == mozilla::layers::LAYERS_BASIC) {
mLayerManager =
new LayerManagerComposite(new BasicCompositor(mWidget));
#ifdef XP_WIN
} else if (aBackendHint == mozilla::layers::LAYERS_D3D11) {
mLayerManager =
new LayerManagerComposite(new CompositorD3D11(mWidget));
#endif
} else {
NS_ERROR("Unsupported backend selected for Async Compositor");
return nullptr;

Просмотреть файл

@ -56,7 +56,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'ReadbackManagerD3D10.h',
]
EXPORTS.mozilla.layers += [
'CompositorD3D11.h',
'ShadowLayerUtilsD3D10.h',
'TextureD3D11.h',
]
EXPORTS.gfxipc += [