gfx/layers/d3d9/LayerManagerD3D9.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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 "LayerManagerD3D9.h"
michael@0 7
michael@0 8 #include "ThebesLayerD3D9.h"
michael@0 9 #include "ContainerLayerD3D9.h"
michael@0 10 #include "ImageLayerD3D9.h"
michael@0 11 #include "ColorLayerD3D9.h"
michael@0 12 #include "CanvasLayerD3D9.h"
michael@0 13 #include "ReadbackLayerD3D9.h"
michael@0 14 #include "gfxWindowsPlatform.h"
michael@0 15 #include "nsIGfxInfo.h"
michael@0 16 #include "nsServiceManagerUtils.h"
michael@0 17 #include "gfxFailure.h"
michael@0 18 #include "gfxPrefs.h"
michael@0 19
michael@0 20 #include "gfxCrashReporterUtils.h"
michael@0 21
michael@0 22 namespace mozilla {
michael@0 23 namespace layers {
michael@0 24
michael@0 25 LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
michael@0 26 : mWidget(aWidget)
michael@0 27 , mDeviceResetCount(0)
michael@0 28 {
michael@0 29 mCurrentCallbackInfo.Callback = nullptr;
michael@0 30 mCurrentCallbackInfo.CallbackData = nullptr;
michael@0 31 }
michael@0 32
michael@0 33 LayerManagerD3D9::~LayerManagerD3D9()
michael@0 34 {
michael@0 35 Destroy();
michael@0 36 }
michael@0 37
michael@0 38 bool
michael@0 39 LayerManagerD3D9::Initialize(bool force)
michael@0 40 {
michael@0 41 ScopedGfxFeatureReporter reporter("D3D9 Layers", force);
michael@0 42
michael@0 43 /* XXX: this preference and blacklist code should move out of the layer manager */
michael@0 44 bool forceAccelerate = gfxPrefs::LayersAccelerationForceEnabled();
michael@0 45
michael@0 46 nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
michael@0 47 if (gfxInfo) {
michael@0 48 int32_t status;
michael@0 49 if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status))) {
michael@0 50 if (status != nsIGfxInfo::FEATURE_NO_INFO && !forceAccelerate)
michael@0 51 {
michael@0 52 NS_WARNING("Direct3D 9-accelerated layers are not supported on this system.");
michael@0 53 return false;
michael@0 54 }
michael@0 55 }
michael@0 56 }
michael@0 57
michael@0 58 mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
michael@0 59 if (!mDeviceManager) {
michael@0 60 return false;
michael@0 61 }
michael@0 62
michael@0 63 mSwapChain = mDeviceManager->
michael@0 64 CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
michael@0 65
michael@0 66 if (!mSwapChain) {
michael@0 67 return false;
michael@0 68 }
michael@0 69
michael@0 70 reporter.SetSuccessful();
michael@0 71 return true;
michael@0 72 }
michael@0 73
michael@0 74 void
michael@0 75 LayerManagerD3D9::SetClippingRegion(const nsIntRegion &aClippingRegion)
michael@0 76 {
michael@0 77 mClippingRegion = aClippingRegion;
michael@0 78 }
michael@0 79
michael@0 80 void
michael@0 81 LayerManagerD3D9::Destroy()
michael@0 82 {
michael@0 83 if (!IsDestroyed()) {
michael@0 84 if (mRoot) {
michael@0 85 static_cast<LayerD3D9*>(mRoot->ImplData())->LayerManagerDestroyed();
michael@0 86 }
michael@0 87 /* Important to release this first since it also holds a reference to the
michael@0 88 * device manager
michael@0 89 */
michael@0 90 mSwapChain = nullptr;
michael@0 91 mDeviceManager = nullptr;
michael@0 92 }
michael@0 93 LayerManager::Destroy();
michael@0 94 }
michael@0 95
michael@0 96 void
michael@0 97 LayerManagerD3D9::BeginTransaction()
michael@0 98 {
michael@0 99 mInTransaction = true;
michael@0 100 }
michael@0 101
michael@0 102 void
michael@0 103 LayerManagerD3D9::BeginTransactionWithTarget(gfxContext *aTarget)
michael@0 104 {
michael@0 105 mInTransaction = true;
michael@0 106 mTarget = aTarget;
michael@0 107 }
michael@0 108
michael@0 109 void
michael@0 110 LayerManagerD3D9::EndConstruction()
michael@0 111 {
michael@0 112 }
michael@0 113
michael@0 114 bool
michael@0 115 LayerManagerD3D9::EndEmptyTransaction(EndTransactionFlags aFlags)
michael@0 116 {
michael@0 117 mInTransaction = false;
michael@0 118
michael@0 119 // If the device reset count from our last EndTransaction doesn't match
michael@0 120 // the current device reset count, the device must have been reset one or
michael@0 121 // more times since our last transaction. In that case, an empty transaction
michael@0 122 // is not possible, because layers may need to be rerendered.
michael@0 123 if (!mRoot || mDeviceResetCount != mDeviceManager->GetDeviceResetCount())
michael@0 124 return false;
michael@0 125
michael@0 126 EndTransaction(nullptr, nullptr, aFlags);
michael@0 127 return true;
michael@0 128 }
michael@0 129
michael@0 130 void
michael@0 131 LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback,
michael@0 132 void* aCallbackData,
michael@0 133 EndTransactionFlags aFlags)
michael@0 134 {
michael@0 135 mInTransaction = false;
michael@0 136
michael@0 137 mDeviceResetCount = mDeviceManager->GetDeviceResetCount();
michael@0 138
michael@0 139 if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
michael@0 140 mCurrentCallbackInfo.Callback = aCallback;
michael@0 141 mCurrentCallbackInfo.CallbackData = aCallbackData;
michael@0 142
michael@0 143 if (aFlags & END_NO_COMPOSITE) {
michael@0 144 // Apply pending tree updates before recomputing effective
michael@0 145 // properties.
michael@0 146 mRoot->ApplyPendingUpdatesToSubtree();
michael@0 147 }
michael@0 148
michael@0 149 // The results of our drawing always go directly into a pixel buffer,
michael@0 150 // so we don't need to pass any global transform here.
michael@0 151 mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
michael@0 152
michael@0 153 SetCompositingDisabled(aFlags & END_NO_COMPOSITE);
michael@0 154 Render();
michael@0 155 /* Clean this out for sanity */
michael@0 156 mCurrentCallbackInfo.Callback = nullptr;
michael@0 157 mCurrentCallbackInfo.CallbackData = nullptr;
michael@0 158 }
michael@0 159
michael@0 160 // Clear mTarget, next transaction could have no target
michael@0 161 mTarget = nullptr;
michael@0 162 }
michael@0 163
michael@0 164 void
michael@0 165 LayerManagerD3D9::SetRoot(Layer *aLayer)
michael@0 166 {
michael@0 167 mRoot = aLayer;
michael@0 168 }
michael@0 169
michael@0 170 already_AddRefed<ThebesLayer>
michael@0 171 LayerManagerD3D9::CreateThebesLayer()
michael@0 172 {
michael@0 173 nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D9(this);
michael@0 174 return layer.forget();
michael@0 175 }
michael@0 176
michael@0 177 already_AddRefed<ContainerLayer>
michael@0 178 LayerManagerD3D9::CreateContainerLayer()
michael@0 179 {
michael@0 180 nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D9(this);
michael@0 181 return layer.forget();
michael@0 182 }
michael@0 183
michael@0 184 already_AddRefed<ImageLayer>
michael@0 185 LayerManagerD3D9::CreateImageLayer()
michael@0 186 {
michael@0 187 nsRefPtr<ImageLayer> layer = new ImageLayerD3D9(this);
michael@0 188 return layer.forget();
michael@0 189 }
michael@0 190
michael@0 191 already_AddRefed<ColorLayer>
michael@0 192 LayerManagerD3D9::CreateColorLayer()
michael@0 193 {
michael@0 194 nsRefPtr<ColorLayer> layer = new ColorLayerD3D9(this);
michael@0 195 return layer.forget();
michael@0 196 }
michael@0 197
michael@0 198 already_AddRefed<CanvasLayer>
michael@0 199 LayerManagerD3D9::CreateCanvasLayer()
michael@0 200 {
michael@0 201 nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D9(this);
michael@0 202 return layer.forget();
michael@0 203 }
michael@0 204
michael@0 205 already_AddRefed<ReadbackLayer>
michael@0 206 LayerManagerD3D9::CreateReadbackLayer()
michael@0 207 {
michael@0 208 nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D9(this);
michael@0 209 return layer.forget();
michael@0 210 }
michael@0 211
michael@0 212 void
michael@0 213 LayerManagerD3D9::ReportFailure(const nsACString &aMsg, HRESULT aCode)
michael@0 214 {
michael@0 215 // We could choose to abort here when hr == E_OUTOFMEMORY.
michael@0 216 nsCString msg;
michael@0 217 msg.Append(aMsg);
michael@0 218 msg.AppendLiteral(" Error code: ");
michael@0 219 msg.AppendInt(uint32_t(aCode));
michael@0 220 NS_WARNING(msg.BeginReading());
michael@0 221
michael@0 222 gfx::LogFailure(msg);
michael@0 223 }
michael@0 224
michael@0 225 void
michael@0 226 LayerManagerD3D9::Render()
michael@0 227 {
michael@0 228 if (mSwapChain->PrepareForRendering() != DeviceOK) {
michael@0 229 return;
michael@0 230 }
michael@0 231
michael@0 232 deviceManager()->SetupRenderState();
michael@0 233
michael@0 234 SetupPipeline();
michael@0 235
michael@0 236 if (CompositingDisabled()) {
michael@0 237 static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
michael@0 238 return;
michael@0 239 }
michael@0 240
michael@0 241 nsIntRect rect;
michael@0 242 mWidget->GetClientBounds(rect);
michael@0 243
michael@0 244 device()->Clear(0, nullptr, D3DCLEAR_TARGET, 0x00000000, 0, 0);
michael@0 245
michael@0 246 device()->BeginScene();
michael@0 247
michael@0 248 const nsIntRect *clipRect = mRoot->GetClipRect();
michael@0 249 RECT r;
michael@0 250 if (clipRect) {
michael@0 251 r.left = (LONG)clipRect->x;
michael@0 252 r.top = (LONG)clipRect->y;
michael@0 253 r.right = (LONG)(clipRect->x + clipRect->width);
michael@0 254 r.bottom = (LONG)(clipRect->y + clipRect->height);
michael@0 255 } else {
michael@0 256 r.left = r.top = 0;
michael@0 257 r.right = rect.width;
michael@0 258 r.bottom = rect.height;
michael@0 259 }
michael@0 260 device()->SetScissorRect(&r);
michael@0 261
michael@0 262 static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
michael@0 263
michael@0 264 if (!mRegionToClear.IsEmpty()) {
michael@0 265 D3DRECT* rects = new D3DRECT[mRegionToClear.GetNumRects()];
michael@0 266 nsIntRegionRectIterator iter(mRegionToClear);
michael@0 267 const nsIntRect *r;
michael@0 268 size_t i = 0;
michael@0 269 while ((r = iter.Next())) {
michael@0 270 rects[i].x1 = r->x;
michael@0 271 rects[i].y1 = r->y;
michael@0 272 rects[i].x2 = r->x + r->width;
michael@0 273 rects[i].y2 = r->y + r->height;
michael@0 274 i++;
michael@0 275 }
michael@0 276
michael@0 277 device()->Clear(i, rects, D3DCLEAR_TARGET,
michael@0 278 0x00000000, 0, 0);
michael@0 279
michael@0 280 delete [] rects;
michael@0 281 }
michael@0 282
michael@0 283 device()->EndScene();
michael@0 284
michael@0 285 if (!mTarget) {
michael@0 286 const nsIntRect *r;
michael@0 287 for (nsIntRegionRectIterator iter(mClippingRegion);
michael@0 288 (r = iter.Next()) != nullptr;) {
michael@0 289 mSwapChain->Present(*r);
michael@0 290 }
michael@0 291 RecordFrame();
michael@0 292 PostPresent();
michael@0 293 } else {
michael@0 294 PaintToTarget();
michael@0 295 }
michael@0 296 }
michael@0 297
michael@0 298 void
michael@0 299 LayerManagerD3D9::SetupPipeline()
michael@0 300 {
michael@0 301 nsIntRect rect;
michael@0 302 mWidget->GetClientBounds(rect);
michael@0 303
michael@0 304 gfx3DMatrix viewMatrix;
michael@0 305 /*
michael@0 306 * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
michael@0 307 * <1.0, -1.0> bottomright)
michael@0 308 */
michael@0 309 viewMatrix._11 = 2.0f / rect.width;
michael@0 310 viewMatrix._22 = -2.0f / rect.height;
michael@0 311 viewMatrix._33 = 0.0f;
michael@0 312 viewMatrix._41 = -1.0f;
michael@0 313 viewMatrix._42 = 1.0f;
michael@0 314
michael@0 315 HRESULT hr = device()->SetVertexShaderConstantF(CBmProjection,
michael@0 316 &viewMatrix._11, 4);
michael@0 317
michael@0 318 if (FAILED(hr)) {
michael@0 319 NS_WARNING("Failed to set projection shader constant!");
michael@0 320 }
michael@0 321
michael@0 322 hr = device()->SetVertexShaderConstantF(CBvTextureCoords,
michael@0 323 ShaderConstantRect(0, 0, 1.0f, 1.0f),
michael@0 324 1);
michael@0 325
michael@0 326 if (FAILED(hr)) {
michael@0 327 NS_WARNING("Failed to set texCoords shader constant!");
michael@0 328 }
michael@0 329
michael@0 330 float offset[] = { 0, 0, 0, 0 };
michael@0 331 hr = device()->SetVertexShaderConstantF(CBvRenderTargetOffset, offset, 1);
michael@0 332
michael@0 333 if (FAILED(hr)) {
michael@0 334 NS_WARNING("Failed to set RenderTargetOffset shader constant!");
michael@0 335 }
michael@0 336 }
michael@0 337
michael@0 338 void
michael@0 339 LayerManagerD3D9::PaintToTarget()
michael@0 340 {
michael@0 341 nsRefPtr<IDirect3DSurface9> backBuff;
michael@0 342 nsRefPtr<IDirect3DSurface9> destSurf;
michael@0 343 device()->GetRenderTarget(0, getter_AddRefs(backBuff));
michael@0 344
michael@0 345 D3DSURFACE_DESC desc;
michael@0 346 backBuff->GetDesc(&desc);
michael@0 347
michael@0 348 device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
michael@0 349 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
michael@0 350 getter_AddRefs(destSurf), nullptr);
michael@0 351
michael@0 352 device()->GetRenderTargetData(backBuff, destSurf);
michael@0 353
michael@0 354 D3DLOCKED_RECT rect;
michael@0 355 destSurf->LockRect(&rect, nullptr, D3DLOCK_READONLY);
michael@0 356
michael@0 357 nsRefPtr<gfxImageSurface> imageSurface =
michael@0 358 new gfxImageSurface((unsigned char*)rect.pBits,
michael@0 359 gfxIntSize(desc.Width, desc.Height),
michael@0 360 rect.Pitch,
michael@0 361 gfxImageFormat::ARGB32);
michael@0 362
michael@0 363 mTarget->SetSource(imageSurface);
michael@0 364 mTarget->SetOperator(gfxContext::OPERATOR_OVER);
michael@0 365 mTarget->Paint();
michael@0 366 destSurf->UnlockRect();
michael@0 367 }
michael@0 368
michael@0 369 LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
michael@0 370 : mD3DManager(aManager)
michael@0 371 {
michael@0 372 }
michael@0 373
michael@0 374 } /* namespace layers */
michael@0 375 } /* namespace mozilla */

mercurial