1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/composite/LayerManagerComposite.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,927 @@ 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 "LayerManagerComposite.h" 1.10 +#include <stddef.h> // for size_t 1.11 +#include <stdint.h> // for uint16_t, uint32_t 1.12 +#include "CanvasLayerComposite.h" // for CanvasLayerComposite 1.13 +#include "ColorLayerComposite.h" // for ColorLayerComposite 1.14 +#include "Composer2D.h" // for Composer2D 1.15 +#include "CompositableHost.h" // for CompositableHost 1.16 +#include "ContainerLayerComposite.h" // for ContainerLayerComposite, etc 1.17 +#include "FPSCounter.h" // for FPSState, FPSCounter 1.18 +#include "FrameMetrics.h" // for FrameMetrics 1.19 +#include "GeckoProfiler.h" // for profiler_set_frame_number, etc 1.20 +#include "ImageLayerComposite.h" // for ImageLayerComposite 1.21 +#include "Layers.h" // for Layer, ContainerLayer, etc 1.22 +#include "ThebesLayerComposite.h" // for ThebesLayerComposite 1.23 +#include "TiledLayerBuffer.h" // for TiledLayerComposer 1.24 +#include "Units.h" // for ScreenIntRect 1.25 +#include "gfx2DGlue.h" // for ToMatrix4x4 1.26 +#include "gfx3DMatrix.h" // for gfx3DMatrix 1.27 +#include "gfxPrefs.h" // for gfxPrefs 1.28 +#ifdef XP_MACOSX 1.29 +#include "gfxPlatformMac.h" 1.30 +#endif 1.31 +#include "gfxRect.h" // for gfxRect 1.32 +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 1.33 +#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef 1.34 +#include "mozilla/gfx/2D.h" // for DrawTarget 1.35 +#include "mozilla/gfx/Matrix.h" // for Matrix4x4 1.36 +#include "mozilla/gfx/Point.h" // for IntSize, Point 1.37 +#include "mozilla/gfx/Rect.h" // for Rect 1.38 +#include "mozilla/gfx/Types.h" // for Color, SurfaceFormat 1.39 +#include "mozilla/layers/Compositor.h" // for Compositor 1.40 +#include "mozilla/layers/CompositorTypes.h" 1.41 +#include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc 1.42 +#include "mozilla/layers/LayersTypes.h" // for etc 1.43 +#include "ipc/ShadowLayerUtils.h" 1.44 +#include "mozilla/mozalloc.h" // for operator new, etc 1.45 +#include "nsAutoPtr.h" // for nsRefPtr 1.46 +#include "nsCOMPtr.h" // for already_AddRefed 1.47 +#include "nsDebug.h" // for NS_WARNING, NS_RUNTIMEABORT, etc 1.48 +#include "nsISupportsImpl.h" // for Layer::AddRef, etc 1.49 +#include "nsIWidget.h" // for nsIWidget 1.50 +#include "nsPoint.h" // for nsIntPoint 1.51 +#include "nsRect.h" // for nsIntRect 1.52 +#include "nsRegion.h" // for nsIntRegion, etc 1.53 +#ifdef MOZ_WIDGET_ANDROID 1.54 +#include <android/log.h> 1.55 +#endif 1.56 +#include "GeckoProfiler.h" 1.57 +#include "TextRenderer.h" // for TextRenderer 1.58 + 1.59 +class gfxContext; 1.60 +struct nsIntSize; 1.61 + 1.62 + 1.63 +namespace mozilla { 1.64 +namespace layers { 1.65 + 1.66 +class ImageLayer; 1.67 + 1.68 +using namespace mozilla::gfx; 1.69 +using namespace mozilla::gl; 1.70 + 1.71 +static LayerComposite* 1.72 +ToLayerComposite(Layer* aLayer) 1.73 +{ 1.74 + return static_cast<LayerComposite*>(aLayer->ImplData()); 1.75 +} 1.76 + 1.77 +static void ClearSubtree(Layer* aLayer) 1.78 +{ 1.79 + ToLayerComposite(aLayer)->CleanupResources(); 1.80 + for (Layer* child = aLayer->GetFirstChild(); child; 1.81 + child = child->GetNextSibling()) { 1.82 + ClearSubtree(child); 1.83 + } 1.84 +} 1.85 + 1.86 +void 1.87 +LayerManagerComposite::ClearCachedResources(Layer* aSubtree) 1.88 +{ 1.89 + MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this); 1.90 + Layer* subtree = aSubtree ? aSubtree : mRoot.get(); 1.91 + if (!subtree) { 1.92 + return; 1.93 + } 1.94 + 1.95 + ClearSubtree(subtree); 1.96 + // FIXME [bjacob] 1.97 + // XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to true here. 1.98 + // Do we need that? 1.99 +} 1.100 + 1.101 +/** 1.102 + * LayerManagerComposite 1.103 + */ 1.104 +LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor) 1.105 +: mCompositor(aCompositor) 1.106 +, mInTransaction(false) 1.107 +, mIsCompositorReady(false) 1.108 +, mDebugOverlayWantsNextFrame(false) 1.109 +, mGeometryChanged(true) 1.110 +{ 1.111 + mTextRenderer = new TextRenderer(aCompositor); 1.112 + MOZ_ASSERT(aCompositor); 1.113 +} 1.114 + 1.115 +LayerManagerComposite::~LayerManagerComposite() 1.116 +{ 1.117 + Destroy(); 1.118 +} 1.119 + 1.120 + 1.121 +bool 1.122 +LayerManagerComposite::Initialize() 1.123 +{ 1.124 + bool result = mCompositor->Initialize(); 1.125 + return result; 1.126 +} 1.127 + 1.128 +void 1.129 +LayerManagerComposite::Destroy() 1.130 +{ 1.131 + if (!mDestroyed) { 1.132 + mCompositor->GetWidget()->CleanupWindowEffects(); 1.133 + if (mRoot) { 1.134 + RootLayer()->Destroy(); 1.135 + } 1.136 + mRoot = nullptr; 1.137 + 1.138 + mCompositor->Destroy(); 1.139 + 1.140 + mDestroyed = true; 1.141 + } 1.142 +} 1.143 + 1.144 +void 1.145 +LayerManagerComposite::UpdateRenderBounds(const nsIntRect& aRect) 1.146 +{ 1.147 + mRenderBounds = aRect; 1.148 +} 1.149 + 1.150 +void 1.151 +LayerManagerComposite::BeginTransaction() 1.152 +{ 1.153 + mInTransaction = true; 1.154 + 1.155 + if (!mCompositor->Ready()) { 1.156 + return; 1.157 + } 1.158 + 1.159 + mIsCompositorReady = true; 1.160 + 1.161 + if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL || 1.162 + Compositor::GetBackend() == LayersBackend::LAYERS_BASIC) { 1.163 + mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot()); 1.164 + } 1.165 +} 1.166 + 1.167 +void 1.168 +LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget) 1.169 +{ 1.170 + mInTransaction = true; 1.171 + 1.172 + if (!mCompositor->Ready()) { 1.173 + return; 1.174 + } 1.175 + 1.176 +#ifdef MOZ_LAYERS_HAVE_LOG 1.177 + MOZ_LAYERS_LOG(("[----- BeginTransaction")); 1.178 + Log(); 1.179 +#endif 1.180 + 1.181 + if (mDestroyed) { 1.182 + NS_WARNING("Call on destroyed layer manager"); 1.183 + return; 1.184 + } 1.185 + 1.186 + mIsCompositorReady = true; 1.187 + mCompositor->SetTargetContext(aTarget); 1.188 + mTarget = aTarget; 1.189 +} 1.190 + 1.191 +bool 1.192 +LayerManagerComposite::EndEmptyTransaction(EndTransactionFlags aFlags) 1.193 +{ 1.194 + NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?"); 1.195 + if (!mRoot) { 1.196 + mInTransaction = false; 1.197 + mIsCompositorReady = false; 1.198 + return false; 1.199 + } 1.200 + 1.201 + EndTransaction(nullptr, nullptr); 1.202 + return true; 1.203 +} 1.204 + 1.205 +void 1.206 +LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback, 1.207 + void* aCallbackData, 1.208 + EndTransactionFlags aFlags) 1.209 +{ 1.210 + NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?"); 1.211 + NS_ASSERTION(!aCallback && !aCallbackData, "Not expecting callbacks here"); 1.212 + mInTransaction = false; 1.213 + 1.214 + if (!mIsCompositorReady) { 1.215 + return; 1.216 + } 1.217 + mIsCompositorReady = false; 1.218 + 1.219 +#ifdef MOZ_LAYERS_HAVE_LOG 1.220 + MOZ_LAYERS_LOG((" ----- (beginning paint)")); 1.221 + Log(); 1.222 +#endif 1.223 + 1.224 + if (mDestroyed) { 1.225 + NS_WARNING("Call on destroyed layer manager"); 1.226 + return; 1.227 + } 1.228 + 1.229 + if (mRoot && mClonedLayerTreeProperties) { 1.230 + nsIntRegion invalid = 1.231 + mClonedLayerTreeProperties->ComputeDifferences(mRoot, nullptr, &mGeometryChanged); 1.232 + mClonedLayerTreeProperties = nullptr; 1.233 + 1.234 + mInvalidRegion.Or(mInvalidRegion, invalid); 1.235 + } else { 1.236 + mInvalidRegion.Or(mInvalidRegion, mRenderBounds); 1.237 + } 1.238 + 1.239 + if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) { 1.240 + if (aFlags & END_NO_COMPOSITE) { 1.241 + // Apply pending tree updates before recomputing effective 1.242 + // properties. 1.243 + mRoot->ApplyPendingUpdatesToSubtree(); 1.244 + } 1.245 + 1.246 + // The results of our drawing always go directly into a pixel buffer, 1.247 + // so we don't need to pass any global transform here. 1.248 + mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4()); 1.249 + 1.250 + Render(); 1.251 + mGeometryChanged = false; 1.252 + } 1.253 + 1.254 + mCompositor->SetTargetContext(nullptr); 1.255 + mTarget = nullptr; 1.256 + 1.257 +#ifdef MOZ_LAYERS_HAVE_LOG 1.258 + Log(); 1.259 + MOZ_LAYERS_LOG(("]----- EndTransaction")); 1.260 +#endif 1.261 +} 1.262 + 1.263 +TemporaryRef<DrawTarget> 1.264 +LayerManagerComposite::CreateOptimalMaskDrawTarget(const IntSize &aSize) 1.265 +{ 1.266 + NS_RUNTIMEABORT("Should only be called on the drawing side"); 1.267 + return nullptr; 1.268 +} 1.269 + 1.270 +already_AddRefed<ThebesLayer> 1.271 +LayerManagerComposite::CreateThebesLayer() 1.272 +{ 1.273 + NS_RUNTIMEABORT("Should only be called on the drawing side"); 1.274 + return nullptr; 1.275 +} 1.276 + 1.277 +already_AddRefed<ContainerLayer> 1.278 +LayerManagerComposite::CreateContainerLayer() 1.279 +{ 1.280 + NS_RUNTIMEABORT("Should only be called on the drawing side"); 1.281 + return nullptr; 1.282 +} 1.283 + 1.284 +already_AddRefed<ImageLayer> 1.285 +LayerManagerComposite::CreateImageLayer() 1.286 +{ 1.287 + NS_RUNTIMEABORT("Should only be called on the drawing side"); 1.288 + return nullptr; 1.289 +} 1.290 + 1.291 +already_AddRefed<ColorLayer> 1.292 +LayerManagerComposite::CreateColorLayer() 1.293 +{ 1.294 + NS_RUNTIMEABORT("Should only be called on the drawing side"); 1.295 + return nullptr; 1.296 +} 1.297 + 1.298 +already_AddRefed<CanvasLayer> 1.299 +LayerManagerComposite::CreateCanvasLayer() 1.300 +{ 1.301 + NS_RUNTIMEABORT("Should only be called on the drawing side"); 1.302 + return nullptr; 1.303 +} 1.304 + 1.305 +LayerComposite* 1.306 +LayerManagerComposite::RootLayer() const 1.307 +{ 1.308 + if (mDestroyed) { 1.309 + NS_WARNING("Call on destroyed layer manager"); 1.310 + return nullptr; 1.311 + } 1.312 + 1.313 + return ToLayerComposite(mRoot); 1.314 +} 1.315 + 1.316 +// Size of the builtin font. 1.317 +static const float FontHeight = 7.f; 1.318 +static const float FontWidth = 4.f; 1.319 +static const float FontStride = 4.f; 1.320 + 1.321 +// Scale the font when drawing it to the viewport for better readability. 1.322 +static const float FontScaleX = 2.f; 1.323 +static const float FontScaleY = 3.f; 1.324 + 1.325 +static void DrawDigits(unsigned int aValue, 1.326 + int aOffsetX, int aOffsetY, 1.327 + Compositor* aCompositor, 1.328 + EffectChain& aEffectChain) 1.329 +{ 1.330 + if (aValue > 999) { 1.331 + aValue = 999; 1.332 + } 1.333 + 1.334 + unsigned int divisor = 100; 1.335 + float textureWidth = FontWidth * 10; 1.336 + gfx::Float opacity = 1; 1.337 + gfx::Matrix4x4 transform; 1.338 + transform.Scale(FontScaleX, FontScaleY, 1); 1.339 + 1.340 + for (size_t n = 0; n < 3; ++n) { 1.341 + unsigned int digit = aValue % (divisor * 10) / divisor; 1.342 + divisor /= 10; 1.343 + 1.344 + RefPtr<TexturedEffect> texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get()); 1.345 + texturedEffect->mTextureCoords = Rect(float(digit * FontWidth) / textureWidth, 0, FontWidth / textureWidth, 1.0f); 1.346 + 1.347 + Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight); 1.348 + Rect clipRect = Rect(0, 0, 300, 100); 1.349 + aCompositor->DrawQuad(drawRect, clipRect, 1.350 + aEffectChain, opacity, transform); 1.351 + } 1.352 +} 1.353 + 1.354 +void FPSState::DrawFPS(TimeStamp aNow, 1.355 + unsigned int aFillRatio, 1.356 + Compositor* aCompositor) 1.357 +{ 1.358 + if (!mFPSTextureSource) { 1.359 + const char *text = 1.360 + " " 1.361 + " XXX XX XXX XXX X X XXX XXX XXX XXX XXX" 1.362 + " X X X X X X X X X X X X X X" 1.363 + " X X X XXX XXX XXX XXX XXX X XXX XXX" 1.364 + " X X X X X X X X X X X X X" 1.365 + " XXX XXX XXX XXX X XXX XXX X XXX X" 1.366 + " "; 1.367 + 1.368 + // Convert the text encoding above to RGBA. 1.369 + int w = FontWidth * 10; 1.370 + int h = FontHeight; 1.371 + uint32_t* buf = (uint32_t *) malloc(w * h * sizeof(uint32_t)); 1.372 + for (int i = 0; i < h; i++) { 1.373 + for (int j = 0; j < w; j++) { 1.374 + uint32_t purple = 0xfff000ff; 1.375 + uint32_t white = 0xffffffff; 1.376 + buf[i * w + j] = (text[i * w + j] == ' ') ? purple : white; 1.377 + } 1.378 + } 1.379 + 1.380 + int bytesPerPixel = 4; 1.381 + RefPtr<DataSourceSurface> fpsSurface = Factory::CreateWrappingDataSourceSurface( 1.382 + reinterpret_cast<uint8_t*>(buf), w * bytesPerPixel, IntSize(w, h), SurfaceFormat::B8G8R8A8); 1.383 + mFPSTextureSource = aCompositor->CreateDataTextureSource(); 1.384 + mFPSTextureSource->Update(fpsSurface); 1.385 + } 1.386 + 1.387 + EffectChain effectChain; 1.388 + effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mFPSTextureSource, Filter::POINT); 1.389 + 1.390 + unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow)); 1.391 + unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow)); 1.392 + 1.393 + DrawDigits(fps, 0, 0, aCompositor, effectChain); 1.394 + DrawDigits(txnFps, FontWidth * 4, 0, aCompositor, effectChain); 1.395 + DrawDigits(aFillRatio, FontWidth * 8, 0, aCompositor, effectChain); 1.396 +} 1.397 + 1.398 +static uint16_t sFrameCount = 0; 1.399 +void 1.400 +LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds) 1.401 +{ 1.402 + if (gfxPrefs::LayersDrawFPS()) { 1.403 + if (!mFPS) { 1.404 + mFPS = new FPSState(); 1.405 + } 1.406 + 1.407 + float fillRatio = mCompositor->GetFillRatio(); 1.408 + mFPS->DrawFPS(TimeStamp::Now(), unsigned(fillRatio), mCompositor); 1.409 + } else { 1.410 + mFPS = nullptr; 1.411 + } 1.412 + 1.413 + if (gfxPrefs::DrawFrameCounter()) { 1.414 + profiler_set_frame_number(sFrameCount); 1.415 + 1.416 + uint16_t frameNumber = sFrameCount; 1.417 + const uint16_t bitWidth = 3; 1.418 + float opacity = 1.0; 1.419 + gfx::Rect clip(0,0, bitWidth*16, bitWidth); 1.420 + for (size_t i = 0; i < 16; i++) { 1.421 + 1.422 + gfx::Color bitColor; 1.423 + if ((frameNumber >> i) & 0x1) { 1.424 + bitColor = gfx::Color(0, 0, 0, 1.0); 1.425 + } else { 1.426 + bitColor = gfx::Color(1.0, 1.0, 1.0, 1.0); 1.427 + } 1.428 + EffectChain effects; 1.429 + effects.mPrimaryEffect = new EffectSolidColor(bitColor); 1.430 + mCompositor->DrawQuad(gfx::Rect(bitWidth*i, 0, bitWidth, bitWidth), 1.431 + clip, 1.432 + effects, 1.433 + opacity, 1.434 + gfx::Matrix4x4()); 1.435 + } 1.436 + // We intentionally overflow at 2^16. 1.437 + sFrameCount++; 1.438 + } 1.439 +} 1.440 + 1.441 +void 1.442 +LayerManagerComposite::Render() 1.443 +{ 1.444 + PROFILER_LABEL("LayerManagerComposite", "Render"); 1.445 + if (mDestroyed) { 1.446 + NS_WARNING("Call on destroyed layer manager"); 1.447 + return; 1.448 + } 1.449 + 1.450 + if (gfxPrefs::LayersDump()) { 1.451 + this->Dump(); 1.452 + } 1.453 + 1.454 + /** Our more efficient but less powerful alter ego, if one is available. */ 1.455 + nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D(); 1.456 + 1.457 + if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) { 1.458 + if (mFPS) { 1.459 + double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now()); 1.460 + if (gfxPrefs::LayersDrawFPS()) { 1.461 + printf_stderr("HWComposer: FPS is %g\n", fps); 1.462 + } 1.463 + } 1.464 + mCompositor->EndFrameForExternalComposition(mWorldMatrix); 1.465 + return; 1.466 + } 1.467 + 1.468 + { 1.469 + PROFILER_LABEL("LayerManagerComposite", "PreRender"); 1.470 + if (!mCompositor->GetWidget()->PreRender(this)) { 1.471 + return; 1.472 + } 1.473 + } 1.474 + 1.475 + nsIntRect clipRect; 1.476 + Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height); 1.477 + Rect actualBounds; 1.478 + if (mRoot->GetClipRect()) { 1.479 + clipRect = *mRoot->GetClipRect(); 1.480 + WorldTransformRect(clipRect); 1.481 + Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height); 1.482 + mCompositor->BeginFrame(mInvalidRegion, &rect, mWorldMatrix, bounds, nullptr, &actualBounds); 1.483 + } else { 1.484 + gfx::Rect rect; 1.485 + mCompositor->BeginFrame(mInvalidRegion, nullptr, mWorldMatrix, bounds, &rect, &actualBounds); 1.486 + clipRect = nsIntRect(rect.x, rect.y, rect.width, rect.height); 1.487 + } 1.488 + 1.489 + // Reset the invalid region now that we've begun compositing. 1.490 + mInvalidRegion.SetEmpty(); 1.491 + 1.492 + if (actualBounds.IsEmpty()) { 1.493 + mCompositor->GetWidget()->PostRender(this); 1.494 + return; 1.495 + } 1.496 + 1.497 + // Allow widget to render a custom background. 1.498 + mCompositor->GetWidget()->DrawWindowUnderlay(this, nsIntRect(actualBounds.x, 1.499 + actualBounds.y, 1.500 + actualBounds.width, 1.501 + actualBounds.height)); 1.502 + 1.503 + // Render our layers. 1.504 + RootLayer()->RenderLayer(clipRect); 1.505 + 1.506 + if (!mRegionToClear.IsEmpty()) { 1.507 + nsIntRegionRectIterator iter(mRegionToClear); 1.508 + const nsIntRect *r; 1.509 + while ((r = iter.Next())) { 1.510 + mCompositor->ClearRect(Rect(r->x, r->y, r->width, r->height)); 1.511 + } 1.512 + } 1.513 + 1.514 + // Allow widget to render a custom foreground. 1.515 + mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x, 1.516 + actualBounds.y, 1.517 + actualBounds.width, 1.518 + actualBounds.height)); 1.519 + 1.520 + // Debugging 1.521 + RenderDebugOverlay(actualBounds); 1.522 + 1.523 + { 1.524 + PROFILER_LABEL("LayerManagerComposite", "EndFrame"); 1.525 + mCompositor->EndFrame(); 1.526 + mCompositor->SetFBAcquireFence(mRoot); 1.527 + } 1.528 + 1.529 + mCompositor->GetWidget()->PostRender(this); 1.530 + 1.531 + RecordFrame(); 1.532 +} 1.533 + 1.534 +void 1.535 +LayerManagerComposite::SetWorldTransform(const gfx::Matrix& aMatrix) 1.536 +{ 1.537 + NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(), 1.538 + "SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles"); 1.539 + NS_ASSERTION(!aMatrix.HasNonIntegerScale(), 1.540 + "SetWorldTransform only accepts matrices with integer scale"); 1.541 + 1.542 + mWorldMatrix = aMatrix; 1.543 +} 1.544 + 1.545 +gfx::Matrix& 1.546 +LayerManagerComposite::GetWorldTransform(void) 1.547 +{ 1.548 + return mWorldMatrix; 1.549 +} 1.550 + 1.551 +void 1.552 +LayerManagerComposite::WorldTransformRect(nsIntRect& aRect) 1.553 +{ 1.554 + gfx::Rect grect(aRect.x, aRect.y, aRect.width, aRect.height); 1.555 + grect = mWorldMatrix.TransformBounds(grect); 1.556 + aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height()); 1.557 +} 1.558 + 1.559 +static void 1.560 +SubtractTransformedRegion(nsIntRegion& aRegion, 1.561 + const nsIntRegion& aRegionToSubtract, 1.562 + const gfx3DMatrix& aTransform) 1.563 +{ 1.564 + if (aRegionToSubtract.IsEmpty()) { 1.565 + return; 1.566 + } 1.567 + 1.568 + // For each rect in the region, find out its bounds in screen space and 1.569 + // subtract it from the screen region. 1.570 + nsIntRegionRectIterator it(aRegionToSubtract); 1.571 + while (const nsIntRect* rect = it.Next()) { 1.572 + gfxRect incompleteRect = aTransform.TransformBounds(gfxRect(*rect)); 1.573 + aRegion.Sub(aRegion, nsIntRect(incompleteRect.x, 1.574 + incompleteRect.y, 1.575 + incompleteRect.width, 1.576 + incompleteRect.height)); 1.577 + } 1.578 +} 1.579 + 1.580 +/* static */ void 1.581 +LayerManagerComposite::ComputeRenderIntegrityInternal(Layer* aLayer, 1.582 + nsIntRegion& aScreenRegion, 1.583 + nsIntRegion& aLowPrecisionScreenRegion, 1.584 + const gfx3DMatrix& aTransform) 1.585 +{ 1.586 + if (aLayer->GetOpacity() <= 0.f || 1.587 + (aScreenRegion.IsEmpty() && aLowPrecisionScreenRegion.IsEmpty())) { 1.588 + return; 1.589 + } 1.590 + 1.591 + // If the layer's a container, recurse into all of its children 1.592 + ContainerLayer* container = aLayer->AsContainerLayer(); 1.593 + if (container) { 1.594 + // Accumulate the transform of intermediate surfaces 1.595 + gfx3DMatrix transform = aTransform; 1.596 + if (container->UseIntermediateSurface()) { 1.597 + gfx::To3DMatrix(aLayer->GetEffectiveTransform(), transform); 1.598 + transform.PreMultiply(aTransform); 1.599 + } 1.600 + for (Layer* child = aLayer->GetFirstChild(); child; 1.601 + child = child->GetNextSibling()) { 1.602 + ComputeRenderIntegrityInternal(child, aScreenRegion, aLowPrecisionScreenRegion, transform); 1.603 + } 1.604 + return; 1.605 + } 1.606 + 1.607 + // Only thebes layers can be incomplete 1.608 + ThebesLayer* thebesLayer = aLayer->AsThebesLayer(); 1.609 + if (!thebesLayer) { 1.610 + return; 1.611 + } 1.612 + 1.613 + // See if there's any incomplete rendering 1.614 + nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion(); 1.615 + incompleteRegion.Sub(incompleteRegion, thebesLayer->GetValidRegion()); 1.616 + 1.617 + if (!incompleteRegion.IsEmpty()) { 1.618 + // Calculate the transform to get between screen and layer space 1.619 + gfx3DMatrix transformToScreen; 1.620 + To3DMatrix(aLayer->GetEffectiveTransform(), transformToScreen); 1.621 + transformToScreen.PreMultiply(aTransform); 1.622 + 1.623 + SubtractTransformedRegion(aScreenRegion, incompleteRegion, transformToScreen); 1.624 + 1.625 + // See if there's any incomplete low-precision rendering 1.626 + TiledLayerComposer* composer = nullptr; 1.627 + LayerComposite* shadow = aLayer->AsLayerComposite(); 1.628 + if (shadow) { 1.629 + composer = shadow->GetTiledLayerComposer(); 1.630 + if (composer) { 1.631 + incompleteRegion.Sub(incompleteRegion, composer->GetValidLowPrecisionRegion()); 1.632 + if (!incompleteRegion.IsEmpty()) { 1.633 + SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen); 1.634 + } 1.635 + } 1.636 + } 1.637 + 1.638 + // If we can't get a valid low precision region, assume it's the same as 1.639 + // the high precision region. 1.640 + if (!composer) { 1.641 + SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen); 1.642 + } 1.643 + } 1.644 +} 1.645 + 1.646 +#ifdef MOZ_ANDROID_OMTC 1.647 +static float 1.648 +GetDisplayportCoverage(const CSSRect& aDisplayPort, 1.649 + const gfx3DMatrix& aTransformToScreen, 1.650 + const nsIntRect& aScreenRect) 1.651 +{ 1.652 + gfxRect transformedDisplayport = 1.653 + aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x, 1.654 + aDisplayPort.y, 1.655 + aDisplayPort.width, 1.656 + aDisplayPort.height)); 1.657 + transformedDisplayport.RoundOut(); 1.658 + nsIntRect displayport = nsIntRect(transformedDisplayport.x, 1.659 + transformedDisplayport.y, 1.660 + transformedDisplayport.width, 1.661 + transformedDisplayport.height); 1.662 + if (!displayport.Contains(aScreenRect)) { 1.663 + nsIntRegion coveredRegion; 1.664 + coveredRegion.And(aScreenRect, displayport); 1.665 + return coveredRegion.Area() / (float)(aScreenRect.width * aScreenRect.height); 1.666 + } 1.667 + 1.668 + return 1.0f; 1.669 +} 1.670 +#endif // MOZ_ANDROID_OMTC 1.671 + 1.672 +float 1.673 +LayerManagerComposite::ComputeRenderIntegrity() 1.674 +{ 1.675 + // We only ever have incomplete rendering when progressive tiles are enabled. 1.676 + Layer* root = GetRoot(); 1.677 + if (!gfxPrefs::UseProgressiveTilePainting() || !root) { 1.678 + return 1.f; 1.679 + } 1.680 + 1.681 + const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics(); 1.682 + nsIntRect screenRect(rootMetrics.mCompositionBounds.x, 1.683 + rootMetrics.mCompositionBounds.y, 1.684 + rootMetrics.mCompositionBounds.width, 1.685 + rootMetrics.mCompositionBounds.height); 1.686 + 1.687 + float lowPrecisionMultiplier = 1.0f; 1.688 + float highPrecisionMultiplier = 1.0f; 1.689 + 1.690 +#ifdef MOZ_ANDROID_OMTC 1.691 + // Use the transform on the primary scrollable layer and its FrameMetrics 1.692 + // to find out how much of the viewport the current displayport covers 1.693 + Layer* primaryScrollable = GetPrimaryScrollableLayer(); 1.694 + if (primaryScrollable) { 1.695 + // This is derived from the code in 1.696 + // AsyncCompositionManager::TransformScrollableLayer 1.697 + const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics(); 1.698 + gfx3DMatrix transform; 1.699 + gfx::To3DMatrix(primaryScrollable->GetEffectiveTransform(), transform); 1.700 + transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1); 1.701 + 1.702 + // Clip the screen rect to the document bounds 1.703 + gfxRect documentBounds = 1.704 + transform.TransformBounds(gfxRect(metrics.mScrollableRect.x - metrics.GetScrollOffset().x, 1.705 + metrics.mScrollableRect.y - metrics.GetScrollOffset().y, 1.706 + metrics.mScrollableRect.width, 1.707 + metrics.mScrollableRect.height)); 1.708 + documentBounds.RoundOut(); 1.709 + screenRect = screenRect.Intersect(nsIntRect(documentBounds.x, documentBounds.y, 1.710 + documentBounds.width, documentBounds.height)); 1.711 + 1.712 + // If the screen rect is empty, the user has scrolled entirely into 1.713 + // over-scroll and so we can be considered to have full integrity. 1.714 + if (screenRect.IsEmpty()) { 1.715 + return 1.0f; 1.716 + } 1.717 + 1.718 + // Work out how much of the critical display-port covers the screen 1.719 + bool hasLowPrecision = false; 1.720 + if (!metrics.mCriticalDisplayPort.IsEmpty()) { 1.721 + hasLowPrecision = true; 1.722 + highPrecisionMultiplier = 1.723 + GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect); 1.724 + } 1.725 + 1.726 + // Work out how much of the display-port covers the screen 1.727 + if (!metrics.mDisplayPort.IsEmpty()) { 1.728 + if (hasLowPrecision) { 1.729 + lowPrecisionMultiplier = 1.730 + GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect); 1.731 + } else { 1.732 + lowPrecisionMultiplier = highPrecisionMultiplier = 1.733 + GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect); 1.734 + } 1.735 + } 1.736 + } 1.737 + 1.738 + // If none of the screen is covered, we have zero integrity. 1.739 + if (highPrecisionMultiplier <= 0.0f && lowPrecisionMultiplier <= 0.0f) { 1.740 + return 0.0f; 1.741 + } 1.742 +#endif // MOZ_ANDROID_OMTC 1.743 + 1.744 + nsIntRegion screenRegion(screenRect); 1.745 + nsIntRegion lowPrecisionScreenRegion(screenRect); 1.746 + gfx3DMatrix transform; 1.747 + ComputeRenderIntegrityInternal(root, screenRegion, 1.748 + lowPrecisionScreenRegion, transform); 1.749 + 1.750 + if (!screenRegion.IsEqual(screenRect)) { 1.751 + // Calculate the area of the region. All rects in an nsRegion are 1.752 + // non-overlapping. 1.753 + float screenArea = screenRect.width * screenRect.height; 1.754 + float highPrecisionIntegrity = screenRegion.Area() / screenArea; 1.755 + float lowPrecisionIntegrity = 1.f; 1.756 + if (!lowPrecisionScreenRegion.IsEqual(screenRect)) { 1.757 + lowPrecisionIntegrity = lowPrecisionScreenRegion.Area() / screenArea; 1.758 + } 1.759 + 1.760 + return ((highPrecisionIntegrity * highPrecisionMultiplier) + 1.761 + (lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2; 1.762 + } 1.763 + 1.764 + return 1.f; 1.765 +} 1.766 + 1.767 +already_AddRefed<ThebesLayerComposite> 1.768 +LayerManagerComposite::CreateThebesLayerComposite() 1.769 +{ 1.770 + if (mDestroyed) { 1.771 + NS_WARNING("Call on destroyed layer manager"); 1.772 + return nullptr; 1.773 + } 1.774 + return nsRefPtr<ThebesLayerComposite>(new ThebesLayerComposite(this)).forget(); 1.775 +} 1.776 + 1.777 +already_AddRefed<ContainerLayerComposite> 1.778 +LayerManagerComposite::CreateContainerLayerComposite() 1.779 +{ 1.780 + if (mDestroyed) { 1.781 + NS_WARNING("Call on destroyed layer manager"); 1.782 + return nullptr; 1.783 + } 1.784 + return nsRefPtr<ContainerLayerComposite>(new ContainerLayerComposite(this)).forget(); 1.785 +} 1.786 + 1.787 +already_AddRefed<ImageLayerComposite> 1.788 +LayerManagerComposite::CreateImageLayerComposite() 1.789 +{ 1.790 + if (mDestroyed) { 1.791 + NS_WARNING("Call on destroyed layer manager"); 1.792 + return nullptr; 1.793 + } 1.794 + return nsRefPtr<ImageLayerComposite>(new ImageLayerComposite(this)).forget(); 1.795 +} 1.796 + 1.797 +already_AddRefed<ColorLayerComposite> 1.798 +LayerManagerComposite::CreateColorLayerComposite() 1.799 +{ 1.800 + if (LayerManagerComposite::mDestroyed) { 1.801 + NS_WARNING("Call on destroyed layer manager"); 1.802 + return nullptr; 1.803 + } 1.804 + return nsRefPtr<ColorLayerComposite>(new ColorLayerComposite(this)).forget(); 1.805 +} 1.806 + 1.807 +already_AddRefed<CanvasLayerComposite> 1.808 +LayerManagerComposite::CreateCanvasLayerComposite() 1.809 +{ 1.810 + if (LayerManagerComposite::mDestroyed) { 1.811 + NS_WARNING("Call on destroyed layer manager"); 1.812 + return nullptr; 1.813 + } 1.814 + return nsRefPtr<CanvasLayerComposite>(new CanvasLayerComposite(this)).forget(); 1.815 +} 1.816 + 1.817 +already_AddRefed<RefLayerComposite> 1.818 +LayerManagerComposite::CreateRefLayerComposite() 1.819 +{ 1.820 + if (LayerManagerComposite::mDestroyed) { 1.821 + NS_WARNING("Call on destroyed layer manager"); 1.822 + return nullptr; 1.823 + } 1.824 + return nsRefPtr<RefLayerComposite>(new RefLayerComposite(this)).forget(); 1.825 +} 1.826 + 1.827 +LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer, 1.828 + EffectChain& aEffects, 1.829 + bool aIs3D) 1.830 + : mCompositable(nullptr) 1.831 +{ 1.832 + if (!aMaskLayer) { 1.833 + return; 1.834 + } 1.835 + 1.836 + mCompositable = ToLayerComposite(aMaskLayer)->GetCompositableHost(); 1.837 + if (!mCompositable) { 1.838 + NS_WARNING("Mask layer with no compositable host"); 1.839 + return; 1.840 + } 1.841 + 1.842 + if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform(), aIs3D)) { 1.843 + mCompositable = nullptr; 1.844 + } 1.845 +} 1.846 + 1.847 +LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect() 1.848 +{ 1.849 + if (!mCompositable) { 1.850 + return; 1.851 + } 1.852 + 1.853 + mCompositable->RemoveMaskEffect(); 1.854 +} 1.855 + 1.856 +TemporaryRef<DrawTarget> 1.857 +LayerManagerComposite::CreateDrawTarget(const IntSize &aSize, 1.858 + SurfaceFormat aFormat) 1.859 +{ 1.860 +#ifdef XP_MACOSX 1.861 + // We don't want to accelerate if the surface is too small which indicates 1.862 + // that it's likely used for an icon/static image. We also don't want to 1.863 + // accelerate anything that is above the maximum texture size of weakest gpu. 1.864 + // Safari uses 5000 area as the minimum for acceleration, we decided 64^2 is more logical. 1.865 + bool useAcceleration = aSize.width <= 4096 && aSize.height <= 4096 && 1.866 + aSize.width > 64 && aSize.height > 64 && 1.867 + gfxPlatformMac::GetPlatform()->UseAcceleratedCanvas(); 1.868 + if (useAcceleration) { 1.869 + return Factory::CreateDrawTarget(BackendType::COREGRAPHICS_ACCELERATED, 1.870 + aSize, aFormat); 1.871 + } 1.872 +#endif 1.873 + return LayerManager::CreateDrawTarget(aSize, aFormat); 1.874 +} 1.875 + 1.876 +LayerComposite::LayerComposite(LayerManagerComposite *aManager) 1.877 + : mCompositeManager(aManager) 1.878 + , mCompositor(aManager->GetCompositor()) 1.879 + , mShadowOpacity(1.0) 1.880 + , mUseShadowClipRect(false) 1.881 + , mShadowTransformSetByAnimation(false) 1.882 + , mDestroyed(false) 1.883 + , mLayerComposited(false) 1.884 +{ } 1.885 + 1.886 +LayerComposite::~LayerComposite() 1.887 +{ 1.888 +} 1.889 + 1.890 +void 1.891 +LayerComposite::Destroy() 1.892 +{ 1.893 + if (!mDestroyed) { 1.894 + mDestroyed = true; 1.895 + CleanupResources(); 1.896 + } 1.897 +} 1.898 + 1.899 +bool 1.900 +LayerManagerComposite::CanUseCanvasLayerForSize(const IntSize &aSize) 1.901 +{ 1.902 + return mCompositor->CanUseCanvasLayerForSize(gfx::IntSize(aSize.width, 1.903 + aSize.height)); 1.904 +} 1.905 + 1.906 +void 1.907 +LayerManagerComposite::NotifyShadowTreeTransaction() 1.908 +{ 1.909 + if (mFPS) { 1.910 + mFPS->NotifyShadowTreeTransaction(); 1.911 + } 1.912 +} 1.913 + 1.914 +#ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS 1.915 + 1.916 +/*static*/ bool 1.917 +LayerManagerComposite::SupportsDirectTexturing() 1.918 +{ 1.919 + return false; 1.920 +} 1.921 + 1.922 +/*static*/ void 1.923 +LayerManagerComposite::PlatformSyncBeforeReplyUpdate() 1.924 +{ 1.925 +} 1.926 + 1.927 +#endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS) 1.928 + 1.929 +} /* layers */ 1.930 +} /* mozilla */