mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
189805593c
The bulk of this patch is fixing up pieces of code that infer the resolution as the inverse of the scaling transform on the root layer. This used to be how various bits of gfx code obtained the resolution, but now that we can set the resolution on the actual presShell that contains the content, we can also just read the resolution from the FrameMetrics directly.
809 lines
24 KiB
C++
809 lines
24 KiB
C++
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "LayerManagerComposite.h"
|
|
#include <stddef.h> // for size_t
|
|
#include <stdint.h> // for uint16_t, uint32_t
|
|
#include "CanvasLayerComposite.h" // for CanvasLayerComposite
|
|
#include "ColorLayerComposite.h" // for ColorLayerComposite
|
|
#include "Composer2D.h" // for Composer2D
|
|
#include "CompositableHost.h" // for CompositableHost
|
|
#include "ContainerLayerComposite.h" // for ContainerLayerComposite, etc
|
|
#include "FrameMetrics.h" // for FrameMetrics
|
|
#include "GeckoProfiler.h" // for profiler_set_frame_number, etc
|
|
#include "ImageLayerComposite.h" // for ImageLayerComposite
|
|
#include "Layers.h" // for Layer, ContainerLayer, etc
|
|
#include "ThebesLayerComposite.h" // for ThebesLayerComposite
|
|
#include "TiledLayerBuffer.h" // for TiledLayerComposer
|
|
#include "Units.h" // for ScreenIntRect
|
|
#include "gfx2DGlue.h" // for ToMatrix4x4
|
|
#include "gfx3DMatrix.h" // for gfx3DMatrix
|
|
#include "gfxMatrix.h" // for gfxMatrix
|
|
#include "gfxPlatform.h" // for gfxPlatform
|
|
#ifdef XP_MACOSX
|
|
#include "gfxPlatformMac.h"
|
|
#endif
|
|
#include "gfxPoint.h" // for gfxIntSize
|
|
#include "gfxRect.h" // for gfxRect
|
|
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
|
#include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef
|
|
#include "mozilla/gfx/2D.h" // for DrawTarget
|
|
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
|
#include "mozilla/gfx/Point.h" // for IntSize, Point
|
|
#include "mozilla/gfx/Rect.h" // for Rect
|
|
#include "mozilla/gfx/Types.h" // for Color, SurfaceFormat
|
|
#include "mozilla/layers/Compositor.h" // for Compositor
|
|
#include "mozilla/layers/CompositorTypes.h"
|
|
#include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc
|
|
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_HAVE_LOG, etc
|
|
#include "ipc/ShadowLayerUtils.h"
|
|
#include "mozilla/mozalloc.h" // for operator new, etc
|
|
#include "nsAutoPtr.h" // for nsRefPtr
|
|
#include "nsCOMPtr.h" // for already_AddRefed
|
|
#include "nsDebug.h" // for NS_WARNING, NS_RUNTIMEABORT, etc
|
|
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
|
|
#include "nsIWidget.h" // for nsIWidget
|
|
#include "nsPoint.h" // for nsIntPoint
|
|
#include "nsRect.h" // for nsIntRect
|
|
#include "nsRegion.h" // for nsIntRegion, etc
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
#include <android/log.h>
|
|
#endif
|
|
#include "GeckoProfiler.h"
|
|
|
|
class gfxASurface;
|
|
class gfxContext;
|
|
struct nsIntSize;
|
|
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
class ImageLayer;
|
|
|
|
using namespace mozilla::gfx;
|
|
using namespace mozilla::gl;
|
|
|
|
static LayerComposite*
|
|
ToLayerComposite(Layer* aLayer)
|
|
{
|
|
return static_cast<LayerComposite*>(aLayer->ImplData());
|
|
}
|
|
|
|
static void ClearSubtree(Layer* aLayer)
|
|
{
|
|
ToLayerComposite(aLayer)->CleanupResources();
|
|
for (Layer* child = aLayer->GetFirstChild(); child;
|
|
child = child->GetNextSibling()) {
|
|
ClearSubtree(child);
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::ClearCachedResources(Layer* aSubtree)
|
|
{
|
|
MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
|
|
Layer* subtree = aSubtree ? aSubtree : mRoot.get();
|
|
if (!subtree) {
|
|
return;
|
|
}
|
|
|
|
ClearSubtree(subtree);
|
|
// FIXME [bjacob]
|
|
// XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to true here.
|
|
// Do we need that?
|
|
}
|
|
|
|
/**
|
|
* LayerManagerComposite
|
|
*/
|
|
LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
|
|
: mCompositor(aCompositor)
|
|
{
|
|
MOZ_ASSERT(aCompositor);
|
|
}
|
|
|
|
LayerManagerComposite::~LayerManagerComposite()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
|
|
bool
|
|
LayerManagerComposite::Initialize()
|
|
{
|
|
bool result = mCompositor->Initialize();
|
|
mComposer2D = mCompositor->GetWidget()->GetComposer2D();
|
|
return result;
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::Destroy()
|
|
{
|
|
if (!mDestroyed) {
|
|
mCompositor->GetWidget()->CleanupWindowEffects();
|
|
if (mRoot) {
|
|
RootLayer()->Destroy();
|
|
}
|
|
mRoot = nullptr;
|
|
|
|
mCompositor->Destroy();
|
|
|
|
mDestroyed = true;
|
|
}
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::UpdateRenderBounds(const nsIntRect& aRect)
|
|
{
|
|
mRenderBounds = aRect;
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::BeginTransaction()
|
|
{
|
|
mInTransaction = true;
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget)
|
|
{
|
|
mInTransaction = true;
|
|
|
|
#ifdef MOZ_LAYERS_HAVE_LOG
|
|
MOZ_LAYERS_LOG(("[----- BeginTransaction"));
|
|
Log();
|
|
#endif
|
|
|
|
if (mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return;
|
|
}
|
|
|
|
mCompositor->SetTargetContext(aTarget);
|
|
}
|
|
|
|
bool
|
|
LayerManagerComposite::EndEmptyTransaction(EndTransactionFlags aFlags)
|
|
{
|
|
mInTransaction = false;
|
|
|
|
if (!mRoot)
|
|
return false;
|
|
|
|
EndTransaction(nullptr, nullptr);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback,
|
|
void* aCallbackData,
|
|
EndTransactionFlags aFlags)
|
|
{
|
|
mInTransaction = false;
|
|
|
|
#ifdef MOZ_LAYERS_HAVE_LOG
|
|
MOZ_LAYERS_LOG((" ----- (beginning paint)"));
|
|
Log();
|
|
#endif
|
|
|
|
if (mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return;
|
|
}
|
|
|
|
if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
|
|
if (aFlags & END_NO_COMPOSITE) {
|
|
// Apply pending tree updates before recomputing effective
|
|
// properties.
|
|
mRoot->ApplyPendingUpdatesToSubtree();
|
|
}
|
|
|
|
// The results of our drawing always go directly into a pixel buffer,
|
|
// so we don't need to pass any global transform here.
|
|
mRoot->ComputeEffectiveTransforms(gfx3DMatrix());
|
|
|
|
mThebesLayerCallback = aCallback;
|
|
mThebesLayerCallbackData = aCallbackData;
|
|
|
|
Render();
|
|
|
|
mThebesLayerCallback = nullptr;
|
|
mThebesLayerCallbackData = nullptr;
|
|
}
|
|
|
|
mCompositor->SetTargetContext(nullptr);
|
|
|
|
#ifdef MOZ_LAYERS_HAVE_LOG
|
|
Log();
|
|
MOZ_LAYERS_LOG(("]----- EndTransaction"));
|
|
#endif
|
|
}
|
|
|
|
already_AddRefed<gfxASurface>
|
|
LayerManagerComposite::CreateOptimalMaskSurface(const gfxIntSize &aSize)
|
|
{
|
|
NS_RUNTIMEABORT("Should only be called on the drawing side");
|
|
return nullptr;
|
|
}
|
|
|
|
already_AddRefed<ThebesLayer>
|
|
LayerManagerComposite::CreateThebesLayer()
|
|
{
|
|
NS_RUNTIMEABORT("Should only be called on the drawing side");
|
|
return nullptr;
|
|
}
|
|
|
|
already_AddRefed<ContainerLayer>
|
|
LayerManagerComposite::CreateContainerLayer()
|
|
{
|
|
NS_RUNTIMEABORT("Should only be called on the drawing side");
|
|
return nullptr;
|
|
}
|
|
|
|
already_AddRefed<ImageLayer>
|
|
LayerManagerComposite::CreateImageLayer()
|
|
{
|
|
NS_RUNTIMEABORT("Should only be called on the drawing side");
|
|
return nullptr;
|
|
}
|
|
|
|
already_AddRefed<ColorLayer>
|
|
LayerManagerComposite::CreateColorLayer()
|
|
{
|
|
NS_RUNTIMEABORT("Should only be called on the drawing side");
|
|
return nullptr;
|
|
}
|
|
|
|
already_AddRefed<CanvasLayer>
|
|
LayerManagerComposite::CreateCanvasLayer()
|
|
{
|
|
NS_RUNTIMEABORT("Should only be called on the drawing side");
|
|
return nullptr;
|
|
}
|
|
|
|
LayerComposite*
|
|
LayerManagerComposite::RootLayer() const
|
|
{
|
|
if (mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return nullptr;
|
|
}
|
|
|
|
return static_cast<LayerComposite*>(mRoot->ImplData());
|
|
}
|
|
|
|
static uint16_t sFrameCount = 0;
|
|
void
|
|
LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
|
|
{
|
|
if (!gfxPlatform::DrawFrameCounter()) {
|
|
return;
|
|
}
|
|
|
|
profiler_set_frame_number(sFrameCount);
|
|
|
|
uint16_t frameNumber = sFrameCount;
|
|
const uint16_t bitWidth = 3;
|
|
float opacity = 1.0;
|
|
gfx::Rect clip(0,0, bitWidth*16, bitWidth);
|
|
for (size_t i = 0; i < 16; i++) {
|
|
|
|
gfx::Color bitColor;
|
|
if ((frameNumber >> i) & 0x1) {
|
|
bitColor = gfx::Color(0, 0, 0, 1.0);
|
|
} else {
|
|
bitColor = gfx::Color(1.0, 1.0, 1.0, 1.0);
|
|
}
|
|
EffectChain effects;
|
|
effects.mPrimaryEffect = new EffectSolidColor(bitColor);
|
|
mCompositor->DrawQuad(gfx::Rect(bitWidth*i, 0, bitWidth, bitWidth),
|
|
clip,
|
|
effects,
|
|
opacity,
|
|
gfx::Matrix4x4(),
|
|
gfx::Point());
|
|
}
|
|
// We intentionally overflow at 2^16.
|
|
sFrameCount++;
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::Render()
|
|
{
|
|
PROFILER_LABEL("LayerManagerComposite", "Render");
|
|
if (mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return;
|
|
}
|
|
|
|
if (mComposer2D && mComposer2D->TryRender(mRoot, mWorldMatrix)) {
|
|
mCompositor->EndFrameForExternalComposition(mWorldMatrix);
|
|
return;
|
|
}
|
|
|
|
{
|
|
PROFILER_LABEL("LayerManagerComposite", "PreRender");
|
|
if (!mCompositor->GetWidget()->PreRender(this)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
nsIntRect clipRect;
|
|
Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
|
|
Rect actualBounds;
|
|
if (mRoot->GetClipRect()) {
|
|
clipRect = *mRoot->GetClipRect();
|
|
WorldTransformRect(clipRect);
|
|
Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
|
|
mCompositor->BeginFrame(&rect, mWorldMatrix, bounds, nullptr, &actualBounds);
|
|
} else {
|
|
gfx::Rect rect;
|
|
mCompositor->BeginFrame(nullptr, mWorldMatrix, bounds, &rect, &actualBounds);
|
|
clipRect = nsIntRect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
|
|
if (actualBounds.IsEmpty()) {
|
|
mCompositor->GetWidget()->PostRender(this);
|
|
return;
|
|
}
|
|
|
|
// Allow widget to render a custom background.
|
|
mCompositor->SaveState();
|
|
mCompositor->GetWidget()->DrawWindowUnderlay(this, nsIntRect(actualBounds.x,
|
|
actualBounds.y,
|
|
actualBounds.width,
|
|
actualBounds.height));
|
|
mCompositor->RestoreState();
|
|
|
|
// Render our layers.
|
|
RootLayer()->RenderLayer(nsIntPoint(0, 0), clipRect);
|
|
|
|
// Allow widget to render a custom foreground.
|
|
mCompositor->SaveState();
|
|
mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x,
|
|
actualBounds.y,
|
|
actualBounds.width,
|
|
actualBounds.height));
|
|
mCompositor->RestoreState();
|
|
|
|
// Debugging
|
|
RenderDebugOverlay(actualBounds);
|
|
|
|
{
|
|
PROFILER_LABEL("LayerManagerComposite", "EndFrame");
|
|
mCompositor->EndFrame();
|
|
}
|
|
|
|
mCompositor->GetWidget()->PostRender(this);
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::SetWorldTransform(const gfxMatrix& aMatrix)
|
|
{
|
|
NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(),
|
|
"SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles");
|
|
NS_ASSERTION(!aMatrix.HasNonIntegerScale(),
|
|
"SetWorldTransform only accepts matrices with integer scale");
|
|
|
|
mWorldMatrix = aMatrix;
|
|
}
|
|
|
|
gfxMatrix&
|
|
LayerManagerComposite::GetWorldTransform(void)
|
|
{
|
|
return mWorldMatrix;
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::WorldTransformRect(nsIntRect& aRect)
|
|
{
|
|
gfxRect grect(aRect.x, aRect.y, aRect.width, aRect.height);
|
|
grect = mWorldMatrix.TransformBounds(grect);
|
|
aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height());
|
|
}
|
|
|
|
static void
|
|
SubtractTransformedRegion(nsIntRegion& aRegion,
|
|
const nsIntRegion& aRegionToSubtract,
|
|
const gfx3DMatrix& aTransform)
|
|
{
|
|
if (aRegionToSubtract.IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
// For each rect in the region, find out its bounds in screen space and
|
|
// subtract it from the screen region.
|
|
nsIntRegionRectIterator it(aRegionToSubtract);
|
|
while (const nsIntRect* rect = it.Next()) {
|
|
gfxRect incompleteRect = aTransform.TransformBounds(gfxRect(*rect));
|
|
aRegion.Sub(aRegion, nsIntRect(incompleteRect.x,
|
|
incompleteRect.y,
|
|
incompleteRect.width,
|
|
incompleteRect.height));
|
|
}
|
|
}
|
|
|
|
/* static */ void
|
|
LayerManagerComposite::ComputeRenderIntegrityInternal(Layer* aLayer,
|
|
nsIntRegion& aScreenRegion,
|
|
nsIntRegion& aLowPrecisionScreenRegion,
|
|
const gfx3DMatrix& aTransform)
|
|
{
|
|
if (aLayer->GetOpacity() <= 0.f ||
|
|
(aScreenRegion.IsEmpty() && aLowPrecisionScreenRegion.IsEmpty())) {
|
|
return;
|
|
}
|
|
|
|
// If the layer's a container, recurse into all of its children
|
|
ContainerLayer* container = aLayer->AsContainerLayer();
|
|
if (container) {
|
|
// Accumulate the transform of intermediate surfaces
|
|
gfx3DMatrix transform = aTransform;
|
|
if (container->UseIntermediateSurface()) {
|
|
transform = aLayer->GetEffectiveTransform();
|
|
transform.PreMultiply(aTransform);
|
|
}
|
|
for (Layer* child = aLayer->GetFirstChild(); child;
|
|
child = child->GetNextSibling()) {
|
|
ComputeRenderIntegrityInternal(child, aScreenRegion, aLowPrecisionScreenRegion, transform);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Only thebes layers can be incomplete
|
|
ThebesLayer* thebesLayer = aLayer->AsThebesLayer();
|
|
if (!thebesLayer) {
|
|
return;
|
|
}
|
|
|
|
// See if there's any incomplete rendering
|
|
nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion();
|
|
incompleteRegion.Sub(incompleteRegion, thebesLayer->GetValidRegion());
|
|
|
|
if (!incompleteRegion.IsEmpty()) {
|
|
// Calculate the transform to get between screen and layer space
|
|
gfx3DMatrix transformToScreen = aLayer->GetEffectiveTransform();
|
|
transformToScreen.PreMultiply(aTransform);
|
|
|
|
SubtractTransformedRegion(aScreenRegion, incompleteRegion, transformToScreen);
|
|
|
|
// See if there's any incomplete low-precision rendering
|
|
TiledLayerComposer* composer = nullptr;
|
|
LayerComposite* shadow = aLayer->AsLayerComposite();
|
|
if (shadow) {
|
|
composer = shadow->GetTiledLayerComposer();
|
|
if (composer) {
|
|
incompleteRegion.Sub(incompleteRegion, composer->GetValidLowPrecisionRegion());
|
|
if (!incompleteRegion.IsEmpty()) {
|
|
SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we can't get a valid low precision region, assume it's the same as
|
|
// the high precision region.
|
|
if (!composer) {
|
|
SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef MOZ_ANDROID_OMTC
|
|
static float
|
|
GetDisplayportCoverage(const CSSRect& aDisplayPort,
|
|
const gfx3DMatrix& aTransformToScreen,
|
|
const nsIntRect& aScreenRect)
|
|
{
|
|
gfxRect transformedDisplayport =
|
|
aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x,
|
|
aDisplayPort.y,
|
|
aDisplayPort.width,
|
|
aDisplayPort.height));
|
|
transformedDisplayport.RoundOut();
|
|
nsIntRect displayport = nsIntRect(transformedDisplayport.x,
|
|
transformedDisplayport.y,
|
|
transformedDisplayport.width,
|
|
transformedDisplayport.height);
|
|
if (!displayport.Contains(aScreenRect)) {
|
|
nsIntRegion coveredRegion;
|
|
coveredRegion.And(aScreenRect, displayport);
|
|
return coveredRegion.Area() / (float)(aScreenRect.width * aScreenRect.height);
|
|
}
|
|
|
|
return 1.0f;
|
|
}
|
|
#endif // MOZ_ANDROID_OMTC
|
|
|
|
float
|
|
LayerManagerComposite::ComputeRenderIntegrity()
|
|
{
|
|
// We only ever have incomplete rendering when progressive tiles are enabled.
|
|
Layer* root = GetRoot();
|
|
if (!gfxPlatform::UseProgressiveTilePainting() || !root) {
|
|
return 1.f;
|
|
}
|
|
|
|
const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics();
|
|
nsIntRect screenRect(rootMetrics.mCompositionBounds.x,
|
|
rootMetrics.mCompositionBounds.y,
|
|
rootMetrics.mCompositionBounds.width,
|
|
rootMetrics.mCompositionBounds.height);
|
|
|
|
float lowPrecisionMultiplier = 1.0f;
|
|
float highPrecisionMultiplier = 1.0f;
|
|
|
|
#ifdef MOZ_ANDROID_OMTC
|
|
// Use the transform on the primary scrollable layer and its FrameMetrics
|
|
// to find out how much of the viewport the current displayport covers
|
|
Layer* primaryScrollable = GetPrimaryScrollableLayer();
|
|
if (primaryScrollable) {
|
|
// This is derived from the code in
|
|
// AsyncCompositionManager::TransformScrollableLayer
|
|
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
|
|
gfx3DMatrix transform = primaryScrollable->GetEffectiveTransform();
|
|
transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1);
|
|
|
|
// Clip the screen rect to the document bounds
|
|
gfxRect documentBounds =
|
|
transform.TransformBounds(gfxRect(metrics.mScrollableRect.x - metrics.mScrollOffset.x,
|
|
metrics.mScrollableRect.y - metrics.mScrollOffset.y,
|
|
metrics.mScrollableRect.width,
|
|
metrics.mScrollableRect.height));
|
|
documentBounds.RoundOut();
|
|
screenRect = screenRect.Intersect(nsIntRect(documentBounds.x, documentBounds.y,
|
|
documentBounds.width, documentBounds.height));
|
|
|
|
// If the screen rect is empty, the user has scrolled entirely into
|
|
// over-scroll and so we can be considered to have full integrity.
|
|
if (screenRect.IsEmpty()) {
|
|
return 1.0f;
|
|
}
|
|
|
|
// Work out how much of the critical display-port covers the screen
|
|
bool hasLowPrecision = false;
|
|
if (!metrics.mCriticalDisplayPort.IsEmpty()) {
|
|
hasLowPrecision = true;
|
|
highPrecisionMultiplier =
|
|
GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect);
|
|
}
|
|
|
|
// Work out how much of the display-port covers the screen
|
|
if (!metrics.mDisplayPort.IsEmpty()) {
|
|
if (hasLowPrecision) {
|
|
lowPrecisionMultiplier =
|
|
GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
|
|
} else {
|
|
lowPrecisionMultiplier = highPrecisionMultiplier =
|
|
GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If none of the screen is covered, we have zero integrity.
|
|
if (highPrecisionMultiplier <= 0.0f && lowPrecisionMultiplier <= 0.0f) {
|
|
return 0.0f;
|
|
}
|
|
#endif // MOZ_ANDROID_OMTC
|
|
|
|
nsIntRegion screenRegion(screenRect);
|
|
nsIntRegion lowPrecisionScreenRegion(screenRect);
|
|
gfx3DMatrix transform;
|
|
ComputeRenderIntegrityInternal(root, screenRegion,
|
|
lowPrecisionScreenRegion, transform);
|
|
|
|
if (!screenRegion.IsEqual(screenRect)) {
|
|
// Calculate the area of the region. All rects in an nsRegion are
|
|
// non-overlapping.
|
|
float screenArea = screenRect.width * screenRect.height;
|
|
float highPrecisionIntegrity = screenRegion.Area() / screenArea;
|
|
float lowPrecisionIntegrity = 1.f;
|
|
if (!lowPrecisionScreenRegion.IsEqual(screenRect)) {
|
|
lowPrecisionIntegrity = lowPrecisionScreenRegion.Area() / screenArea;
|
|
}
|
|
|
|
return ((highPrecisionIntegrity * highPrecisionMultiplier) +
|
|
(lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2;
|
|
}
|
|
|
|
return 1.f;
|
|
}
|
|
|
|
already_AddRefed<ThebesLayerComposite>
|
|
LayerManagerComposite::CreateThebesLayerComposite()
|
|
{
|
|
if (mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return nullptr;
|
|
}
|
|
return nsRefPtr<ThebesLayerComposite>(new ThebesLayerComposite(this)).forget();
|
|
}
|
|
|
|
already_AddRefed<ContainerLayerComposite>
|
|
LayerManagerComposite::CreateContainerLayerComposite()
|
|
{
|
|
if (mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return nullptr;
|
|
}
|
|
return nsRefPtr<ContainerLayerComposite>(new ContainerLayerComposite(this)).forget();
|
|
}
|
|
|
|
already_AddRefed<ImageLayerComposite>
|
|
LayerManagerComposite::CreateImageLayerComposite()
|
|
{
|
|
if (mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return nullptr;
|
|
}
|
|
return nsRefPtr<ImageLayerComposite>(new ImageLayerComposite(this)).forget();
|
|
}
|
|
|
|
already_AddRefed<ColorLayerComposite>
|
|
LayerManagerComposite::CreateColorLayerComposite()
|
|
{
|
|
if (LayerManagerComposite::mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return nullptr;
|
|
}
|
|
return nsRefPtr<ColorLayerComposite>(new ColorLayerComposite(this)).forget();
|
|
}
|
|
|
|
already_AddRefed<CanvasLayerComposite>
|
|
LayerManagerComposite::CreateCanvasLayerComposite()
|
|
{
|
|
if (LayerManagerComposite::mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return nullptr;
|
|
}
|
|
return nsRefPtr<CanvasLayerComposite>(new CanvasLayerComposite(this)).forget();
|
|
}
|
|
|
|
already_AddRefed<RefLayerComposite>
|
|
LayerManagerComposite::CreateRefLayerComposite()
|
|
{
|
|
if (LayerManagerComposite::mDestroyed) {
|
|
NS_WARNING("Call on destroyed layer manager");
|
|
return nullptr;
|
|
}
|
|
return nsRefPtr<RefLayerComposite>(new RefLayerComposite(this)).forget();
|
|
}
|
|
|
|
LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
|
|
EffectChain& aEffects,
|
|
bool aIs3D)
|
|
: mCompositable(nullptr)
|
|
{
|
|
if (!aMaskLayer) {
|
|
return;
|
|
}
|
|
|
|
mCompositable = static_cast<LayerComposite*>(aMaskLayer->ImplData())->GetCompositableHost();
|
|
if (!mCompositable) {
|
|
NS_WARNING("Mask layer with no compositable host");
|
|
return;
|
|
}
|
|
|
|
gfx::Matrix4x4 transform;
|
|
ToMatrix4x4(aMaskLayer->GetEffectiveTransform(), transform);
|
|
mCompositable->AddMaskEffect(aEffects, transform, aIs3D);
|
|
}
|
|
|
|
LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect()
|
|
{
|
|
if (!mCompositable) {
|
|
return;
|
|
}
|
|
|
|
mCompositable->RemoveMaskEffect();
|
|
}
|
|
|
|
TemporaryRef<DrawTarget>
|
|
LayerManagerComposite::CreateDrawTarget(const IntSize &aSize,
|
|
SurfaceFormat aFormat)
|
|
{
|
|
#ifdef XP_MACOSX
|
|
// We don't want to accelerate if the surface is too small which indicates
|
|
// that it's likely used for an icon/static image. We also don't want to
|
|
// accelerate anything that is above the maximum texture size of weakest gpu.
|
|
// Safari uses 5000 area as the minimum for acceleration, we decided 64^2 is more logical.
|
|
bool useAcceleration = aSize.width <= 4096 && aSize.height <= 4096 &&
|
|
aSize.width > 64 && aSize.height > 64 &&
|
|
gfxPlatformMac::GetPlatform()->UseAcceleratedCanvas();
|
|
if (useAcceleration) {
|
|
return Factory::CreateDrawTarget(BACKEND_COREGRAPHICS_ACCELERATED,
|
|
aSize, aFormat);
|
|
}
|
|
#endif
|
|
return LayerManager::CreateDrawTarget(aSize, aFormat);
|
|
}
|
|
|
|
LayerComposite::LayerComposite(LayerManagerComposite *aManager)
|
|
: mCompositeManager(aManager)
|
|
, mCompositor(aManager->GetCompositor())
|
|
, mShadowOpacity(1.0)
|
|
, mUseShadowClipRect(false)
|
|
, mShadowTransformSetByAnimation(false)
|
|
, mDestroyed(false)
|
|
, mLayerComposited(false)
|
|
{ }
|
|
|
|
LayerComposite::~LayerComposite()
|
|
{
|
|
}
|
|
|
|
void
|
|
LayerComposite::Destroy()
|
|
{
|
|
if (!mDestroyed) {
|
|
mDestroyed = true;
|
|
CleanupResources();
|
|
}
|
|
}
|
|
|
|
const nsIntSize&
|
|
LayerManagerComposite::GetWidgetSize()
|
|
{
|
|
return mCompositor->GetWidgetSize();
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::SetCompositorID(uint32_t aID)
|
|
{
|
|
NS_ASSERTION(mCompositor, "No compositor");
|
|
mCompositor->SetCompositorID(aID);
|
|
}
|
|
|
|
void
|
|
LayerManagerComposite::NotifyShadowTreeTransaction()
|
|
{
|
|
mCompositor->NotifyLayersTransaction();
|
|
}
|
|
|
|
bool
|
|
LayerManagerComposite::CanUseCanvasLayerForSize(const gfxIntSize &aSize)
|
|
{
|
|
return mCompositor->CanUseCanvasLayerForSize(gfx::IntSize(aSize.width,
|
|
aSize.height));
|
|
}
|
|
|
|
TextureFactoryIdentifier
|
|
LayerManagerComposite::GetTextureFactoryIdentifier()
|
|
{
|
|
return mCompositor->GetTextureFactoryIdentifier();
|
|
}
|
|
|
|
int32_t
|
|
LayerManagerComposite::GetMaxTextureSize() const
|
|
{
|
|
return mCompositor->GetMaxTextureSize();
|
|
}
|
|
|
|
#ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
|
|
|
|
/*static*/ already_AddRefed<TextureImage>
|
|
LayerManagerComposite::OpenDescriptorForDirectTexturing(GLContext*,
|
|
const SurfaceDescriptor&,
|
|
GLenum)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/*static*/ bool
|
|
LayerManagerComposite::SupportsDirectTexturing()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*static*/ void
|
|
LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
|
|
{
|
|
}
|
|
|
|
#endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
|
|
|
|
} /* layers */
|
|
} /* mozilla */
|