gfx/layers/d3d11/CompositorD3D11.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "CompositorD3D11.h"
michael@0 7
michael@0 8 #include "TextureD3D11.h"
michael@0 9 #include "CompositorD3D11Shaders.h"
michael@0 10
michael@0 11 #include "gfxWindowsPlatform.h"
michael@0 12 #include "nsIWidget.h"
michael@0 13 #include "mozilla/layers/ImageHost.h"
michael@0 14 #include "mozilla/layers/ContentHost.h"
michael@0 15 #include "mozilla/layers/Effects.h"
michael@0 16 #include "nsWindowsHelpers.h"
michael@0 17 #include "gfxPrefs.h"
michael@0 18
michael@0 19 #ifdef MOZ_METRO
michael@0 20 #include <DXGI1_2.h>
michael@0 21 #endif
michael@0 22
michael@0 23 namespace mozilla {
michael@0 24
michael@0 25 using namespace gfx;
michael@0 26
michael@0 27 namespace layers {
michael@0 28
michael@0 29 struct Vertex
michael@0 30 {
michael@0 31 float position[2];
michael@0 32 };
michael@0 33
michael@0 34 // {1E4D7BEB-D8EC-4A0B-BF0A-63E6DE129425}
michael@0 35 static const GUID sDeviceAttachmentsD3D11 =
michael@0 36 { 0x1e4d7beb, 0xd8ec, 0x4a0b, { 0xbf, 0xa, 0x63, 0xe6, 0xde, 0x12, 0x94, 0x25 } };
michael@0 37 // {88041664-C835-4AA8-ACB8-7EC832357ED8}
michael@0 38 static const GUID sLayerManagerCount =
michael@0 39 { 0x88041664, 0xc835, 0x4aa8, { 0xac, 0xb8, 0x7e, 0xc8, 0x32, 0x35, 0x7e, 0xd8 } };
michael@0 40
michael@0 41 const FLOAT sBlendFactor[] = { 0, 0, 0, 0 };
michael@0 42
michael@0 43 struct DeviceAttachmentsD3D11
michael@0 44 {
michael@0 45 RefPtr<ID3D11InputLayout> mInputLayout;
michael@0 46 RefPtr<ID3D11Buffer> mVertexBuffer;
michael@0 47 RefPtr<ID3D11VertexShader> mVSQuadShader[3];
michael@0 48 RefPtr<ID3D11PixelShader> mSolidColorShader[2];
michael@0 49 RefPtr<ID3D11PixelShader> mRGBAShader[3];
michael@0 50 RefPtr<ID3D11PixelShader> mRGBShader[2];
michael@0 51 RefPtr<ID3D11PixelShader> mYCbCrShader[2];
michael@0 52 RefPtr<ID3D11PixelShader> mComponentAlphaShader[2];
michael@0 53 RefPtr<ID3D11Buffer> mPSConstantBuffer;
michael@0 54 RefPtr<ID3D11Buffer> mVSConstantBuffer;
michael@0 55 RefPtr<ID3D11RasterizerState> mRasterizerState;
michael@0 56 RefPtr<ID3D11SamplerState> mLinearSamplerState;
michael@0 57 RefPtr<ID3D11SamplerState> mPointSamplerState;
michael@0 58 RefPtr<ID3D11BlendState> mPremulBlendState;
michael@0 59 RefPtr<ID3D11BlendState> mNonPremulBlendState;
michael@0 60 RefPtr<ID3D11BlendState> mComponentBlendState;
michael@0 61 RefPtr<ID3D11BlendState> mDisabledBlendState;
michael@0 62 };
michael@0 63
michael@0 64 CompositorD3D11::CompositorD3D11(nsIWidget* aWidget)
michael@0 65 : mAttachments(nullptr)
michael@0 66 , mWidget(aWidget)
michael@0 67 , mHwnd(nullptr)
michael@0 68 , mDisableSequenceForNextFrame(false)
michael@0 69 {
michael@0 70 SetBackend(LayersBackend::LAYERS_D3D11);
michael@0 71 }
michael@0 72
michael@0 73 CompositorD3D11::~CompositorD3D11()
michael@0 74 {
michael@0 75 if (mDevice) {
michael@0 76 int referenceCount = 0;
michael@0 77 UINT size = sizeof(referenceCount);
michael@0 78 HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
michael@0 79 NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device.");
michael@0 80 referenceCount--;
michael@0 81 mDevice->SetPrivateData(sLayerManagerCount,
michael@0 82 sizeof(referenceCount),
michael@0 83 &referenceCount);
michael@0 84
michael@0 85 if (!referenceCount) {
michael@0 86 DeviceAttachmentsD3D11 *attachments;
michael@0 87 size = sizeof(attachments);
michael@0 88 mDevice->GetPrivateData(sDeviceAttachmentsD3D11, &size, &attachments);
michael@0 89 // No LayerManagers left for this device. Clear out interfaces stored
michael@0 90 // which hold a reference to the device.
michael@0 91 mDevice->SetPrivateData(sDeviceAttachmentsD3D11, 0, nullptr);
michael@0 92
michael@0 93 delete attachments;
michael@0 94 }
michael@0 95 }
michael@0 96 }
michael@0 97
michael@0 98 bool
michael@0 99 CompositorD3D11::Initialize()
michael@0 100 {
michael@0 101 HRESULT hr;
michael@0 102
michael@0 103 mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
michael@0 104
michael@0 105 if (!mDevice) {
michael@0 106 return false;
michael@0 107 }
michael@0 108
michael@0 109 mDevice->GetImmediateContext(byRef(mContext));
michael@0 110
michael@0 111 if (!mContext) {
michael@0 112 return false;
michael@0 113 }
michael@0 114
michael@0 115 mHwnd = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
michael@0 116
michael@0 117 memset(&mVSConstants, 0, sizeof(VertexShaderConstants));
michael@0 118
michael@0 119 int referenceCount = 0;
michael@0 120 UINT size = sizeof(referenceCount);
michael@0 121 // If this isn't there yet it'll fail, count will remain 0, which is correct.
michael@0 122 mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
michael@0 123 referenceCount++;
michael@0 124 mDevice->SetPrivateData(sLayerManagerCount,
michael@0 125 sizeof(referenceCount),
michael@0 126 &referenceCount);
michael@0 127
michael@0 128 size = sizeof(DeviceAttachmentsD3D11*);
michael@0 129 if (FAILED(mDevice->GetPrivateData(sDeviceAttachmentsD3D11,
michael@0 130 &size,
michael@0 131 &mAttachments))) {
michael@0 132 mAttachments = new DeviceAttachmentsD3D11;
michael@0 133 mDevice->SetPrivateData(sDeviceAttachmentsD3D11,
michael@0 134 sizeof(mAttachments),
michael@0 135 &mAttachments);
michael@0 136
michael@0 137 D3D11_INPUT_ELEMENT_DESC layout[] =
michael@0 138 {
michael@0 139 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
michael@0 140 };
michael@0 141
michael@0 142 hr = mDevice->CreateInputLayout(layout,
michael@0 143 sizeof(layout) / sizeof(D3D11_INPUT_ELEMENT_DESC),
michael@0 144 LayerQuadVS,
michael@0 145 sizeof(LayerQuadVS),
michael@0 146 byRef(mAttachments->mInputLayout));
michael@0 147
michael@0 148 if (FAILED(hr)) {
michael@0 149 return false;
michael@0 150 }
michael@0 151
michael@0 152 Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
michael@0 153 CD3D11_BUFFER_DESC bufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER);
michael@0 154 D3D11_SUBRESOURCE_DATA data;
michael@0 155 data.pSysMem = (void*)vertices;
michael@0 156
michael@0 157 hr = mDevice->CreateBuffer(&bufferDesc, &data, byRef(mAttachments->mVertexBuffer));
michael@0 158
michael@0 159 if (FAILED(hr)) {
michael@0 160 return false;
michael@0 161 }
michael@0 162
michael@0 163 if (!CreateShaders()) {
michael@0 164 return false;
michael@0 165 }
michael@0 166
michael@0 167 CD3D11_BUFFER_DESC cBufferDesc(sizeof(VertexShaderConstants),
michael@0 168 D3D11_BIND_CONSTANT_BUFFER,
michael@0 169 D3D11_USAGE_DYNAMIC,
michael@0 170 D3D11_CPU_ACCESS_WRITE);
michael@0 171
michael@0 172 hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mVSConstantBuffer));
michael@0 173 if (FAILED(hr)) {
michael@0 174 return false;
michael@0 175 }
michael@0 176
michael@0 177 cBufferDesc.ByteWidth = sizeof(PixelShaderConstants);
michael@0 178 hr = mDevice->CreateBuffer(&cBufferDesc, nullptr, byRef(mAttachments->mPSConstantBuffer));
michael@0 179 if (FAILED(hr)) {
michael@0 180 return false;
michael@0 181 }
michael@0 182
michael@0 183 CD3D11_RASTERIZER_DESC rastDesc(D3D11_DEFAULT);
michael@0 184 rastDesc.CullMode = D3D11_CULL_NONE;
michael@0 185 rastDesc.ScissorEnable = TRUE;
michael@0 186
michael@0 187 hr = mDevice->CreateRasterizerState(&rastDesc, byRef(mAttachments->mRasterizerState));
michael@0 188 if (FAILED(hr)) {
michael@0 189 return false;
michael@0 190 }
michael@0 191
michael@0 192 CD3D11_SAMPLER_DESC samplerDesc(D3D11_DEFAULT);
michael@0 193 samplerDesc.AddressU = samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
michael@0 194 hr = mDevice->CreateSamplerState(&samplerDesc, byRef(mAttachments->mLinearSamplerState));
michael@0 195 if (FAILED(hr)) {
michael@0 196 return false;
michael@0 197 }
michael@0 198
michael@0 199 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
michael@0 200 hr = mDevice->CreateSamplerState(&samplerDesc, byRef(mAttachments->mPointSamplerState));
michael@0 201 if (FAILED(hr)) {
michael@0 202 return false;
michael@0 203 }
michael@0 204
michael@0 205 CD3D11_BLEND_DESC blendDesc(D3D11_DEFAULT);
michael@0 206 D3D11_RENDER_TARGET_BLEND_DESC rtBlendPremul = {
michael@0 207 TRUE,
michael@0 208 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
michael@0 209 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
michael@0 210 D3D11_COLOR_WRITE_ENABLE_ALL
michael@0 211 };
michael@0 212 blendDesc.RenderTarget[0] = rtBlendPremul;
michael@0 213 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mPremulBlendState));
michael@0 214 if (FAILED(hr)) {
michael@0 215 return false;
michael@0 216 }
michael@0 217
michael@0 218 D3D11_RENDER_TARGET_BLEND_DESC rtBlendNonPremul = {
michael@0 219 TRUE,
michael@0 220 D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
michael@0 221 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
michael@0 222 D3D11_COLOR_WRITE_ENABLE_ALL
michael@0 223 };
michael@0 224 blendDesc.RenderTarget[0] = rtBlendNonPremul;
michael@0 225 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mNonPremulBlendState));
michael@0 226 if (FAILED(hr)) {
michael@0 227 return false;
michael@0 228 }
michael@0 229
michael@0 230 if (gfxPrefs::ComponentAlphaEnabled()) {
michael@0 231 D3D11_RENDER_TARGET_BLEND_DESC rtBlendComponent = {
michael@0 232 TRUE,
michael@0 233 D3D11_BLEND_ONE,
michael@0 234 D3D11_BLEND_INV_SRC1_COLOR,
michael@0 235 D3D11_BLEND_OP_ADD,
michael@0 236 D3D11_BLEND_ONE,
michael@0 237 D3D11_BLEND_INV_SRC_ALPHA,
michael@0 238 D3D11_BLEND_OP_ADD,
michael@0 239 D3D11_COLOR_WRITE_ENABLE_ALL
michael@0 240 };
michael@0 241 blendDesc.RenderTarget[0] = rtBlendComponent;
michael@0 242 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mComponentBlendState));
michael@0 243 if (FAILED(hr)) {
michael@0 244 return false;
michael@0 245 }
michael@0 246 }
michael@0 247
michael@0 248 D3D11_RENDER_TARGET_BLEND_DESC rtBlendDisabled = {
michael@0 249 FALSE,
michael@0 250 D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
michael@0 251 D3D11_BLEND_ONE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_OP_ADD,
michael@0 252 D3D11_COLOR_WRITE_ENABLE_ALL
michael@0 253 };
michael@0 254 blendDesc.RenderTarget[0] = rtBlendDisabled;
michael@0 255 hr = mDevice->CreateBlendState(&blendDesc, byRef(mAttachments->mDisabledBlendState));
michael@0 256 if (FAILED(hr)) {
michael@0 257 return false;
michael@0 258 }
michael@0 259 }
michael@0 260
michael@0 261 nsRefPtr<IDXGIDevice> dxgiDevice;
michael@0 262 nsRefPtr<IDXGIAdapter> dxgiAdapter;
michael@0 263
michael@0 264 mDevice->QueryInterface(dxgiDevice.StartAssignment());
michael@0 265 dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
michael@0 266
michael@0 267 #ifdef MOZ_METRO
michael@0 268 if (IsRunningInWindowsMetro()) {
michael@0 269 nsRefPtr<IDXGIFactory2> dxgiFactory;
michael@0 270 dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
michael@0 271
michael@0 272 nsIntRect rect;
michael@0 273 mWidget->GetClientBounds(rect);
michael@0 274
michael@0 275 DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 };
michael@0 276 // Automatically detect the width and the height from the winrt CoreWindow
michael@0 277 swapDesc.Width = rect.width;
michael@0 278 swapDesc.Height = rect.height;
michael@0 279 // This is the most common swapchain format
michael@0 280 swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
michael@0 281 swapDesc.Stereo = false;
michael@0 282 // Don't use multi-sampling
michael@0 283 swapDesc.SampleDesc.Count = 1;
michael@0 284 swapDesc.SampleDesc.Quality = 0;
michael@0 285 swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
michael@0 286 // Use double buffering to enable flip
michael@0 287 swapDesc.BufferCount = 2;
michael@0 288 swapDesc.Scaling = DXGI_SCALING_NONE;
michael@0 289 // All Metro style apps must use this SwapEffect
michael@0 290 swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
michael@0 291 swapDesc.Flags = 0;
michael@0 292
michael@0 293 /**
michael@0 294 * Create a swap chain, this swap chain will contain the backbuffer for
michael@0 295 * the window we draw to. The front buffer is the full screen front
michael@0 296 * buffer.
michael@0 297 */
michael@0 298 nsRefPtr<IDXGISwapChain1> swapChain1;
michael@0 299 hr = dxgiFactory->CreateSwapChainForCoreWindow(
michael@0 300 dxgiDevice, (IUnknown *)mWidget->GetNativeData(NS_NATIVE_ICOREWINDOW),
michael@0 301 &swapDesc, nullptr, getter_AddRefs(swapChain1));
michael@0 302 if (FAILED(hr)) {
michael@0 303 return false;
michael@0 304 }
michael@0 305 mSwapChain = swapChain1;
michael@0 306 } else
michael@0 307 #endif
michael@0 308 {
michael@0 309 nsRefPtr<IDXGIFactory> dxgiFactory;
michael@0 310 dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
michael@0 311
michael@0 312 DXGI_SWAP_CHAIN_DESC swapDesc;
michael@0 313 ::ZeroMemory(&swapDesc, sizeof(swapDesc));
michael@0 314 swapDesc.BufferDesc.Width = 0;
michael@0 315 swapDesc.BufferDesc.Height = 0;
michael@0 316 swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
michael@0 317 swapDesc.BufferDesc.RefreshRate.Numerator = 60;
michael@0 318 swapDesc.BufferDesc.RefreshRate.Denominator = 1;
michael@0 319 swapDesc.SampleDesc.Count = 1;
michael@0 320 swapDesc.SampleDesc.Quality = 0;
michael@0 321 swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
michael@0 322 swapDesc.BufferCount = 1;
michael@0 323 swapDesc.OutputWindow = mHwnd;
michael@0 324 swapDesc.Windowed = TRUE;
michael@0 325 // We don't really need this flag, however it seems on some NVidia hardware
michael@0 326 // smaller area windows do not present properly without this flag. This flag
michael@0 327 // should have no negative consequences by itself. See bug 613790. This flag
michael@0 328 // is broken on optimus devices. As a temporary solution we don't set it
michael@0 329 // there, the only way of reliably detecting we're on optimus is looking for
michael@0 330 // the DLL. See Bug 623807.
michael@0 331 if (gfxWindowsPlatform::IsOptimus()) {
michael@0 332 swapDesc.Flags = 0;
michael@0 333 } else {
michael@0 334 swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
michael@0 335 }
michael@0 336
michael@0 337 /**
michael@0 338 * Create a swap chain, this swap chain will contain the backbuffer for
michael@0 339 * the window we draw to. The front buffer is the full screen front
michael@0 340 * buffer.
michael@0 341 */
michael@0 342 hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, byRef(mSwapChain));
michael@0 343 if (FAILED(hr)) {
michael@0 344 return false;
michael@0 345 }
michael@0 346
michael@0 347 // We need this because we don't want DXGI to respond to Alt+Enter.
michael@0 348 dxgiFactory->MakeWindowAssociation(swapDesc.OutputWindow,
michael@0 349 DXGI_MWA_NO_WINDOW_CHANGES);
michael@0 350 }
michael@0 351
michael@0 352 return true;
michael@0 353 }
michael@0 354
michael@0 355 TemporaryRef<DataTextureSource>
michael@0 356 CompositorD3D11::CreateDataTextureSource(TextureFlags aFlags)
michael@0 357 {
michael@0 358 RefPtr<DataTextureSource> result = new DataTextureSourceD3D11(gfx::SurfaceFormat::UNKNOWN,
michael@0 359 this, aFlags);
michael@0 360 return result.forget();
michael@0 361 }
michael@0 362
michael@0 363 TextureFactoryIdentifier
michael@0 364 CompositorD3D11::GetTextureFactoryIdentifier()
michael@0 365 {
michael@0 366 TextureFactoryIdentifier ident;
michael@0 367 ident.mMaxTextureSize = GetMaxTextureSize();
michael@0 368 ident.mParentProcessId = XRE_GetProcessType();
michael@0 369 ident.mParentBackend = LayersBackend::LAYERS_D3D11;
michael@0 370 return ident;
michael@0 371 }
michael@0 372
michael@0 373 bool
michael@0 374 CompositorD3D11::CanUseCanvasLayerForSize(const gfx::IntSize& aSize)
michael@0 375 {
michael@0 376 int32_t maxTextureSize = GetMaxTextureSize();
michael@0 377
michael@0 378 if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
michael@0 379 return false;
michael@0 380 }
michael@0 381
michael@0 382 return true;
michael@0 383 }
michael@0 384
michael@0 385 int32_t
michael@0 386 CompositorD3D11::GetMaxTextureSize() const
michael@0 387 {
michael@0 388 return GetMaxTextureSizeForFeatureLevel(mFeatureLevel);
michael@0 389 }
michael@0 390
michael@0 391 TemporaryRef<CompositingRenderTarget>
michael@0 392 CompositorD3D11::CreateRenderTarget(const gfx::IntRect& aRect,
michael@0 393 SurfaceInitMode aInit)
michael@0 394 {
michael@0 395 CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aRect.width, aRect.height, 1, 1,
michael@0 396 D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
michael@0 397
michael@0 398 RefPtr<ID3D11Texture2D> texture;
michael@0 399 mDevice->CreateTexture2D(&desc, nullptr, byRef(texture));
michael@0 400 NS_ASSERTION(texture, "Could not create texture");
michael@0 401 if (!texture) {
michael@0 402 return nullptr;
michael@0 403 }
michael@0 404
michael@0 405 RefPtr<CompositingRenderTargetD3D11> rt = new CompositingRenderTargetD3D11(texture, aRect.TopLeft());
michael@0 406 rt->SetSize(IntSize(aRect.width, aRect.height));
michael@0 407
michael@0 408 if (aInit == INIT_MODE_CLEAR) {
michael@0 409 FLOAT clear[] = { 0, 0, 0, 0 };
michael@0 410 mContext->ClearRenderTargetView(rt->mRTView, clear);
michael@0 411 }
michael@0 412
michael@0 413 return rt;
michael@0 414 }
michael@0 415
michael@0 416 TemporaryRef<CompositingRenderTarget>
michael@0 417 CompositorD3D11::CreateRenderTargetFromSource(const gfx::IntRect &aRect,
michael@0 418 const CompositingRenderTarget* aSource,
michael@0 419 const gfx::IntPoint &aSourcePoint)
michael@0 420 {
michael@0 421 CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
michael@0 422 aRect.width, aRect.height, 1, 1,
michael@0 423 D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
michael@0 424
michael@0 425 RefPtr<ID3D11Texture2D> texture;
michael@0 426 mDevice->CreateTexture2D(&desc, nullptr, byRef(texture));
michael@0 427 NS_ASSERTION(texture, "Could not create texture");
michael@0 428 if (!texture) {
michael@0 429 return nullptr;
michael@0 430 }
michael@0 431
michael@0 432 if (aSource) {
michael@0 433 const CompositingRenderTargetD3D11* sourceD3D11 =
michael@0 434 static_cast<const CompositingRenderTargetD3D11*>(aSource);
michael@0 435
michael@0 436 D3D11_BOX srcBox;
michael@0 437 srcBox.left = aSourcePoint.x;
michael@0 438 srcBox.top = aSourcePoint.y;
michael@0 439 srcBox.front = 0;
michael@0 440 srcBox.right = aSourcePoint.x + aRect.width;
michael@0 441 srcBox.bottom = aSourcePoint.y + aRect.height;
michael@0 442 srcBox.back = 0;
michael@0 443
michael@0 444 const IntSize& srcSize = sourceD3D11->GetSize();
michael@0 445 MOZ_ASSERT(srcSize.width >= 0 && srcSize.height >= 0,
michael@0 446 "render targets should have nonnegative sizes");
michael@0 447 if (srcBox.right <= static_cast<uint32_t>(srcSize.width) &&
michael@0 448 srcBox.bottom <= static_cast<uint32_t>(srcSize.height)) {
michael@0 449 mContext->CopySubresourceRegion(texture, 0,
michael@0 450 0, 0, 0,
michael@0 451 sourceD3D11->GetD3D11Texture(), 0,
michael@0 452 &srcBox);
michael@0 453 } else {
michael@0 454 NS_WARNING("Could not copy render target - source rect out of bounds");
michael@0 455 }
michael@0 456 }
michael@0 457
michael@0 458 RefPtr<CompositingRenderTargetD3D11> rt =
michael@0 459 new CompositingRenderTargetD3D11(texture, aRect.TopLeft());
michael@0 460 rt->SetSize(aRect.Size());
michael@0 461
michael@0 462 return rt;
michael@0 463 }
michael@0 464
michael@0 465 void
michael@0 466 CompositorD3D11::SetRenderTarget(CompositingRenderTarget* aRenderTarget)
michael@0 467 {
michael@0 468 MOZ_ASSERT(aRenderTarget);
michael@0 469 CompositingRenderTargetD3D11* newRT =
michael@0 470 static_cast<CompositingRenderTargetD3D11*>(aRenderTarget);
michael@0 471 ID3D11RenderTargetView* view = newRT->mRTView;
michael@0 472 mCurrentRT = newRT;
michael@0 473 mContext->OMSetRenderTargets(1, &view, nullptr);
michael@0 474 PrepareViewport(newRT->GetSize(), gfx::Matrix());
michael@0 475 }
michael@0 476
michael@0 477 void
michael@0 478 CompositorD3D11::SetPSForEffect(Effect* aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat)
michael@0 479 {
michael@0 480 switch (aEffect->mType) {
michael@0 481 case EFFECT_SOLID_COLOR:
michael@0 482 mContext->PSSetShader(mAttachments->mSolidColorShader[aMaskType], nullptr, 0);
michael@0 483 return;
michael@0 484 case EFFECT_RENDER_TARGET:
michael@0 485 mContext->PSSetShader(mAttachments->mRGBAShader[aMaskType], nullptr, 0);
michael@0 486 return;
michael@0 487 case EFFECT_RGB:
michael@0 488 mContext->PSSetShader((aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8)
michael@0 489 ? mAttachments->mRGBAShader[aMaskType]
michael@0 490 : mAttachments->mRGBShader[aMaskType], nullptr, 0);
michael@0 491 return;
michael@0 492 case EFFECT_YCBCR:
michael@0 493 mContext->PSSetShader(mAttachments->mYCbCrShader[aMaskType], nullptr, 0);
michael@0 494 return;
michael@0 495 case EFFECT_COMPONENT_ALPHA:
michael@0 496 mContext->PSSetShader(mAttachments->mComponentAlphaShader[aMaskType], nullptr, 0);
michael@0 497 return;
michael@0 498 default:
michael@0 499 NS_WARNING("No shader to load");
michael@0 500 return;
michael@0 501 }
michael@0 502 }
michael@0 503
michael@0 504 void
michael@0 505 CompositorD3D11::ClearRect(const gfx::Rect& aRect)
michael@0 506 {
michael@0 507 mContext->OMSetBlendState(mAttachments->mDisabledBlendState, sBlendFactor, 0xFFFFFFFF);
michael@0 508
michael@0 509 Matrix4x4 identity;
michael@0 510 memcpy(&mVSConstants.layerTransform, &identity._11, 64);
michael@0 511
michael@0 512 mVSConstants.layerQuad = aRect;
michael@0 513 mVSConstants.renderTargetOffset[0] = 0;
michael@0 514 mVSConstants.renderTargetOffset[1] = 0;
michael@0 515 mPSConstants.layerOpacity[0] = 1.0f;
michael@0 516
michael@0 517 D3D11_RECT scissor;
michael@0 518 scissor.left = aRect.x;
michael@0 519 scissor.right = aRect.XMost();
michael@0 520 scissor.top = aRect.y;
michael@0 521 scissor.bottom = aRect.YMost();
michael@0 522 mContext->RSSetScissorRects(1, &scissor);
michael@0 523 mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
michael@0 524 mContext->VSSetShader(mAttachments->mVSQuadShader[MaskNone], nullptr, 0);
michael@0 525
michael@0 526 mContext->PSSetShader(mAttachments->mSolidColorShader[MaskNone], nullptr, 0);
michael@0 527 mPSConstants.layerColor[0] = 0;
michael@0 528 mPSConstants.layerColor[1] = 0;
michael@0 529 mPSConstants.layerColor[2] = 0;
michael@0 530 mPSConstants.layerColor[3] = 0;
michael@0 531
michael@0 532 UpdateConstantBuffers();
michael@0 533
michael@0 534 mContext->Draw(4, 0);
michael@0 535
michael@0 536 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
michael@0 537 }
michael@0 538
michael@0 539 void
michael@0 540 CompositorD3D11::DrawQuad(const gfx::Rect& aRect,
michael@0 541 const gfx::Rect& aClipRect,
michael@0 542 const EffectChain& aEffectChain,
michael@0 543 gfx::Float aOpacity,
michael@0 544 const gfx::Matrix4x4& aTransform)
michael@0 545 {
michael@0 546 MOZ_ASSERT(mCurrentRT, "No render target");
michael@0 547 memcpy(&mVSConstants.layerTransform, &aTransform._11, 64);
michael@0 548 IntPoint origin = mCurrentRT->GetOrigin();
michael@0 549 mVSConstants.renderTargetOffset[0] = origin.x;
michael@0 550 mVSConstants.renderTargetOffset[1] = origin.y;
michael@0 551 mVSConstants.layerQuad = aRect;
michael@0 552
michael@0 553 mPSConstants.layerOpacity[0] = aOpacity;
michael@0 554
michael@0 555 bool restoreBlendMode = false;
michael@0 556
michael@0 557 MaskType maskType = MaskNone;
michael@0 558
michael@0 559 if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
michael@0 560 if (aTransform.Is2D()) {
michael@0 561 maskType = Mask2d;
michael@0 562 } else {
michael@0 563 MOZ_ASSERT(aEffectChain.mPrimaryEffect->mType == EFFECT_RGB);
michael@0 564 maskType = Mask3d;
michael@0 565 }
michael@0 566
michael@0 567 EffectMask* maskEffect =
michael@0 568 static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
michael@0 569 TextureSourceD3D11* source = maskEffect->mMaskTexture->AsSourceD3D11();
michael@0 570
michael@0 571 if (!source) {
michael@0 572 NS_WARNING("Missing texture source!");
michael@0 573 return;
michael@0 574 }
michael@0 575
michael@0 576 RefPtr<ID3D11ShaderResourceView> view;
michael@0 577 mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
michael@0 578
michael@0 579 ID3D11ShaderResourceView* srView = view;
michael@0 580 mContext->PSSetShaderResources(3, 1, &srView);
michael@0 581
michael@0 582 const gfx::Matrix4x4& maskTransform = maskEffect->mMaskTransform;
michael@0 583 NS_ASSERTION(maskTransform.Is2D(), "How did we end up with a 3D transform here?!");
michael@0 584 Rect bounds = Rect(Point(), Size(maskEffect->mSize));
michael@0 585
michael@0 586 mVSConstants.maskQuad = maskTransform.As2D().TransformBounds(bounds);
michael@0 587 }
michael@0 588
michael@0 589
michael@0 590 D3D11_RECT scissor;
michael@0 591 scissor.left = aClipRect.x;
michael@0 592 scissor.right = aClipRect.XMost();
michael@0 593 scissor.top = aClipRect.y;
michael@0 594 scissor.bottom = aClipRect.YMost();
michael@0 595 mContext->RSSetScissorRects(1, &scissor);
michael@0 596 mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
michael@0 597 mContext->VSSetShader(mAttachments->mVSQuadShader[maskType], nullptr, 0);
michael@0 598
michael@0 599
michael@0 600 switch (aEffectChain.mPrimaryEffect->mType) {
michael@0 601 case EFFECT_SOLID_COLOR: {
michael@0 602 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, SurfaceFormat::UNKNOWN);
michael@0 603
michael@0 604 Color color =
michael@0 605 static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
michael@0 606 mPSConstants.layerColor[0] = color.r * color.a * aOpacity;
michael@0 607 mPSConstants.layerColor[1] = color.g * color.a * aOpacity;
michael@0 608 mPSConstants.layerColor[2] = color.b * color.a * aOpacity;
michael@0 609 mPSConstants.layerColor[3] = color.a * aOpacity;
michael@0 610 }
michael@0 611 break;
michael@0 612 case EFFECT_RGB:
michael@0 613 case EFFECT_RENDER_TARGET:
michael@0 614 {
michael@0 615 TexturedEffect* texturedEffect =
michael@0 616 static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
michael@0 617
michael@0 618 mVSConstants.textureCoords = texturedEffect->mTextureCoords;
michael@0 619
michael@0 620 TextureSourceD3D11* source = texturedEffect->mTexture->AsSourceD3D11();
michael@0 621
michael@0 622 if (!source) {
michael@0 623 NS_WARNING("Missing texture source!");
michael@0 624 return;
michael@0 625 }
michael@0 626
michael@0 627 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, texturedEffect->mTexture->GetFormat());
michael@0 628
michael@0 629 RefPtr<ID3D11ShaderResourceView> view;
michael@0 630 mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
michael@0 631
michael@0 632 ID3D11ShaderResourceView* srView = view;
michael@0 633 mContext->PSSetShaderResources(0, 1, &srView);
michael@0 634
michael@0 635 if (!texturedEffect->mPremultiplied) {
michael@0 636 mContext->OMSetBlendState(mAttachments->mNonPremulBlendState, sBlendFactor, 0xFFFFFFFF);
michael@0 637 restoreBlendMode = true;
michael@0 638 }
michael@0 639
michael@0 640 SetSamplerForFilter(texturedEffect->mFilter);
michael@0 641 }
michael@0 642 break;
michael@0 643 case EFFECT_YCBCR: {
michael@0 644 EffectYCbCr* ycbcrEffect =
michael@0 645 static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
michael@0 646
michael@0 647 SetSamplerForFilter(Filter::LINEAR);
michael@0 648
michael@0 649 mVSConstants.textureCoords = ycbcrEffect->mTextureCoords;
michael@0 650
michael@0 651 const int Y = 0, Cb = 1, Cr = 2;
michael@0 652 TextureSource* source = ycbcrEffect->mTexture;
michael@0 653
michael@0 654 if (!source) {
michael@0 655 NS_WARNING("No texture to composite");
michael@0 656 return;
michael@0 657 }
michael@0 658
michael@0 659 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, ycbcrEffect->mTexture->GetFormat());
michael@0 660
michael@0 661 if (!source->GetSubSource(Y) || !source->GetSubSource(Cb) || !source->GetSubSource(Cr)) {
michael@0 662 // This can happen if we failed to upload the textures, most likely
michael@0 663 // because of unsupported dimensions (we don't tile YCbCr textures).
michael@0 664 return;
michael@0 665 }
michael@0 666
michael@0 667 TextureSourceD3D11* sourceY = source->GetSubSource(Y)->AsSourceD3D11();
michael@0 668 TextureSourceD3D11* sourceCb = source->GetSubSource(Cb)->AsSourceD3D11();
michael@0 669 TextureSourceD3D11* sourceCr = source->GetSubSource(Cr)->AsSourceD3D11();
michael@0 670
michael@0 671 RefPtr<ID3D11ShaderResourceView> views[3];
michael@0 672 mDevice->CreateShaderResourceView(sourceY->GetD3D11Texture(),
michael@0 673 nullptr, byRef(views[0]));
michael@0 674 mDevice->CreateShaderResourceView(sourceCb->GetD3D11Texture(),
michael@0 675 nullptr, byRef(views[1]));
michael@0 676 mDevice->CreateShaderResourceView(sourceCr->GetD3D11Texture(),
michael@0 677 nullptr, byRef(views[2]));
michael@0 678
michael@0 679 ID3D11ShaderResourceView* srViews[3] = { views[0], views[1], views[2] };
michael@0 680 mContext->PSSetShaderResources(0, 3, srViews);
michael@0 681 }
michael@0 682 break;
michael@0 683 case EFFECT_COMPONENT_ALPHA:
michael@0 684 {
michael@0 685 MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
michael@0 686 MOZ_ASSERT(mAttachments->mComponentBlendState);
michael@0 687 EffectComponentAlpha* effectComponentAlpha =
michael@0 688 static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
michael@0 689
michael@0 690 TextureSourceD3D11* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D11();
michael@0 691 TextureSourceD3D11* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D11();
michael@0 692
michael@0 693 if (!sourceOnWhite || !sourceOnBlack) {
michael@0 694 NS_WARNING("Missing texture source(s)!");
michael@0 695 return;
michael@0 696 }
michael@0 697
michael@0 698 SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, effectComponentAlpha->mOnWhite->GetFormat());
michael@0 699
michael@0 700 SetSamplerForFilter(effectComponentAlpha->mFilter);
michael@0 701
michael@0 702 mVSConstants.textureCoords = effectComponentAlpha->mTextureCoords;
michael@0 703 RefPtr<ID3D11ShaderResourceView> views[2];
michael@0 704 mDevice->CreateShaderResourceView(sourceOnBlack->GetD3D11Texture(), nullptr, byRef(views[0]));
michael@0 705 mDevice->CreateShaderResourceView(sourceOnWhite->GetD3D11Texture(), nullptr, byRef(views[1]));
michael@0 706
michael@0 707 ID3D11ShaderResourceView* srViews[2] = { views[0], views[1] };
michael@0 708 mContext->PSSetShaderResources(0, 2, srViews);
michael@0 709
michael@0 710 mContext->OMSetBlendState(mAttachments->mComponentBlendState, sBlendFactor, 0xFFFFFFFF);
michael@0 711 restoreBlendMode = true;
michael@0 712 }
michael@0 713 break;
michael@0 714 default:
michael@0 715 NS_WARNING("Unknown shader type");
michael@0 716 return;
michael@0 717 }
michael@0 718 UpdateConstantBuffers();
michael@0 719
michael@0 720 mContext->Draw(4, 0);
michael@0 721 if (restoreBlendMode) {
michael@0 722 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
michael@0 723 }
michael@0 724 }
michael@0 725
michael@0 726 void
michael@0 727 CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
michael@0 728 const Rect* aClipRectIn,
michael@0 729 const gfx::Matrix& aTransform,
michael@0 730 const Rect& aRenderBounds,
michael@0 731 Rect* aClipRectOut,
michael@0 732 Rect* aRenderBoundsOut)
michael@0 733 {
michael@0 734 // Don't composite if we are minimised. Other than for the sake of efficency,
michael@0 735 // this is important because resizing our buffers when mimised will fail and
michael@0 736 // cause a crash when we're restored.
michael@0 737 NS_ASSERTION(mHwnd, "Couldn't find an HWND when initialising?");
michael@0 738 if (::IsIconic(mHwnd)) {
michael@0 739 *aRenderBoundsOut = Rect();
michael@0 740 return;
michael@0 741 }
michael@0 742
michael@0 743 UpdateRenderTarget();
michael@0 744
michael@0 745 // Failed to create a render target or the view.
michael@0 746 if (!mDefaultRT || !mDefaultRT->mRTView ||
michael@0 747 mSize.width == 0 || mSize.height == 0) {
michael@0 748 *aRenderBoundsOut = Rect();
michael@0 749 return;
michael@0 750 }
michael@0 751
michael@0 752 mContext->IASetInputLayout(mAttachments->mInputLayout);
michael@0 753
michael@0 754 ID3D11Buffer* buffer = mAttachments->mVertexBuffer;
michael@0 755 UINT size = sizeof(Vertex);
michael@0 756 UINT offset = 0;
michael@0 757 mContext->IASetVertexBuffers(0, 1, &buffer, &size, &offset);
michael@0 758
michael@0 759 if (aClipRectOut) {
michael@0 760 *aClipRectOut = Rect(0, 0, mSize.width, mSize.height);
michael@0 761 }
michael@0 762 if (aRenderBoundsOut) {
michael@0 763 *aRenderBoundsOut = Rect(0, 0, mSize.width, mSize.height);
michael@0 764 }
michael@0 765
michael@0 766 D3D11_RECT scissor;
michael@0 767 if (aClipRectIn) {
michael@0 768 scissor.left = aClipRectIn->x;
michael@0 769 scissor.right = aClipRectIn->XMost();
michael@0 770 scissor.top = aClipRectIn->y;
michael@0 771 scissor.bottom = aClipRectIn->YMost();
michael@0 772 } else {
michael@0 773 scissor.left = scissor.top = 0;
michael@0 774 scissor.right = mSize.width;
michael@0 775 scissor.bottom = mSize.height;
michael@0 776 }
michael@0 777 mContext->RSSetScissorRects(1, &scissor);
michael@0 778
michael@0 779 FLOAT black[] = { 0, 0, 0, 0 };
michael@0 780 mContext->ClearRenderTargetView(mDefaultRT->mRTView, black);
michael@0 781
michael@0 782 mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
michael@0 783 mContext->RSSetState(mAttachments->mRasterizerState);
michael@0 784
michael@0 785 SetRenderTarget(mDefaultRT);
michael@0 786 }
michael@0 787
michael@0 788 void
michael@0 789 CompositorD3D11::EndFrame()
michael@0 790 {
michael@0 791 mContext->Flush();
michael@0 792
michael@0 793 nsIntSize oldSize = mSize;
michael@0 794 EnsureSize();
michael@0 795 if (oldSize == mSize) {
michael@0 796 mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0);
michael@0 797 mDisableSequenceForNextFrame = false;
michael@0 798 if (mTarget) {
michael@0 799 PaintToTarget();
michael@0 800 }
michael@0 801 }
michael@0 802
michael@0 803 mCurrentRT = nullptr;
michael@0 804 }
michael@0 805
michael@0 806 void
michael@0 807 CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize,
michael@0 808 const gfx::Matrix& aWorldTransform)
michael@0 809 {
michael@0 810 D3D11_VIEWPORT viewport;
michael@0 811 viewport.MaxDepth = 1.0f;
michael@0 812 viewport.MinDepth = 0;
michael@0 813 viewport.Width = aSize.width;
michael@0 814 viewport.Height = aSize.height;
michael@0 815 viewport.TopLeftX = 0;
michael@0 816 viewport.TopLeftY = 0;
michael@0 817
michael@0 818 mContext->RSSetViewports(1, &viewport);
michael@0 819
michael@0 820 Matrix viewMatrix;
michael@0 821 viewMatrix.Translate(-1.0, 1.0);
michael@0 822 viewMatrix.Scale(2.0f / float(aSize.width), 2.0f / float(aSize.height));
michael@0 823 viewMatrix.Scale(1.0f, -1.0f);
michael@0 824
michael@0 825 viewMatrix = aWorldTransform * viewMatrix;
michael@0 826
michael@0 827 Matrix4x4 projection = Matrix4x4::From2D(viewMatrix);
michael@0 828 projection._33 = 0.0f;
michael@0 829
michael@0 830 memcpy(&mVSConstants.projection, &projection, sizeof(mVSConstants.projection));
michael@0 831 }
michael@0 832
michael@0 833 void
michael@0 834 CompositorD3D11::EnsureSize()
michael@0 835 {
michael@0 836 nsIntRect rect;
michael@0 837 mWidget->GetClientBounds(rect);
michael@0 838
michael@0 839 mSize = rect.Size();
michael@0 840 }
michael@0 841
michael@0 842 void
michael@0 843 CompositorD3D11::VerifyBufferSize()
michael@0 844 {
michael@0 845 DXGI_SWAP_CHAIN_DESC swapDesc;
michael@0 846 mSwapChain->GetDesc(&swapDesc);
michael@0 847
michael@0 848 if ((swapDesc.BufferDesc.Width == mSize.width &&
michael@0 849 swapDesc.BufferDesc.Height == mSize.height) ||
michael@0 850 mSize.width == 0 || mSize.height == 0) {
michael@0 851 return;
michael@0 852 }
michael@0 853
michael@0 854 mDefaultRT = nullptr;
michael@0 855
michael@0 856 if (IsRunningInWindowsMetro()) {
michael@0 857 mSwapChain->ResizeBuffers(2, mSize.width, mSize.height,
michael@0 858 DXGI_FORMAT_B8G8R8A8_UNORM,
michael@0 859 0);
michael@0 860 mDisableSequenceForNextFrame = true;
michael@0 861 } else if (gfxWindowsPlatform::IsOptimus()) {
michael@0 862 mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
michael@0 863 DXGI_FORMAT_B8G8R8A8_UNORM,
michael@0 864 0);
michael@0 865 } else {
michael@0 866 mSwapChain->ResizeBuffers(1, mSize.width, mSize.height,
michael@0 867 DXGI_FORMAT_B8G8R8A8_UNORM,
michael@0 868 DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
michael@0 869 }
michael@0 870 }
michael@0 871
michael@0 872 void
michael@0 873 CompositorD3D11::UpdateRenderTarget()
michael@0 874 {
michael@0 875 EnsureSize();
michael@0 876 VerifyBufferSize();
michael@0 877
michael@0 878 if (mDefaultRT) {
michael@0 879 return;
michael@0 880 }
michael@0 881
michael@0 882 HRESULT hr;
michael@0 883
michael@0 884 nsRefPtr<ID3D11Texture2D> backBuf;
michael@0 885
michael@0 886 hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
michael@0 887 if (FAILED(hr)) {
michael@0 888 return;
michael@0 889 }
michael@0 890
michael@0 891 mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0));
michael@0 892 mDefaultRT->SetSize(mSize.ToIntSize());
michael@0 893 }
michael@0 894
michael@0 895 bool
michael@0 896 CompositorD3D11::CreateShaders()
michael@0 897 {
michael@0 898 HRESULT hr;
michael@0 899
michael@0 900 hr = mDevice->CreateVertexShader(LayerQuadVS,
michael@0 901 sizeof(LayerQuadVS),
michael@0 902 nullptr,
michael@0 903 byRef(mAttachments->mVSQuadShader[MaskNone]));
michael@0 904 if (FAILED(hr)) {
michael@0 905 return false;
michael@0 906 }
michael@0 907
michael@0 908 hr = mDevice->CreateVertexShader(LayerQuadMaskVS,
michael@0 909 sizeof(LayerQuadMaskVS),
michael@0 910 nullptr,
michael@0 911 byRef(mAttachments->mVSQuadShader[Mask2d]));
michael@0 912 if (FAILED(hr)) {
michael@0 913 return false;
michael@0 914 }
michael@0 915
michael@0 916 hr = mDevice->CreateVertexShader(LayerQuadMask3DVS,
michael@0 917 sizeof(LayerQuadMask3DVS),
michael@0 918 nullptr,
michael@0 919 byRef(mAttachments->mVSQuadShader[Mask3d]));
michael@0 920 if (FAILED(hr)) {
michael@0 921 return false;
michael@0 922 }
michael@0 923
michael@0 924 #define LOAD_PIXEL_SHADER(x) hr = mDevice->CreatePixelShader(x, sizeof(x), nullptr, byRef(mAttachments->m##x[MaskNone])); \
michael@0 925 if (FAILED(hr)) { \
michael@0 926 return false; \
michael@0 927 } \
michael@0 928 hr = mDevice->CreatePixelShader(x##Mask, sizeof(x##Mask), nullptr, byRef(mAttachments->m##x[Mask2d])); \
michael@0 929 if (FAILED(hr)) { \
michael@0 930 return false; \
michael@0 931 }
michael@0 932
michael@0 933 LOAD_PIXEL_SHADER(SolidColorShader);
michael@0 934 LOAD_PIXEL_SHADER(RGBShader);
michael@0 935 LOAD_PIXEL_SHADER(RGBAShader);
michael@0 936 LOAD_PIXEL_SHADER(YCbCrShader);
michael@0 937 if (gfxPrefs::ComponentAlphaEnabled()) {
michael@0 938 LOAD_PIXEL_SHADER(ComponentAlphaShader);
michael@0 939 }
michael@0 940
michael@0 941 #undef LOAD_PIXEL_SHADER
michael@0 942
michael@0 943 hr = mDevice->CreatePixelShader(RGBAShaderMask3D,
michael@0 944 sizeof(RGBAShaderMask3D),
michael@0 945 nullptr,
michael@0 946 byRef(mAttachments->mRGBAShader[Mask3d]));
michael@0 947 if (FAILED(hr)) {
michael@0 948 return false;
michael@0 949 }
michael@0 950
michael@0 951 return true;
michael@0 952 }
michael@0 953
michael@0 954 void
michael@0 955 CompositorD3D11::UpdateConstantBuffers()
michael@0 956 {
michael@0 957 D3D11_MAPPED_SUBRESOURCE resource;
michael@0 958 mContext->Map(mAttachments->mVSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
michael@0 959 *(VertexShaderConstants*)resource.pData = mVSConstants;
michael@0 960 mContext->Unmap(mAttachments->mVSConstantBuffer, 0);
michael@0 961 mContext->Map(mAttachments->mPSConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
michael@0 962 *(PixelShaderConstants*)resource.pData = mPSConstants;
michael@0 963 mContext->Unmap(mAttachments->mPSConstantBuffer, 0);
michael@0 964
michael@0 965 ID3D11Buffer *buffer = mAttachments->mVSConstantBuffer;
michael@0 966
michael@0 967 mContext->VSSetConstantBuffers(0, 1, &buffer);
michael@0 968
michael@0 969 buffer = mAttachments->mPSConstantBuffer;
michael@0 970 mContext->PSSetConstantBuffers(0, 1, &buffer);
michael@0 971 }
michael@0 972
michael@0 973 void
michael@0 974 CompositorD3D11::SetSamplerForFilter(Filter aFilter)
michael@0 975 {
michael@0 976 ID3D11SamplerState *sampler;
michael@0 977 switch (aFilter) {
michael@0 978 default:
michael@0 979 case Filter::LINEAR:
michael@0 980 sampler = mAttachments->mLinearSamplerState;
michael@0 981 break;
michael@0 982 case Filter::POINT:
michael@0 983 sampler = mAttachments->mPointSamplerState;
michael@0 984 break;
michael@0 985 }
michael@0 986
michael@0 987 mContext->PSSetSamplers(0, 1, &sampler);
michael@0 988 }
michael@0 989
michael@0 990 void
michael@0 991 CompositorD3D11::PaintToTarget()
michael@0 992 {
michael@0 993 nsRefPtr<ID3D11Texture2D> backBuf;
michael@0 994
michael@0 995 mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
michael@0 996
michael@0 997 D3D11_TEXTURE2D_DESC bbDesc;
michael@0 998 backBuf->GetDesc(&bbDesc);
michael@0 999
michael@0 1000 CD3D11_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height);
michael@0 1001 softDesc.MipLevels = 1;
michael@0 1002 softDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
michael@0 1003 softDesc.Usage = D3D11_USAGE_STAGING;
michael@0 1004 softDesc.BindFlags = 0;
michael@0 1005
michael@0 1006 nsRefPtr<ID3D11Texture2D> readTexture;
michael@0 1007
michael@0 1008 HRESULT hr = mDevice->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture));
michael@0 1009 mContext->CopyResource(readTexture, backBuf);
michael@0 1010
michael@0 1011 D3D11_MAPPED_SUBRESOURCE map;
michael@0 1012 mContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &map);
michael@0 1013 RefPtr<DataSourceSurface> sourceSurface =
michael@0 1014 Factory::CreateWrappingDataSourceSurface((uint8_t*)map.pData,
michael@0 1015 map.RowPitch,
michael@0 1016 IntSize(bbDesc.Width, bbDesc.Height),
michael@0 1017 SurfaceFormat::B8G8R8A8);
michael@0 1018 mTarget->CopySurface(sourceSurface,
michael@0 1019 IntRect(0, 0, bbDesc.Width, bbDesc.Height),
michael@0 1020 IntPoint());
michael@0 1021 mTarget->Flush();
michael@0 1022 mContext->Unmap(readTexture, 0);
michael@0 1023 }
michael@0 1024
michael@0 1025 }
michael@0 1026 }

mercurial