1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,894 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <algorithm> 1.10 + 1.11 +#include "LayerManagerD3D10.h" 1.12 +#include "LayerManagerD3D10Effect.h" 1.13 +#include "gfxWindowsPlatform.h" 1.14 +#include "gfx2DGlue.h" 1.15 +#include "gfxD2DSurface.h" 1.16 +#include "gfxFailure.h" 1.17 +#include "cairo-win32.h" 1.18 +#include "dxgi.h" 1.19 + 1.20 +#include "ContainerLayerD3D10.h" 1.21 +#include "ThebesLayerD3D10.h" 1.22 +#include "ColorLayerD3D10.h" 1.23 +#include "CanvasLayerD3D10.h" 1.24 +#include "ReadbackLayerD3D10.h" 1.25 +#include "ImageLayerD3D10.h" 1.26 +#include "mozilla/layers/PLayerChild.h" 1.27 +#include "mozilla/WidgetUtils.h" 1.28 + 1.29 +#include "../d3d9/Nv3DVUtils.h" 1.30 + 1.31 +#include "gfxCrashReporterUtils.h" 1.32 +#include "nsWindowsHelpers.h" 1.33 +#ifdef MOZ_METRO 1.34 +#include "DXGI1_2.h" 1.35 +#endif 1.36 + 1.37 +using namespace std; 1.38 +using namespace mozilla::dom; 1.39 +using namespace mozilla::gfx; 1.40 + 1.41 +namespace mozilla { 1.42 +namespace layers { 1.43 + 1.44 +struct Vertex 1.45 +{ 1.46 + float position[2]; 1.47 +}; 1.48 + 1.49 +// {592BF306-0EED-4F76-9D03-A0846450F472} 1.50 +static const GUID sDeviceAttachments = 1.51 +{ 0x592bf306, 0xeed, 0x4f76, { 0x9d, 0x3, 0xa0, 0x84, 0x64, 0x50, 0xf4, 0x72 } }; 1.52 +// {716AEDB1-C9C3-4B4D-8332-6F65D44AF6A8} 1.53 +static const GUID sLayerManagerCount = 1.54 +{ 0x716aedb1, 0xc9c3, 0x4b4d, { 0x83, 0x32, 0x6f, 0x65, 0xd4, 0x4a, 0xf6, 0xa8 } }; 1.55 + 1.56 +LayerManagerD3D10::LayerManagerD3D10(nsIWidget *aWidget) 1.57 + : mWidget(aWidget) 1.58 + , mDisableSequenceForNextFrame(false) 1.59 +{ 1.60 +} 1.61 + 1.62 +struct DeviceAttachments 1.63 +{ 1.64 + nsRefPtr<ID3D10Effect> mEffect; 1.65 + nsRefPtr<ID3D10InputLayout> mInputLayout; 1.66 + nsRefPtr<ID3D10Buffer> mVertexBuffer; 1.67 + nsRefPtr<ReadbackManagerD3D10> mReadbackManager; 1.68 +}; 1.69 + 1.70 +LayerManagerD3D10::~LayerManagerD3D10() 1.71 +{ 1.72 + if (mDevice) { 1.73 + int referenceCount = 0; 1.74 + UINT size = sizeof(referenceCount); 1.75 + HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount); 1.76 + NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device."); 1.77 + referenceCount--; 1.78 + mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount); 1.79 + 1.80 + if (!referenceCount) { 1.81 + DeviceAttachments *attachments; 1.82 + size = sizeof(attachments); 1.83 + mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments); 1.84 + // No LayerManagers left for this device. Clear out interfaces stored which 1.85 + // hold a reference to the device. 1.86 + mDevice->SetPrivateData(sDeviceAttachments, 0, nullptr); 1.87 + 1.88 + delete attachments; 1.89 + } 1.90 + } 1.91 + 1.92 + Destroy(); 1.93 +} 1.94 + 1.95 +static inline void 1.96 +SetHRESULT(HRESULT* aHresultPtr, HRESULT aHresult) 1.97 +{ 1.98 + if (aHresultPtr) { 1.99 + *aHresultPtr = aHresult; 1.100 + } 1.101 +} 1.102 + 1.103 +bool 1.104 +LayerManagerD3D10::Initialize(bool force, HRESULT* aHresultPtr) 1.105 +{ 1.106 + ScopedGfxFeatureReporter reporter("D3D10 Layers", force); 1.107 + 1.108 + HRESULT hr = E_UNEXPECTED; 1.109 + 1.110 + /* Create an Nv3DVUtils instance */ 1.111 + if (!mNv3DVUtils) { 1.112 + mNv3DVUtils = new Nv3DVUtils(); 1.113 + if (!mNv3DVUtils) { 1.114 + NS_WARNING("Could not create a new instance of Nv3DVUtils.\n"); 1.115 + } 1.116 + } 1.117 + 1.118 + /* Initialize the Nv3DVUtils object */ 1.119 + if (mNv3DVUtils) { 1.120 + mNv3DVUtils->Initialize(); 1.121 + } 1.122 + 1.123 + mDevice = gfxWindowsPlatform::GetPlatform()->GetD3D10Device(); 1.124 + if (!mDevice) { 1.125 + SetHRESULT(aHresultPtr, hr); 1.126 + return false; 1.127 + } 1.128 + 1.129 + /* 1.130 + * Do some post device creation setup 1.131 + */ 1.132 + if (mNv3DVUtils) { 1.133 + IUnknown* devUnknown = nullptr; 1.134 + if (mDevice) { 1.135 + mDevice->QueryInterface(IID_IUnknown, (void **)&devUnknown); 1.136 + } 1.137 + mNv3DVUtils->SetDeviceInfo(devUnknown); 1.138 + } 1.139 + 1.140 + int referenceCount = 0; 1.141 + UINT size = sizeof(referenceCount); 1.142 + // If this isn't there yet it'll fail, count will remain 0, which is correct. 1.143 + mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount); 1.144 + referenceCount++; 1.145 + mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount); 1.146 + 1.147 + DeviceAttachments *attachments; 1.148 + size = sizeof(DeviceAttachments*); 1.149 + if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) { 1.150 + attachments = new DeviceAttachments; 1.151 + mDevice->SetPrivateData(sDeviceAttachments, sizeof(attachments), &attachments); 1.152 + 1.153 + SetLastError(0); 1.154 + decltype(D3D10CreateEffectFromMemory)* createEffect = 1.155 + (decltype(D3D10CreateEffectFromMemory)*) 1.156 + GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateEffectFromMemory"); 1.157 + if (!createEffect) { 1.158 + SetHRESULT(aHresultPtr, HRESULT_FROM_WIN32(GetLastError())); 1.159 + return false; 1.160 + } 1.161 + 1.162 + hr = createEffect((void*)g_main, 1.163 + sizeof(g_main), 1.164 + D3D10_EFFECT_SINGLE_THREADED, 1.165 + mDevice, 1.166 + nullptr, 1.167 + getter_AddRefs(mEffect)); 1.168 + 1.169 + if (FAILED(hr)) { 1.170 + SetHRESULT(aHresultPtr, hr); 1.171 + return false; 1.172 + } 1.173 + 1.174 + attachments->mEffect = mEffect; 1.175 + 1.176 + D3D10_INPUT_ELEMENT_DESC layout[] = 1.177 + { 1.178 + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, 1.179 + }; 1.180 + D3D10_PASS_DESC passDesc; 1.181 + mEffect->GetTechniqueByName("RenderRGBLayerPremul")->GetPassByIndex(0)-> 1.182 + GetDesc(&passDesc); 1.183 + 1.184 + hr = mDevice->CreateInputLayout(layout, 1.185 + sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC), 1.186 + passDesc.pIAInputSignature, 1.187 + passDesc.IAInputSignatureSize, 1.188 + getter_AddRefs(mInputLayout)); 1.189 + 1.190 + if (FAILED(hr)) { 1.191 + SetHRESULT(aHresultPtr, hr); 1.192 + return false; 1.193 + } 1.194 + 1.195 + attachments->mInputLayout = mInputLayout; 1.196 + 1.197 + Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} }; 1.198 + CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER); 1.199 + D3D10_SUBRESOURCE_DATA data; 1.200 + data.pSysMem = (void*)vertices; 1.201 + 1.202 + hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer)); 1.203 + 1.204 + if (FAILED(hr)) { 1.205 + SetHRESULT(aHresultPtr, hr); 1.206 + return false; 1.207 + } 1.208 + 1.209 + attachments->mVertexBuffer = mVertexBuffer; 1.210 + } else { 1.211 + mEffect = attachments->mEffect; 1.212 + mVertexBuffer = attachments->mVertexBuffer; 1.213 + mInputLayout = attachments->mInputLayout; 1.214 + } 1.215 + 1.216 + nsRefPtr<IDXGIDevice> dxgiDevice; 1.217 + nsRefPtr<IDXGIAdapter> dxgiAdapter; 1.218 + 1.219 + mDevice->QueryInterface(dxgiDevice.StartAssignment()); 1.220 + dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter)); 1.221 + 1.222 +#ifdef MOZ_METRO 1.223 + if (IsRunningInWindowsMetro()) { 1.224 + nsRefPtr<IDXGIFactory2> dxgiFactory; 1.225 + dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment())); 1.226 + 1.227 + nsIntRect rect; 1.228 + mWidget->GetClientBounds(rect); 1.229 + 1.230 + DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 }; 1.231 + // Automatically detect the width and the height from the winrt CoreWindow 1.232 + swapDesc.Width = rect.width; 1.233 + swapDesc.Height = rect.height; 1.234 + // This is the most common swapchain format 1.235 + swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 1.236 + swapDesc.Stereo = false; 1.237 + // Don't use multi-sampling 1.238 + swapDesc.SampleDesc.Count = 1; 1.239 + swapDesc.SampleDesc.Quality = 0; 1.240 + swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 1.241 + // Use double buffering to enable flip 1.242 + swapDesc.BufferCount = 2; 1.243 + swapDesc.Scaling = DXGI_SCALING_NONE; 1.244 + // All Metro style apps must use this SwapEffect 1.245 + swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; 1.246 + swapDesc.Flags = 0; 1.247 + 1.248 + /** 1.249 + * Create a swap chain, this swap chain will contain the backbuffer for 1.250 + * the window we draw to. The front buffer is the full screen front 1.251 + * buffer. 1.252 + */ 1.253 + nsRefPtr<IDXGISwapChain1> swapChain1; 1.254 + hr = dxgiFactory->CreateSwapChainForCoreWindow( 1.255 + dxgiDevice, (IUnknown *)mWidget->GetNativeData(NS_NATIVE_ICOREWINDOW), 1.256 + &swapDesc, nullptr, getter_AddRefs(swapChain1)); 1.257 + if (FAILED(hr)) { 1.258 + SetHRESULT(aHresultPtr, hr); 1.259 + return false; 1.260 + } 1.261 + mSwapChain = swapChain1; 1.262 + } else 1.263 +#endif 1.264 + { 1.265 + nsRefPtr<IDXGIFactory> dxgiFactory; 1.266 + dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment())); 1.267 + 1.268 + DXGI_SWAP_CHAIN_DESC swapDesc; 1.269 + ::ZeroMemory(&swapDesc, sizeof(swapDesc)); 1.270 + swapDesc.BufferDesc.Width = 0; 1.271 + swapDesc.BufferDesc.Height = 0; 1.272 + swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 1.273 + swapDesc.BufferDesc.RefreshRate.Numerator = 60; 1.274 + swapDesc.BufferDesc.RefreshRate.Denominator = 1; 1.275 + swapDesc.SampleDesc.Count = 1; 1.276 + swapDesc.SampleDesc.Quality = 0; 1.277 + swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 1.278 + swapDesc.BufferCount = 1; 1.279 + swapDesc.OutputWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW); 1.280 + swapDesc.Windowed = TRUE; 1.281 + // We don't really need this flag, however it seems on some NVidia hardware 1.282 + // smaller area windows do not present properly without this flag. This flag 1.283 + // should have no negative consequences by itself. See bug 613790. This flag 1.284 + // is broken on optimus devices. As a temporary solution we don't set it 1.285 + // there, the only way of reliably detecting we're on optimus is looking for 1.286 + // the DLL. See Bug 623807. 1.287 + if (gfxWindowsPlatform::IsOptimus()) { 1.288 + swapDesc.Flags = 0; 1.289 + } else { 1.290 + swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE; 1.291 + } 1.292 + 1.293 + /** 1.294 + * Create a swap chain, this swap chain will contain the backbuffer for 1.295 + * the window we draw to. The front buffer is the full screen front 1.296 + * buffer. 1.297 + */ 1.298 + hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, getter_AddRefs(mSwapChain)); 1.299 + if (FAILED(hr)) { 1.300 + return false; 1.301 + } 1.302 + 1.303 + // We need this because we don't want DXGI to respond to Alt+Enter. 1.304 + dxgiFactory->MakeWindowAssociation(swapDesc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES); 1.305 + } 1.306 + 1.307 + reporter.SetSuccessful(); 1.308 + return true; 1.309 +} 1.310 + 1.311 +void 1.312 +LayerManagerD3D10::Destroy() 1.313 +{ 1.314 + if (!IsDestroyed()) { 1.315 + if (mRoot) { 1.316 + static_cast<LayerD3D10*>(mRoot->ImplData())->LayerManagerDestroyed(); 1.317 + } 1.318 + // XXX need to be careful here about surface destruction 1.319 + // racing with share-to-chrome message 1.320 + } 1.321 + LayerManager::Destroy(); 1.322 +} 1.323 + 1.324 +void 1.325 +LayerManagerD3D10::SetRoot(Layer *aRoot) 1.326 +{ 1.327 + mRoot = aRoot; 1.328 +} 1.329 + 1.330 +void 1.331 +LayerManagerD3D10::BeginTransaction() 1.332 +{ 1.333 + mInTransaction = true; 1.334 + 1.335 +#ifdef MOZ_LAYERS_HAVE_LOG 1.336 + MOZ_LAYERS_LOG(("[----- BeginTransaction")); 1.337 + Log(); 1.338 +#endif 1.339 +} 1.340 + 1.341 +void 1.342 +LayerManagerD3D10::BeginTransactionWithTarget(gfxContext* aTarget) 1.343 +{ 1.344 + mInTransaction = true; 1.345 + mTarget = aTarget; 1.346 +} 1.347 + 1.348 +bool 1.349 +LayerManagerD3D10::EndEmptyTransaction(EndTransactionFlags aFlags) 1.350 +{ 1.351 + mInTransaction = false; 1.352 + 1.353 + if (!mRoot) 1.354 + return false; 1.355 + 1.356 + EndTransaction(nullptr, nullptr, aFlags); 1.357 + return true; 1.358 +} 1.359 + 1.360 +void 1.361 +LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback, 1.362 + void* aCallbackData, 1.363 + EndTransactionFlags aFlags) 1.364 +{ 1.365 + mInTransaction = false; 1.366 + 1.367 + if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) { 1.368 + mCurrentCallbackInfo.Callback = aCallback; 1.369 + mCurrentCallbackInfo.CallbackData = aCallbackData; 1.370 + 1.371 + if (aFlags & END_NO_COMPOSITE) { 1.372 + // Apply pending tree updates before recomputing effective 1.373 + // properties. 1.374 + mRoot->ApplyPendingUpdatesToSubtree(); 1.375 + } 1.376 + 1.377 + // The results of our drawing always go directly into a pixel buffer, 1.378 + // so we don't need to pass any global transform here. 1.379 + mRoot->ComputeEffectiveTransforms(Matrix4x4()); 1.380 + 1.381 +#ifdef MOZ_LAYERS_HAVE_LOG 1.382 + MOZ_LAYERS_LOG((" ----- (beginning paint)")); 1.383 + Log(); 1.384 +#endif 1.385 + 1.386 + Render(aFlags); 1.387 + mCurrentCallbackInfo.Callback = nullptr; 1.388 + mCurrentCallbackInfo.CallbackData = nullptr; 1.389 + } 1.390 + 1.391 +#ifdef MOZ_LAYERS_HAVE_LOG 1.392 + Log(); 1.393 + MOZ_LAYERS_LOG(("]----- EndTransaction")); 1.394 +#endif 1.395 + 1.396 + mTarget = nullptr; 1.397 +} 1.398 + 1.399 +already_AddRefed<ThebesLayer> 1.400 +LayerManagerD3D10::CreateThebesLayer() 1.401 +{ 1.402 + nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D10(this); 1.403 + return layer.forget(); 1.404 +} 1.405 + 1.406 +already_AddRefed<ContainerLayer> 1.407 +LayerManagerD3D10::CreateContainerLayer() 1.408 +{ 1.409 + nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D10(this); 1.410 + return layer.forget(); 1.411 +} 1.412 + 1.413 +already_AddRefed<ImageLayer> 1.414 +LayerManagerD3D10::CreateImageLayer() 1.415 +{ 1.416 + nsRefPtr<ImageLayer> layer = new ImageLayerD3D10(this); 1.417 + return layer.forget(); 1.418 +} 1.419 + 1.420 +already_AddRefed<ColorLayer> 1.421 +LayerManagerD3D10::CreateColorLayer() 1.422 +{ 1.423 + nsRefPtr<ColorLayer> layer = new ColorLayerD3D10(this); 1.424 + return layer.forget(); 1.425 +} 1.426 + 1.427 +already_AddRefed<CanvasLayer> 1.428 +LayerManagerD3D10::CreateCanvasLayer() 1.429 +{ 1.430 + nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D10(this); 1.431 + return layer.forget(); 1.432 +} 1.433 + 1.434 +already_AddRefed<ReadbackLayer> 1.435 +LayerManagerD3D10::CreateReadbackLayer() 1.436 +{ 1.437 + nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D10(this); 1.438 + return layer.forget(); 1.439 +} 1.440 + 1.441 +static void ReleaseTexture(void *texture) 1.442 +{ 1.443 + static_cast<ID3D10Texture2D*>(texture)->Release(); 1.444 +} 1.445 + 1.446 +TemporaryRef<DrawTarget> 1.447 +LayerManagerD3D10::CreateOptimalDrawTarget(const IntSize &aSize, 1.448 + SurfaceFormat aFormat) 1.449 +{ 1.450 + if ((aFormat != SurfaceFormat::B8G8R8X8 && 1.451 + aFormat != SurfaceFormat::B8G8R8A8)) { 1.452 + return LayerManager::CreateOptimalDrawTarget(aSize, aFormat); 1.453 + } 1.454 + 1.455 + nsRefPtr<ID3D10Texture2D> texture; 1.456 + 1.457 + CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1); 1.458 + desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; 1.459 + desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE; 1.460 + 1.461 + HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)); 1.462 + 1.463 + if (FAILED(hr)) { 1.464 + NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!"); 1.465 + return LayerManager::CreateOptimalDrawTarget(aSize, aFormat); 1.466 + } 1.467 + 1.468 + RefPtr<DrawTarget> dt = 1.469 + Factory::CreateDrawTargetForD3D10Texture(texture, aFormat); 1.470 + 1.471 + if (!dt) { 1.472 + return LayerManager::CreateOptimalDrawTarget(aSize, aFormat); 1.473 + } 1.474 + 1.475 + return dt; 1.476 +} 1.477 + 1.478 + 1.479 +TemporaryRef<DrawTarget> 1.480 +LayerManagerD3D10::CreateOptimalMaskDrawTarget(const IntSize &aSize) 1.481 +{ 1.482 + return CreateOptimalDrawTarget(aSize, SurfaceFormat::B8G8R8A8); 1.483 +} 1.484 + 1.485 + 1.486 +TemporaryRef<DrawTarget> 1.487 +LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize, 1.488 + SurfaceFormat aFormat) 1.489 +{ 1.490 + if ((aFormat != SurfaceFormat::B8G8R8A8 && 1.491 + aFormat != SurfaceFormat::B8G8R8X8) || 1.492 + gfxPlatform::GetPlatform()->GetPreferredCanvasBackend() != BackendType::DIRECT2D) { 1.493 + return LayerManager::CreateDrawTarget(aSize, aFormat); 1.494 + } 1.495 + 1.496 + nsRefPtr<ID3D10Texture2D> texture; 1.497 + 1.498 + CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1); 1.499 + desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; 1.500 + 1.501 + HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)); 1.502 + 1.503 + if (FAILED(hr)) { 1.504 + NS_WARNING("Failed to create new texture for CreateOptimalDrawTarget!"); 1.505 + return LayerManager::CreateDrawTarget(aSize, aFormat); 1.506 + } 1.507 + 1.508 + RefPtr<DrawTarget> surface = 1.509 + Factory::CreateDrawTargetForD3D10Texture(texture, aFormat); 1.510 + 1.511 + if (!surface) { 1.512 + return LayerManager::CreateDrawTarget(aSize, aFormat); 1.513 + } 1.514 + 1.515 + return surface; 1.516 +} 1.517 + 1.518 +ReadbackManagerD3D10* 1.519 +LayerManagerD3D10::readbackManager() 1.520 +{ 1.521 + EnsureReadbackManager(); 1.522 + return mReadbackManager; 1.523 +} 1.524 + 1.525 +void 1.526 +LayerManagerD3D10::SetViewport(const nsIntSize &aViewport) 1.527 +{ 1.528 + mViewport = aViewport; 1.529 + 1.530 + D3D10_VIEWPORT viewport; 1.531 + viewport.MaxDepth = 1.0f; 1.532 + viewport.MinDepth = 0; 1.533 + viewport.Width = aViewport.width; 1.534 + viewport.Height = aViewport.height; 1.535 + viewport.TopLeftX = 0; 1.536 + viewport.TopLeftY = 0; 1.537 + 1.538 + mDevice->RSSetViewports(1, &viewport); 1.539 + 1.540 + gfx3DMatrix projection; 1.541 + /* 1.542 + * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, 1.543 + * <1.0, -1.0> bottomright) 1.544 + */ 1.545 + projection._11 = 2.0f / aViewport.width; 1.546 + projection._22 = -2.0f / aViewport.height; 1.547 + projection._33 = 0.0f; 1.548 + projection._41 = -1.0f; 1.549 + projection._42 = 1.0f; 1.550 + projection._44 = 1.0f; 1.551 + 1.552 + HRESULT hr = mEffect->GetVariableByName("mProjection")-> 1.553 + SetRawValue(&projection._11, 0, 64); 1.554 + 1.555 + if (FAILED(hr)) { 1.556 + NS_WARNING("Failed to set projection matrix."); 1.557 + } 1.558 +} 1.559 + 1.560 +void 1.561 +LayerManagerD3D10::SetupInputAssembler() 1.562 +{ 1.563 + mDevice->IASetInputLayout(mInputLayout); 1.564 + 1.565 + UINT stride = sizeof(Vertex); 1.566 + UINT offset = 0; 1.567 + ID3D10Buffer *buffer = mVertexBuffer; 1.568 + mDevice->IASetVertexBuffers(0, 1, &buffer, &stride, &offset); 1.569 + mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); 1.570 +} 1.571 + 1.572 +void 1.573 +LayerManagerD3D10::SetupPipeline() 1.574 +{ 1.575 + VerifyBufferSize(); 1.576 + UpdateRenderTarget(); 1.577 + 1.578 + nsIntRect rect; 1.579 + mWidget->GetClientBounds(rect); 1.580 + 1.581 + HRESULT hr; 1.582 + 1.583 + hr = mEffect->GetVariableByName("vTextureCoords")->AsVector()-> 1.584 + SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); 1.585 + 1.586 + if (FAILED(hr)) { 1.587 + NS_WARNING("Failed to set Texture Coordinates."); 1.588 + return; 1.589 + } 1.590 + 1.591 + ID3D10RenderTargetView *view = mRTView; 1.592 + mDevice->OMSetRenderTargets(1, &view, nullptr); 1.593 + 1.594 + SetupInputAssembler(); 1.595 + 1.596 + SetViewport(nsIntSize(rect.width, rect.height)); 1.597 +} 1.598 + 1.599 +void 1.600 +LayerManagerD3D10::UpdateRenderTarget() 1.601 +{ 1.602 + if (mRTView || !mSwapChain) { 1.603 + return; 1.604 + } 1.605 + 1.606 + HRESULT hr; 1.607 + 1.608 + nsRefPtr<ID3D10Texture2D> backBuf; 1.609 + hr = mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment()); 1.610 + if (FAILED(hr)) { 1.611 + return; 1.612 + } 1.613 + mDevice->CreateRenderTargetView(backBuf, nullptr, getter_AddRefs(mRTView)); 1.614 +} 1.615 + 1.616 +void 1.617 +LayerManagerD3D10::VerifyBufferSize() 1.618 +{ 1.619 + nsIntRect rect; 1.620 + mWidget->GetClientBounds(rect); 1.621 + 1.622 + if (mSwapChain) { 1.623 + DXGI_SWAP_CHAIN_DESC swapDesc; 1.624 + mSwapChain->GetDesc(&swapDesc); 1.625 + 1.626 + if (swapDesc.BufferDesc.Width == rect.width && 1.627 + swapDesc.BufferDesc.Height == rect.height) { 1.628 + return; 1.629 + } 1.630 + 1.631 + mRTView = nullptr; 1.632 + if (IsRunningInWindowsMetro()) { 1.633 + mSwapChain->ResizeBuffers(2, rect.width, rect.height, 1.634 + DXGI_FORMAT_B8G8R8A8_UNORM, 1.635 + 0); 1.636 + mDisableSequenceForNextFrame = true; 1.637 + } else if (gfxWindowsPlatform::IsOptimus()) { 1.638 + mSwapChain->ResizeBuffers(1, rect.width, rect.height, 1.639 + DXGI_FORMAT_B8G8R8A8_UNORM, 1.640 + 0); 1.641 + } else { 1.642 + mSwapChain->ResizeBuffers(1, rect.width, rect.height, 1.643 + DXGI_FORMAT_B8G8R8A8_UNORM, 1.644 + DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE); 1.645 + } 1.646 + } 1.647 +} 1.648 + 1.649 +void 1.650 +LayerManagerD3D10::EnsureReadbackManager() 1.651 +{ 1.652 + if (mReadbackManager) { 1.653 + return; 1.654 + } 1.655 + 1.656 + DeviceAttachments *attachments; 1.657 + UINT size = sizeof(DeviceAttachments*); 1.658 + if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) { 1.659 + // Strange! This shouldn't happen ... return a readback manager for this 1.660 + // layer manager only. 1.661 + mReadbackManager = new ReadbackManagerD3D10(); 1.662 + gfx::LogFailure(NS_LITERAL_CSTRING("Couldn't get device attachments for device.")); 1.663 + return; 1.664 + } 1.665 + 1.666 + if (attachments->mReadbackManager) { 1.667 + mReadbackManager = attachments->mReadbackManager; 1.668 + return; 1.669 + } 1.670 + 1.671 + mReadbackManager = new ReadbackManagerD3D10(); 1.672 + attachments->mReadbackManager = mReadbackManager; 1.673 +} 1.674 + 1.675 +void 1.676 +LayerManagerD3D10::Render(EndTransactionFlags aFlags) 1.677 +{ 1.678 + static_cast<LayerD3D10*>(mRoot->ImplData())->Validate(); 1.679 + 1.680 + if (aFlags & END_NO_COMPOSITE) { 1.681 + return; 1.682 + } 1.683 + 1.684 + SetupPipeline(); 1.685 + 1.686 + float black[] = { 0, 0, 0, 0 }; 1.687 + device()->ClearRenderTargetView(mRTView, black); 1.688 + 1.689 + nsIntRect rect; 1.690 + mWidget->GetClientBounds(rect); 1.691 + 1.692 + const nsIntRect *clipRect = mRoot->GetClipRect(); 1.693 + D3D10_RECT r; 1.694 + if (clipRect) { 1.695 + r.left = (LONG)clipRect->x; 1.696 + r.top = (LONG)clipRect->y; 1.697 + r.right = (LONG)(clipRect->x + clipRect->width); 1.698 + r.bottom = (LONG)(clipRect->y + clipRect->height); 1.699 + } else { 1.700 + r.left = r.top = 0; 1.701 + r.right = rect.width; 1.702 + r.bottom = rect.height; 1.703 + } 1.704 + device()->RSSetScissorRects(1, &r); 1.705 + 1.706 + static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer(); 1.707 + 1.708 + if (!mRegionToClear.IsEmpty()) { 1.709 + float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 1.710 + gfx::Matrix4x4 transform; 1.711 + effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform, 0, 64); 1.712 + effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color); 1.713 + 1.714 + ID3D10EffectTechnique *technique = effect()->GetTechniqueByName("RenderClearLayer"); 1.715 + 1.716 + nsIntRegionRectIterator iter(mRegionToClear); 1.717 + const nsIntRect *r; 1.718 + while ((r = iter.Next())) { 1.719 + effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector( 1.720 + ShaderConstantRectD3D10( 1.721 + (float)r->x, 1.722 + (float)r->y, 1.723 + (float)r->width, 1.724 + (float)r->height) 1.725 + ); 1.726 + 1.727 + technique->GetPassByIndex(0)->Apply(0); 1.728 + device()->Draw(4, 0); 1.729 + } 1.730 + } 1.731 + 1.732 + // See bug 630197 - we have some reasons to believe if an earlier call 1.733 + // returned an error, the upcoming present call may raise an exception. 1.734 + // This will check if any of the calls done recently has returned an error 1.735 + // and bails on composition. On the -next- frame we will then abandon 1.736 + // hardware acceleration from gfxWindowsPlatform::VerifyD2DDevice. 1.737 + // This might not be the 'optimal' solution but it will help us assert 1.738 + // whether our thoughts of the causes of the issues are correct. 1.739 + if (FAILED(mDevice->GetDeviceRemovedReason())) { 1.740 + return; 1.741 + } 1.742 + 1.743 + if (mTarget) { 1.744 + PaintToTarget(); 1.745 + } else { 1.746 + mSwapChain->Present(0, mDisableSequenceForNextFrame ? DXGI_PRESENT_DO_NOT_SEQUENCE : 0); 1.747 + mDisableSequenceForNextFrame = false; 1.748 + } 1.749 + RecordFrame(); 1.750 + PostPresent(); 1.751 +} 1.752 + 1.753 +void 1.754 +LayerManagerD3D10::PaintToTarget() 1.755 +{ 1.756 + nsRefPtr<ID3D10Texture2D> backBuf; 1.757 + 1.758 + mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment()); 1.759 + 1.760 + D3D10_TEXTURE2D_DESC bbDesc; 1.761 + backBuf->GetDesc(&bbDesc); 1.762 + 1.763 + CD3D10_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height); 1.764 + softDesc.MipLevels = 1; 1.765 + softDesc.CPUAccessFlags = D3D10_CPU_ACCESS_READ; 1.766 + softDesc.Usage = D3D10_USAGE_STAGING; 1.767 + softDesc.BindFlags = 0; 1.768 + 1.769 + nsRefPtr<ID3D10Texture2D> readTexture; 1.770 + 1.771 + HRESULT hr = device()->CreateTexture2D(&softDesc, nullptr, getter_AddRefs(readTexture)); 1.772 + if (FAILED(hr)) { 1.773 + ReportFailure(NS_LITERAL_CSTRING("LayerManagerD3D10::PaintToTarget(): Failed to create texture"), 1.774 + hr); 1.775 + return; 1.776 + } 1.777 + 1.778 + device()->CopyResource(readTexture, backBuf); 1.779 + 1.780 + D3D10_MAPPED_TEXTURE2D map; 1.781 + readTexture->Map(0, D3D10_MAP_READ, 0, &map); 1.782 + 1.783 + nsRefPtr<gfxImageSurface> tmpSurface = 1.784 + new gfxImageSurface((unsigned char*)map.pData, 1.785 + gfxIntSize(bbDesc.Width, bbDesc.Height), 1.786 + map.RowPitch, 1.787 + gfxImageFormat::ARGB32); 1.788 + 1.789 + mTarget->SetSource(tmpSurface); 1.790 + mTarget->SetOperator(gfxContext::OPERATOR_OVER); 1.791 + mTarget->Paint(); 1.792 + 1.793 + readTexture->Unmap(0); 1.794 +} 1.795 + 1.796 +void 1.797 +LayerManagerD3D10::ReportFailure(const nsACString &aMsg, HRESULT aCode) 1.798 +{ 1.799 + // We could choose to abort here when hr == E_OUTOFMEMORY. 1.800 + nsCString msg; 1.801 + msg.Append(aMsg); 1.802 + msg.AppendLiteral(" Error code: "); 1.803 + msg.AppendInt(uint32_t(aCode)); 1.804 + NS_WARNING(msg.BeginReading()); 1.805 + 1.806 + gfx::LogFailure(msg); 1.807 +} 1.808 + 1.809 +LayerD3D10::LayerD3D10(LayerManagerD3D10 *aManager) 1.810 + : mD3DManager(aManager) 1.811 +{ 1.812 +} 1.813 + 1.814 +ID3D10EffectTechnique* 1.815 +LayerD3D10::SelectShader(uint8_t aFlags) 1.816 +{ 1.817 + switch (aFlags) { 1.818 + case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_MASK): 1.819 + return effect()->GetTechniqueByName("RenderRGBALayerNonPremulMask"); 1.820 + case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_LINEAR | SHADER_NO_MASK): 1.821 + return effect()->GetTechniqueByName("RenderRGBALayerNonPremul"); 1.822 + case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_NO_MASK): 1.823 + return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPoint"); 1.824 + case (SHADER_RGBA | SHADER_NON_PREMUL | SHADER_POINT | SHADER_MASK): 1.825 + return effect()->GetTechniqueByName("RenderRGBALayerNonPremulPointMask"); 1.826 + case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK_3D): 1.827 + return effect()->GetTechniqueByName("RenderRGBALayerPremulMask3D"); 1.828 + case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK): 1.829 + return effect()->GetTechniqueByName("RenderRGBALayerPremulMask"); 1.830 + case (SHADER_RGBA | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK): 1.831 + return effect()->GetTechniqueByName("RenderRGBALayerPremul"); 1.832 + case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_MASK): 1.833 + return effect()->GetTechniqueByName("RenderRGBALayerPremulPointMask"); 1.834 + case (SHADER_RGBA | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK): 1.835 + return effect()->GetTechniqueByName("RenderRGBALayerPremulPoint"); 1.836 + case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_MASK): 1.837 + return effect()->GetTechniqueByName("RenderRGBLayerPremulPointMask"); 1.838 + case (SHADER_RGB | SHADER_PREMUL | SHADER_POINT | SHADER_NO_MASK): 1.839 + return effect()->GetTechniqueByName("RenderRGBLayerPremulPoint"); 1.840 + case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_MASK): 1.841 + return effect()->GetTechniqueByName("RenderRGBLayerPremulMask"); 1.842 + case (SHADER_RGB | SHADER_PREMUL | SHADER_LINEAR | SHADER_NO_MASK): 1.843 + return effect()->GetTechniqueByName("RenderRGBLayerPremul"); 1.844 + case (SHADER_SOLID | SHADER_MASK): 1.845 + return effect()->GetTechniqueByName("RenderSolidColorLayerMask"); 1.846 + case (SHADER_SOLID | SHADER_NO_MASK): 1.847 + return effect()->GetTechniqueByName("RenderSolidColorLayer"); 1.848 + case (SHADER_COMPONENT_ALPHA | SHADER_MASK): 1.849 + return effect()->GetTechniqueByName("RenderComponentAlphaLayerMask"); 1.850 + case (SHADER_COMPONENT_ALPHA | SHADER_NO_MASK): 1.851 + return effect()->GetTechniqueByName("RenderComponentAlphaLayer"); 1.852 + case (SHADER_YCBCR | SHADER_MASK): 1.853 + return effect()->GetTechniqueByName("RenderYCbCrLayerMask"); 1.854 + case (SHADER_YCBCR | SHADER_NO_MASK): 1.855 + return effect()->GetTechniqueByName("RenderYCbCrLayer"); 1.856 + default: 1.857 + NS_ERROR("Invalid shader."); 1.858 + return nullptr; 1.859 + } 1.860 +} 1.861 + 1.862 +uint8_t 1.863 +LayerD3D10::LoadMaskTexture() 1.864 +{ 1.865 + if (Layer* maskLayer = GetLayer()->GetMaskLayer()) { 1.866 + IntSize size; 1.867 + nsRefPtr<ID3D10ShaderResourceView> maskSRV = 1.868 + static_cast<LayerD3D10*>(maskLayer->ImplData())->GetAsTexture(&size); 1.869 + 1.870 + if (!maskSRV) { 1.871 + return SHADER_NO_MASK; 1.872 + } 1.873 + 1.874 + Matrix maskTransform; 1.875 + Matrix4x4 effectiveTransform = maskLayer->GetEffectiveTransform(); 1.876 + bool maskIs2D = effectiveTransform.CanDraw2D(&maskTransform); 1.877 + NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!"); 1.878 + Rect bounds = Rect(Point(), Size(size)); 1.879 + bounds = maskTransform.TransformBounds(bounds); 1.880 + 1.881 + effect()->GetVariableByName("vMaskQuad")->AsVector()->SetFloatVector( 1.882 + ShaderConstantRectD3D10( 1.883 + (float)bounds.x, 1.884 + (float)bounds.y, 1.885 + (float)bounds.width, 1.886 + (float)bounds.height) 1.887 + ); 1.888 + 1.889 + effect()->GetVariableByName("tMask")->AsShaderResource()->SetResource(maskSRV); 1.890 + return SHADER_MASK; 1.891 + } 1.892 + 1.893 + return SHADER_NO_MASK; 1.894 +} 1.895 + 1.896 +} 1.897 +}