1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,375 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 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 "LayerManagerD3D9.h" 1.10 + 1.11 +#include "ThebesLayerD3D9.h" 1.12 +#include "ContainerLayerD3D9.h" 1.13 +#include "ImageLayerD3D9.h" 1.14 +#include "ColorLayerD3D9.h" 1.15 +#include "CanvasLayerD3D9.h" 1.16 +#include "ReadbackLayerD3D9.h" 1.17 +#include "gfxWindowsPlatform.h" 1.18 +#include "nsIGfxInfo.h" 1.19 +#include "nsServiceManagerUtils.h" 1.20 +#include "gfxFailure.h" 1.21 +#include "gfxPrefs.h" 1.22 + 1.23 +#include "gfxCrashReporterUtils.h" 1.24 + 1.25 +namespace mozilla { 1.26 +namespace layers { 1.27 + 1.28 +LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget) 1.29 + : mWidget(aWidget) 1.30 + , mDeviceResetCount(0) 1.31 +{ 1.32 + mCurrentCallbackInfo.Callback = nullptr; 1.33 + mCurrentCallbackInfo.CallbackData = nullptr; 1.34 +} 1.35 + 1.36 +LayerManagerD3D9::~LayerManagerD3D9() 1.37 +{ 1.38 + Destroy(); 1.39 +} 1.40 + 1.41 +bool 1.42 +LayerManagerD3D9::Initialize(bool force) 1.43 +{ 1.44 + ScopedGfxFeatureReporter reporter("D3D9 Layers", force); 1.45 + 1.46 + /* XXX: this preference and blacklist code should move out of the layer manager */ 1.47 + bool forceAccelerate = gfxPrefs::LayersAccelerationForceEnabled(); 1.48 + 1.49 + nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); 1.50 + if (gfxInfo) { 1.51 + int32_t status; 1.52 + if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) { 1.53 + if (status != nsIGfxInfo::FEATURE_NO_INFO && !forceAccelerate) 1.54 + { 1.55 + NS_WARNING("Direct3D 9-accelerated layers are not supported on this system."); 1.56 + return false; 1.57 + } 1.58 + } 1.59 + } 1.60 + 1.61 + mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager(); 1.62 + if (!mDeviceManager) { 1.63 + return false; 1.64 + } 1.65 + 1.66 + mSwapChain = mDeviceManager-> 1.67 + CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW)); 1.68 + 1.69 + if (!mSwapChain) { 1.70 + return false; 1.71 + } 1.72 + 1.73 + reporter.SetSuccessful(); 1.74 + return true; 1.75 +} 1.76 + 1.77 +void 1.78 +LayerManagerD3D9::SetClippingRegion(const nsIntRegion &aClippingRegion) 1.79 +{ 1.80 + mClippingRegion = aClippingRegion; 1.81 +} 1.82 + 1.83 +void 1.84 +LayerManagerD3D9::Destroy() 1.85 +{ 1.86 + if (!IsDestroyed()) { 1.87 + if (mRoot) { 1.88 + static_cast<LayerD3D9*>(mRoot->ImplData())->LayerManagerDestroyed(); 1.89 + } 1.90 + /* Important to release this first since it also holds a reference to the 1.91 + * device manager 1.92 + */ 1.93 + mSwapChain = nullptr; 1.94 + mDeviceManager = nullptr; 1.95 + } 1.96 + LayerManager::Destroy(); 1.97 +} 1.98 + 1.99 +void 1.100 +LayerManagerD3D9::BeginTransaction() 1.101 +{ 1.102 + mInTransaction = true; 1.103 +} 1.104 + 1.105 +void 1.106 +LayerManagerD3D9::BeginTransactionWithTarget(gfxContext *aTarget) 1.107 +{ 1.108 + mInTransaction = true; 1.109 + mTarget = aTarget; 1.110 +} 1.111 + 1.112 +void 1.113 +LayerManagerD3D9::EndConstruction() 1.114 +{ 1.115 +} 1.116 + 1.117 +bool 1.118 +LayerManagerD3D9::EndEmptyTransaction(EndTransactionFlags aFlags) 1.119 +{ 1.120 + mInTransaction = false; 1.121 + 1.122 + // If the device reset count from our last EndTransaction doesn't match 1.123 + // the current device reset count, the device must have been reset one or 1.124 + // more times since our last transaction. In that case, an empty transaction 1.125 + // is not possible, because layers may need to be rerendered. 1.126 + if (!mRoot || mDeviceResetCount != mDeviceManager->GetDeviceResetCount()) 1.127 + return false; 1.128 + 1.129 + EndTransaction(nullptr, nullptr, aFlags); 1.130 + return true; 1.131 +} 1.132 + 1.133 +void 1.134 +LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback, 1.135 + void* aCallbackData, 1.136 + EndTransactionFlags aFlags) 1.137 +{ 1.138 + mInTransaction = false; 1.139 + 1.140 + mDeviceResetCount = mDeviceManager->GetDeviceResetCount(); 1.141 + 1.142 + if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) { 1.143 + mCurrentCallbackInfo.Callback = aCallback; 1.144 + mCurrentCallbackInfo.CallbackData = aCallbackData; 1.145 + 1.146 + if (aFlags & END_NO_COMPOSITE) { 1.147 + // Apply pending tree updates before recomputing effective 1.148 + // properties. 1.149 + mRoot->ApplyPendingUpdatesToSubtree(); 1.150 + } 1.151 + 1.152 + // The results of our drawing always go directly into a pixel buffer, 1.153 + // so we don't need to pass any global transform here. 1.154 + mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4()); 1.155 + 1.156 + SetCompositingDisabled(aFlags & END_NO_COMPOSITE); 1.157 + Render(); 1.158 + /* Clean this out for sanity */ 1.159 + mCurrentCallbackInfo.Callback = nullptr; 1.160 + mCurrentCallbackInfo.CallbackData = nullptr; 1.161 + } 1.162 + 1.163 + // Clear mTarget, next transaction could have no target 1.164 + mTarget = nullptr; 1.165 +} 1.166 + 1.167 +void 1.168 +LayerManagerD3D9::SetRoot(Layer *aLayer) 1.169 +{ 1.170 + mRoot = aLayer; 1.171 +} 1.172 + 1.173 +already_AddRefed<ThebesLayer> 1.174 +LayerManagerD3D9::CreateThebesLayer() 1.175 +{ 1.176 + nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D9(this); 1.177 + return layer.forget(); 1.178 +} 1.179 + 1.180 +already_AddRefed<ContainerLayer> 1.181 +LayerManagerD3D9::CreateContainerLayer() 1.182 +{ 1.183 + nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D9(this); 1.184 + return layer.forget(); 1.185 +} 1.186 + 1.187 +already_AddRefed<ImageLayer> 1.188 +LayerManagerD3D9::CreateImageLayer() 1.189 +{ 1.190 + nsRefPtr<ImageLayer> layer = new ImageLayerD3D9(this); 1.191 + return layer.forget(); 1.192 +} 1.193 + 1.194 +already_AddRefed<ColorLayer> 1.195 +LayerManagerD3D9::CreateColorLayer() 1.196 +{ 1.197 + nsRefPtr<ColorLayer> layer = new ColorLayerD3D9(this); 1.198 + return layer.forget(); 1.199 +} 1.200 + 1.201 +already_AddRefed<CanvasLayer> 1.202 +LayerManagerD3D9::CreateCanvasLayer() 1.203 +{ 1.204 + nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D9(this); 1.205 + return layer.forget(); 1.206 +} 1.207 + 1.208 +already_AddRefed<ReadbackLayer> 1.209 +LayerManagerD3D9::CreateReadbackLayer() 1.210 +{ 1.211 + nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D9(this); 1.212 + return layer.forget(); 1.213 +} 1.214 + 1.215 +void 1.216 +LayerManagerD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode) 1.217 +{ 1.218 + // We could choose to abort here when hr == E_OUTOFMEMORY. 1.219 + nsCString msg; 1.220 + msg.Append(aMsg); 1.221 + msg.AppendLiteral(" Error code: "); 1.222 + msg.AppendInt(uint32_t(aCode)); 1.223 + NS_WARNING(msg.BeginReading()); 1.224 + 1.225 + gfx::LogFailure(msg); 1.226 +} 1.227 + 1.228 +void 1.229 +LayerManagerD3D9::Render() 1.230 +{ 1.231 + if (mSwapChain->PrepareForRendering() != DeviceOK) { 1.232 + return; 1.233 + } 1.234 + 1.235 + deviceManager()->SetupRenderState(); 1.236 + 1.237 + SetupPipeline(); 1.238 + 1.239 + if (CompositingDisabled()) { 1.240 + static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer(); 1.241 + return; 1.242 + } 1.243 + 1.244 + nsIntRect rect; 1.245 + mWidget->GetClientBounds(rect); 1.246 + 1.247 + device()->Clear(0, nullptr, D3DCLEAR_TARGET, 0x00000000, 0, 0); 1.248 + 1.249 + device()->BeginScene(); 1.250 + 1.251 + const nsIntRect *clipRect = mRoot->GetClipRect(); 1.252 + RECT r; 1.253 + if (clipRect) { 1.254 + r.left = (LONG)clipRect->x; 1.255 + r.top = (LONG)clipRect->y; 1.256 + r.right = (LONG)(clipRect->x + clipRect->width); 1.257 + r.bottom = (LONG)(clipRect->y + clipRect->height); 1.258 + } else { 1.259 + r.left = r.top = 0; 1.260 + r.right = rect.width; 1.261 + r.bottom = rect.height; 1.262 + } 1.263 + device()->SetScissorRect(&r); 1.264 + 1.265 + static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer(); 1.266 + 1.267 + if (!mRegionToClear.IsEmpty()) { 1.268 + D3DRECT* rects = new D3DRECT[mRegionToClear.GetNumRects()]; 1.269 + nsIntRegionRectIterator iter(mRegionToClear); 1.270 + const nsIntRect *r; 1.271 + size_t i = 0; 1.272 + while ((r = iter.Next())) { 1.273 + rects[i].x1 = r->x; 1.274 + rects[i].y1 = r->y; 1.275 + rects[i].x2 = r->x + r->width; 1.276 + rects[i].y2 = r->y + r->height; 1.277 + i++; 1.278 + } 1.279 + 1.280 + device()->Clear(i, rects, D3DCLEAR_TARGET, 1.281 + 0x00000000, 0, 0); 1.282 + 1.283 + delete [] rects; 1.284 + } 1.285 + 1.286 + device()->EndScene(); 1.287 + 1.288 + if (!mTarget) { 1.289 + const nsIntRect *r; 1.290 + for (nsIntRegionRectIterator iter(mClippingRegion); 1.291 + (r = iter.Next()) != nullptr;) { 1.292 + mSwapChain->Present(*r); 1.293 + } 1.294 + RecordFrame(); 1.295 + PostPresent(); 1.296 + } else { 1.297 + PaintToTarget(); 1.298 + } 1.299 +} 1.300 + 1.301 +void 1.302 +LayerManagerD3D9::SetupPipeline() 1.303 +{ 1.304 + nsIntRect rect; 1.305 + mWidget->GetClientBounds(rect); 1.306 + 1.307 + gfx3DMatrix viewMatrix; 1.308 + /* 1.309 + * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, 1.310 + * <1.0, -1.0> bottomright) 1.311 + */ 1.312 + viewMatrix._11 = 2.0f / rect.width; 1.313 + viewMatrix._22 = -2.0f / rect.height; 1.314 + viewMatrix._33 = 0.0f; 1.315 + viewMatrix._41 = -1.0f; 1.316 + viewMatrix._42 = 1.0f; 1.317 + 1.318 + HRESULT hr = device()->SetVertexShaderConstantF(CBmProjection, 1.319 + &viewMatrix._11, 4); 1.320 + 1.321 + if (FAILED(hr)) { 1.322 + NS_WARNING("Failed to set projection shader constant!"); 1.323 + } 1.324 + 1.325 + hr = device()->SetVertexShaderConstantF(CBvTextureCoords, 1.326 + ShaderConstantRect(0, 0, 1.0f, 1.0f), 1.327 + 1); 1.328 + 1.329 + if (FAILED(hr)) { 1.330 + NS_WARNING("Failed to set texCoords shader constant!"); 1.331 + } 1.332 + 1.333 + float offset[] = { 0, 0, 0, 0 }; 1.334 + hr = device()->SetVertexShaderConstantF(CBvRenderTargetOffset, offset, 1); 1.335 + 1.336 + if (FAILED(hr)) { 1.337 + NS_WARNING("Failed to set RenderTargetOffset shader constant!"); 1.338 + } 1.339 +} 1.340 + 1.341 +void 1.342 +LayerManagerD3D9::PaintToTarget() 1.343 +{ 1.344 + nsRefPtr<IDirect3DSurface9> backBuff; 1.345 + nsRefPtr<IDirect3DSurface9> destSurf; 1.346 + device()->GetRenderTarget(0, getter_AddRefs(backBuff)); 1.347 + 1.348 + D3DSURFACE_DESC desc; 1.349 + backBuff->GetDesc(&desc); 1.350 + 1.351 + device()->CreateOffscreenPlainSurface(desc.Width, desc.Height, 1.352 + D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, 1.353 + getter_AddRefs(destSurf), nullptr); 1.354 + 1.355 + device()->GetRenderTargetData(backBuff, destSurf); 1.356 + 1.357 + D3DLOCKED_RECT rect; 1.358 + destSurf->LockRect(&rect, nullptr, D3DLOCK_READONLY); 1.359 + 1.360 + nsRefPtr<gfxImageSurface> imageSurface = 1.361 + new gfxImageSurface((unsigned char*)rect.pBits, 1.362 + gfxIntSize(desc.Width, desc.Height), 1.363 + rect.Pitch, 1.364 + gfxImageFormat::ARGB32); 1.365 + 1.366 + mTarget->SetSource(imageSurface); 1.367 + mTarget->SetOperator(gfxContext::OPERATOR_OVER); 1.368 + mTarget->Paint(); 1.369 + destSurf->UnlockRect(); 1.370 +} 1.371 + 1.372 +LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager) 1.373 + : mD3DManager(aManager) 1.374 +{ 1.375 +} 1.376 + 1.377 +} /* namespace layers */ 1.378 +} /* namespace mozilla */