2010-05-21 07:20:48 +04:00
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2012-05-21 15:12:37 +04:00
* 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/. */
2010-05-21 07:20:48 +04:00
2012-12-15 03:58:45 +04:00
# include "mozilla/DebugOnly.h"
2010-05-21 07:20:48 +04:00
# include "FrameLayerBuilder.h"
2017-06-09 22:14:53 +03:00
# include "gfxContext.h"
2015-04-12 05:03:00 +03:00
# include "mozilla/LookAndFeel.h"
# include "mozilla/Maybe.h"
# include "mozilla/dom/ProfileTimelineMarkerBinding.h"
2014-06-27 15:19:40 +04:00
# include "mozilla/gfx/Matrix.h"
2015-04-12 05:03:00 +03:00
# include "ActiveLayerTracker.h"
2010-07-16 01:08:05 +04:00
# include "BasicLayers.h"
2013-10-02 04:57:50 +04:00
# include "ImageContainer.h"
2015-10-23 00:02:14 +03:00
# include "ImageLayers.h"
2015-04-12 05:03:00 +03:00
# include "LayerTreeInvalidation.h"
# include "Layers.h"
2015-10-22 23:04:35 +03:00
# include "LayerUserData.h"
2015-04-12 05:03:00 +03:00
# include "MaskLayerImageCache.h"
# include "UnitTransforms.h"
# include "Units.h"
2013-12-30 03:35:53 +04:00
# include "gfx2DGlue.h"
2015-10-28 16:31:00 +03:00
# include "gfxEnv.h"
2015-04-12 05:03:00 +03:00
# include "gfxUtils.h"
2016-06-07 23:10:18 +03:00
# include "nsAutoPtr.h"
2015-09-10 13:24:34 +03:00
# include "nsAnimationManager.h"
2015-04-12 05:03:00 +03:00
# include "nsDisplayList.h"
2014-09-09 22:54:08 +04:00
# include "nsDocShell.h"
2015-04-12 05:03:00 +03:00
# include "nsIScrollableFrame.h"
2014-09-04 09:02:27 +04:00
# include "nsImageFrame.h"
2015-04-12 05:03:00 +03:00
# include "nsLayoutUtils.h"
# include "nsPresContext.h"
# include "nsPrintfCString.h"
# include "nsSVGIntegrationUtils.h"
2015-09-10 13:24:34 +03:00
# include "nsTransitionManager.h"
2015-08-31 15:56:37 +03:00
# include "mozilla/LayerTimelineMarker.h"
2010-07-16 01:07:51 +04:00
2015-12-10 00:28:10 +03:00
# include "mozilla/EffectCompositor.h"
2015-04-12 05:03:00 +03:00
# include "mozilla/Move.h"
# include "mozilla/ReverseIterator.h"
2013-11-06 23:10:50 +04:00
# include "mozilla/gfx/2D.h"
2015-04-12 05:03:00 +03:00
# include "mozilla/gfx/Tools.h"
2016-05-10 13:18:11 +03:00
# include "mozilla/layers/ShadowLayers.h"
# include "mozilla/layers/TextureClient.h"
# include "mozilla/layers/TextureWrapperImage.h"
2016-08-23 07:09:32 +03:00
# include "mozilla/Unused.h"
2015-04-12 05:03:00 +03:00
# include "GeckoProfiler.h"
# include "LayersLogging.h"
# include "gfxPrefs.h"
2011-11-15 08:59:03 +04:00
2013-01-15 16:22:03 +04:00
# include <algorithm>
2016-11-28 19:03:53 +03:00
# include <functional>
2012-07-31 21:28:21 +04:00
2010-05-21 07:20:48 +04:00
using namespace mozilla : : layers ;
2012-10-02 08:00:09 +04:00
using namespace mozilla : : gfx ;
2010-05-21 07:20:48 +04:00
namespace mozilla {
2015-03-03 02:43:58 +03:00
class PaintedDisplayItemLayerUserData ;
2017-05-10 06:07:37 +03:00
static nsTHashtable < nsPtrHashKey < DisplayItemData > > * sAliveDisplayItemDatas ;
2015-04-21 21:13:54 +03:00
2015-07-15 12:05:06 +03:00
/**
* The address of gPaintedDisplayItemLayerUserData is used as the user
* data key for PaintedLayers created by FrameLayerBuilder .
* It identifies PaintedLayers used to draw non - layer content , which are
* therefore eligible for recycling . We want display items to be able to
* create their own dedicated PaintedLayers in BuildLayer , if necessary ,
* and we wouldn ' t want to accidentally recycle those .
* The user data is a PaintedDisplayItemLayerUserData .
*/
uint8_t gPaintedDisplayItemLayerUserData ;
/**
* The address of gColorLayerUserData is used as the user
* data key for ColorLayers created by FrameLayerBuilder .
* The user data is null .
*/
uint8_t gColorLayerUserData ;
/**
* The address of gImageLayerUserData is used as the user
* data key for ImageLayers created by FrameLayerBuilder .
* The user data is null .
*/
uint8_t gImageLayerUserData ;
/**
* The address of gLayerManagerUserData is used as the user
* data key for retained LayerManagers managed by FrameLayerBuilder .
* The user data is a LayerManagerData .
*/
uint8_t gLayerManagerUserData ;
/**
* The address of gMaskLayerUserData is used as the user
* data key for mask layers managed by FrameLayerBuilder .
* The user data is a MaskLayerUserData .
*/
uint8_t gMaskLayerUserData ;
2016-11-01 11:43:34 +03:00
/**
* The address of gCSSMaskLayerUserData is used as the user
* data key for mask layers of css masking managed by FrameLayerBuilder .
* The user data is a CSSMaskLayerUserData .
*/
uint8_t gCSSMaskLayerUserData ;
2015-07-15 12:05:06 +03:00
2016-05-10 13:18:11 +03:00
// a global cache of image containers used for mask layers
static MaskLayerImageCache * gMaskLayerImageCache = nullptr ;
static inline MaskLayerImageCache * GetMaskLayerImageCache ( )
{
if ( ! gMaskLayerImageCache ) {
gMaskLayerImageCache = new MaskLayerImageCache ( ) ;
}
return gMaskLayerImageCache ;
}
2015-10-23 00:00:16 +03:00
FrameLayerBuilder : : FrameLayerBuilder ( )
: mRetainingManager ( nullptr )
2017-04-29 03:32:05 +03:00
, mContainingPaintedLayer ( nullptr )
, mInactiveLayerClip ( nullptr )
2015-10-23 00:00:16 +03:00
, mDetectedDOMModification ( false )
, mInvalidateAllLayers ( false )
, mInLayerTreeCompressionMode ( false )
2017-10-07 01:32:30 +03:00
, mIsInactiveLayerManager ( false )
2015-10-23 00:00:16 +03:00
, mContainerLayerGeneration ( 0 )
, mMaxContainerLayerGeneration ( 0 )
{
MOZ_COUNT_CTOR ( FrameLayerBuilder ) ;
}
FrameLayerBuilder : : ~ FrameLayerBuilder ( )
{
2016-05-10 13:18:11 +03:00
GetMaskLayerImageCache ( ) - > Sweep ( ) ;
2015-10-23 00:00:16 +03:00
MOZ_COUNT_DTOR ( FrameLayerBuilder ) ;
}
2017-05-10 06:07:37 +03:00
DisplayItemData : : DisplayItemData ( LayerManagerData * aParent , uint32_t aKey ,
Layer * aLayer , nsIFrame * aFrame )
2012-10-12 03:38:24 +04:00
2017-05-10 06:07:37 +03:00
: mRefCnt ( 0 )
, mParent ( aParent )
2015-04-11 00:11:04 +03:00
, mLayer ( aLayer )
2012-08-21 08:06:46 +04:00
, mDisplayItemKey ( aKey )
2014-07-23 10:03:24 +04:00
, mItem ( nullptr )
2012-10-12 06:39:46 +04:00
, mUsed ( true )
2012-11-07 02:04:53 +04:00
, mIsInvalid ( false )
2012-10-12 03:38:24 +04:00
{
2017-05-10 06:07:37 +03:00
MOZ_COUNT_CTOR ( DisplayItemData ) ;
2015-04-21 21:13:54 +03:00
if ( ! sAliveDisplayItemDatas ) {
2017-05-10 06:07:37 +03:00
sAliveDisplayItemDatas = new nsTHashtable < nsPtrHashKey < DisplayItemData > > ( ) ;
2015-04-21 21:13:54 +03:00
}
MOZ_RELEASE_ASSERT ( ! sAliveDisplayItemDatas - > Contains ( this ) ) ;
sAliveDisplayItemDatas - > PutEntry ( this ) ;
2015-04-11 00:30:09 +03:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2014-07-23 10:03:24 +04:00
if ( aFrame ) {
AddFrame ( aFrame ) ;
}
2015-04-21 21:13:54 +03:00
2012-10-12 03:38:24 +04:00
}
2012-08-21 08:06:46 +04:00
2012-10-12 03:38:24 +04:00
void
2017-05-10 06:07:37 +03:00
DisplayItemData : : AddFrame ( nsIFrame * aFrame )
2012-10-12 03:38:24 +04:00
{
2015-04-11 00:30:09 +03:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2012-10-12 06:39:46 +04:00
mFrameList . AppendElement ( aFrame ) ;
2017-05-10 06:07:38 +03:00
SmallPointerArray < DisplayItemData > & array = aFrame - > DisplayItemData ( ) ;
array . AppendElement ( this ) ;
2012-08-29 09:47:15 +04:00
}
2012-10-12 03:38:24 +04:00
void
2017-05-10 06:07:37 +03:00
DisplayItemData : : RemoveFrame ( nsIFrame * aFrame )
2012-10-16 05:23:07 +04:00
{
2015-03-16 23:04:00 +03:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2015-04-11 00:34:04 +03:00
bool result = mFrameList . RemoveElement ( aFrame ) ;
MOZ_RELEASE_ASSERT ( result , " Can't remove a frame that wasn't added! " ) ;
2012-10-16 05:23:07 +04:00
2017-05-10 06:07:38 +03:00
SmallPointerArray < DisplayItemData > & array = aFrame - > DisplayItemData ( ) ;
array . RemoveElement ( this ) ;
2012-10-16 05:23:07 +04:00
}
void
2017-05-10 06:07:37 +03:00
DisplayItemData : : EndUpdate ( )
2014-07-23 10:03:24 +04:00
{
2015-03-16 23:04:00 +03:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2014-07-23 10:03:24 +04:00
MOZ_ASSERT ( ! mItem ) ;
mIsInvalid = false ;
mUsed = false ;
}
void
2017-05-10 06:07:37 +03:00
DisplayItemData : : EndUpdate ( nsAutoPtr < nsDisplayItemGeometry > aGeometry )
2014-07-23 10:03:24 +04:00
{
2015-03-16 23:04:00 +03:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2014-07-23 10:03:24 +04:00
MOZ_ASSERT ( mItem ) ;
2015-11-06 06:57:47 +03:00
MOZ_ASSERT ( mGeometry | | aGeometry ) ;
2014-07-23 10:03:24 +04:00
2015-11-06 06:57:47 +03:00
if ( aGeometry ) {
mGeometry = aGeometry ;
}
2014-07-23 10:03:24 +04:00
mClip = mItem - > GetClip ( ) ;
2017-03-21 03:07:49 +03:00
mChangedFrameInvalidations . SetEmpty ( ) ;
2014-07-23 10:03:24 +04:00
mItem = nullptr ;
EndUpdate ( ) ;
}
void
2017-05-10 06:07:37 +03:00
DisplayItemData : : BeginUpdate ( Layer * aLayer , LayerState aState ,
uint32_t aContainerLayerGeneration ,
nsDisplayItem * aItem /* = nullptr */ )
2012-10-12 03:38:24 +04:00
{
2015-04-11 00:30:09 +03:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2015-03-16 23:04:00 +03:00
MOZ_RELEASE_ASSERT ( aLayer ) ;
2012-10-12 06:39:46 +04:00
mLayer = aLayer ;
mOptLayer = nullptr ;
mInactiveManager = nullptr ;
mLayerState = aState ;
mContainerLayerGeneration = aContainerLayerGeneration ;
mUsed = true ;
2012-10-16 05:23:07 +04:00
2014-09-26 21:06:08 +04:00
if ( aLayer - > AsPaintedLayer ( ) ) {
2014-07-23 10:03:24 +04:00
mItem = aItem ;
}
2012-10-16 05:23:07 +04:00
if ( ! aItem ) {
return ;
}
2014-07-23 10:03:24 +04:00
// We avoid adding or removing element unnecessarily
// since we have to modify userdata each time
2016-02-02 18:36:30 +03:00
AutoTArray < nsIFrame * , 4 > copy ( mFrameList ) ;
2013-04-19 16:02:13 +04:00
if ( ! copy . RemoveElement ( aItem - > Frame ( ) ) ) {
AddFrame ( aItem - > Frame ( ) ) ;
2017-03-21 03:07:49 +03:00
mChangedFrameInvalidations . Or ( mChangedFrameInvalidations ,
aItem - > Frame ( ) - > GetVisualOverflowRect ( ) ) ;
2012-10-16 05:23:07 +04:00
}
2016-02-02 18:36:30 +03:00
AutoTArray < nsIFrame * , 4 > mergedFrames ;
2012-10-16 05:23:07 +04:00
aItem - > GetMergedFrames ( & mergedFrames ) ;
for ( uint32_t i = 0 ; i < mergedFrames . Length ( ) ; + + i ) {
if ( ! copy . RemoveElement ( mergedFrames [ i ] ) ) {
AddFrame ( mergedFrames [ i ] ) ;
2017-03-21 03:07:49 +03:00
mChangedFrameInvalidations . Or ( mChangedFrameInvalidations ,
mergedFrames [ i ] - > GetVisualOverflowRect ( ) ) ;
2012-10-16 05:23:07 +04:00
}
}
for ( uint32_t i = 0 ; i < copy . Length ( ) ; i + + ) {
2014-03-20 10:49:27 +04:00
RemoveFrame ( copy [ i ] ) ;
2017-03-21 03:07:49 +03:00
mChangedFrameInvalidations . Or ( mChangedFrameInvalidations ,
copy [ i ] - > GetVisualOverflowRect ( ) ) ;
2012-10-16 05:23:07 +04:00
}
2012-10-12 03:38:24 +04:00
}
2016-01-28 06:23:59 +03:00
static const nsIFrame * sDestroyedFrame = nullptr ;
2017-05-10 06:07:37 +03:00
DisplayItemData : : ~ DisplayItemData ( )
2012-10-12 03:38:24 +04:00
{
2017-05-10 06:07:37 +03:00
MOZ_COUNT_DTOR ( DisplayItemData ) ;
2015-04-11 00:30:09 +03:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2012-10-12 03:38:24 +04:00
for ( uint32_t i = 0 ; i < mFrameList . Length ( ) ; i + + ) {
2012-10-12 06:39:46 +04:00
nsIFrame * frame = mFrameList [ i ] ;
if ( frame = = sDestroyedFrame ) {
2012-10-12 03:38:24 +04:00
continue ;
}
2017-05-10 06:07:38 +03:00
SmallPointerArray < DisplayItemData > & array = frame - > DisplayItemData ( ) ;
array . RemoveElement ( this ) ;
2012-10-12 03:38:24 +04:00
}
2015-04-21 21:13:54 +03:00
2017-06-06 19:12:17 +03:00
MOZ_RELEASE_ASSERT ( sAliveDisplayItemDatas ) ;
nsPtrHashKey < mozilla : : DisplayItemData > * entry
= sAliveDisplayItemDatas - > GetEntry ( this ) ;
MOZ_RELEASE_ASSERT ( entry ) ;
sAliveDisplayItemDatas - > RemoveEntry ( entry ) ;
2015-04-21 21:13:54 +03:00
if ( sAliveDisplayItemDatas - > Count ( ) = = 0 ) {
delete sAliveDisplayItemDatas ;
sAliveDisplayItemDatas = nullptr ;
}
2012-10-12 03:38:24 +04:00
}
2012-08-21 08:06:46 +04:00
2015-09-16 17:05:00 +03:00
void
2017-05-10 06:07:37 +03:00
DisplayItemData : : ClearAnimationCompositorState ( )
2015-09-16 17:05:00 +03:00
{
2017-08-07 07:07:43 +03:00
if ( mDisplayItemKey ! = static_cast < uint32_t > ( DisplayItemType : : TYPE_TRANSFORM ) & &
mDisplayItemKey ! = static_cast < uint32_t > ( DisplayItemType : : TYPE_OPACITY ) ) {
2015-09-16 17:05:00 +03:00
return ;
}
for ( nsIFrame * frame : mFrameList ) {
2017-08-07 07:07:43 +03:00
nsCSSPropertyID prop = mDisplayItemKey = = static_cast < uint32_t > ( DisplayItemType : : TYPE_TRANSFORM ) ?
2015-09-16 17:05:00 +03:00
eCSSProperty_transform : eCSSProperty_opacity ;
2016-01-13 01:54:56 +03:00
EffectCompositor : : ClearIsRunningOnCompositor ( frame , prop ) ;
2015-09-16 17:05:00 +03:00
}
}
2017-03-21 03:07:49 +03:00
const nsRegion &
DisplayItemData : : GetChangedFrameInvalidations ( )
2012-08-29 09:47:15 +04:00
{
2017-03-21 03:07:49 +03:00
return mChangedFrameInvalidations ;
2012-08-29 09:47:15 +04:00
}
2017-05-10 06:07:37 +03:00
DisplayItemData *
DisplayItemData : : AssertDisplayItemData ( DisplayItemData * aData )
2017-04-25 06:02:48 +03:00
{
MOZ_RELEASE_ASSERT ( aData ) ;
MOZ_RELEASE_ASSERT ( sAliveDisplayItemDatas & & sAliveDisplayItemDatas - > Contains ( aData ) ) ;
MOZ_RELEASE_ASSERT ( aData - > mLayer ) ;
return aData ;
}
2010-05-21 07:20:48 +04:00
/**
2010-07-16 01:07:51 +04:00
* This is the userdata we associate with a layer manager .
2010-05-21 07:20:48 +04:00
*/
2010-09-02 13:18:39 +04:00
class LayerManagerData : public LayerUserData {
2010-05-21 07:20:48 +04:00
public :
2014-09-01 07:36:37 +04:00
explicit LayerManagerData ( LayerManager * aManager )
2012-10-12 03:38:24 +04:00
: mLayerManager ( aManager )
2012-10-12 06:39:46 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-12 03:38:24 +04:00
, mParent ( nullptr )
2012-10-12 06:39:46 +04:00
# endif
2012-10-12 03:38:24 +04:00
, mInvalidateAllLayers ( false )
2010-05-21 07:20:48 +04:00
{
2010-09-02 13:18:39 +04:00
MOZ_COUNT_CTOR ( LayerManagerData ) ;
2010-05-21 07:20:48 +04:00
}
2010-09-02 13:18:39 +04:00
~ LayerManagerData ( ) {
2012-08-29 09:48:41 +04:00
MOZ_COUNT_DTOR ( LayerManagerData ) ;
2010-09-02 13:18:39 +04:00
}
2014-03-20 10:49:27 +04:00
2012-10-12 03:38:25 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
void Dump ( const char * aPrefix = " " ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " %sLayerManagerData %p \n " , aPrefix , this ) ;
2015-07-15 12:05:06 +03:00
for ( auto iter = mDisplayItems . Iter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
FrameLayerBuilder : : DisplayItemData * data = iter . Get ( ) - > GetKey ( ) ;
nsAutoCString prefix ;
prefix + = aPrefix ;
prefix + = " " ;
const char * layerState ;
switch ( data - > mLayerState ) {
case LAYER_NONE :
layerState = " LAYER_NONE " ; break ;
case LAYER_INACTIVE :
layerState = " LAYER_INACTIVE " ; break ;
case LAYER_ACTIVE :
layerState = " LAYER_ACTIVE " ; break ;
case LAYER_ACTIVE_FORCE :
layerState = " LAYER_ACTIVE_FORCE " ; break ;
case LAYER_ACTIVE_EMPTY :
layerState = " LAYER_ACTIVE_EMPTY " ; break ;
case LAYER_SVG_EFFECTS :
layerState = " LAYER_SVG_EFFECTS " ; break ;
}
2017-08-07 07:07:43 +03:00
uint32_t mask = ( 1 < < TYPE_BITS ) - 1 ;
2015-07-15 12:05:06 +03:00
nsAutoCString str ;
str + = prefix ;
str + = nsPrintfCString ( " Frame %p " , data - > mFrameList [ 0 ] ) ;
str + = nsDisplayItem : : DisplayItemTypeName ( static_cast < nsDisplayItem : : Type > ( data - > mDisplayItemKey & mask ) ) ;
2017-08-07 07:07:43 +03:00
if ( ( data - > mDisplayItemKey > > TYPE_BITS ) ) {
str + = nsPrintfCString ( " (%i) " , data - > mDisplayItemKey > > TYPE_BITS ) ;
2015-07-15 12:05:06 +03:00
}
str + = nsPrintfCString ( " , %s, Layer %p " , layerState , data - > mLayer . get ( ) ) ;
if ( data - > mOptLayer ) {
str + = nsPrintfCString ( " , OptLayer %p " , data - > mOptLayer . get ( ) ) ;
}
if ( data - > mInactiveManager ) {
str + = nsPrintfCString ( " , InactiveLayerManager %p " , data - > mInactiveManager . get ( ) ) ;
}
str + = " \n " ;
printf_stderr ( " %s " , str . get ( ) ) ;
if ( data - > mInactiveManager ) {
prefix + = " " ;
printf_stderr ( " %sDumping inactive layer info: \n " , prefix . get ( ) ) ;
LayerManagerData * lmd = static_cast < LayerManagerData * >
( data - > mInactiveManager - > GetUserData ( & gLayerManagerUserData ) ) ;
lmd - > Dump ( prefix . get ( ) ) ;
}
}
2012-10-12 03:38:25 +04:00
}
# endif
2010-07-16 01:07:51 +04:00
/**
* Tracks which frames have layers associated with them .
*/
2012-10-12 03:38:24 +04:00
LayerManager * mLayerManager ;
2012-10-12 06:39:46 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-12 03:38:24 +04:00
LayerManagerData * mParent ;
2012-10-12 06:39:46 +04:00
# endif
2017-05-10 06:07:37 +03:00
nsTHashtable < nsRefPtrHashKey < DisplayItemData > > mDisplayItems ;
2011-09-29 10:19:26 +04:00
bool mInvalidateAllLayers ;
2010-07-16 01:07:51 +04:00
} ;
2012-08-29 09:48:41 +04:00
/* static */ void
FrameLayerBuilder : : DestroyDisplayItemDataFor ( nsIFrame * aFrame )
{
2017-05-10 06:07:38 +03:00
RemoveFrameFromLayerManager ( aFrame , aFrame - > DisplayItemData ( ) ) ;
aFrame - > DisplayItemData ( ) . Clear ( ) ;
2012-08-29 09:48:41 +04:00
}
2015-03-04 08:21:55 +03:00
struct AssignedDisplayItem
{
AssignedDisplayItem ( nsDisplayItem * aItem ,
const DisplayItemClip & aClip ,
LayerState aLayerState )
: mItem ( aItem )
, mClip ( aClip )
, mLayerState ( aLayerState )
{ }
nsDisplayItem * mItem ;
DisplayItemClip mClip ;
LayerState mLayerState ;
} ;
2013-12-16 16:11:01 +04:00
/**
2014-09-26 21:06:08 +04:00
* We keep a stack of these to represent the PaintedLayers that are
2013-12-16 16:11:01 +04:00
* currently available to have display items added to .
* We use a stack here because as much as possible we want to
2014-09-26 21:06:08 +04:00
* assign display items to existing PaintedLayers , and to the lowest
* PaintedLayer in z - order . This reduces the number of layers and
2013-12-16 16:11:01 +04:00
* makes it more likely a display item will be rendered to an opaque
* layer , giving us the best chance of getting subpixel AA .
*/
2014-09-26 21:06:08 +04:00
class PaintedLayerData {
2013-12-16 16:11:01 +04:00
public :
2015-06-16 20:41:59 +03:00
PaintedLayerData ( ) :
mAnimatedGeometryRoot ( nullptr ) ,
2017-02-01 01:07:35 +03:00
mASR ( nullptr ) ,
2014-02-26 08:17:18 +04:00
mReferenceFrame ( nullptr ) ,
2013-12-16 16:11:01 +04:00
mLayer ( nullptr ) ,
2015-12-14 06:06:00 +03:00
mSolidColor ( NS_RGBA ( 0 , 0 , 0 , 0 ) ) ,
2013-12-16 16:11:01 +04:00
mIsSolidColorInVisibleRegion ( false ) ,
mNeedComponentAlpha ( false ) ,
mForceTransparentSurface ( false ) ,
2014-06-23 08:24:00 +04:00
mHideAllLayersBelow ( false ) ,
2014-08-31 07:29:24 +04:00
mOpaqueForAnimatedGeometryRootParent ( false ) ,
2015-06-27 01:13:50 +03:00
mDisableFlattening ( false ) ,
2015-09-17 04:31:00 +03:00
mBackfaceHidden ( false ) ,
2017-07-20 12:34:15 +03:00
mShouldPaintOnContentSide ( false ) ,
2013-12-16 16:11:01 +04:00
mImage ( nullptr ) ,
mCommonClipCount ( - 1 ) ,
2015-06-16 20:41:59 +03:00
mNewChildLayersIndex ( - 1 )
2014-02-21 05:11:17 +04:00
{ }
2014-11-26 01:05:39 +03:00
# ifdef MOZ_DUMP_PAINTING
/**
* Keep track of important decisions for debugging .
*/
2015-05-10 17:18:52 +03:00
nsCString mLog ;
2014-11-26 01:05:39 +03:00
2014-11-26 21:58:15 +03:00
# define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
2014-12-31 23:21:58 +03:00
if ( gfxPrefs : : LayersDumpDecision ( ) ) { \
pld - > mLog . AppendPrintf ( " \t \t \t \t " ) ; \
pld - > mLog . AppendPrintf ( __VA_ARGS__ ) ; \
}
2014-11-26 01:05:39 +03:00
# else
# define FLB_LOG_PAINTED_LAYER_DECISION(...)
# endif
2013-12-16 16:11:01 +04:00
/**
2014-09-26 21:06:08 +04:00
* Record that an item has been added to the PaintedLayer , so we
2013-12-16 16:11:01 +04:00
* need to update our regions .
* @ param aVisibleRect the area of the item that ' s visible
* @ param aSolidColor if non - null , the visible area of the item is
* a constant color given by * aSolidColor
*/
void Accumulate ( ContainerState * aState ,
nsDisplayItem * aItem ,
const nsIntRect & aVisibleRect ,
2015-03-04 08:21:55 +03:00
const DisplayItemClip & aClip ,
2017-09-12 21:14:27 +03:00
LayerState aLayerState ,
nsDisplayList * aList ) ;
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * GetAnimatedGeometryRoot ( ) { return mAnimatedGeometryRoot ; }
2013-12-16 16:11:01 +04:00
2016-07-21 02:02:09 +03:00
/**
* A region including the horizontal pan , vertical pan , and no action regions .
*/
nsRegion CombinedTouchActionRegion ( ) ;
2013-12-16 16:16:24 +04:00
/**
2014-11-26 01:05:39 +03:00
* Add the given hit regions to the hit regions to the hit retions for this
* PaintedLayer .
2013-12-16 16:16:24 +04:00
*/
2015-09-01 02:53:34 +03:00
void AccumulateEventRegions ( ContainerState * aState , nsDisplayLayerEventRegions * aEventRegions ) ;
2013-12-16 16:16:24 +04:00
2013-12-16 16:11:01 +04:00
/**
2015-05-13 10:23:46 +03:00
* If this represents only a nsDisplayImage , and the image type supports being
* optimized to an ImageLayer , returns true .
2013-12-16 16:11:01 +04:00
*/
2015-05-13 10:23:46 +03:00
bool CanOptimizeToImageLayer ( nsDisplayListBuilder * aBuilder ) ;
/**
* If this represents only a nsDisplayImage , and the image type supports being
* optimized to an ImageLayer , returns an ImageContainer for the underlying
* image if one is available .
*/
already_AddRefed < ImageContainer > GetContainerForImageLayer ( nsDisplayListBuilder * aBuilder ) ;
2013-12-16 16:11:01 +04:00
2015-02-18 21:01:40 +03:00
bool VisibleAboveRegionIntersects ( const nsIntRegion & aRegion ) const
2015-04-02 21:22:40 +03:00
{ return ! mVisibleAboveRegion . Intersect ( aRegion ) . IsEmpty ( ) ; }
bool VisibleRegionIntersects ( const nsIntRegion & aRegion ) const
{ return ! mVisibleRegion . Intersect ( aRegion ) . IsEmpty ( ) ; }
2014-02-26 08:17:18 +04:00
2013-12-16 16:11:01 +04:00
/**
* The region of visible content in the layer , relative to the
* container layer ( which is at the snapped top - left of the display
* list reference frame ) .
*/
2015-06-16 20:41:59 +03:00
nsIntRegion mVisibleRegion ;
2013-12-16 16:11:01 +04:00
/**
* The region of visible content in the layer that is opaque .
* Same coordinate system as mVisibleRegion .
*/
nsIntRegion mOpaqueRegion ;
2013-12-16 16:16:24 +04:00
/**
2014-09-26 21:06:08 +04:00
* The definitely - hit region for this PaintedLayer .
2013-12-16 16:16:24 +04:00
*/
2014-06-20 07:56:36 +04:00
nsRegion mHitRegion ;
2013-12-16 16:16:24 +04:00
/**
2014-09-26 21:06:08 +04:00
* The maybe - hit region for this PaintedLayer .
2013-12-16 16:16:24 +04:00
*/
2014-06-20 07:56:36 +04:00
nsRegion mMaybeHitRegion ;
2013-12-16 16:16:24 +04:00
/**
2014-09-26 21:06:08 +04:00
* The dispatch - to - content hit region for this PaintedLayer .
2013-12-16 16:16:24 +04:00
*/
2014-06-20 07:56:36 +04:00
nsRegion mDispatchToContentHitRegion ;
2015-03-24 16:13:24 +03:00
/**
* The region for this PaintedLayer that is sensitive to events
* but disallows panning and zooming . This is an approximation
* and any deviation from the true region will be part of the
* mDispatchToContentHitRegion .
*/
nsRegion mNoActionRegion ;
/**
* The region for this PaintedLayer that is sensitive to events and
* allows horizontal panning but not zooming . This is an approximation
* and any deviation from the true region will be part of the
* mDispatchToContentHitRegion .
*/
nsRegion mHorizontalPanRegion ;
/**
* The region for this PaintedLayer that is sensitive to events and
* allows vertical panning but not zooming . This is an approximation
* and any deviation from the true region will be part of the
* mDispatchToContentHitRegion .
*/
nsRegion mVerticalPanRegion ;
2015-09-01 02:53:34 +03:00
/**
2015-09-04 19:14:28 +03:00
* Scaled versions of the bounds of mHitRegion and mMaybeHitRegion .
2015-09-01 02:53:34 +03:00
* We store these because FindPaintedLayerFor ( ) needs to consume them
2015-09-04 19:14:28 +03:00
* in this form , and it ' s a hot code path so we don ' t want to scale
2015-09-01 02:53:34 +03:00
* them inside that function .
*/
2015-09-04 19:14:28 +03:00
nsIntRect mScaledHitRegionBounds ;
nsIntRect mScaledMaybeHitRegionBounds ;
2013-12-16 16:11:01 +04:00
/**
* The " active scrolled root " for all content in the layer . Must
2014-09-26 21:06:08 +04:00
* be non - null ; all content in a PaintedLayer must have the same
2013-12-16 16:11:01 +04:00
* active scrolled root .
*/
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * mASR ;
2015-08-27 01:16:51 +03:00
/**
2017-02-01 01:07:35 +03:00
* The chain of clips that should apply to this layer .
2015-08-27 01:16:51 +03:00
*/
2017-02-01 01:07:35 +03:00
const DisplayItemClipChain * mClipChain ;
2015-03-04 08:21:55 +03:00
/**
* The offset between mAnimatedGeometryRoot and the reference frame .
*/
nsPoint mAnimatedGeometryRootOffset ;
2014-02-26 08:17:18 +04:00
/**
* If non - null , the frame from which we ' ll extract " fixed positioning "
* metadata for this layer . This can be a position : fixed frame or a viewport
* frame ; the latter case is used for background - attachment : fixed content .
*/
2013-12-16 16:11:01 +04:00
const nsIFrame * mReferenceFrame ;
2014-09-26 21:06:08 +04:00
PaintedLayer * mLayer ;
2013-12-16 16:11:01 +04:00
/**
* If mIsSolidColorInVisibleRegion is true , this is the color of the visible
* region .
*/
nscolor mSolidColor ;
/**
* True if every pixel in mVisibleRegion will have color mSolidColor .
*/
bool mIsSolidColorInVisibleRegion ;
/**
* True if there is any text visible in the layer that ' s over
* transparent pixels in the layer .
*/
bool mNeedComponentAlpha ;
/**
* Set if the layer should be treated as transparent , even if its entire
* area is covered by opaque display items . For example , this needs to
* be set if something is going to " punch holes " in the layer by clearing
* part of its surface .
*/
bool mForceTransparentSurface ;
2014-06-23 08:24:00 +04:00
/**
2014-09-26 21:06:08 +04:00
* Set if all layers below this PaintedLayer should be hidden .
2014-06-23 08:24:00 +04:00
*/
bool mHideAllLayersBelow ;
2014-08-31 07:29:24 +04:00
/**
* Set if the opaque region for this layer can be applied to the parent
* animated geometry root of this layer ' s animated geometry root .
2014-09-26 21:06:08 +04:00
* We set this when a PaintedLayer ' s animated geometry root is a scrollframe
* and the PaintedLayer completely fills the displayport of the scrollframe .
2014-08-31 07:29:24 +04:00
*/
bool mOpaqueForAnimatedGeometryRootParent ;
2015-06-27 01:13:50 +03:00
/**
* Set if there is content in the layer that must avoid being flattened .
*/
bool mDisableFlattening ;
2015-09-17 04:31:00 +03:00
/**
* Set if the backface of this region is hidden to the user .
* Content that backface is hidden should not be draw on the layer
* with visible backface .
*/
bool mBackfaceHidden ;
2017-07-20 12:34:15 +03:00
/**
* Set if it is better to render this layer on the content process , for
* example if it contains native theme widgets .
*/
bool mShouldPaintOnContentSide ;
2013-12-16 16:11:01 +04:00
/**
* Stores the pointer to the nsDisplayImage if we want to
* convert this to an ImageLayer .
*/
nsDisplayImageContainer * mImage ;
/**
* Stores the clip that we need to apply to the image or , if there is no
* image , a clip for SOME item in the layer . There is no guarantee which
* item ' s clip will be stored here and mItemClip should not be used to clip
* the whole layer - only some part of the clip should be used , as determined
2014-09-26 21:07:06 +04:00
* by PaintedDisplayItemLayerUserData : : GetCommonClipCount ( ) - which may even be
2013-12-16 16:11:01 +04:00
* no part at all .
*/
DisplayItemClip mItemClip ;
/**
* The first mCommonClipCount rounded rectangle clips are identical for
* all items in the layer .
* - 1 if there are no items in the layer ; must be > = 0 by the time that this
* data is popped from the stack .
*/
int32_t mCommonClipCount ;
2014-06-23 08:24:00 +04:00
/**
* Index of this layer in mNewChildLayers .
*/
int32_t mNewChildLayersIndex ;
2013-12-16 16:11:01 +04:00
/*
* Updates mCommonClipCount by checking for rounded rect clips in common
* between the clip on a new item ( aCurrentClip ) and the common clips
* on items already in the layer ( the first mCommonClipCount rounded rects
* in mItemClip ) .
*/
void UpdateCommonClipCount ( const DisplayItemClip & aCurrentClip ) ;
/**
* The region of visible content above the layer and below the
2015-04-02 21:22:40 +03:00
* next PaintedLayerData currently in the stack , if any .
2013-12-16 16:11:01 +04:00
* This is a conservative approximation : it contains the true region .
*/
2015-06-16 20:41:59 +03:00
nsIntRegion mVisibleAboveRegion ;
2015-03-04 08:21:55 +03:00
/**
* All the display items that have been assigned to this painted layer .
* These items get added by Accumulate ( ) .
*/
nsTArray < AssignedDisplayItem > mAssignedDisplayItems ;
2014-08-22 19:53:24 +04:00
2013-12-16 16:11:01 +04:00
} ;
2014-06-23 08:24:00 +04:00
struct NewLayerEntry {
NewLayerEntry ( )
: mAnimatedGeometryRoot ( nullptr )
2017-02-01 01:07:35 +03:00
, mASR ( nullptr )
, mClipChain ( nullptr )
, mScrollMetadataASR ( nullptr )
2014-06-23 08:24:00 +04:00
, mLayerContentsVisibleRect ( 0 , 0 , - 1 , - 1 )
2016-01-14 02:42:27 +03:00
, mLayerState ( LAYER_INACTIVE )
2014-06-23 08:24:00 +04:00
, mHideAllLayersBelow ( false )
, mOpaqueForAnimatedGeometryRootParent ( false )
2014-07-23 02:53:37 +04:00
, mPropagateComponentAlphaFlattening ( true )
2015-09-17 04:31:00 +03:00
, mUntransformedVisibleRegion ( false )
2017-02-01 01:07:35 +03:00
, mIsFixedToRootScrollFrame ( false )
2014-06-23 08:24:00 +04:00
{ }
2014-09-26 21:06:08 +04:00
// mLayer is null if the previous entry is for a PaintedLayer that hasn't
2014-06-23 08:24:00 +04:00
// been optimized to some other form (yet).
2015-10-18 08:24:48 +03:00
RefPtr < Layer > mLayer ;
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * mASR ;
const DisplayItemClipChain * mClipChain ;
const ActiveScrolledRoot * mScrollMetadataASR ;
2016-03-29 02:14:52 +03:00
// If non-null, this ScrollMetadata is set to the be the first ScrollMetadata
2014-08-31 07:29:24 +04:00
// on the layer.
2016-03-29 02:14:52 +03:00
UniquePtr < ScrollMetadata > mBaseScrollMetadata ;
2014-06-23 08:24:00 +04:00
// The following are only used for retained layers (for occlusion
// culling of those layers). These regions are all relative to the
// container reference frame.
nsIntRegion mVisibleRegion ;
nsIntRegion mOpaqueRegion ;
// This rect is in the layer's own coordinate space. The computed visible
// region for the layer cannot extend beyond this rect.
nsIntRect mLayerContentsVisibleRect ;
2016-01-14 02:42:27 +03:00
LayerState mLayerState ;
2014-06-23 08:24:00 +04:00
bool mHideAllLayersBelow ;
// When mOpaqueForAnimatedGeometryRootParent is true, the opaque region of
// this layer is opaque in the same position even subject to the animation of
// geometry of mAnimatedGeometryRoot. For example when mAnimatedGeometryRoot
// is a scrolled frame and the scrolled content is opaque everywhere in the
// displayport, we can set this flag.
// When this flag is set, we can treat this opaque region as covering
// content whose animated geometry root is the animated geometry root for
// mAnimatedGeometryRoot->GetParent().
bool mOpaqueForAnimatedGeometryRootParent ;
2014-07-23 02:53:37 +04:00
// If true, then the content flags for this layer should contribute
// to our decision to flatten component alpha layers, false otherwise.
bool mPropagateComponentAlphaFlattening ;
2015-09-17 04:31:00 +03:00
// mVisibleRegion is relative to the associated frame before
// transform.
bool mUntransformedVisibleRegion ;
2017-02-01 01:07:35 +03:00
bool mIsFixedToRootScrollFrame ;
2014-06-23 08:24:00 +04:00
} ;
2015-04-02 21:22:40 +03:00
class PaintedLayerDataTree ;
/**
* This is tree node type for PaintedLayerDataTree .
* Each node corresponds to a different animated geometry root , and contains
* a stack of PaintedLayerDatas , in bottom - to - top order .
* There is at most one node per animated geometry root . The ancestor and
* descendant relations in PaintedLayerDataTree tree mirror those in the frame
* tree .
* Each node can have clip that describes the potential extents that items in
* this node can cover . If mHasClip is false , it means that the node ' s contents
* can move anywhere .
* Testing against the clip instead of the node ' s actual contents has the
* advantage that the node ' s contents can move or animate without affecting
* content in other nodes . So we don ' t need to re - layerize during animations
* ( sync or async ) , and during async animations everything is guaranteed to
* look correct .
* The contents of a node ' s PaintedLayerData stack all share the node ' s
* animated geometry root . The child nodes are on top of the PaintedLayerData
* stack , in z - order , and the clip rects of the child nodes are allowed to
* intersect with the visible region or visible above region of their parent
* node ' s PaintedLayerDatas .
*/
class PaintedLayerDataNode {
public :
PaintedLayerDataNode ( PaintedLayerDataTree & aTree ,
PaintedLayerDataNode * aParent ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
~ PaintedLayerDataNode ( ) ;
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * GetAnimatedGeometryRoot ( ) const { return mAnimatedGeometryRoot ; }
2015-04-02 21:22:40 +03:00
/**
* Whether this node ' s contents can potentially intersect aRect .
* aRect is in our tree ' s ContainerState ' s coordinate space .
*/
bool Intersects ( const nsIntRect & aRect ) const
{ return ! mHasClip | | mClipRect . Intersects ( aRect ) ; }
/**
* Create a PaintedLayerDataNode for aAnimatedGeometryRoot , add it to our
* children , and return it .
*/
2015-11-25 01:53:51 +03:00
PaintedLayerDataNode * AddChildNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
/**
* Find a PaintedLayerData in our mPaintedLayerDataStack that aItem can be
* added to . Creates a new PaintedLayerData by calling
* aNewPaintedLayerCallback if necessary .
*/
template < typename NewPaintedLayerCallbackType >
PaintedLayerData * FindPaintedLayerFor ( const nsIntRect & aVisibleRect ,
2015-09-17 04:31:00 +03:00
bool aBackfaceHidden ,
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * aASR ,
const DisplayItemClipChain * aClipChain ,
2015-04-02 21:22:40 +03:00
NewPaintedLayerCallbackType aNewPaintedLayerCallback ) ;
/**
* Find an opaque background color for aRegion . Pulls a color from the parent
* geometry root if appropriate , but only if that color is present underneath
* the whole clip of this node , so that this node ' s contents can animate or
* move ( possibly async ) without having to change the background color .
* @ param aUnderIndex Searching will start in mPaintedLayerDataStack right
* below aUnderIndex .
*/
enum { ABOVE_TOP = - 1 } ;
nscolor FindOpaqueBackgroundColor ( const nsIntRegion & aRegion ,
int32_t aUnderIndex = ABOVE_TOP ) const ;
/**
* Same as FindOpaqueBackgroundColor , but only returns a color if absolutely
* nothing is in between , so that it can be used for a layer that can move
* anywhere inside our clip .
*/
nscolor FindOpaqueBackgroundColorCoveringEverything ( ) const ;
/**
* Adds aRect to this node ' s top PaintedLayerData ' s mVisibleAboveRegion ,
* or mVisibleAboveBackgroundRegion if mPaintedLayerDataStack is empty .
*/
void AddToVisibleAboveRegion ( const nsIntRect & aRect ) ;
/**
* Call this if all of our existing content can potentially be covered , so
* nothing can merge with it and all new content needs to create new items
* on top . This will finish all of our children and pop our whole
* mPaintedLayerDataStack .
*/
void SetAllDrawingAbove ( ) ;
/**
* Finish this node : Finish all children , finish our PaintedLayer contents ,
* and ( if requested ) adjust our parent ' s visible above region to include
* our clip .
*/
void Finish ( bool aParentNeedsAccurateVisibleAboveRegion ) ;
/**
* Finish any children that intersect aRect .
*/
void FinishChildrenIntersecting ( const nsIntRect & aRect ) ;
/**
* Finish all children .
*/
void FinishAllChildren ( ) { FinishAllChildren ( true ) ; }
protected :
/**
* Finish the topmost item in mPaintedLayerDataStack and pop it from the
* stack .
*/
void PopPaintedLayerData ( ) ;
/**
* Finish all items in mPaintedLayerDataStack and clear the stack .
*/
void PopAllPaintedLayerData ( ) ;
/**
* Finish all of our child nodes , but don ' t touch mPaintedLayerDataStack .
*/
void FinishAllChildren ( bool aThisNodeNeedsAccurateVisibleAboveRegion ) ;
/**
* Pass off opaque background color searching to our parent node , if we have
* one .
*/
nscolor FindOpaqueBackgroundColorInParentNode ( ) const ;
PaintedLayerDataTree & mTree ;
PaintedLayerDataNode * mParent ;
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2015-04-02 21:22:40 +03:00
/**
* Our contents : a PaintedLayerData stack and our child nodes .
*/
nsTArray < PaintedLayerData > mPaintedLayerDataStack ;
/**
* UniquePtr is used here in the sense of " unique ownership " , i . e . there is
* only one owner . Not in the sense of " this is the only pointer to the
* node " : There are two other, non-owning, pointers to our child nodes: The
* node ' s respective children point to their parent node with their mParent
* pointer , and the tree keeps a map of animated geometry root to node in its
* mNodes member . These outside pointers are the reason that mChildren isn ' t
* just an nsTArray < PaintedLayerDataNode > ( since the pointers would become
* invalid whenever the array expands its capacity ) .
*/
nsTArray < UniquePtr < PaintedLayerDataNode > > mChildren ;
/**
* The region that ' s covered between our " background " and the bottom of
* mPaintedLayerDataStack . This is used to indicate whether we can pull
* a background color from our parent node . If mVisibleAboveBackgroundRegion
* should be considered infinite , mAllDrawingAboveBackground will be true and
* the value of mVisibleAboveBackgroundRegion will be meaningless .
*/
2015-06-16 20:41:59 +03:00
nsIntRegion mVisibleAboveBackgroundRegion ;
2015-04-02 21:22:40 +03:00
/**
* Our clip , if we have any . If not , that means we can move anywhere , and
* mHasClip will be false and mClipRect will be meaningless .
*/
nsIntRect mClipRect ;
bool mHasClip ;
/**
* Whether mVisibleAboveBackgroundRegion should be considered infinite .
*/
bool mAllDrawingAboveBackground ;
} ;
class ContainerState ;
/**
* A tree of PaintedLayerDataNodes . At any point in time , the tree only
* contains nodes for animated geometry roots that new items can potentially
* merge into . Any time content is added on top that overlaps existing things
* in such a way that we no longer want to merge new items with some existing
* content , that existing content gets " finished " .
* The public - facing methods of this class are FindPaintedLayerFor ,
* AddingOwnLayer , and Finish . The other public methods are for
* PaintedLayerDataNode .
* The tree calls out to its containing ContainerState for some things .
* All coordinates / rects in the tree or the tree nodes are in the
* ContainerState ' s coordinate space , i . e . relative to the reference frame and
* in layer pixels .
* The clip rects of sibling nodes never overlap . This is ensured by finishing
* existing nodes before adding new ones , if this property were to be violated .
* The root tree node doesn ' t get finished until the ContainerState is
* finished .
* The tree ' s root node is always the root reference frame of the builder . We
* don ' t stop at the container state ' s mContainerAnimatedGeometryRoot because
* some of our contents can have animated geometry roots that are not
* descendants of the container ' s animated geometry root . Every animated
* geometry root we encounter for our contents needs to have a defined place in
* the tree .
*/
class PaintedLayerDataTree {
public :
PaintedLayerDataTree ( ContainerState & aContainerState ,
nscolor & aBackgroundColor )
: mContainerState ( aContainerState )
, mContainerUniformBackgroundColor ( aBackgroundColor )
{ }
~ PaintedLayerDataTree ( )
{
MOZ_ASSERT ( ! mRoot ) ;
MOZ_ASSERT ( mNodes . Count ( ) = = 0 ) ;
}
/**
* Notify our contents that some non - PaintedLayer content has been added .
* * aRect needs to be a rectangle that doesn ' t move with respect to
* aAnimatedGeometryRoot and that contains the added item .
* If aRect is null , the extents will be considered infinite .
* If aOutUniformBackgroundColor is non - null , it will be set to an opaque
* color that can be pulled into the background of the added content , or
* transparent if that is not possible .
*/
2015-11-25 01:53:51 +03:00
void AddingOwnLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 21:22:40 +03:00
const nsIntRect * aRect ,
nscolor * aOutUniformBackgroundColor ) ;
/**
* Find a PaintedLayerData for aItem . This can either be an existing
* PaintedLayerData from inside a node in our tree , or a new one that gets
* created by a call out to aNewPaintedLayerCallback .
*/
template < typename NewPaintedLayerCallbackType >
2015-11-25 01:53:51 +03:00
PaintedLayerData * FindPaintedLayerFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * aASR ,
const DisplayItemClipChain * aClipChain ,
2015-04-02 21:22:40 +03:00
const nsIntRect & aVisibleRect ,
2015-09-17 04:31:00 +03:00
bool aBackfaceidden ,
2015-04-02 21:22:40 +03:00
NewPaintedLayerCallbackType aNewPaintedLayerCallback ) ;
/**
* Finish everything .
*/
void Finish ( ) ;
/**
* Get the parent animated geometry root of aAnimatedGeometryRoot .
* That ' s either aAnimatedGeometryRoot ' s animated geometry root , or , if
* that ' s aAnimatedGeometryRoot itself , then it ' s the animated geometry
* root for aAnimatedGeometryRoot ' s cross - doc parent frame .
*/
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * GetParentAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
/**
* Whether aAnimatedGeometryRoot has an intrinsic clip that doesn ' t move with
* respect to aAnimatedGeometryRoot ' s parent animated geometry root .
* If aAnimatedGeometryRoot is a scroll frame , this will be the scroll frame ' s
* scroll port , otherwise there is no clip .
* This method doesn ' t have much to do with PaintedLayerDataTree , but this is
* where we have easy access to a display list builder , which we use to get
* the clip rect result into the right coordinate space .
*/
2015-11-25 01:53:51 +03:00
bool IsClippedWithRespectToParentAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 21:22:40 +03:00
nsIntRect * aOutClip ) ;
/**
* Called by PaintedLayerDataNode when it is finished , so that we can drop
* our pointers to it .
*/
2015-11-25 01:53:51 +03:00
void NodeWasFinished ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
nsDisplayListBuilder * Builder ( ) const ;
ContainerState & ContState ( ) const { return mContainerState ; }
nscolor UniformBackgroundColor ( ) const { return mContainerUniformBackgroundColor ; }
protected :
/**
* Finish all nodes that potentially intersect * aRect , where * aRect is a rect
* that doesn ' t move with respect to aAnimatedGeometryRoot .
* If aRect is null , * aRect will be considered infinite .
*/
2015-11-25 01:53:51 +03:00
void FinishPotentiallyIntersectingNodes ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 21:22:40 +03:00
const nsIntRect * aRect ) ;
/**
* Make sure that there is a node for aAnimatedGeometryRoot and all of its
* ancestor geometry roots . Return the node for aAnimatedGeometryRoot .
*/
2015-11-25 01:53:51 +03:00
PaintedLayerDataNode * EnsureNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
/**
* Find an existing node in the tree for an ancestor of aAnimatedGeometryRoot .
* * aOutAncestorChild will be set to the last ancestor that was encountered
* in the search up from aAnimatedGeometryRoot ; it will be a child animated
* geometry root of the result , if neither are null .
*/
PaintedLayerDataNode *
2015-11-25 01:53:51 +03:00
FindNodeForAncestorAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
AnimatedGeometryRoot * * aOutAncestorChild ) ;
2015-04-02 21:22:40 +03:00
ContainerState & mContainerState ;
UniquePtr < PaintedLayerDataNode > mRoot ;
/**
* The uniform opaque color from behind this container layer , or
* NS_RGBA ( 0 , 0 , 0 , 0 ) if the background behind this container layer is not
* uniform and opaque . This color can be pulled into PaintedLayers that are
* directly above the background .
*/
nscolor mContainerUniformBackgroundColor ;
/**
* A hash map for quick access the node belonging to a particular animated
* geometry root .
*/
2015-11-25 01:53:51 +03:00
nsDataHashtable < nsPtrHashKey < AnimatedGeometryRoot > , PaintedLayerDataNode * > mNodes ;
2015-04-02 21:22:40 +03:00
} ;
2010-07-16 01:07:51 +04:00
/**
* This is a helper object used to build up the layer children for
* a ContainerLayer .
*/
class ContainerState {
public :
ContainerState ( nsDisplayListBuilder * aBuilder ,
LayerManager * aManager ,
2012-07-17 21:03:51 +04:00
FrameLayerBuilder * aLayerBuilder ,
2010-07-16 01:07:51 +04:00
nsIFrame * aContainerFrame ,
2012-09-28 15:19:39 +04:00
nsDisplayItem * aContainerItem ,
2014-06-09 08:48:00 +04:00
const nsRect & aContainerBounds ,
2011-06-22 16:11:27 +04:00
ContainerLayer * aContainerLayer ,
2014-09-06 08:16:33 +04:00
const ContainerLayerParameters & aParameters ,
2015-02-25 19:47:22 +03:00
bool aFlattenToSingleLayer ,
2015-12-22 18:54:19 +03:00
nscolor aBackgroundColor ,
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * aContainerASR ,
const ActiveScrolledRoot * aContainerScrollMetadataASR ,
const ActiveScrolledRoot * aContainerCompositorASR ) :
2010-07-16 01:07:51 +04:00
mBuilder ( aBuilder ) , mManager ( aManager ) ,
2012-07-17 21:03:51 +04:00
mLayerBuilder ( aLayerBuilder ) ,
2012-09-28 15:19:39 +04:00
mContainerFrame ( aContainerFrame ) ,
mContainerLayer ( aContainerLayer ) ,
2014-06-09 08:48:00 +04:00
mContainerBounds ( aContainerBounds ) ,
2017-02-01 01:07:35 +03:00
mContainerASR ( aContainerASR ) ,
mContainerScrollMetadataASR ( aContainerScrollMetadataASR ) ,
mContainerCompositorASR ( aContainerCompositorASR ) ,
2011-06-22 16:11:27 +04:00
mParameters ( aParameters ) ,
2015-04-02 21:22:40 +03:00
mPaintedLayerDataTree ( * this , aBackgroundColor ) ,
2017-03-04 18:18:00 +03:00
mFlattenToSingleLayer ( aFlattenToSingleLayer ) ,
mLastDisplayPortAGR ( nullptr )
2010-05-21 07:20:48 +04:00
{
2012-04-10 15:24:18 +04:00
nsPresContext * presContext = aContainerFrame - > PresContext ( ) ;
mAppUnitsPerDevPixel = presContext - > AppUnitsPerDevPixel ( ) ;
2014-06-20 07:56:36 +04:00
mContainerReferenceFrame =
const_cast < nsIFrame * > ( aContainerItem ? aContainerItem - > ReferenceFrameForChildren ( ) :
mBuilder - > FindReferenceFrameFor ( mContainerFrame ) ) ;
2015-04-02 21:22:40 +03:00
bool isAtRoot = ! aContainerItem | | ( aContainerItem - > Frame ( ) = = mBuilder - > RootReferenceFrame ( ) ) ;
2017-06-07 08:27:17 +03:00
MOZ_ASSERT ( ! isAtRoot | | mContainerReferenceFrame = = mBuilder - > RootReferenceFrame ( ) ) ;
2015-04-02 21:22:40 +03:00
mContainerAnimatedGeometryRoot = isAtRoot
2015-11-25 01:53:51 +03:00
? aBuilder - > GetRootAnimatedGeometryRoot ( )
: aContainerItem - > GetAnimatedGeometryRoot ( ) ;
2015-11-03 11:03:47 +03:00
MOZ_ASSERT ( ! mBuilder - > IsPaintingToWindow ( ) | |
nsLayoutUtils : : IsAncestorFrameCrossDoc ( mBuilder - > RootReferenceFrame ( ) ,
2015-11-25 01:53:51 +03:00
* mContainerAnimatedGeometryRoot ) ) ;
2012-04-10 15:24:18 +04:00
// When AllowResidualTranslation is false, display items will be drawn
// scaled with a translation by integer pixels, so we know how the snapping
// will work.
mSnappingEnabled = aManager - > IsSnappingEffectiveTransforms ( ) & &
! mParameters . AllowResidualTranslation ( ) ;
2010-07-16 01:08:03 +04:00
CollectOldLayers ( ) ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:51 +04:00
/**
* This is the method that actually walks a display list and builds
2013-03-04 13:56:02 +04:00
* the child layers .
2010-07-16 01:07:51 +04:00
*/
2014-09-06 08:16:33 +04:00
void ProcessDisplayItems ( nsDisplayList * aList ) ;
2010-07-16 01:07:51 +04:00
/**
2014-09-26 21:06:08 +04:00
* This finalizes all the open PaintedLayers by popping every element off
* mPaintedLayerDataStack , then sets the children of the container layer
2010-07-16 01:07:51 +04:00
* to be all the layers in mNewChildLayers in that order and removes any
* layers as children of the container that aren ' t in mNewChildLayers .
2010-12-20 04:26:14 +03:00
* @ param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA ,
* set * aTextContentFlags to CONTENT_COMPONENT_ALPHA
2010-07-16 01:07:51 +04:00
*/
2015-12-16 08:24:06 +03:00
void Finish ( uint32_t * aTextContentFlags ,
2014-06-23 08:24:00 +04:00
const nsIntRect & aContainerPixelBounds ,
2016-01-14 02:42:27 +03:00
nsDisplayList * aChildItems , bool * aHasComponentAlphaChildren ) ;
2014-07-17 19:24:47 +04:00
2012-04-10 15:24:18 +04:00
nscoord GetAppUnitsPerDevPixel ( ) { return mAppUnitsPerDevPixel ; }
2015-03-26 01:08:56 +03:00
nsIntRect ScaleToNearestPixels ( const nsRect & aRect ) const
2012-04-10 15:24:18 +04:00
{
return aRect . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-26 01:08:56 +03:00
nsIntRegion ScaleRegionToNearestPixels ( const nsRegion & aRegion ) const
2012-07-23 07:00:36 +04:00
{
return aRegion . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-26 01:08:56 +03:00
nsIntRect ScaleToOutsidePixels ( const nsRect & aRect , bool aSnap = false ) const
2012-04-10 15:24:18 +04:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2016-11-24 08:11:30 +03:00
nsIntRegion ScaleToOutsidePixels ( const nsRegion & aRegion , bool aSnap = false ) const
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleRegionToNearestPixels ( aRegion ) ;
}
return aRegion . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-26 01:08:56 +03:00
nsIntRect ScaleToInsidePixels ( const nsRect & aRect , bool aSnap = false ) const
2012-04-10 15:24:18 +04:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToInsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-26 01:08:56 +03:00
nsIntRegion ScaleRegionToInsidePixels ( const nsRegion & aRegion , bool aSnap = false ) const
2012-07-23 07:00:36 +04:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleRegionToNearestPixels ( aRegion ) ;
}
return aRegion . ScaleToInsidePixels ( mParameters . mXScale , mParameters . mYScale ,
2013-12-16 16:11:59 +04:00
mAppUnitsPerDevPixel ) ;
}
2015-03-26 01:08:56 +03:00
nsIntRegion ScaleRegionToOutsidePixels ( const nsRegion & aRegion , bool aSnap = false ) const
2013-12-16 16:11:59 +04:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleRegionToNearestPixels ( aRegion ) ;
}
return aRegion . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
2012-07-23 07:00:36 +04:00
mAppUnitsPerDevPixel ) ;
}
2014-06-23 08:24:00 +04:00
nsIFrame * GetContainerFrame ( ) const { return mContainerFrame ; }
2015-04-02 21:22:40 +03:00
nsDisplayListBuilder * Builder ( ) const { return mBuilder ; }
2014-06-23 08:24:00 +04:00
2015-06-27 00:26:06 +03:00
/**
* Check if we are currently inside an inactive layer .
*/
bool IsInInactiveLayer ( ) const {
return mLayerBuilder - > GetContainingPaintedLayerData ( ) ;
}
2014-06-23 08:24:00 +04:00
/**
2015-09-17 04:31:00 +03:00
* Sets aOuterVisibleRegion as aLayer ' s visible region .
* @ param aOuterVisibleRegion
* is in the coordinate space of the container reference frame .
* @ param aLayerContentsVisibleRect , if non - null , is in the layer ' s own
* coordinate system .
* @ param aOuterUntransformed is true if the given aOuterVisibleRegion
* is already untransformed with the matrix of the layer .
2014-06-23 08:24:00 +04:00
*/
void SetOuterVisibleRegionForLayer ( Layer * aLayer ,
const nsIntRegion & aOuterVisibleRegion ,
2015-09-17 04:31:00 +03:00
const nsIntRect * aLayerContentsVisibleRect = nullptr ,
bool aOuterUntransformed = false ) const ;
2014-06-23 08:24:00 +04:00
2015-04-02 21:22:40 +03:00
/**
* Try to determine whether the PaintedLayer aData has a single opaque color
* covering aRect . If successful , return that color , otherwise return
* NS_RGBA ( 0 , 0 , 0 , 0 ) .
* If aRect turns out not to intersect any content in the layer ,
* * aOutIntersectsLayer will be set to false .
*/
nscolor FindOpaqueBackgroundColorInLayer ( const PaintedLayerData * aData ,
const nsIntRect & aRect ,
bool * aOutIntersectsLayer ) const ;
/**
* Indicate that we are done adding items to the PaintedLayer represented by
* aData . Make sure that a real PaintedLayer exists for it , and set the final
* visible region and opaque - content .
*/
template < typename FindOpaqueBackgroundColorCallbackType >
void FinishPaintedLayerData ( PaintedLayerData & aData , FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor ) ;
2010-07-16 01:07:51 +04:00
protected :
2014-09-26 21:06:08 +04:00
friend class PaintedLayerData ;
2010-05-21 07:20:48 +04:00
2015-03-03 03:24:18 +03:00
LayerManager : : PaintedLayerCreationHint
2015-11-25 01:53:51 +03:00
GetLayerCreationHint ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-03-03 03:24:18 +03:00
2010-07-16 01:07:51 +04:00
/**
2015-03-04 08:18:47 +03:00
* Creates a new PaintedLayer and sets up the transform on the PaintedLayer
2010-07-16 01:08:03 +04:00
* to account for scrolling .
2010-07-16 01:07:51 +04:00
*/
2015-03-04 08:18:47 +03:00
already_AddRefed < PaintedLayer > CreatePaintedLayer ( PaintedLayerData * aData ) ;
2015-03-03 02:43:58 +03:00
2015-03-03 03:25:13 +03:00
/**
* Find a PaintedLayer for recycling , recycle it and prepare it for use , or
* return null if no suitable layer was found .
*/
2015-11-25 01:53:51 +03:00
already_AddRefed < PaintedLayer > AttemptToRecyclePaintedLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-04 08:21:00 +03:00
nsDisplayItem * aItem ,
2015-03-03 03:25:13 +03:00
const nsPoint & aTopLeft ) ;
2015-03-03 02:43:58 +03:00
/**
* Recycle aLayer and do any necessary invalidation .
*/
PaintedDisplayItemLayerUserData * RecyclePaintedLayer ( PaintedLayer * aLayer ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-03 02:43:58 +03:00
bool & didResetScrollPositionForLayerPixelAlignment ) ;
/**
2015-03-04 08:18:47 +03:00
* Perform the last step of CreatePaintedLayer / AttemptToRecyclePaintedLayer :
* Initialize aData , set up the layer ' s transform for scrolling , and
* invalidate the layer for layer pixel alignment changes if necessary .
2015-03-03 02:43:58 +03:00
*/
void PreparePaintedLayerForUse ( PaintedLayer * aLayer ,
PaintedDisplayItemLayerUserData * aData ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-03 02:43:58 +03:00
const nsIFrame * aReferenceFrame ,
const nsPoint & aTopLeft ,
bool aDidResetScrollPositionForLayerPixelAlignment ) ;
2015-05-13 10:23:46 +03:00
/**
* Attempt to prepare an ImageLayer based upon the provided PaintedLayerData .
* Returns nullptr on failure .
*/
already_AddRefed < Layer > PrepareImageLayer ( PaintedLayerData * aData ) ;
/**
* Attempt to prepare a ColorLayer based upon the provided PaintedLayerData .
* Returns nullptr on failure .
*/
already_AddRefed < Layer > PrepareColorLayer ( PaintedLayerData * aData ) ;
2010-07-16 01:07:51 +04:00
/**
2010-07-16 01:08:03 +04:00
* Grab the next recyclable ColorLayer , or create one if there are no
* more recyclable ColorLayers .
*/
2014-09-26 21:07:06 +04:00
already_AddRefed < ColorLayer > CreateOrRecycleColorLayer ( PaintedLayer * aPainted ) ;
2011-01-18 00:47:18 +03:00
/**
* Grab the next recyclable ImageLayer , or create one if there are no
* more recyclable ImageLayers .
*/
2014-09-26 21:07:06 +04:00
already_AddRefed < ImageLayer > CreateOrRecycleImageLayer ( PaintedLayer * aPainted ) ;
2012-02-08 02:26:40 +04:00
/**
* Grab a recyclable ImageLayer for use as a mask layer for aLayer ( that is a
* mask layer which has been used for aLayer before ) , or create one if such
* a layer doesn ' t exist .
2015-06-21 19:28:10 +03:00
*
* Since mask layers can exist either on the layer directly , or as a side -
* attachment to FrameMetrics ( for ancestor scrollframe clips ) , we key the
* recycle operation on both the originating layer and the mask layer ' s
* index in the layer , if any .
2012-02-08 02:26:40 +04:00
*/
2015-06-21 19:28:10 +03:00
struct MaskLayerKey ;
2016-11-07 17:32:43 +03:00
already_AddRefed < ImageLayer >
CreateOrRecycleMaskImageLayerFor ( const MaskLayerKey & aKey ,
2017-08-10 09:02:01 +03:00
void ( * aSetUserData ) ( Layer * aLayer ) ) ;
2010-07-16 01:08:03 +04:00
/**
2014-09-26 21:06:08 +04:00
* Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes them
2010-07-16 01:07:51 +04:00
* available for recycling .
*/
2010-07-16 01:08:03 +04:00
void CollectOldLayers ( ) ;
2010-07-16 01:08:05 +04:00
/**
2014-09-26 21:06:08 +04:00
* If aItem used to belong to a PaintedLayer , invalidates the area of
* aItem in that layer . If aNewLayer is a PaintedLayer , invalidates the area of
2010-07-16 01:08:05 +04:00
* aItem in that layer .
*/
2014-03-20 10:49:27 +04:00
void InvalidateForLayerChange ( nsDisplayItem * aItem ,
2014-09-26 21:06:08 +04:00
PaintedLayer * aNewLayer ) ;
2014-06-23 08:24:00 +04:00
/**
* Returns true if aItem ' s opaque area ( in aOpaque ) covers the entire
* scrollable area of its presshell .
*/
bool ItemCoversScrollableArea ( nsDisplayItem * aItem , const nsRegion & aOpaque ) ;
/**
2017-02-01 01:07:35 +03:00
* Set ScrollMetadata and scroll - induced clipping on aEntry ' s layer .
2014-08-31 07:29:24 +04:00
*/
void SetupScrollingMetadata ( NewLayerEntry * aEntry ) ;
/**
* Applies occlusion culling .
2014-06-23 08:24:00 +04:00
* For each layer in mNewChildLayers , remove from its visible region the
* opaque regions of the layers at higher z - index , but only if they have
* the same animated geometry root and fixed - pos frame ancestor .
* The opaque region for the child layers that share the same animated
* geometry root as the container frame is returned in
* * aOpaqueRegionForContainer .
2014-08-31 07:29:24 +04:00
*
* Also sets scroll metadata on the layers .
2014-06-23 08:24:00 +04:00
*/
2014-08-31 07:29:24 +04:00
void PostprocessRetainedLayers ( nsIntRegion * aOpaqueRegionForContainer ) ;
2014-06-23 08:24:00 +04:00
/**
* Computes the snapped opaque area of aItem . Sets aList ' s opaque flag
* if it covers the entire list bounds . Sets * aHideAllLayersBelow to true
* this item covers the entire viewport so that all layers below are
* permanently invisible .
*/
nsIntRegion ComputeOpaqueRect ( nsDisplayItem * aItem ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2017-04-21 05:03:40 +03:00
const ActiveScrolledRoot * aASR ,
2014-06-23 08:24:00 +04:00
const DisplayItemClip & aClip ,
nsDisplayList * aList ,
2014-08-31 07:29:24 +04:00
bool * aHideAllLayersBelow ,
bool * aOpaqueForAnimatedGeometryRootParent ) ;
2014-06-23 08:24:00 +04:00
2010-07-16 01:07:51 +04:00
/**
2015-04-02 21:22:40 +03:00
* Return a PaintedLayerData object that is initialized for a layer that
* aItem will be assigned to .
* @ param aItem The item that is going to be added .
* @ param aVisibleRect The visible rect of the item .
* @ param aAnimatedGeometryRoot The item ' s animated geometry root .
2017-02-01 01:07:35 +03:00
* @ param aASR The active scrolled root that moves this PaintedLayer .
* @ param aClipChain The clip chain that the compositor needs to
* apply to this layer .
* @ param aScrollMetadataASR The leaf ASR for which scroll metadata needs to be
* set on the layer , because either the layer itself
* or its scrolled clip need to move with that ASR .
2015-04-02 21:22:40 +03:00
* @ param aTopLeft The offset between aAnimatedGeometryRoot and
* the reference frame .
2010-07-16 01:07:51 +04:00
*/
2015-04-02 21:22:40 +03:00
PaintedLayerData NewPaintedLayerData ( nsDisplayItem * aItem ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * aASR ,
const DisplayItemClipChain * aClipChain ,
const ActiveScrolledRoot * aScrollMetadataASR ,
const nsPoint & aTopLeft ) ;
2010-05-21 07:20:48 +04:00
2012-02-08 02:27:44 +04:00
/* Build a mask layer to represent the clipping region. Will return null if
* there is no clipping specified or a mask layer cannot be built .
* Builds an ImageLayer for the appropriate backend ; the mask is relative to
* aLayer ' s visible region .
* aLayer is the layer to be clipped .
2014-06-23 08:24:00 +04:00
* relative to the container reference frame
2014-09-26 21:06:08 +04:00
* aRoundedRectClipCount is used when building mask layers for PaintedLayers ,
2012-02-08 02:27:44 +04:00
* SetupMaskLayer will build a mask layer for only the first
* aRoundedRectClipCount rounded rects in aClip
*/
2013-03-04 13:55:59 +04:00
void SetupMaskLayer ( Layer * aLayer , const DisplayItemClip & aClip ,
2012-09-28 10:57:33 +04:00
uint32_t aRoundedRectClipCount = UINT32_MAX ) ;
2012-02-08 02:27:44 +04:00
2016-05-07 02:02:26 +03:00
/**
* If | aClip | has rounded corners , create a mask layer for them , and
* add it to | aLayer | ' s ancestor mask layers , returning an index into
* the array of ancestor mask layers . Returns an empty Maybe if
* | aClip | does not have rounded corners , or if no mask layer could
* be created .
*/
Maybe < size_t > SetupMaskLayerForScrolledClip ( Layer * aLayer ,
const DisplayItemClip & aClip ) ;
2016-11-07 17:32:43 +03:00
/*
* Create / find a mask layer with suitable size for aMaskItem to paint
* css - positioned - masking onto .
*/
void SetupMaskLayerForCSSMask ( Layer * aLayer , nsDisplayMask * aMaskItem ) ;
2015-06-21 02:47:57 +03:00
already_AddRefed < Layer > CreateMaskLayer (
Layer * aLayer , const DisplayItemClip & aClip ,
const Maybe < size_t > & aForAncestorMaskLayer ,
uint32_t aRoundedRectClipCount = UINT32_MAX ) ;
2013-09-26 01:07:26 +04:00
bool ChooseAnimatedGeometryRoot ( const nsDisplayList & aList ,
2017-02-01 01:07:35 +03:00
AnimatedGeometryRoot * * aAnimatedGeometryRoot ,
const ActiveScrolledRoot * * aASR ) ;
2012-12-12 00:36:22 +04:00
2017-03-04 18:18:00 +03:00
/**
* Get the display port for an AGR .
* The result would be cached for later reusing .
*/
nsRect GetDisplayPortForAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2010-07-16 01:07:51 +04:00
nsDisplayListBuilder * mBuilder ;
LayerManager * mManager ;
2012-07-17 21:03:51 +04:00
FrameLayerBuilder * mLayerBuilder ;
2010-07-16 01:07:51 +04:00
nsIFrame * mContainerFrame ;
2014-06-20 07:56:36 +04:00
nsIFrame * mContainerReferenceFrame ;
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * mContainerAnimatedGeometryRoot ;
2010-07-16 01:07:51 +04:00
ContainerLayer * mContainerLayer ;
2014-06-09 08:48:00 +04:00
nsRect mContainerBounds ;
2017-02-01 01:07:35 +03:00
// Due to the way we store scroll annotations in the layer tree, we need to
// keep track of three (possibly different) ASRs here.
// mContainerASR is the ASR of the container display item that this
// ContainerState was created for.
// mContainerScrollMetadataASR is the ASR of the leafmost scroll metadata
// that's in effect on mContainerLayer.
// mContainerCompositorASR is the ASR that mContainerLayer moves with on
// the compositor / APZ side, taking into account both the scroll meta data
// and the fixed position annotation on itself and its ancestors.
const ActiveScrolledRoot * mContainerASR ;
const ActiveScrolledRoot * mContainerScrollMetadataASR ;
const ActiveScrolledRoot * mContainerCompositorASR ;
2016-02-26 18:52:07 +03:00
# ifdef DEBUG
nsRect mAccumulatedChildBounds ;
# endif
2013-09-27 10:01:16 +04:00
ContainerLayerParameters mParameters ;
2010-07-16 01:07:51 +04:00
/**
2014-09-26 21:06:08 +04:00
* The region of PaintedLayers that should be invalidated every time
2010-07-16 01:07:51 +04:00
* we recycle one .
*/
2014-09-26 21:07:06 +04:00
nsIntRegion mInvalidPaintedContent ;
2015-04-02 21:22:40 +03:00
PaintedLayerDataTree mPaintedLayerDataTree ;
2010-07-16 01:07:51 +04:00
/**
* We collect the list of children in here . During ProcessDisplayItems ,
* the layers in this array either have mContainerLayer as their parent ,
* or no parent .
2014-09-26 21:06:08 +04:00
* PaintedLayers have two entries in this array : the second one is used only if
* the PaintedLayer is optimized away to a ColorLayer or ImageLayer .
* It ' s essential that this array is only appended to , since PaintedLayerData
* records the index of its PaintedLayer in this array .
2010-07-16 01:07:51 +04:00
*/
2016-02-02 18:36:30 +03:00
typedef AutoTArray < NewLayerEntry , 1 > AutoLayersArray ;
2010-11-09 05:48:59 +03:00
AutoLayersArray mNewChildLayers ;
2015-03-04 08:21:00 +03:00
nsTHashtable < nsRefPtrHashKey < PaintedLayer > > mPaintedLayersAvailableForRecycling ;
2012-04-10 15:24:18 +04:00
nscoord mAppUnitsPerDevPixel ;
bool mSnappingEnabled ;
2014-09-06 08:16:33 +04:00
bool mFlattenToSingleLayer ;
2015-06-21 19:28:10 +03:00
struct MaskLayerKey {
MaskLayerKey ( ) : mLayer ( nullptr ) { }
MaskLayerKey ( Layer * aLayer , const Maybe < size_t > & aAncestorIndex )
: mLayer ( aLayer ) ,
mAncestorIndex ( aAncestorIndex )
{ }
PLDHashNumber Hash ( ) const {
// Hash the layer and add the layer index to the hash.
return ( NS_PTR_TO_UINT32 ( mLayer ) > > 2 )
+ ( mAncestorIndex ? ( * mAncestorIndex + 1 ) : 0 ) ;
}
bool operator = = ( const MaskLayerKey & aOther ) const {
return mLayer = = aOther . mLayer & &
mAncestorIndex = = aOther . mAncestorIndex ;
}
Layer * mLayer ;
Maybe < size_t > mAncestorIndex ;
} ;
2015-10-18 08:24:48 +03:00
nsDataHashtable < nsGenericHashKey < MaskLayerKey > , RefPtr < ImageLayer > >
2015-06-21 19:28:10 +03:00
mRecycledMaskImageLayers ;
2017-03-04 18:18:00 +03:00
// Keep display port of AGR to avoid wasting time on doing the same
// thing repeatly.
AnimatedGeometryRoot * mLastDisplayPortAGR ;
nsRect mLastDisplayPortRect ;
2010-05-21 07:20:48 +04:00
} ;
2014-09-26 21:07:06 +04:00
class PaintedDisplayItemLayerUserData : public LayerUserData
2010-09-02 13:18:39 +04:00
{
public :
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData ( ) :
2012-09-06 08:07:53 +04:00
mMaskClipCount ( 0 ) ,
2011-06-22 16:11:28 +04:00
mForcedBackgroundColor ( NS_RGBA ( 0 , 0 , 0 , 0 ) ) ,
mXScale ( 1.f ) , mYScale ( 1.f ) ,
2012-08-29 09:47:15 +04:00
mAppUnitsPerDevPixel ( 0 ) ,
2012-09-17 02:25:33 +04:00
mTranslation ( 0 , 0 ) ,
2015-09-15 16:41:42 +03:00
mAnimatedGeometryRootPosition ( 0 , 0 ) { }
2010-09-02 13:18:39 +04:00
2012-09-04 05:02:56 +04:00
/**
2014-09-26 21:07:06 +04:00
* Record the number of clips in the PaintedLayer ' s mask layer .
2012-09-04 05:02:56 +04:00
* Should not be reset when the layer is recycled since it is used to track
* changes in the use of mask layers .
*/
uint32_t mMaskClipCount ;
2011-01-04 13:35:57 +03:00
/**
* A color that should be painted over the bounds of the layer ' s visible
* region before any other content is painted .
*/
2010-09-02 13:18:39 +04:00
nscolor mForcedBackgroundColor ;
2012-09-04 05:02:56 +04:00
2011-06-22 16:11:27 +04:00
/**
* The resolution scale used .
*/
float mXScale , mYScale ;
2012-02-08 02:27:44 +04:00
2012-08-29 09:47:15 +04:00
/**
* The appunits per dev pixel for the items in this layer .
*/
nscoord mAppUnitsPerDevPixel ;
2012-09-17 02:25:33 +04:00
/**
2014-09-26 21:06:08 +04:00
* The offset from the PaintedLayer ' s 0 , 0 to the
2012-09-17 02:25:33 +04:00
* reference frame . This isn ' t necessarily the same as the transform
2014-09-26 21:06:08 +04:00
* set on the PaintedLayer since we might also be applying an extra
2012-09-17 02:25:33 +04:00
* offset specified by the parent ContainerLayer /
*/
nsIntPoint mTranslation ;
2011-06-22 16:11:28 +04:00
/**
2014-09-26 21:06:08 +04:00
* We try to make 0 , 0 of the PaintedLayer be the top - left of the
2011-06-22 16:11:28 +04:00
* border - box of the " active scrolled root " frame ( i . e . the nearest ancestor
* frame for the display items that is being actively scrolled ) . But
2014-09-26 21:06:08 +04:00
* we force the PaintedLayer transform to be an integer translation , and we may
* have a resolution scale , so we have to snap the PaintedLayer transform , so
2011-06-22 16:11:28 +04:00
* 0 , 0 may not be exactly the top - left of the active scrolled root . Here we
2014-09-26 21:06:08 +04:00
* store the coordinates in PaintedLayer space of the top - left of the
2011-06-22 16:11:28 +04:00
* active scrolled root .
*/
2013-09-26 01:07:26 +04:00
gfxPoint mAnimatedGeometryRootPosition ;
2012-08-20 14:00:49 +04:00
2012-08-29 09:47:15 +04:00
nsIntRegion mRegionToInvalidate ;
2012-09-28 15:19:39 +04:00
// The offset between the active scrolled root of this layer
2014-03-20 10:49:27 +04:00
// and the root of the container for the previous and current
2012-09-28 15:19:39 +04:00
// paints respectively.
2013-09-26 01:07:26 +04:00
nsPoint mLastAnimatedGeometryRootOrigin ;
nsPoint mAnimatedGeometryRootOrigin ;
2012-08-29 09:47:15 +04:00
2015-10-18 08:24:48 +03:00
RefPtr < ColorLayer > mColorLayer ;
RefPtr < ImageLayer > mImageLayer ;
2015-07-21 11:19:25 +03:00
2015-09-15 16:41:42 +03:00
// The region for which display item visibility for this layer has already
// been calculated. Used to reduce the number of calls to
// RecomputeVisibilityForItems if it is known in advance that a larger
// region will be painted during a transaction than in a single call to
// DrawPaintedLayer, for example when progressive paint is enabled.
nsIntRegion mVisibilityComputedRegion ;
2017-03-29 16:37:00 +03:00
/**
* This is set when the painted layer has no component alpha .
*/
bool mDisabledAlpha ;
2010-09-02 13:18:39 +04:00
} ;
2012-02-08 02:26:33 +04:00
/*
* User data for layers which will be used as masks .
*/
struct MaskLayerUserData : public LayerUserData
{
2014-03-11 02:12:48 +04:00
MaskLayerUserData ( )
: mScaleX ( - 1.0f )
, mScaleY ( - 1.0f )
, mAppUnitsPerDevPixel ( - 1 )
{ }
2016-11-07 18:27:35 +03:00
MaskLayerUserData ( const DisplayItemClip & aClip ,
uint32_t aRoundedRectClipCount ,
int32_t aAppUnitsPerDevPixel ,
const ContainerLayerParameters & aParams )
: mScaleX ( aParams . mXScale )
, mScaleY ( aParams . mYScale )
, mOffset ( aParams . mOffset )
, mAppUnitsPerDevPixel ( aAppUnitsPerDevPixel )
{
aClip . AppendRoundedRects ( & mRoundedClipRects , aRoundedRectClipCount ) ;
}
void operator = ( MaskLayerUserData & & aOther )
{
mScaleX = aOther . mScaleX ;
mScaleY = aOther . mScaleY ;
mOffset = aOther . mOffset ;
mAppUnitsPerDevPixel = aOther . mAppUnitsPerDevPixel ;
mRoundedClipRects . SwapElements ( aOther . mRoundedClipRects ) ;
}
2012-06-26 06:43:30 +04:00
bool
operator = = ( const MaskLayerUserData & aOther ) const
{
return mRoundedClipRects = = aOther . mRoundedClipRects & &
mScaleX = = aOther . mScaleX & &
2013-04-04 06:59:24 +04:00
mScaleY = = aOther . mScaleY & &
2013-08-09 13:42:05 +04:00
mOffset = = aOther . mOffset & &
mAppUnitsPerDevPixel = = aOther . mAppUnitsPerDevPixel ;
2012-06-26 06:43:30 +04:00
}
2015-07-13 07:09:57 +03:00
// Keeps a MaskLayerImageKey alive by managing its mLayerCount member-var
MaskLayerImageCache : : MaskLayerImageKeyRef mImageKey ;
2012-02-08 02:26:33 +04:00
// properties of the mask layer; the mask layer may be re-used if these
// remain unchanged.
2013-03-04 13:55:59 +04:00
nsTArray < DisplayItemClip : : RoundedRect > mRoundedClipRects ;
2012-06-26 06:43:30 +04:00
// scale from the masked layer which is applied to the mask
float mScaleX , mScaleY ;
2013-09-27 10:01:16 +04:00
// The ContainerLayerParameters offset which is applied to the mask's transform.
2013-04-04 06:59:24 +04:00
nsIntPoint mOffset ;
2013-08-09 13:42:05 +04:00
int32_t mAppUnitsPerDevPixel ;
2012-02-08 02:26:33 +04:00
} ;
2016-11-01 11:43:34 +03:00
/*
* User data for layers which will be used as masks for css positioned mask .
*/
struct CSSMaskLayerUserData : public LayerUserData
{
CSSMaskLayerUserData ( )
2017-01-06 12:53:30 +03:00
: mMaskStyle ( nsStyleImageLayers : : LayerType : : Mask )
2016-11-01 11:43:34 +03:00
{ }
Bug 1350663 - Repaint mask layer when the offset between mask region and mask layer changed. r=mstange
Let's said we have a div,
<div id="outer" style="width:200px, height:200px;
mask="url(opaque-200X100-transparent-200X100.png)"">
<div id="innter" style="position:fixed;
left:0px; top:0px; width:200px; height:100px;
mask-repeat: no-repeat;
background-color: blue;"></div>
</div>
Some hints:
1. '#inner' is out-of-flow
2. '#outer' itself does not draw any things, no background/ border, etc....
3. Mask applied on '#outer'.
4. opaque-100X200-transparent-100X200.png is a 200X200 image. The upper side of
this image is opaque; the lower side of this image is transparent.
After page load, you will see a 200X100 blue rect on left-top corner. This blue
rect is contributed by 200X100 blue '#inner' and 200X100 opaque upper part of
mask. So far so good.
Then you scroll down 100px. '#inner' is not moved, since it's an out-of-flow
element, mask move up 100px with '#outter'. Ideally, you should see nothing in
the view, since '#inner' is now masked by transparent part of the image mask.
On FF, you will still see a 200X100 blue rect in view as if no scrolling at all,
which is wrong.
Here is the root cause of this bug:
1. At beginning, we create a 200X100 mask layer, which fit the size of '#inner'.
Not 200X200 of '#outer', since '#outer' basically draw nothing, we smartly
choose a more compact draw target for painting the mask.
2. Things go wrong after scrolling down. By scroll down 100px, the size of the
mask layer is still "200X100", so we _think_ cached mask layer is still
reusable, but it is not.
Before scrolling, we paint (0, 0, 200, 100) portion of the 200X200 mask onto
mask layer; after scrolling, we should paint (0, _100_, 200, 100) portion of
mask onto mask layer. We did not keep this kind of offset information in
CSSMaskLayerUserData, so we don't know that the cached mask layer should be
rejected.
It's difficult to create a reftest for this bug as well. With scrollTo, we may
mimic an environment of this error, but since reftest harness will trigger
whole viewport repaint while taking a snapshot, we actually can not repro this
issue on it.
MozReview-Commit-ID: H5xaUSssMRh
--HG--
extra : rebase_source : 47103b6638e50dd2fb39f7b47e9cdc653446cd20
2017-05-14 14:28:01 +03:00
CSSMaskLayerUserData ( nsIFrame * aFrame , const nsIntRect & aMaskBounds ,
const nsPoint & aMaskLayerOffset )
2017-05-12 15:17:14 +03:00
: mMaskBounds ( aMaskBounds ) ,
Bug 1350663 - Repaint mask layer when the offset between mask region and mask layer changed. r=mstange
Let's said we have a div,
<div id="outer" style="width:200px, height:200px;
mask="url(opaque-200X100-transparent-200X100.png)"">
<div id="innter" style="position:fixed;
left:0px; top:0px; width:200px; height:100px;
mask-repeat: no-repeat;
background-color: blue;"></div>
</div>
Some hints:
1. '#inner' is out-of-flow
2. '#outer' itself does not draw any things, no background/ border, etc....
3. Mask applied on '#outer'.
4. opaque-100X200-transparent-100X200.png is a 200X200 image. The upper side of
this image is opaque; the lower side of this image is transparent.
After page load, you will see a 200X100 blue rect on left-top corner. This blue
rect is contributed by 200X100 blue '#inner' and 200X100 opaque upper part of
mask. So far so good.
Then you scroll down 100px. '#inner' is not moved, since it's an out-of-flow
element, mask move up 100px with '#outter'. Ideally, you should see nothing in
the view, since '#inner' is now masked by transparent part of the image mask.
On FF, you will still see a 200X100 blue rect in view as if no scrolling at all,
which is wrong.
Here is the root cause of this bug:
1. At beginning, we create a 200X100 mask layer, which fit the size of '#inner'.
Not 200X200 of '#outer', since '#outer' basically draw nothing, we smartly
choose a more compact draw target for painting the mask.
2. Things go wrong after scrolling down. By scroll down 100px, the size of the
mask layer is still "200X100", so we _think_ cached mask layer is still
reusable, but it is not.
Before scrolling, we paint (0, 0, 200, 100) portion of the 200X200 mask onto
mask layer; after scrolling, we should paint (0, _100_, 200, 100) portion of
mask onto mask layer. We did not keep this kind of offset information in
CSSMaskLayerUserData, so we don't know that the cached mask layer should be
rejected.
It's difficult to create a reftest for this bug as well. With scrollTo, we may
mimic an environment of this error, but since reftest harness will trigger
whole viewport repaint while taking a snapshot, we actually can not repro this
issue on it.
MozReview-Commit-ID: H5xaUSssMRh
--HG--
extra : rebase_source : 47103b6638e50dd2fb39f7b47e9cdc653446cd20
2017-05-14 14:28:01 +03:00
mMaskStyle ( aFrame - > StyleSVGReset ( ) - > mMask ) ,
mMaskLayerOffset ( aMaskLayerOffset )
2017-01-06 12:53:30 +03:00
{
}
2016-11-01 11:43:34 +03:00
2017-01-06 12:53:30 +03:00
void operator = ( CSSMaskLayerUserData & & aOther )
2016-11-01 11:43:34 +03:00
{
2017-05-12 15:17:14 +03:00
mMaskBounds = aOther . mMaskBounds ;
2017-01-06 12:53:30 +03:00
mMaskStyle = Move ( aOther . mMaskStyle ) ;
Bug 1350663 - Repaint mask layer when the offset between mask region and mask layer changed. r=mstange
Let's said we have a div,
<div id="outer" style="width:200px, height:200px;
mask="url(opaque-200X100-transparent-200X100.png)"">
<div id="innter" style="position:fixed;
left:0px; top:0px; width:200px; height:100px;
mask-repeat: no-repeat;
background-color: blue;"></div>
</div>
Some hints:
1. '#inner' is out-of-flow
2. '#outer' itself does not draw any things, no background/ border, etc....
3. Mask applied on '#outer'.
4. opaque-100X200-transparent-100X200.png is a 200X200 image. The upper side of
this image is opaque; the lower side of this image is transparent.
After page load, you will see a 200X100 blue rect on left-top corner. This blue
rect is contributed by 200X100 blue '#inner' and 200X100 opaque upper part of
mask. So far so good.
Then you scroll down 100px. '#inner' is not moved, since it's an out-of-flow
element, mask move up 100px with '#outter'. Ideally, you should see nothing in
the view, since '#inner' is now masked by transparent part of the image mask.
On FF, you will still see a 200X100 blue rect in view as if no scrolling at all,
which is wrong.
Here is the root cause of this bug:
1. At beginning, we create a 200X100 mask layer, which fit the size of '#inner'.
Not 200X200 of '#outer', since '#outer' basically draw nothing, we smartly
choose a more compact draw target for painting the mask.
2. Things go wrong after scrolling down. By scroll down 100px, the size of the
mask layer is still "200X100", so we _think_ cached mask layer is still
reusable, but it is not.
Before scrolling, we paint (0, 0, 200, 100) portion of the 200X200 mask onto
mask layer; after scrolling, we should paint (0, _100_, 200, 100) portion of
mask onto mask layer. We did not keep this kind of offset information in
CSSMaskLayerUserData, so we don't know that the cached mask layer should be
rejected.
It's difficult to create a reftest for this bug as well. With scrollTo, we may
mimic an environment of this error, but since reftest harness will trigger
whole viewport repaint while taking a snapshot, we actually can not repro this
issue on it.
MozReview-Commit-ID: H5xaUSssMRh
--HG--
extra : rebase_source : 47103b6638e50dd2fb39f7b47e9cdc653446cd20
2017-05-14 14:28:01 +03:00
mMaskLayerOffset = aOther . mMaskLayerOffset ;
2016-11-01 11:43:34 +03:00
}
bool
2017-05-26 20:38:54 +03:00
operator = = ( const CSSMaskLayerUserData & aOther ) const
2016-11-01 11:43:34 +03:00
{
2017-05-26 20:38:54 +03:00
if ( ! mMaskBounds . IsEqualInterior ( aOther . mMaskBounds ) ) {
2016-11-01 11:43:34 +03:00
return false ;
}
Bug 1350663 - Repaint mask layer when the offset between mask region and mask layer changed. r=mstange
Let's said we have a div,
<div id="outer" style="width:200px, height:200px;
mask="url(opaque-200X100-transparent-200X100.png)"">
<div id="innter" style="position:fixed;
left:0px; top:0px; width:200px; height:100px;
mask-repeat: no-repeat;
background-color: blue;"></div>
</div>
Some hints:
1. '#inner' is out-of-flow
2. '#outer' itself does not draw any things, no background/ border, etc....
3. Mask applied on '#outer'.
4. opaque-100X200-transparent-100X200.png is a 200X200 image. The upper side of
this image is opaque; the lower side of this image is transparent.
After page load, you will see a 200X100 blue rect on left-top corner. This blue
rect is contributed by 200X100 blue '#inner' and 200X100 opaque upper part of
mask. So far so good.
Then you scroll down 100px. '#inner' is not moved, since it's an out-of-flow
element, mask move up 100px with '#outter'. Ideally, you should see nothing in
the view, since '#inner' is now masked by transparent part of the image mask.
On FF, you will still see a 200X100 blue rect in view as if no scrolling at all,
which is wrong.
Here is the root cause of this bug:
1. At beginning, we create a 200X100 mask layer, which fit the size of '#inner'.
Not 200X200 of '#outer', since '#outer' basically draw nothing, we smartly
choose a more compact draw target for painting the mask.
2. Things go wrong after scrolling down. By scroll down 100px, the size of the
mask layer is still "200X100", so we _think_ cached mask layer is still
reusable, but it is not.
Before scrolling, we paint (0, 0, 200, 100) portion of the 200X200 mask onto
mask layer; after scrolling, we should paint (0, _100_, 200, 100) portion of
mask onto mask layer. We did not keep this kind of offset information in
CSSMaskLayerUserData, so we don't know that the cached mask layer should be
rejected.
It's difficult to create a reftest for this bug as well. With scrollTo, we may
mimic an environment of this error, but since reftest harness will trigger
whole viewport repaint while taking a snapshot, we actually can not repro this
issue on it.
MozReview-Commit-ID: H5xaUSssMRh
--HG--
extra : rebase_source : 47103b6638e50dd2fb39f7b47e9cdc653446cd20
2017-05-14 14:28:01 +03:00
// Make sure we draw the same portion of the mask onto mask layer.
if ( mMaskLayerOffset ! = aOther . mMaskLayerOffset ) {
return false ;
}
2017-01-06 12:53:30 +03:00
return mMaskStyle = = aOther . mMaskStyle ;
2016-11-01 11:43:34 +03:00
}
private :
2017-05-12 15:17:14 +03:00
nsIntRect mMaskBounds ;
2017-01-06 12:53:30 +03:00
nsStyleImageLayers mMaskStyle ;
Bug 1350663 - Repaint mask layer when the offset between mask region and mask layer changed. r=mstange
Let's said we have a div,
<div id="outer" style="width:200px, height:200px;
mask="url(opaque-200X100-transparent-200X100.png)"">
<div id="innter" style="position:fixed;
left:0px; top:0px; width:200px; height:100px;
mask-repeat: no-repeat;
background-color: blue;"></div>
</div>
Some hints:
1. '#inner' is out-of-flow
2. '#outer' itself does not draw any things, no background/ border, etc....
3. Mask applied on '#outer'.
4. opaque-100X200-transparent-100X200.png is a 200X200 image. The upper side of
this image is opaque; the lower side of this image is transparent.
After page load, you will see a 200X100 blue rect on left-top corner. This blue
rect is contributed by 200X100 blue '#inner' and 200X100 opaque upper part of
mask. So far so good.
Then you scroll down 100px. '#inner' is not moved, since it's an out-of-flow
element, mask move up 100px with '#outter'. Ideally, you should see nothing in
the view, since '#inner' is now masked by transparent part of the image mask.
On FF, you will still see a 200X100 blue rect in view as if no scrolling at all,
which is wrong.
Here is the root cause of this bug:
1. At beginning, we create a 200X100 mask layer, which fit the size of '#inner'.
Not 200X200 of '#outer', since '#outer' basically draw nothing, we smartly
choose a more compact draw target for painting the mask.
2. Things go wrong after scrolling down. By scroll down 100px, the size of the
mask layer is still "200X100", so we _think_ cached mask layer is still
reusable, but it is not.
Before scrolling, we paint (0, 0, 200, 100) portion of the 200X200 mask onto
mask layer; after scrolling, we should paint (0, _100_, 200, 100) portion of
mask onto mask layer. We did not keep this kind of offset information in
CSSMaskLayerUserData, so we don't know that the cached mask layer should be
rejected.
It's difficult to create a reftest for this bug as well. With scrollTo, we may
mimic an environment of this error, but since reftest harness will trigger
whole viewport repaint while taking a snapshot, we actually can not repro this
issue on it.
MozReview-Commit-ID: H5xaUSssMRh
--HG--
extra : rebase_source : 47103b6638e50dd2fb39f7b47e9cdc653446cd20
2017-05-14 14:28:01 +03:00
nsPoint mMaskLayerOffset ; // The offset from the origin of mask bounds to
// the origin of mask layer.
2016-11-01 11:43:34 +03:00
} ;
2016-10-26 17:17:24 +03:00
/*
* A helper object to create a draw target for painting mask and create a
* image container to hold the drawing result . The caller can then bind this
* image container with a image mask layer via ImageLayer : : SetContainer .
*/
2016-05-10 13:18:11 +03:00
class MaskImageData
{
public :
MaskImageData ( const gfx : : IntSize & aSize , LayerManager * aLayerManager )
: mTextureClientLocked ( false )
, mSize ( aSize )
, mLayerManager ( aLayerManager )
{
2016-10-26 17:17:24 +03:00
MOZ_ASSERT ( ! mSize . IsEmpty ( ) ) ;
MOZ_ASSERT ( mLayerManager ) ;
2016-05-10 13:18:11 +03:00
}
~ MaskImageData ( )
{
if ( mTextureClientLocked ) {
MOZ_ASSERT ( mTextureClient ) ;
// Clear DrawTarget before Unlock.
mDrawTarget = nullptr ;
mTextureClient - > Unlock ( ) ;
}
}
gfx : : DrawTarget * CreateDrawTarget ( )
{
if ( mDrawTarget ) {
return mDrawTarget ;
}
2017-08-10 05:43:11 +03:00
if ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_BASIC ) {
2016-05-10 13:18:11 +03:00
mDrawTarget = mLayerManager - > CreateOptimalMaskDrawTarget ( mSize ) ;
return mDrawTarget ;
}
2017-08-10 05:43:11 +03:00
MOZ_ASSERT ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_CLIENT | |
mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_WR ) ;
2016-05-10 13:18:11 +03:00
2017-08-10 05:43:11 +03:00
KnowsCompositor * knowsCompositor = mLayerManager - > AsKnowsCompositor ( ) ;
if ( ! knowsCompositor ) {
2016-05-10 13:18:11 +03:00
return nullptr ;
}
mTextureClient =
2017-08-10 05:43:11 +03:00
TextureClient : : CreateForDrawing ( knowsCompositor ,
2016-05-10 13:18:11 +03:00
SurfaceFormat : : A8 ,
mSize ,
BackendSelector : : Content ,
TextureFlags : : DISALLOW_BIGIMAGE ,
TextureAllocationFlags : : ALLOC_CLEAR_BUFFER ) ;
if ( ! mTextureClient ) {
return nullptr ;
}
mTextureClientLocked = mTextureClient - > Lock ( OpenMode : : OPEN_READ_WRITE ) ;
if ( ! mTextureClientLocked ) {
return nullptr ;
}
mDrawTarget = mTextureClient - > BorrowDrawTarget ( ) ;
return mDrawTarget ;
}
2016-10-26 17:17:24 +03:00
already_AddRefed < ImageContainer > CreateImageAndImageContainer ( )
{
RefPtr < ImageContainer > container = mLayerManager - > CreateImageContainer ( ) ;
RefPtr < Image > image = CreateImage ( ) ;
if ( ! image ) {
return nullptr ;
}
container - > SetCurrentImageInTransaction ( image ) ;
return container . forget ( ) ;
}
private :
2016-05-10 13:18:11 +03:00
already_AddRefed < Image > CreateImage ( )
{
2017-08-10 05:43:11 +03:00
if ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_BASIC & &
2016-05-10 13:18:11 +03:00
mDrawTarget ) {
RefPtr < SourceSurface > surface = mDrawTarget - > Snapshot ( ) ;
RefPtr < SourceSurfaceImage > image = new SourceSurfaceImage ( mSize , surface ) ;
2016-09-23 00:43:11 +03:00
// Disallow BIGIMAGE (splitting into multiple textures) for mask
// layer images
image - > SetTextureFlags ( TextureFlags : : DISALLOW_BIGIMAGE ) ;
2016-05-10 13:18:11 +03:00
return image . forget ( ) ;
}
2017-08-10 05:43:11 +03:00
if ( ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_CLIENT | |
mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_WR ) & &
2016-05-10 13:18:11 +03:00
mTextureClient & &
mDrawTarget ) {
RefPtr < TextureWrapperImage > image =
new TextureWrapperImage ( mTextureClient , gfx : : IntRect ( gfx : : IntPoint ( 0 , 0 ) , mSize ) ) ;
return image . forget ( ) ;
}
2016-10-26 17:17:24 +03:00
2016-05-10 13:18:11 +03:00
return nullptr ;
}
bool mTextureClientLocked ;
gfx : : IntSize mSize ;
LayerManager * mLayerManager ;
RefPtr < gfx : : DrawTarget > mDrawTarget ;
RefPtr < TextureClient > mTextureClient ;
} ;
2012-02-08 02:27:44 +04:00
/**
* Helper functions for getting user data and casting it to the correct type .
* aLayer is the layer where the user data is stored .
*/
MaskLayerUserData * GetMaskLayerUserData ( Layer * aLayer )
{
return static_cast < MaskLayerUserData * > ( aLayer - > GetUserData ( & gMaskLayerUserData ) ) ;
}
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * GetPaintedDisplayItemLayerUserData ( Layer * aLayer )
2012-02-08 02:27:44 +04:00
{
2014-09-26 21:07:06 +04:00
return static_cast < PaintedDisplayItemLayerUserData * > (
aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2012-02-08 02:27:44 +04:00
}
2012-06-26 06:43:30 +04:00
/* static */ void
FrameLayerBuilder : : Shutdown ( )
{
if ( gMaskLayerImageCache ) {
delete gMaskLayerImageCache ;
2012-07-30 18:20:58 +04:00
gMaskLayerImageCache = nullptr ;
2012-06-26 06:43:30 +04:00
}
}
2010-09-17 23:09:08 +04:00
void
2013-12-16 16:16:24 +04:00
FrameLayerBuilder : : Init ( nsDisplayListBuilder * aBuilder , LayerManager * aManager ,
2017-04-29 03:32:05 +03:00
PaintedLayerData * aLayerData ,
2017-10-07 01:32:30 +03:00
bool aIsInactiveLayerManager ,
2017-04-29 03:32:05 +03:00
const DisplayItemClip * aInactiveLayerClip )
2010-09-17 23:09:08 +04:00
{
2012-08-29 09:47:15 +04:00
mDisplayListBuilder = aBuilder ;
2012-09-16 14:32:59 +04:00
mRootPresContext = aBuilder - > RootReferenceFrame ( ) - > PresContext ( ) - > GetRootPresContext ( ) ;
2010-09-17 23:09:08 +04:00
if ( mRootPresContext ) {
mInitialDOMGeneration = mRootPresContext - > GetDOMGeneration ( ) ;
}
2014-09-26 21:06:08 +04:00
mContainingPaintedLayer = aLayerData ;
2017-10-07 01:32:30 +03:00
mIsInactiveLayerManager = aIsInactiveLayerManager ;
2017-04-29 03:32:05 +03:00
mInactiveLayerClip = aInactiveLayerClip ;
2012-08-29 09:48:15 +04:00
aManager - > SetUserData ( & gLayerManagerLayerBuilder , this ) ;
2010-09-17 23:09:08 +04:00
}
2011-11-15 08:59:03 +04:00
void
FrameLayerBuilder : : FlashPaint ( gfxContext * aContext )
{
2013-03-12 22:01:00 +04:00
float r = float ( rand ( ) ) / RAND_MAX ;
float g = float ( rand ( ) ) / RAND_MAX ;
float b = float ( rand ( ) ) / RAND_MAX ;
2015-09-24 09:42:58 +03:00
aContext - > SetColor ( Color ( r , g , b , 0.4f ) ) ;
2013-03-12 22:01:00 +04:00
aContext - > Paint ( ) ;
2011-11-15 08:59:03 +04:00
}
2017-05-10 06:07:37 +03:00
DisplayItemData *
2012-10-12 03:38:24 +04:00
FrameLayerBuilder : : GetDisplayItemData ( nsIFrame * aFrame , uint32_t aKey )
{
2017-05-10 06:07:38 +03:00
const SmallPointerArray < DisplayItemData > & array = aFrame - > DisplayItemData ( ) ;
for ( uint32_t i = 0 ; i < array . Length ( ) ; i + + ) {
DisplayItemData * item = DisplayItemData : : AssertDisplayItemData ( array . ElementAt ( i ) ) ;
if ( item - > mDisplayItemKey = = aKey & &
item - > mLayer - > Manager ( ) = = mRetainingManager ) {
return item ;
2012-10-12 03:38:24 +04:00
}
2012-08-29 09:47:15 +04:00
}
2012-10-12 03:38:24 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2012-08-29 09:47:15 +04:00
nsACString &
AppendToString ( nsACString & s , const nsIntRect & r ,
const char * pfx = " " , const char * sfx = " " )
{
s + = pfx ;
s + = nsPrintfCString (
" (x=%d, y=%d, w=%d, h=%d) " ,
r . x , r . y , r . width , r . height ) ;
return s + = sfx ;
}
nsACString &
AppendToString ( nsACString & s , const nsIntRegion & r ,
const char * pfx = " " , const char * sfx = " " )
{
s + = pfx ;
s + = " < " ;
2016-01-19 04:20:59 +03:00
for ( auto iter = r . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
AppendToString ( s , iter . Get ( ) ) + = " ; " ;
2012-08-29 09:47:15 +04:00
}
s + = " > " ;
return s + = sfx ;
}
/**
* Invalidate aRegion in aLayer . aLayer is in the coordinate system
* * after * aTranslation has been applied , so we need to
* apply the inverse of that transform before calling InvalidateRegion .
*/
2016-03-29 01:37:07 +03:00
static void
InvalidatePostTransformRegion ( PaintedLayer * aLayer , const nsIntRegion & aRegion ,
const nsIntPoint & aTranslation )
2012-08-29 09:47:15 +04:00
{
// Convert the region from the coordinates of the container layer
// (relative to the snapped top-left of the display list reference frame)
2014-09-26 21:06:08 +04:00
// to the PaintedLayer's own coordinates
2016-03-29 01:37:07 +03:00
nsIntRegion rgn = aRegion ;
2012-08-29 09:47:15 +04:00
rgn . MoveBy ( - aTranslation ) ;
2016-03-29 01:37:07 +03:00
aLayer - > InvalidateRegion ( rgn ) ;
2015-05-29 00:39:34 +03:00
# ifdef MOZ_DUMP_PAINTING
2016-03-29 01:37:07 +03:00
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
nsAutoCString str ;
AppendToString ( str , rgn ) ;
printf_stderr ( " Invalidating layer %p: %s \n " , aLayer , str . get ( ) ) ;
2015-05-29 00:39:34 +03:00
}
2016-03-29 01:37:07 +03:00
# endif
2012-08-29 09:47:15 +04:00
}
2012-10-16 05:10:43 +04:00
static void
2014-09-26 21:06:08 +04:00
InvalidatePostTransformRegion ( PaintedLayer * aLayer , const nsRect & aRect ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2012-10-16 05:10:43 +04:00
const nsIntPoint & aTranslation )
{
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * > ( aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2012-10-16 05:10:43 +04:00
nsRect rect = aClip . ApplyNonRoundedIntersection ( aRect ) ;
nsIntRect pixelRect = rect . ScaleToOutsidePixels ( data - > mXScale , data - > mYScale , data - > mAppUnitsPerDevPixel ) ;
2016-03-29 01:37:07 +03:00
InvalidatePostTransformRegion ( aLayer , pixelRect , aTranslation ) ;
2012-10-16 05:10:43 +04:00
}
2012-08-29 09:47:15 +04:00
static nsIntPoint
2014-09-26 21:06:08 +04:00
GetTranslationForPaintedLayer ( PaintedLayer * aLayer )
2012-08-29 09:47:15 +04:00
{
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * >
( aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2014-09-26 21:06:08 +04:00
NS_ASSERTION ( data , " Must be a tracked painted layer! " ) ;
2012-08-29 09:47:15 +04:00
return data - > mTranslation ;
}
/**
* Some frames can have multiple , nested , retaining layer managers
* associated with them ( normal manager , inactive managers , SVG effects ) .
* In these cases we store the ' outermost ' LayerManager data property
* on the frame since we can walk down the chain from there .
*
* If one of these frames has just been destroyed , we will free the inner
* layer manager when removing the entry from mFramesWithLayers . Destroying
2014-03-20 10:49:27 +04:00
* the layer manager destroys the LayerManagerData and calls into
2012-10-12 06:39:46 +04:00
* the DisplayItemData destructor . If the inner layer manager had any
2012-08-29 09:47:15 +04:00
* items with the same frame , then we attempt to retrieve properties
* from the deleted frame .
*
* Cache the destroyed frame pointer here so we can avoid crashing in this case .
*/
2010-07-16 01:07:51 +04:00
/* static */ void
2016-01-28 06:23:59 +03:00
FrameLayerBuilder : : RemoveFrameFromLayerManager ( const nsIFrame * aFrame ,
2017-05-10 06:07:38 +03:00
SmallPointerArray < DisplayItemData > & aArray )
2010-07-16 01:07:51 +04:00
{
2015-04-11 00:34:28 +03:00
MOZ_RELEASE_ASSERT ( ! sDestroyedFrame ) ;
2012-10-12 03:38:24 +04:00
sDestroyedFrame = aFrame ;
// Hold a reference to all the items so that they don't get
// deleted from under us.
2015-10-18 08:24:48 +03:00
nsTArray < RefPtr < DisplayItemData > > arrayCopy ;
2017-05-10 06:07:38 +03:00
for ( DisplayItemData * data : aArray ) {
2016-01-28 06:23:59 +03:00
arrayCopy . AppendElement ( data ) ;
2012-10-12 03:38:24 +04:00
}
2012-08-29 09:47:15 +04:00
2012-10-12 03:38:25 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2016-01-28 06:23:59 +03:00
if ( aArray - > Length ( ) ) {
LayerManagerData * rootData = aArray - > ElementAt ( 0 ) - > mParent ;
2012-10-12 03:38:25 +04:00
while ( rootData - > mParent ) {
rootData = rootData - > mParent ;
}
2013-11-24 02:44:18 +04:00
printf_stderr ( " Removing frame %p - dumping display data \n " , aFrame ) ;
2012-10-12 03:38:25 +04:00
rootData - > Dump ( ) ;
}
# endif
2017-05-10 06:07:38 +03:00
for ( DisplayItemData * data : aArray ) {
2014-09-26 21:06:08 +04:00
PaintedLayer * t = data - > mLayer - > AsPaintedLayer ( ) ;
2012-08-29 09:47:15 +04:00
if ( t ) {
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * paintedData =
static_cast < PaintedDisplayItemLayerUserData * > ( t - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2017-04-21 10:27:48 +03:00
if ( paintedData & & data - > mGeometry ) {
2012-10-12 03:38:24 +04:00
nsRegion old = data - > mGeometry - > ComputeInvalidationRegion ( ) ;
2014-09-26 21:07:06 +04:00
nsIntRegion rgn = old . ScaleToOutsidePixels ( paintedData - > mXScale , paintedData - > mYScale , paintedData - > mAppUnitsPerDevPixel ) ;
2014-09-26 21:06:08 +04:00
rgn . MoveBy ( - GetTranslationForPaintedLayer ( t ) ) ;
2014-09-26 21:07:06 +04:00
paintedData - > mRegionToInvalidate . Or ( paintedData - > mRegionToInvalidate , rgn ) ;
paintedData - > mRegionToInvalidate . SimplifyOutward ( 8 ) ;
2012-08-29 09:47:15 +04:00
}
}
2012-10-12 03:38:24 +04:00
data - > mParent - > mDisplayItems . RemoveEntry ( data ) ;
2012-09-27 19:34:46 +04:00
}
2012-09-28 15:19:39 +04:00
2012-10-12 03:38:24 +04:00
arrayCopy . Clear ( ) ;
2013-10-08 22:47:21 +04:00
sDestroyedFrame = nullptr ;
2010-07-16 01:07:51 +04:00
}
void
2011-01-19 11:27:54 +03:00
FrameLayerBuilder : : DidBeginRetainedLayerTransaction ( LayerManager * aManager )
2010-07-16 01:07:51 +04:00
{
mRetainingManager = aManager ;
LayerManagerData * data = static_cast < LayerManagerData * >
2010-09-02 13:18:39 +04:00
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2010-07-16 01:07:51 +04:00
if ( data ) {
mInvalidateAllLayers = data - > mInvalidateAllLayers ;
2012-08-29 09:48:41 +04:00
} else {
2012-10-12 03:38:24 +04:00
data = new LayerManagerData ( aManager ) ;
2012-08-29 09:48:41 +04:00
aManager - > SetUserData ( & gLayerManagerUserData , data ) ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:51 +04:00
}
2010-05-21 07:20:48 +04:00
2012-09-25 00:31:30 +04:00
void
2012-10-12 06:39:46 +04:00
FrameLayerBuilder : : StoreOptimizedLayerForFrame ( nsDisplayItem * aItem , Layer * aLayer )
2012-09-25 00:31:30 +04:00
{
2012-10-12 06:39:46 +04:00
if ( ! mRetainingManager ) {
2012-09-25 00:31:30 +04:00
return ;
2012-10-12 06:39:46 +04:00
}
2012-09-25 00:31:30 +04:00
2012-10-12 06:39:46 +04:00
DisplayItemData * data = GetDisplayItemDataForManager ( aItem , aLayer - > Manager ( ) ) ;
NS_ASSERTION ( data , " Must have already stored data for this item! " ) ;
data - > mOptLayer = aLayer ;
2017-04-21 10:27:48 +03:00
data - > mItem = nullptr ;
2012-09-25 00:31:30 +04:00
}
2010-07-16 01:07:51 +04:00
void
2012-08-29 09:47:15 +04:00
FrameLayerBuilder : : DidEndTransaction ( )
2010-07-16 01:07:51 +04:00
{
2012-06-26 06:43:30 +04:00
GetMaskLayerImageCache ( ) - > Sweep ( ) ;
2010-07-16 01:08:11 +04:00
}
void
2012-08-29 09:47:15 +04:00
FrameLayerBuilder : : WillEndTransaction ( )
2010-07-16 01:08:11 +04:00
{
2012-08-29 09:47:15 +04:00
if ( ! mRetainingManager ) {
2010-07-16 01:08:11 +04:00
return ;
2012-08-29 09:47:15 +04:00
}
2010-05-21 07:20:48 +04:00
2012-08-29 09:47:15 +04:00
// We need to save the data we'll need to support retaining.
2010-07-16 01:07:51 +04:00
LayerManagerData * data = static_cast < LayerManagerData * >
2010-09-02 13:18:39 +04:00
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-08-29 09:48:41 +04:00
NS_ASSERTION ( data , " Must have data! " ) ;
2012-12-13 00:47:05 +04:00
2015-07-15 12:05:06 +03:00
// Update all the frames that used to have layers.
for ( auto iter = data - > mDisplayItems . Iter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
DisplayItemData * data = iter . Get ( ) - > GetKey ( ) ;
if ( ! data - > mUsed ) {
// This item was visible, but isn't anymore.
PaintedLayer * t = data - > mLayer - > AsPaintedLayer ( ) ;
if ( t & & data - > mGeometry ) {
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
2015-07-15 12:05:06 +03:00
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
printf_stderr ( " Invalidating unused display item (%i) belonging to frame %p from layer %p \n " , data - > mDisplayItemKey , data - > mFrameList [ 0 ] , t ) ;
}
2012-12-13 00:47:05 +04:00
# endif
2015-07-15 12:05:06 +03:00
InvalidatePostTransformRegion ( t ,
data - > mGeometry - > ComputeInvalidationRegion ( ) ,
data - > mClip ,
GetLastPaintOffset ( t ) ) ;
}
2015-09-16 17:05:00 +03:00
data - > ClearAnimationCompositorState ( ) ;
2015-07-15 12:05:06 +03:00
iter . Remove ( ) ;
} else {
ComputeGeometryChangeForItem ( data ) ;
2012-12-13 00:47:05 +04:00
}
2010-07-16 01:07:51 +04:00
}
2015-07-15 12:05:06 +03:00
data - > mInvalidateAllLayers = false ;
2012-10-12 03:38:25 +04:00
}
2017-05-10 06:07:37 +03:00
/* static */ DisplayItemData *
2014-03-20 10:49:27 +04:00
FrameLayerBuilder : : GetDisplayItemDataForManager ( nsDisplayItem * aItem ,
2012-08-29 09:48:45 +04:00
LayerManager * aManager )
2012-08-29 09:47:15 +04:00
{
2017-05-10 06:07:38 +03:00
const SmallPointerArray < DisplayItemData > & array =
aItem - > Frame ( ) - > DisplayItemData ( ) ;
for ( uint32_t i = 0 ; i < array . Length ( ) ; i + + ) {
DisplayItemData * item = DisplayItemData : : AssertDisplayItemData ( array . ElementAt ( i ) ) ;
if ( item - > mDisplayItemKey = = aItem - > GetPerFrameKey ( ) & &
item - > mLayer - > Manager ( ) = = aManager ) {
return item ;
2012-08-29 09:47:15 +04:00
}
}
return nullptr ;
}
2012-08-29 09:48:45 +04:00
bool
2012-12-14 02:51:00 +04:00
FrameLayerBuilder : : HasRetainedDataFor ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2012-08-29 09:48:45 +04:00
{
2017-05-10 06:07:38 +03:00
const SmallPointerArray < DisplayItemData > & array =
aFrame - > DisplayItemData ( ) ;
for ( uint32_t i = 0 ; i < array . Length ( ) ; i + + ) {
if ( DisplayItemData : : AssertDisplayItemData ( array . ElementAt ( i ) ) - > mDisplayItemKey = = aDisplayItemKey ) {
return true ;
2012-10-12 03:38:24 +04:00
}
2012-08-29 09:48:45 +04:00
}
return false ;
}
2012-11-07 02:04:53 +04:00
void
2012-12-14 02:50:57 +04:00
FrameLayerBuilder : : IterateRetainedDataFor ( nsIFrame * aFrame , DisplayItemDataCallback aCallback )
2012-11-07 02:04:53 +04:00
{
2017-05-10 06:07:38 +03:00
const SmallPointerArray < DisplayItemData > & array = aFrame - > DisplayItemData ( ) ;
2014-03-20 10:49:27 +04:00
2017-05-10 06:07:38 +03:00
for ( uint32_t i = 0 ; i < array . Length ( ) ; i + + ) {
DisplayItemData * data = DisplayItemData : : AssertDisplayItemData ( array . ElementAt ( i ) ) ;
2017-08-07 07:07:43 +03:00
if ( data - > mDisplayItemKey ! = 0 ) {
2012-11-19 14:54:50 +04:00
aCallback ( aFrame , data ) ;
}
2012-11-07 02:04:53 +04:00
}
}
2017-05-10 06:07:37 +03:00
DisplayItemData *
2012-08-29 14:53:27 +04:00
FrameLayerBuilder : : GetOldLayerForFrame ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2010-07-16 01:07:51 +04:00
{
// If we need to build a new layer tree, then just refuse to recycle
// anything.
if ( ! mRetainingManager | | mInvalidateAllLayers )
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
2012-10-12 03:38:24 +04:00
DisplayItemData * data = GetDisplayItemData ( aFrame , aDisplayItemKey ) ;
2010-07-16 01:07:51 +04:00
2012-10-12 03:38:24 +04:00
if ( data & & data - > mLayer - > Manager ( ) = = mRetainingManager ) {
return data ;
2010-05-21 07:20:48 +04:00
}
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-05-21 07:20:48 +04:00
}
2012-08-29 14:53:27 +04:00
Layer *
2014-03-20 10:49:27 +04:00
FrameLayerBuilder : : GetOldLayerFor ( nsDisplayItem * aItem ,
nsDisplayItemGeometry * * aOldGeometry ,
2014-07-23 10:03:24 +04:00
DisplayItemClip * * aOldClip )
2012-08-29 14:53:27 +04:00
{
uint32_t key = aItem - > GetPerFrameKey ( ) ;
2013-04-19 16:02:13 +04:00
nsIFrame * frame = aItem - > Frame ( ) ;
2012-08-29 14:53:27 +04:00
2013-04-19 16:01:41 +04:00
DisplayItemData * oldData = GetOldLayerForFrame ( frame , key ) ;
if ( oldData ) {
if ( aOldGeometry ) {
* aOldGeometry = oldData - > mGeometry . get ( ) ;
2012-08-29 14:53:27 +04:00
}
2013-04-19 16:01:41 +04:00
if ( aOldClip ) {
* aOldClip = & oldData - > mClip ;
}
return oldData - > mLayer ;
2012-08-29 14:53:27 +04:00
}
return nullptr ;
2014-03-20 10:49:27 +04:00
}
2012-08-29 14:53:27 +04:00
2014-07-23 10:03:24 +04:00
void
FrameLayerBuilder : : ClearCachedGeometry ( nsDisplayItem * aItem )
{
uint32_t key = aItem - > GetPerFrameKey ( ) ;
nsIFrame * frame = aItem - > Frame ( ) ;
DisplayItemData * oldData = GetOldLayerForFrame ( frame , key ) ;
if ( oldData ) {
oldData - > mGeometry = nullptr ;
}
}
2017-09-28 03:43:11 +03:00
/* static */ DisplayItemData *
FrameLayerBuilder : : GetOldDataFor ( nsDisplayItem * aItem )
2012-07-17 21:03:51 +04:00
{
2017-09-28 03:43:11 +03:00
const SmallPointerArray < DisplayItemData > & array = aItem - > Frame ( ) - > DisplayItemData ( ) ;
2012-07-17 21:03:51 +04:00
2017-05-10 06:07:38 +03:00
for ( uint32_t i = 0 ; i < array . Length ( ) ; i + + ) {
DisplayItemData * data = DisplayItemData : : AssertDisplayItemData ( array . ElementAt ( i ) ) ;
2012-08-29 09:47:15 +04:00
2017-09-28 03:43:11 +03:00
if ( data - > mDisplayItemKey = = aItem - > GetPerFrameKey ( ) ) {
return data ;
2012-08-29 09:47:15 +04:00
}
}
2012-10-12 03:38:24 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2016-07-08 23:30:47 +03:00
// Reset state that should not persist when a layer is recycled.
static void
ResetLayerStateForRecycling ( Layer * aLayer ) {
// Currently, this clears the mask layer and ancestor mask layers.
// Other cleanup may be added here.
aLayer - > SetMaskLayer ( nullptr ) ;
aLayer - > SetAncestorMaskLayers ( { } ) ;
}
2010-07-16 01:08:03 +04:00
already_AddRefed < ColorLayer >
2014-09-26 21:07:06 +04:00
ContainerState : : CreateOrRecycleColorLayer ( PaintedLayer * aPainted )
2010-07-16 01:08:03 +04:00
{
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * > ( aPainted - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2015-10-18 08:24:48 +03:00
RefPtr < ColorLayer > layer = data - > mColorLayer ;
2012-08-20 14:00:49 +04:00
if ( layer ) {
2016-07-09 00:25:09 +03:00
ResetLayerStateForRecycling ( layer ) ;
2014-08-22 19:53:24 +04:00
layer - > ClearExtraDumpInfo ( ) ;
2010-07-16 01:08:03 +04:00
} else {
// Create a new layer
layer = mManager - > CreateColorLayer ( ) ;
if ( ! layer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2014-09-26 21:07:06 +04:00
// Mark this layer as being used for painting display items
2012-08-20 14:00:49 +04:00
data - > mColorLayer = layer ;
2012-07-30 18:20:58 +04:00
layer - > SetUserData ( & gColorLayerUserData , nullptr ) ;
2014-03-20 10:49:27 +04:00
2014-09-26 21:06:08 +04:00
// Remove other layer types we might have stored for this PaintedLayer
2012-08-20 14:00:49 +04:00
data - > mImageLayer = nullptr ;
2010-07-16 01:08:03 +04:00
}
return layer . forget ( ) ;
}
2011-01-18 00:47:18 +03:00
already_AddRefed < ImageLayer >
2014-09-26 21:07:06 +04:00
ContainerState : : CreateOrRecycleImageLayer ( PaintedLayer * aPainted )
2011-01-18 00:47:18 +03:00
{
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * > ( aPainted - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2015-10-18 08:24:48 +03:00
RefPtr < ImageLayer > layer = data - > mImageLayer ;
2012-08-20 14:00:49 +04:00
if ( layer ) {
2016-07-09 00:25:09 +03:00
ResetLayerStateForRecycling ( layer ) ;
2014-08-22 19:53:24 +04:00
layer - > ClearExtraDumpInfo ( ) ;
2011-01-18 00:47:18 +03:00
} else {
// Create a new layer
layer = mManager - > CreateImageLayer ( ) ;
if ( ! layer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2014-09-26 21:07:06 +04:00
// Mark this layer as being used for painting display items
2012-08-20 14:00:49 +04:00
data - > mImageLayer = layer ;
2012-07-30 18:20:58 +04:00
layer - > SetUserData ( & gImageLayerUserData , nullptr ) ;
2012-08-20 14:00:49 +04:00
2014-09-26 21:06:08 +04:00
// Remove other layer types we might have stored for this PaintedLayer
2012-08-20 14:00:49 +04:00
data - > mColorLayer = nullptr ;
2011-01-18 00:47:18 +03:00
}
return layer . forget ( ) ;
}
2012-02-08 02:26:40 +04:00
already_AddRefed < ImageLayer >
2016-11-07 17:32:43 +03:00
ContainerState : : CreateOrRecycleMaskImageLayerFor ( const MaskLayerKey & aKey ,
2017-08-10 09:02:01 +03:00
void ( * aSetUserData ) ( Layer * aLayer ) )
2012-02-08 02:26:40 +04:00
{
2015-10-18 08:24:48 +03:00
RefPtr < ImageLayer > result = mRecycledMaskImageLayers . Get ( aKey ) ;
2015-06-21 19:28:10 +03:00
if ( result ) {
mRecycledMaskImageLayers . Remove ( aKey ) ;
aKey . mLayer - > ClearExtraDumpInfo ( ) ;
2012-06-26 06:43:30 +04:00
// XXX if we use clip on mask layers, null it out here
2012-02-08 02:26:40 +04:00
} else {
// Create a new layer
result = mManager - > CreateImageLayer ( ) ;
if ( ! result )
2012-07-30 18:20:58 +04:00
return nullptr ;
2016-11-07 17:32:43 +03:00
aSetUserData ( result ) ;
2012-02-08 02:26:40 +04:00
}
2014-03-20 10:49:27 +04:00
2012-02-08 02:26:40 +04:00
return result . forget ( ) ;
}
2012-05-10 09:24:20 +04:00
static const double SUBPIXEL_OFFSET_EPSILON = 0.02 ;
/**
* This normally computes NSToIntRoundUp ( aValue ) . However , if that would
* give a residual near 0.5 while aOldResidual is near - 0.5 , or
* it would give a residual near - 0.5 while aOldResidual is near 0.5 , then
* instead we return the integer in the other direction so that the residual
* is close to aOldResidual .
*/
2012-08-22 19:56:38 +04:00
static int32_t
2012-05-10 09:24:20 +04:00
RoundToMatchResidual ( double aValue , double aOldResidual )
{
2012-08-22 19:56:38 +04:00
int32_t v = NSToIntRoundUp ( aValue ) ;
2012-05-10 09:24:20 +04:00
double residual = aValue - v ;
if ( aOldResidual < 0 ) {
if ( residual > 0 & & fabs ( residual - 1.0 - aOldResidual ) < SUBPIXEL_OFFSET_EPSILON ) {
// Round up instead
2012-08-22 19:56:38 +04:00
return int32_t ( ceil ( aValue ) ) ;
2012-05-10 09:24:20 +04:00
}
} else if ( aOldResidual > 0 ) {
if ( residual < 0 & & fabs ( residual + 1.0 - aOldResidual ) < SUBPIXEL_OFFSET_EPSILON ) {
// Round down instead
2012-08-22 19:56:38 +04:00
return int32_t ( floor ( aValue ) ) ;
2012-05-10 09:24:20 +04:00
}
}
return v ;
2012-05-10 09:24:18 +04:00
}
2012-08-17 03:40:10 +04:00
static void
2015-11-25 01:53:51 +03:00
ResetScrollPositionForLayerPixelAlignment ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2012-08-17 03:40:10 +04:00
{
2015-11-25 01:53:51 +03:00
nsIScrollableFrame * sf = nsLayoutUtils : : GetScrollableFrameFor ( * aAnimatedGeometryRoot ) ;
2012-08-17 03:40:10 +04:00
if ( sf ) {
sf - > ResetScrollPositionForLayerPixelAlignment ( ) ;
}
}
static void
2015-11-25 01:53:51 +03:00
InvalidateEntirePaintedLayer ( PaintedLayer * aLayer , AnimatedGeometryRoot * aAnimatedGeometryRoot , const char * aReason )
2012-08-17 03:40:10 +04:00
{
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2015-02-04 01:18:44 +03:00
printf_stderr ( " Invalidating entire layer %p: %s \n " , aLayer , aReason ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
2017-06-16 00:29:18 +03:00
aLayer - > InvalidateWholeLayer ( ) ;
2014-03-07 03:31:47 +04:00
aLayer - > SetInvalidRectToVisibleRegion ( ) ;
2013-09-26 01:07:26 +04:00
ResetScrollPositionForLayerPixelAlignment ( aAnimatedGeometryRoot ) ;
2012-08-17 03:40:10 +04:00
}
2015-03-03 03:24:18 +03:00
LayerManager : : PaintedLayerCreationHint
2015-11-25 01:53:51 +03:00
ContainerState : : GetLayerCreationHint ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-03-03 03:24:18 +03:00
{
// Check whether the layer will be scrollable. This is used as a hint to
// influence whether tiled layers are used or not.
2015-09-20 19:28:18 +03:00
2016-03-08 22:43:32 +03:00
// Check creation hint inherited from our parent.
if ( mParameters . mLayerCreationHint = = LayerManager : : SCROLLABLE ) {
return LayerManager : : SCROLLABLE ;
}
2015-09-20 19:28:18 +03:00
// Check whether there's any active scroll frame on the animated geometry
// root chain.
2015-11-25 01:53:51 +03:00
for ( AnimatedGeometryRoot * agr = aAnimatedGeometryRoot ;
2016-08-11 08:52:56 +03:00
agr & & agr ! = mContainerAnimatedGeometryRoot ;
2015-11-25 01:53:51 +03:00
agr = agr - > mParentAGR ) {
nsIFrame * fParent = nsLayoutUtils : : GetCrossDocParentFrame ( * agr ) ;
2015-09-20 19:28:18 +03:00
if ( ! fParent ) {
break ;
}
nsIScrollableFrame * scrollable = do_QueryFrame ( fParent ) ;
2017-04-20 08:16:43 +03:00
if ( scrollable ) {
2015-09-20 19:28:18 +03:00
return LayerManager : : SCROLLABLE ;
}
2015-03-03 03:24:18 +03:00
}
return LayerManager : : NONE ;
}
2015-03-03 03:25:13 +03:00
already_AddRefed < PaintedLayer >
2015-11-25 01:53:51 +03:00
ContainerState : : AttemptToRecyclePaintedLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-04 08:21:00 +03:00
nsDisplayItem * aItem ,
2015-03-03 03:25:13 +03:00
const nsPoint & aTopLeft )
{
2015-03-04 08:21:00 +03:00
Layer * oldLayer = mLayerBuilder - > GetOldLayerFor ( aItem ) ;
2017-06-17 01:06:04 +03:00
if ( ! oldLayer | | ! oldLayer - > AsPaintedLayer ( ) ) {
2015-03-03 03:25:13 +03:00
return nullptr ;
}
2017-06-17 01:06:04 +03:00
if ( ! mPaintedLayersAvailableForRecycling . EnsureRemoved ( oldLayer - > AsPaintedLayer ( ) ) ) {
// Not found.
return nullptr ;
}
// Try to recycle the layer.
2015-10-18 08:24:48 +03:00
RefPtr < PaintedLayer > layer = oldLayer - > AsPaintedLayer ( ) ;
2015-03-03 03:25:13 +03:00
// Check if the layer hint has changed and whether or not the layer should
// be recreated because of it.
2015-07-29 19:03:01 +03:00
if ( ! layer - > IsOptimizedFor ( GetLayerCreationHint ( aAnimatedGeometryRoot ) ) ) {
2015-03-03 03:25:13 +03:00
return nullptr ;
}
bool didResetScrollPositionForLayerPixelAlignment = false ;
PaintedDisplayItemLayerUserData * data =
RecyclePaintedLayer ( layer , aAnimatedGeometryRoot ,
didResetScrollPositionForLayerPixelAlignment ) ;
2015-03-04 08:21:00 +03:00
PreparePaintedLayerForUse ( layer , data , aAnimatedGeometryRoot , aItem - > ReferenceFrame ( ) ,
2015-03-03 03:25:13 +03:00
aTopLeft ,
didResetScrollPositionForLayerPixelAlignment ) ;
return layer . forget ( ) ;
}
2014-09-26 21:06:08 +04:00
already_AddRefed < PaintedLayer >
2015-03-04 08:18:47 +03:00
ContainerState : : CreatePaintedLayer ( PaintedLayerData * aData )
2010-07-16 01:07:51 +04:00
{
2015-03-03 03:24:18 +03:00
LayerManager : : PaintedLayerCreationHint creationHint =
2015-03-04 08:21:00 +03:00
GetLayerCreationHint ( aData - > mAnimatedGeometryRoot ) ;
2014-06-13 20:11:08 +04:00
2015-03-03 03:25:13 +03:00
// Create a new painted layer
2015-10-18 08:24:48 +03:00
RefPtr < PaintedLayer > layer = mManager - > CreatePaintedLayerWithHint ( creationHint ) ;
2015-03-03 03:25:13 +03:00
if ( ! layer ) {
return nullptr ;
2014-06-13 20:11:08 +04:00
}
2015-03-03 03:25:13 +03:00
// Mark this layer as being used for painting display items
2015-03-04 08:21:00 +03:00
PaintedDisplayItemLayerUserData * userData = new PaintedDisplayItemLayerUserData ( ) ;
2017-03-29 16:37:00 +03:00
userData - > mDisabledAlpha =
mParameters . mDisableSubpixelAntialiasingInDescendants ;
2015-03-04 08:21:00 +03:00
layer - > SetUserData ( & gPaintedDisplayItemLayerUserData , userData ) ;
ResetScrollPositionForLayerPixelAlignment ( aData - > mAnimatedGeometryRoot ) ;
2015-03-03 02:43:58 +03:00
2015-03-04 08:21:00 +03:00
PreparePaintedLayerForUse ( layer , userData , aData - > mAnimatedGeometryRoot ,
aData - > mReferenceFrame ,
aData - > mAnimatedGeometryRootOffset , true ) ;
2015-03-03 02:43:58 +03:00
return layer . forget ( ) ;
}
PaintedDisplayItemLayerUserData *
ContainerState : : RecyclePaintedLayer ( PaintedLayer * aLayer ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-03 02:43:58 +03:00
bool & didResetScrollPositionForLayerPixelAlignment )
{
// Clear clip rect and mask layer so we don't accidentally stay clipped.
// We will reapply any necessary clipping.
2016-07-08 23:30:47 +03:00
ResetLayerStateForRecycling ( aLayer ) ;
2015-03-03 02:43:58 +03:00
aLayer - > ClearExtraDumpInfo ( ) ;
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * > (
aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
NS_ASSERTION ( data , " Recycled PaintedLayers must have user data " ) ;
// This gets called on recycled PaintedLayers that are going to be in the
// final layer tree, so it's a convenient time to invalidate the
// content that changed where we don't know what PaintedLayer it belonged
// to, or if we need to invalidate the entire layer, we can do that.
// This needs to be done before we update the PaintedLayer to its new
// transform. See nsGfxScrollFrame::InvalidateInternal, where
// we ensure that mInvalidPaintedContent is updated according to the
// scroll position as of the most recent paint.
if ( ! FuzzyEqual ( data - > mXScale , mParameters . mXScale , 0.00001f ) | |
! FuzzyEqual ( data - > mYScale , mParameters . mYScale , 0.00001f ) | |
data - > mAppUnitsPerDevPixel ! = mAppUnitsPerDevPixel ) {
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
printf_stderr ( " Recycled layer %p changed scale \n " , aLayer ) ;
}
# endif
InvalidateEntirePaintedLayer ( aLayer , aAnimatedGeometryRoot , " recycled layer changed state " ) ;
didResetScrollPositionForLayerPixelAlignment = true ;
}
if ( ! data - > mRegionToInvalidate . IsEmpty ( ) ) {
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
printf_stderr ( " Invalidating deleted frame content from layer %p \n " , aLayer ) ;
}
# endif
aLayer - > InvalidateRegion ( data - > mRegionToInvalidate ) ;
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
nsAutoCString str ;
AppendToString ( str , data - > mRegionToInvalidate ) ;
printf_stderr ( " Invalidating layer %p: %s \n " , aLayer , str . get ( ) ) ;
}
# endif
data - > mRegionToInvalidate . SetEmpty ( ) ;
}
return data ;
}
void
ContainerState : : PreparePaintedLayerForUse ( PaintedLayer * aLayer ,
PaintedDisplayItemLayerUserData * aData ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-03 02:43:58 +03:00
const nsIFrame * aReferenceFrame ,
const nsPoint & aTopLeft ,
bool didResetScrollPositionForLayerPixelAlignment )
{
2015-03-04 20:08:28 +03:00
aData - > mXScale = mParameters . mXScale ;
aData - > mYScale = mParameters . mYScale ;
aData - > mLastAnimatedGeometryRootOrigin = aData - > mAnimatedGeometryRootOrigin ;
aData - > mAnimatedGeometryRootOrigin = aTopLeft ;
aData - > mAppUnitsPerDevPixel = mAppUnitsPerDevPixel ;
aLayer - > SetAllowResidualTranslation ( mParameters . AllowResidualTranslation ( ) ) ;
2015-03-03 02:43:58 +03:00
2015-03-04 20:08:28 +03:00
mLayerBuilder - > SavePreviousDataForLayer ( aLayer , aData - > mMaskClipCount ) ;
2010-07-16 01:07:51 +04:00
2015-03-04 20:08:28 +03:00
// Set up transform so that 0,0 in the PaintedLayer corresponds to the
2013-09-26 01:07:26 +04:00
// (pixel-snapped) top-left of the aAnimatedGeometryRoot.
2015-11-25 01:53:51 +03:00
nsPoint offset = ( * aAnimatedGeometryRoot ) - > GetOffsetToCrossDoc ( aReferenceFrame ) ;
nscoord appUnitsPerDevPixel = ( * aAnimatedGeometryRoot ) - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2011-06-22 16:11:28 +04:00
gfxPoint scaledOffset (
NSAppUnitsToDoublePixels ( offset . x , appUnitsPerDevPixel ) * mParameters . mXScale ,
NSAppUnitsToDoublePixels ( offset . y , appUnitsPerDevPixel ) * mParameters . mYScale ) ;
2012-05-10 09:24:20 +04:00
// We call RoundToMatchResidual here so that the residual after rounding
2015-03-04 20:08:28 +03:00
// is close to aData->mAnimatedGeometryRootPosition if possible.
nsIntPoint pixOffset ( RoundToMatchResidual ( scaledOffset . x , aData - > mAnimatedGeometryRootPosition . x ) ,
RoundToMatchResidual ( scaledOffset . y , aData - > mAnimatedGeometryRootPosition . y ) ) ;
aData - > mTranslation = pixOffset ;
2012-09-17 02:25:33 +04:00
pixOffset + = mParameters . mOffset ;
2014-09-10 17:26:12 +04:00
Matrix matrix = Matrix : : Translation ( pixOffset . x , pixOffset . y ) ;
2015-03-04 20:08:28 +03:00
aLayer - > SetBaseTransform ( Matrix4x4 : : From2D ( matrix ) ) ;
2010-07-16 01:07:51 +04:00
2015-09-15 16:41:42 +03:00
aData - > mVisibilityComputedRegion . SetEmpty ( ) ;
2015-07-21 11:19:25 +03:00
2011-06-22 16:11:28 +04:00
// Calculate exact position of the top-left of the active scrolled root.
// This might not be 0,0 due to the snapping in ScaleToNearestPixels.
2014-01-27 19:28:33 +04:00
gfxPoint animatedGeometryRootTopLeft = scaledOffset - ThebesPoint ( matrix . GetTranslation ( ) ) + mParameters . mOffset ;
2017-03-29 16:37:00 +03:00
const bool disableAlpha =
mParameters . mDisableSubpixelAntialiasingInDescendants ;
if ( aData - > mDisabledAlpha ! = disableAlpha ) {
aData - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
InvalidateEntirePaintedLayer ( aLayer , aAnimatedGeometryRoot , " change of subpixel-AA " ) ;
aData - > mDisabledAlpha = disableAlpha ;
return ;
}
// FIXME: Temporary workaround for bug 681192 and bug 724786.
# ifndef MOZ_WIDGET_ANDROID
2011-06-22 16:11:28 +04:00
// If it has changed, then we need to invalidate the entire layer since the
// pixels in the layer buffer have the content at a (subpixel) offset
// from what we need.
2015-03-04 20:08:28 +03:00
if ( ! animatedGeometryRootTopLeft . WithinEpsilonOf ( aData - > mAnimatedGeometryRootPosition , SUBPIXEL_OFFSET_EPSILON ) ) {
aData - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
InvalidateEntirePaintedLayer ( aLayer , aAnimatedGeometryRoot , " subpixel offset " ) ;
2012-08-17 03:40:10 +04:00
} else if ( didResetScrollPositionForLayerPixelAlignment ) {
2015-03-04 20:08:28 +03:00
aData - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
2011-06-22 16:11:28 +04:00
}
2015-03-03 02:29:12 +03:00
# else
2015-11-02 08:53:26 +03:00
Unused < < didResetScrollPositionForLayerPixelAlignment ;
2014-06-30 14:31:07 +04:00
# endif
2010-07-16 01:07:51 +04:00
}
2013-11-18 00:33:21 +04:00
# if defined(DEBUG) || defined(MOZ_DUMP_PAINTING)
2010-07-16 01:07:51 +04:00
/**
2013-03-04 13:56:02 +04:00
* Returns the appunits per dev pixel for the item ' s frame
2010-07-16 01:07:51 +04:00
*/
2012-08-22 19:56:38 +04:00
static int32_t
2010-07-16 01:07:51 +04:00
AppUnitsPerDevPixel ( nsDisplayItem * aItem )
{
2010-08-08 22:49:06 +04:00
// The underlying frame for zoom items is the root frame of the subdocument.
// But zoom display items report their bounds etc using the parent document's
// APD because zoom items act as a conversion layer between the two different
// APDs.
2017-08-07 07:07:43 +03:00
if ( aItem - > GetType ( ) = = DisplayItemType : : TYPE_ZOOM ) {
2010-08-08 22:49:06 +04:00
return static_cast < nsDisplayZoom * > ( aItem ) - > GetParentAppUnitsPerDevPixel ( ) ;
}
2013-04-19 16:02:13 +04:00
return aItem - > Frame ( ) - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2010-07-16 01:07:51 +04:00
}
2012-10-10 09:00:05 +04:00
# endif
2010-07-16 01:07:51 +04:00
/**
2014-06-23 08:24:00 +04:00
* Set the visible region for aLayer .
* aOuterVisibleRegion is the visible region relative to the parent layer .
2014-07-11 05:17:47 +04:00
* aLayerContentsVisibleRect , if non - null , is a rectangle in the layer ' s
* own coordinate system to which the layer ' s visible region is restricted .
2014-06-23 08:24:00 +04:00
* Consumes * aOuterVisibleRegion .
2010-07-16 01:07:51 +04:00
*/
static void
2014-06-23 08:24:00 +04:00
SetOuterVisibleRegion ( Layer * aLayer , nsIntRegion * aOuterVisibleRegion ,
2015-09-17 04:31:00 +03:00
const nsIntRect * aLayerContentsVisibleRect = nullptr ,
bool aOuterUntransformed = false )
2010-07-16 01:07:51 +04:00
{
2014-08-22 17:40:02 +04:00
Matrix4x4 transform = aLayer - > GetTransform ( ) ;
Matrix transform2D ;
2015-09-17 04:31:00 +03:00
if ( aOuterUntransformed ) {
if ( aLayerContentsVisibleRect ) {
aOuterVisibleRegion - > And ( * aOuterVisibleRegion ,
* aLayerContentsVisibleRect ) ;
}
} else if ( transform . Is2D ( & transform2D ) & & ! transform2D . HasNonIntegerTranslation ( ) ) {
2014-06-23 08:24:00 +04:00
aOuterVisibleRegion - > MoveBy ( - int ( transform2D . _31 ) , - int ( transform2D . _32 ) ) ;
2014-07-11 05:17:47 +04:00
if ( aLayerContentsVisibleRect ) {
aOuterVisibleRegion - > And ( * aOuterVisibleRegion , * aLayerContentsVisibleRect ) ;
}
2013-03-22 06:17:29 +04:00
} else {
2014-06-23 08:24:00 +04:00
nsIntRect outerRect = aOuterVisibleRegion - > GetBounds ( ) ;
// if 'transform' is not invertible, then nothing will be displayed
// for the layer, so it doesn't really matter what we do here
2014-08-22 17:40:02 +04:00
Rect outerVisible ( outerRect . x , outerRect . y , outerRect . width , outerRect . height ) ;
transform . Invert ( ) ;
2015-03-13 23:42:00 +03:00
Rect layerContentsVisible ( - float ( INT32_MAX ) / 2 , - float ( INT32_MAX ) / 2 ,
float ( INT32_MAX ) , float ( INT32_MAX ) ) ;
2014-07-11 05:17:47 +04:00
if ( aLayerContentsVisibleRect ) {
NS_ASSERTION ( aLayerContentsVisibleRect - > width > = 0 & &
aLayerContentsVisibleRect - > height > = 0 ,
" Bad layer contents rectangle " ) ;
// restrict to aLayerContentsVisibleRect before call GfxRectToIntRect,
// in case layerVisible is extremely large (as it can be when
// projecting through the inverse of a 3D transform)
2015-03-13 23:42:00 +03:00
layerContentsVisible = Rect (
2014-07-11 05:17:47 +04:00
aLayerContentsVisibleRect - > x , aLayerContentsVisibleRect - > y ,
aLayerContentsVisibleRect - > width , aLayerContentsVisibleRect - > height ) ;
}
2015-03-13 23:42:00 +03:00
gfxRect layerVisible = ThebesRect ( transform . ProjectRectBounds ( outerVisible , layerContentsVisible ) ) ;
2014-06-23 08:24:00 +04:00
layerVisible . RoundOut ( ) ;
nsIntRect visRect ;
if ( gfxUtils : : GfxRectToIntRect ( layerVisible , & visRect ) ) {
* aOuterVisibleRegion = visRect ;
} else {
aOuterVisibleRegion - > SetEmpty ( ) ;
2014-06-18 07:12:55 +04:00
}
2010-07-16 01:07:51 +04:00
}
2014-06-23 08:24:00 +04:00
2015-11-29 10:07:55 +03:00
aLayer - > SetVisibleRegion ( LayerIntRegion : : FromUnknownRegion ( * aOuterVisibleRegion ) ) ;
2014-06-23 08:24:00 +04:00
}
void
ContainerState : : SetOuterVisibleRegionForLayer ( Layer * aLayer ,
const nsIntRegion & aOuterVisibleRegion ,
2015-09-17 04:31:00 +03:00
const nsIntRect * aLayerContentsVisibleRect ,
bool aOuterUntransformed ) const
2014-06-23 08:24:00 +04:00
{
nsIntRegion visRegion = aOuterVisibleRegion ;
2015-09-17 04:31:00 +03:00
if ( ! aOuterUntransformed ) {
visRegion . MoveBy ( mParameters . mOffset ) ;
}
SetOuterVisibleRegion ( aLayer , & visRegion , aLayerContentsVisibleRect ,
aOuterUntransformed ) ;
2010-07-16 01:07:51 +04:00
}
2010-09-02 13:18:39 +04:00
nscolor
2015-04-02 21:22:40 +03:00
ContainerState : : FindOpaqueBackgroundColorInLayer ( const PaintedLayerData * aData ,
const nsIntRect & aRect ,
bool * aOutIntersectsLayer ) const
2010-09-02 13:18:39 +04:00
{
2015-04-02 21:22:40 +03:00
* aOutIntersectsLayer = true ;
2010-09-02 13:18:39 +04:00
2015-04-02 21:22:40 +03:00
// Scan the candidate's display items.
nsIntRect deviceRect = aRect ;
2015-04-21 18:04:57 +03:00
nsRect appUnitRect = ToAppUnits ( deviceRect , mAppUnitsPerDevPixel ) ;
2015-04-02 21:22:40 +03:00
appUnitRect . ScaleInverseRoundOut ( mParameters . mXScale , mParameters . mYScale ) ;
2011-06-22 16:11:27 +04:00
2015-04-02 21:22:40 +03:00
for ( auto & assignedItem : Reversed ( aData - > mAssignedDisplayItems ) ) {
nsDisplayItem * item = assignedItem . mItem ;
bool snap ;
nsRect bounds = item - > GetBounds ( mBuilder , & snap ) ;
if ( snap & & mSnappingEnabled ) {
nsIntRect snappedBounds = ScaleToNearestPixels ( bounds ) ;
if ( ! snappedBounds . Intersects ( deviceRect ) )
continue ;
2012-12-05 06:53:17 +04:00
2015-04-02 21:22:40 +03:00
if ( ! snappedBounds . Contains ( deviceRect ) )
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
2012-12-05 06:53:17 +04:00
2015-04-02 21:22:40 +03:00
} else {
// The layer's visible rect is already (close enough to) pixel
// aligned, so no need to round out and in here.
if ( ! bounds . Intersects ( appUnitRect ) )
continue ;
2012-12-05 06:53:17 +04:00
2015-04-02 21:22:40 +03:00
if ( ! bounds . Contains ( appUnitRect ) )
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2012-12-05 06:53:17 +04:00
2015-04-02 21:22:40 +03:00
if ( item - > IsInvisibleInRect ( appUnitRect ) ) {
continue ;
}
2012-12-05 06:53:17 +04:00
2015-04-02 21:22:40 +03:00
if ( assignedItem . mClip . IsRectAffectedByClip ( deviceRect ,
mParameters . mXScale ,
mParameters . mYScale ,
mAppUnitsPerDevPixel ) ) {
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2014-06-03 16:50:42 +04:00
2016-05-19 11:07:52 +03:00
Maybe < nscolor > color = item - > IsUniform ( mBuilder ) ;
if ( color & & NS_GET_A ( * color ) = = 255 )
return * color ;
2015-04-02 21:22:40 +03:00
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2014-07-23 10:12:08 +04:00
2015-04-02 21:22:40 +03:00
* aOutIntersectsLayer = false ;
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2012-12-05 06:53:17 +04:00
2015-04-02 21:22:40 +03:00
nscolor
PaintedLayerDataNode : : FindOpaqueBackgroundColor ( const nsIntRegion & aTargetVisibleRegion ,
int32_t aUnderIndex ) const
{
if ( aUnderIndex = = ABOVE_TOP ) {
aUnderIndex = mPaintedLayerDataStack . Length ( ) ;
}
for ( int32_t i = aUnderIndex - 1 ; i > = 0 ; - - i ) {
const PaintedLayerData * candidate = & mPaintedLayerDataStack [ i ] ;
if ( candidate - > VisibleAboveRegionIntersects ( aTargetVisibleRegion ) ) {
// Some non-PaintedLayer content between target and candidate; this is
// hopeless
2015-02-20 22:46:09 +03:00
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
2012-12-05 06:53:17 +04:00
}
2015-04-02 21:22:40 +03:00
if ( ! candidate - > VisibleRegionIntersects ( aTargetVisibleRegion ) ) {
// The layer doesn't intersect our target, ignore it and move on
continue ;
}
bool intersectsLayer = true ;
nsIntRect rect = aTargetVisibleRegion . GetBounds ( ) ;
nscolor color = mTree . ContState ( ) . FindOpaqueBackgroundColorInLayer (
candidate , rect , & intersectsLayer ) ;
if ( ! intersectsLayer ) {
continue ;
}
return color ;
2010-09-02 13:18:39 +04:00
}
2015-04-02 21:22:40 +03:00
if ( mAllDrawingAboveBackground | |
! mVisibleAboveBackgroundRegion . Intersect ( aTargetVisibleRegion ) . IsEmpty ( ) ) {
// Some non-PaintedLayer content is between this node's background and target.
2015-02-25 19:47:22 +03:00
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2015-04-02 21:22:40 +03:00
return FindOpaqueBackgroundColorInParentNode ( ) ;
}
nscolor
PaintedLayerDataNode : : FindOpaqueBackgroundColorCoveringEverything ( ) const
{
if ( ! mPaintedLayerDataStack . IsEmpty ( ) | |
2015-04-05 21:05:44 +03:00
mAllDrawingAboveBackground | |
2015-04-02 21:22:40 +03:00
! mVisibleAboveBackgroundRegion . IsEmpty ( ) ) {
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
return FindOpaqueBackgroundColorInParentNode ( ) ;
}
nscolor
PaintedLayerDataNode : : FindOpaqueBackgroundColorInParentNode ( ) const
{
if ( mParent ) {
if ( mHasClip ) {
// Check whether our parent node has uniform content behind our whole
// clip.
// There's one tricky case here: If our parent node is also a scrollable,
// and is currently scrolled in such a way that this inner one is
// clipped by it, then it's not really clear how we should determine
// whether we have a uniform background in the parent: There might be
// non-uniform content in the parts that our scroll port covers in the
// parent and that are currently outside the parent's clip.
// For now, we'll fail to pull a background color in that case.
return mParent - > FindOpaqueBackgroundColor ( mClipRect ) ;
}
return mParent - > FindOpaqueBackgroundColorCoveringEverything ( ) ;
}
// We are the root.
return mTree . UniformBackgroundColor ( ) ;
2010-09-02 13:18:39 +04:00
}
2012-02-08 02:27:44 +04:00
void
2014-09-26 21:06:08 +04:00
PaintedLayerData : : UpdateCommonClipCount (
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aCurrentClip )
2012-02-08 02:27:44 +04:00
{
if ( mCommonClipCount > = 0 ) {
2013-03-04 13:56:00 +04:00
mCommonClipCount = mItemClip . GetCommonRoundedRectCount ( aCurrentClip , mCommonClipCount ) ;
2012-02-08 02:27:44 +04:00
} else {
// first item in the layer
2013-03-04 13:56:00 +04:00
mCommonClipCount = aCurrentClip . GetRoundedRectCount ( ) ;
2012-07-31 21:28:21 +04:00
}
2012-02-08 02:27:44 +04:00
}
2015-05-13 10:23:46 +03:00
bool
PaintedLayerData : : CanOptimizeToImageLayer ( nsDisplayListBuilder * aBuilder )
{
if ( ! mImage ) {
2015-05-14 00:23:52 +03:00
return false ;
2015-05-13 10:23:46 +03:00
}
return mImage - > CanOptimizeToImageLayer ( mLayer - > Manager ( ) , aBuilder ) ;
}
2012-01-30 09:16:54 +04:00
already_AddRefed < ImageContainer >
2015-05-13 10:23:46 +03:00
PaintedLayerData : : GetContainerForImageLayer ( nsDisplayListBuilder * aBuilder )
2011-01-18 00:47:18 +03:00
{
2012-02-08 02:27:44 +04:00
if ( ! mImage ) {
2012-07-30 18:20:58 +04:00
return nullptr ;
2011-01-18 00:47:18 +03:00
}
2012-11-28 06:34:45 +04:00
return mImage - > GetContainer ( mLayer - > Manager ( ) , aBuilder ) ;
2011-01-18 00:47:18 +03:00
}
2015-04-02 21:22:40 +03:00
PaintedLayerDataNode : : PaintedLayerDataNode ( PaintedLayerDataTree & aTree ,
PaintedLayerDataNode * aParent ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 21:22:40 +03:00
: mTree ( aTree )
, mParent ( aParent )
, mAnimatedGeometryRoot ( aAnimatedGeometryRoot )
, mAllDrawingAboveBackground ( false )
{
2015-11-25 01:53:51 +03:00
MOZ_ASSERT ( nsLayoutUtils : : IsAncestorFrameCrossDoc ( mTree . Builder ( ) - > RootReferenceFrame ( ) , * mAnimatedGeometryRoot ) ) ;
2015-04-02 21:22:40 +03:00
mHasClip = mTree . IsClippedWithRespectToParentAnimatedGeometryRoot ( mAnimatedGeometryRoot , & mClipRect ) ;
}
PaintedLayerDataNode : : ~ PaintedLayerDataNode ( )
{
MOZ_ASSERT ( mPaintedLayerDataStack . IsEmpty ( ) ) ;
MOZ_ASSERT ( mChildren . IsEmpty ( ) ) ;
}
PaintedLayerDataNode *
2015-11-25 01:53:51 +03:00
PaintedLayerDataNode : : AddChildNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 21:22:40 +03:00
{
2015-11-25 01:53:51 +03:00
MOZ_ASSERT ( aAnimatedGeometryRoot - > mParentAGR = = mAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
UniquePtr < PaintedLayerDataNode > child =
2015-06-16 20:41:59 +03:00
MakeUnique < PaintedLayerDataNode > ( mTree , this , aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
mChildren . AppendElement ( Move ( child ) ) ;
return mChildren . LastElement ( ) . get ( ) ;
}
template < typename NewPaintedLayerCallbackType >
PaintedLayerData *
PaintedLayerDataNode : : FindPaintedLayerFor ( const nsIntRect & aVisibleRect ,
2015-09-17 04:31:00 +03:00
bool aBackfaceHidden ,
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * aASR ,
const DisplayItemClipChain * aClipChain ,
2015-04-02 21:22:40 +03:00
NewPaintedLayerCallbackType aNewPaintedLayerCallback )
{
if ( ! mPaintedLayerDataStack . IsEmpty ( ) ) {
2016-06-02 23:44:32 +03:00
PaintedLayerData * lowestUsableLayer = nullptr ;
for ( auto & data : Reversed ( mPaintedLayerDataStack ) ) {
if ( data . mVisibleAboveRegion . Intersects ( aVisibleRect ) ) {
break ;
2015-04-02 21:22:40 +03:00
}
2016-06-02 23:44:32 +03:00
if ( data . mBackfaceHidden = = aBackfaceHidden & &
2017-02-01 01:07:35 +03:00
data . mASR = = aASR & &
DisplayItemClipChain : : Equal ( data . mClipChain , aClipChain ) ) {
2016-06-02 23:44:32 +03:00
lowestUsableLayer = & data ;
}
// Also check whether the event-regions intersect the visible rect,
// unless we're in an inactive layer, in which case the event-regions
// will be hoisted out into their own layer.
// For performance reasons, we check the intersection with the bounds
// of the event-regions.
if ( ! mTree . ContState ( ) . IsInInactiveLayer ( ) & &
( data . mScaledHitRegionBounds . Intersects ( aVisibleRect ) | |
data . mScaledMaybeHitRegionBounds . Intersects ( aVisibleRect ) ) ) {
break ;
}
2016-11-24 08:11:30 +03:00
// If the visible region intersects with the current layer then we
// can't possibly use any of the layers below it, so stop the search
// now.
//
// If we're trying to minimize painted layer size and we don't
// intersect the current visible region, then make sure we don't
// use this painted layer.
2017-06-23 22:55:55 +03:00
if ( data . mVisibleRegion . Intersects ( aVisibleRect ) ) {
2016-06-02 23:44:32 +03:00
break ;
2016-11-24 08:11:30 +03:00
} else if ( gfxPrefs : : LayoutSmallerPaintedLayers ( ) ) {
lowestUsableLayer = nullptr ;
2015-04-02 21:22:40 +03:00
}
}
2016-06-02 23:44:32 +03:00
if ( lowestUsableLayer ) {
return lowestUsableLayer ;
}
2015-04-02 21:22:40 +03:00
}
return mPaintedLayerDataStack . AppendElement ( aNewPaintedLayerCallback ( ) ) ;
}
void
PaintedLayerDataNode : : FinishChildrenIntersecting ( const nsIntRect & aRect )
{
for ( int32_t i = mChildren . Length ( ) - 1 ; i > = 0 ; i - - ) {
if ( mChildren [ i ] - > Intersects ( aRect ) ) {
mChildren [ i ] - > Finish ( true ) ;
mChildren . RemoveElementAt ( i ) ;
}
}
}
void
PaintedLayerDataNode : : FinishAllChildren ( bool aThisNodeNeedsAccurateVisibleAboveRegion )
{
for ( int32_t i = mChildren . Length ( ) - 1 ; i > = 0 ; i - - ) {
mChildren [ i ] - > Finish ( aThisNodeNeedsAccurateVisibleAboveRegion ) ;
}
mChildren . Clear ( ) ;
}
void
PaintedLayerDataNode : : Finish ( bool aParentNeedsAccurateVisibleAboveRegion )
{
// Skip "visible above region" maintenance, because this node is going away.
FinishAllChildren ( false ) ;
PopAllPaintedLayerData ( ) ;
if ( mParent & & aParentNeedsAccurateVisibleAboveRegion ) {
if ( mHasClip ) {
mParent - > AddToVisibleAboveRegion ( mClipRect ) ;
} else {
mParent - > SetAllDrawingAbove ( ) ;
}
}
mTree . NodeWasFinished ( mAnimatedGeometryRoot ) ;
}
void
PaintedLayerDataNode : : AddToVisibleAboveRegion ( const nsIntRect & aRect )
{
2015-06-16 20:41:59 +03:00
nsIntRegion & visibleAboveRegion = mPaintedLayerDataStack . IsEmpty ( )
2015-04-02 21:22:40 +03:00
? mVisibleAboveBackgroundRegion
: mPaintedLayerDataStack . LastElement ( ) . mVisibleAboveRegion ;
2015-06-16 20:41:59 +03:00
visibleAboveRegion . Or ( visibleAboveRegion , aRect ) ;
visibleAboveRegion . SimplifyOutward ( 8 ) ;
2015-04-02 21:22:40 +03:00
}
void
PaintedLayerDataNode : : SetAllDrawingAbove ( )
{
PopAllPaintedLayerData ( ) ;
mAllDrawingAboveBackground = true ;
mVisibleAboveBackgroundRegion . SetEmpty ( ) ;
}
void
PaintedLayerDataNode : : PopPaintedLayerData ( )
{
MOZ_ASSERT ( ! mPaintedLayerDataStack . IsEmpty ( ) ) ;
size_t lastIndex = mPaintedLayerDataStack . Length ( ) - 1 ;
PaintedLayerData & data = mPaintedLayerDataStack [ lastIndex ] ;
mTree . ContState ( ) . FinishPaintedLayerData ( data , [ this , & data , lastIndex ] ( ) {
2015-06-16 20:41:59 +03:00
return this - > FindOpaqueBackgroundColor ( data . mVisibleRegion , lastIndex ) ;
2015-04-02 21:22:40 +03:00
} ) ;
mPaintedLayerDataStack . RemoveElementAt ( lastIndex ) ;
}
void
PaintedLayerDataNode : : PopAllPaintedLayerData ( )
{
while ( ! mPaintedLayerDataStack . IsEmpty ( ) ) {
PopPaintedLayerData ( ) ;
}
}
nsDisplayListBuilder *
PaintedLayerDataTree : : Builder ( ) const
{
return mContainerState . Builder ( ) ;
}
void
PaintedLayerDataTree : : Finish ( )
{
if ( mRoot ) {
mRoot - > Finish ( false ) ;
}
MOZ_ASSERT ( mNodes . Count ( ) = = 0 ) ;
mRoot = nullptr ;
}
void
2015-11-25 01:53:51 +03:00
PaintedLayerDataTree : : NodeWasFinished ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 21:22:40 +03:00
{
mNodes . Remove ( aAnimatedGeometryRoot ) ;
}
void
2015-11-25 01:53:51 +03:00
PaintedLayerDataTree : : AddingOwnLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 21:22:40 +03:00
const nsIntRect * aRect ,
nscolor * aOutUniformBackgroundColor )
{
FinishPotentiallyIntersectingNodes ( aAnimatedGeometryRoot , aRect ) ;
PaintedLayerDataNode * node = EnsureNodeFor ( aAnimatedGeometryRoot ) ;
if ( aRect ) {
if ( aOutUniformBackgroundColor ) {
* aOutUniformBackgroundColor = node - > FindOpaqueBackgroundColor ( * aRect ) ;
}
node - > AddToVisibleAboveRegion ( * aRect ) ;
} else {
if ( aOutUniformBackgroundColor ) {
* aOutUniformBackgroundColor = node - > FindOpaqueBackgroundColorCoveringEverything ( ) ;
}
node - > SetAllDrawingAbove ( ) ;
}
}
template < typename NewPaintedLayerCallbackType >
PaintedLayerData *
2015-11-25 01:53:51 +03:00
PaintedLayerDataTree : : FindPaintedLayerFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * aASR ,
const DisplayItemClipChain * aClipChain ,
2015-04-02 21:22:40 +03:00
const nsIntRect & aVisibleRect ,
2015-09-17 04:31:00 +03:00
bool aBackfaceHidden ,
2015-04-02 21:22:40 +03:00
NewPaintedLayerCallbackType aNewPaintedLayerCallback )
{
2016-06-02 23:44:32 +03:00
const nsIntRect * bounds = & aVisibleRect ;
2015-04-02 21:22:40 +03:00
FinishPotentiallyIntersectingNodes ( aAnimatedGeometryRoot , bounds ) ;
2016-05-27 18:29:19 +03:00
PaintedLayerDataNode * node = EnsureNodeFor ( aAnimatedGeometryRoot ) ;
2016-01-07 18:50:23 +03:00
2015-07-02 05:08:20 +03:00
PaintedLayerData * data =
2017-02-01 01:07:35 +03:00
node - > FindPaintedLayerFor ( aVisibleRect , aBackfaceHidden , aASR , aClipChain ,
2015-09-17 04:31:00 +03:00
aNewPaintedLayerCallback ) ;
2015-07-02 05:08:20 +03:00
return data ;
2015-04-02 21:22:40 +03:00
}
void
2015-11-25 01:53:51 +03:00
PaintedLayerDataTree : : FinishPotentiallyIntersectingNodes ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 21:22:40 +03:00
const nsIntRect * aRect )
{
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * ancestorThatIsChildOfCommonAncestor = nullptr ;
2015-04-02 21:22:40 +03:00
PaintedLayerDataNode * ancestorNode =
FindNodeForAncestorAnimatedGeometryRoot ( aAnimatedGeometryRoot ,
& ancestorThatIsChildOfCommonAncestor ) ;
if ( ! ancestorNode ) {
// None of our ancestors are in the tree. This should only happen if this
// is the very first item we're looking at.
MOZ_ASSERT ( ! mRoot ) ;
return ;
}
2015-11-25 01:53:51 +03:00
if ( ancestorNode - > GetAnimatedGeometryRoot ( ) = = aAnimatedGeometryRoot ) {
2015-04-02 21:22:40 +03:00
// aAnimatedGeometryRoot already has a node in the tree.
// This is the common case.
MOZ_ASSERT ( ! ancestorThatIsChildOfCommonAncestor ) ;
if ( aRect ) {
ancestorNode - > FinishChildrenIntersecting ( * aRect ) ;
} else {
ancestorNode - > FinishAllChildren ( ) ;
}
return ;
}
// We have found an existing ancestor, but it's a proper ancestor of our
// animated geometry root.
// ancestorThatIsChildOfCommonAncestor is the last animated geometry root
// encountered on the way up from aAnimatedGeometryRoot to ancestorNode.
MOZ_ASSERT ( ancestorThatIsChildOfCommonAncestor ) ;
2015-11-25 01:53:51 +03:00
MOZ_ASSERT ( nsLayoutUtils : : IsAncestorFrameCrossDoc ( * ancestorThatIsChildOfCommonAncestor , * aAnimatedGeometryRoot ) ) ;
MOZ_ASSERT ( ancestorThatIsChildOfCommonAncestor - > mParentAGR = = ancestorNode - > GetAnimatedGeometryRoot ( ) ) ;
2015-04-02 21:22:40 +03:00
// ancestorThatIsChildOfCommonAncestor is not in the tree yet!
MOZ_ASSERT ( ! mNodes . Get ( ancestorThatIsChildOfCommonAncestor ) ) ;
// We're about to add a node for ancestorThatIsChildOfCommonAncestor, so we
// finish all intersecting siblings.
nsIntRect clip ;
if ( IsClippedWithRespectToParentAnimatedGeometryRoot ( ancestorThatIsChildOfCommonAncestor , & clip ) ) {
ancestorNode - > FinishChildrenIntersecting ( clip ) ;
} else {
ancestorNode - > FinishAllChildren ( ) ;
}
}
PaintedLayerDataNode *
2015-11-25 01:53:51 +03:00
PaintedLayerDataTree : : EnsureNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 21:22:40 +03:00
{
MOZ_ASSERT ( aAnimatedGeometryRoot ) ;
PaintedLayerDataNode * node = mNodes . Get ( aAnimatedGeometryRoot ) ;
if ( node ) {
return node ;
}
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * parentAnimatedGeometryRoot = aAnimatedGeometryRoot - > mParentAGR ;
2015-04-02 21:22:40 +03:00
if ( ! parentAnimatedGeometryRoot ) {
MOZ_ASSERT ( ! mRoot ) ;
2015-11-25 01:53:51 +03:00
MOZ_ASSERT ( * aAnimatedGeometryRoot = = Builder ( ) - > RootReferenceFrame ( ) ) ;
2015-06-16 20:41:59 +03:00
mRoot = MakeUnique < PaintedLayerDataNode > ( * this , nullptr , aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
node = mRoot . get ( ) ;
} else {
PaintedLayerDataNode * parentNode = EnsureNodeFor ( parentAnimatedGeometryRoot ) ;
MOZ_ASSERT ( parentNode ) ;
node = parentNode - > AddChildNodeFor ( aAnimatedGeometryRoot ) ;
}
MOZ_ASSERT ( node ) ;
mNodes . Put ( aAnimatedGeometryRoot , node ) ;
return node ;
}
bool
2015-11-25 01:53:51 +03:00
PaintedLayerDataTree : : IsClippedWithRespectToParentAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 21:22:40 +03:00
nsIntRect * aOutClip )
{
2015-11-25 01:53:51 +03:00
nsIScrollableFrame * scrollableFrame = nsLayoutUtils : : GetScrollableFrameFor ( * aAnimatedGeometryRoot ) ;
2015-04-02 21:22:40 +03:00
if ( ! scrollableFrame ) {
return false ;
}
nsIFrame * scrollFrame = do_QueryFrame ( scrollableFrame ) ;
nsRect scrollPort = scrollableFrame - > GetScrollPortRect ( ) + Builder ( ) - > ToReferenceFrame ( scrollFrame ) ;
* aOutClip = mContainerState . ScaleToNearestPixels ( scrollPort ) ;
return true ;
}
PaintedLayerDataNode *
2015-11-25 01:53:51 +03:00
PaintedLayerDataTree : : FindNodeForAncestorAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
AnimatedGeometryRoot * * aOutAncestorChild )
2015-04-02 21:22:40 +03:00
{
if ( ! aAnimatedGeometryRoot ) {
return nullptr ;
}
PaintedLayerDataNode * node = mNodes . Get ( aAnimatedGeometryRoot ) ;
if ( node ) {
return node ;
}
* aOutAncestorChild = aAnimatedGeometryRoot ;
2015-11-25 01:53:51 +03:00
return FindNodeForAncestorAnimatedGeometryRoot ( aAnimatedGeometryRoot - > mParentAGR , aOutAncestorChild ) ;
2015-04-02 21:22:40 +03:00
}
2014-04-22 18:27:44 +04:00
static bool
2014-09-26 21:06:08 +04:00
CanOptimizeAwayPaintedLayer ( PaintedLayerData * aData ,
2014-04-22 18:27:44 +04:00
FrameLayerBuilder * aLayerBuilder )
{
2014-06-23 08:24:00 +04:00
if ( ! aLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
2014-04-22 18:27:44 +04:00
return false ;
}
2014-09-26 21:06:08 +04:00
// If there's no painted layer with valid content in it that we can reuse,
2014-04-22 18:27:44 +04:00
// always create a color or image layer (and potentially throw away an
2014-09-26 21:06:08 +04:00
// existing completely invalid painted layer).
2014-04-22 18:27:44 +04:00
if ( aData - > mLayer - > GetValidRegion ( ) . IsEmpty ( ) ) {
return true ;
}
2014-09-26 21:06:08 +04:00
// There is an existing painted layer we can reuse. Throwing it away can make
2014-04-22 18:27:44 +04:00
// compositing cheaper (see bug 946952), but it might cause us to re-allocate
2014-09-26 21:06:08 +04:00
// the painted layer frequently due to an animation. So we only discard it if
2014-04-22 18:27:44 +04:00
// we're in tree compression mode, which is triggered at a low frequency.
return aLayerBuilder - > CheckInLayerTreeCompressionMode ( ) ;
}
2014-06-23 08:24:00 +04:00
# ifdef DEBUG
static int32_t FindIndexOfLayerIn ( nsTArray < NewLayerEntry > & aArray ,
Layer * aLayer )
{
for ( uint32_t i = 0 ; i < aArray . Length ( ) ; + + i ) {
if ( aArray [ i ] . mLayer = = aLayer ) {
return i ;
}
}
return - 1 ;
}
# endif
2015-05-13 10:23:46 +03:00
already_AddRefed < Layer >
ContainerState : : PrepareImageLayer ( PaintedLayerData * aData )
{
2015-10-18 08:24:48 +03:00
RefPtr < ImageContainer > imageContainer =
2015-05-13 10:23:46 +03:00
aData - > GetContainerForImageLayer ( mBuilder ) ;
if ( ! imageContainer ) {
return nullptr ;
}
2015-10-18 08:24:48 +03:00
RefPtr < ImageLayer > imageLayer = CreateOrRecycleImageLayer ( aData - > mLayer ) ;
2015-05-13 10:23:46 +03:00
imageLayer - > SetContainer ( imageContainer ) ;
aData - > mImage - > ConfigureLayer ( imageLayer , mParameters ) ;
imageLayer - > SetPostScale ( mParameters . mXScale ,
mParameters . mYScale ) ;
if ( aData - > mItemClip . HasClip ( ) ) {
ParentLayerIntRect clip =
ViewAs < ParentLayerPixel > ( ScaleToNearestPixels ( aData - > mItemClip . GetClipRect ( ) ) ) ;
clip . MoveBy ( ViewAs < ParentLayerPixel > ( mParameters . mOffset ) ) ;
imageLayer - > SetClipRect ( Some ( clip ) ) ;
} else {
imageLayer - > SetClipRect ( Nothing ( ) ) ;
}
FLB_LOG_PAINTED_LAYER_DECISION ( aData ,
" Selected image layer=%p \n " , imageLayer . get ( ) ) ;
return imageLayer . forget ( ) ;
}
already_AddRefed < Layer >
ContainerState : : PrepareColorLayer ( PaintedLayerData * aData )
{
2015-10-18 08:24:48 +03:00
RefPtr < ColorLayer > colorLayer = CreateOrRecycleColorLayer ( aData - > mLayer ) ;
2015-09-25 04:16:45 +03:00
colorLayer - > SetColor ( Color : : FromABGR ( aData - > mSolidColor ) ) ;
2015-05-13 10:23:46 +03:00
// Copy transform
colorLayer - > SetBaseTransform ( aData - > mLayer - > GetBaseTransform ( ) ) ;
colorLayer - > SetPostScale ( aData - > mLayer - > GetPostXScale ( ) ,
aData - > mLayer - > GetPostYScale ( ) ) ;
nsIntRect visibleRect = aData - > mVisibleRegion . GetBounds ( ) ;
visibleRect . MoveBy ( - GetTranslationForPaintedLayer ( aData - > mLayer ) ) ;
colorLayer - > SetBounds ( visibleRect ) ;
colorLayer - > SetClipRect ( Nothing ( ) ) ;
FLB_LOG_PAINTED_LAYER_DECISION ( aData ,
" Selected color layer=%p \n " , colorLayer . get ( ) ) ;
return colorLayer . forget ( ) ;
}
2010-07-16 01:07:51 +04:00
2015-09-17 04:31:00 +03:00
static void
SetBackfaceHiddenForLayer ( bool aBackfaceHidden , Layer * aLayer )
{
if ( aBackfaceHidden ) {
aLayer - > SetContentFlags ( aLayer - > GetContentFlags ( ) |
Layer : : CONTENT_BACKFACE_HIDDEN ) ;
} else {
aLayer - > SetContentFlags ( aLayer - > GetContentFlags ( ) &
~ Layer : : CONTENT_BACKFACE_HIDDEN ) ;
}
}
2015-04-02 21:22:40 +03:00
template < typename FindOpaqueBackgroundColorCallbackType >
void ContainerState : : FinishPaintedLayerData ( PaintedLayerData & aData , FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor )
{
PaintedLayerData * data = & aData ;
2010-07-16 01:07:51 +04:00
2015-03-04 08:18:47 +03:00
if ( ! data - > mLayer ) {
// No layer was recycled, so we create a new one.
2015-10-18 08:24:48 +03:00
RefPtr < PaintedLayer > paintedLayer = CreatePaintedLayer ( data ) ;
2015-03-04 08:18:47 +03:00
data - > mLayer = paintedLayer ;
2015-03-04 05:32:08 +03:00
2015-03-04 08:18:47 +03:00
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , paintedLayer ) < 0 ,
" Layer already in list??? " ) ;
mNewChildLayers [ data - > mNewChildLayersIndex ] . mLayer = paintedLayer . forget ( ) ;
}
2015-03-04 05:32:08 +03:00
2015-03-04 08:21:55 +03:00
for ( auto & item : data - > mAssignedDisplayItems ) {
2017-08-07 07:07:43 +03:00
MOZ_ASSERT ( item . mItem - > GetType ( ) ! = DisplayItemType : : TYPE_LAYER_EVENT_REGIONS ) ;
2017-04-14 09:59:49 +03:00
2015-03-04 08:21:55 +03:00
InvalidateForLayerChange ( item . mItem , data - > mLayer ) ;
mLayerBuilder - > AddPaintedDisplayItem ( data , item . mItem , item . mClip ,
* this , item . mLayerState ,
data - > mAnimatedGeometryRootOffset ) ;
}
2014-06-23 08:24:00 +04:00
NewLayerEntry * newLayerEntry = & mNewChildLayers [ data - > mNewChildLayersIndex ] ;
2015-03-17 01:37:04 +03:00
2015-10-18 08:24:48 +03:00
RefPtr < Layer > layer ;
2015-05-13 10:23:46 +03:00
bool canOptimizeToImageLayer = data - > CanOptimizeToImageLayer ( mBuilder ) ;
2014-08-22 19:53:24 +04:00
2014-11-26 21:58:15 +03:00
FLB_LOG_PAINTED_LAYER_DECISION ( data , " Selecting layer for pld=%p \n " , data ) ;
2015-05-13 10:23:46 +03:00
FLB_LOG_PAINTED_LAYER_DECISION ( data , " Solid=%i, hasImage=%c, canOptimizeAwayPaintedLayer=%i \n " ,
data - > mIsSolidColorInVisibleRegion , canOptimizeToImageLayer ? ' y ' : ' n ' ,
2014-09-26 21:06:08 +04:00
CanOptimizeAwayPaintedLayer ( data , mLayerBuilder ) ) ;
2014-08-22 19:53:24 +04:00
2015-05-13 10:23:46 +03:00
if ( ( data - > mIsSolidColorInVisibleRegion | | canOptimizeToImageLayer ) & &
2014-09-26 21:06:08 +04:00
CanOptimizeAwayPaintedLayer ( data , mLayerBuilder ) ) {
2015-05-13 10:23:46 +03:00
NS_ASSERTION ( ! ( data - > mIsSolidColorInVisibleRegion & & canOptimizeToImageLayer ) ,
2011-01-18 00:47:18 +03:00
" Can't be a solid color as well as an image! " ) ;
2015-05-13 10:23:46 +03:00
layer = canOptimizeToImageLayer ? PrepareImageLayer ( data )
: PrepareColorLayer ( data ) ;
if ( layer ) {
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , layer ) < 0 ,
" Layer already in list??? " ) ;
NS_ASSERTION ( newLayerEntry - > mLayer = = data - > mLayer ,
" Painted layer at wrong index " ) ;
// Store optimized layer in reserved slot
2017-02-01 01:07:35 +03:00
NewLayerEntry * paintedLayerEntry = newLayerEntry ;
2015-05-13 10:23:46 +03:00
newLayerEntry = & mNewChildLayers [ data - > mNewChildLayersIndex + 1 ] ;
NS_ASSERTION ( ! newLayerEntry - > mLayer , " Slot already occupied? " ) ;
newLayerEntry - > mLayer = layer ;
newLayerEntry - > mAnimatedGeometryRoot = data - > mAnimatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
newLayerEntry - > mASR = paintedLayerEntry - > mASR ;
newLayerEntry - > mClipChain = paintedLayerEntry - > mClipChain ;
newLayerEntry - > mScrollMetadataASR = paintedLayerEntry - > mScrollMetadataASR ;
2015-05-13 10:23:46 +03:00
// Hide the PaintedLayer. We leave it in the layer tree so that we
// can find and recycle it later.
ParentLayerIntRect emptyRect ;
data - > mLayer - > SetClipRect ( Some ( emptyRect ) ) ;
2015-11-29 10:07:55 +03:00
data - > mLayer - > SetVisibleRegion ( LayerIntRegion ( ) ) ;
2017-06-16 00:29:18 +03:00
data - > mLayer - > InvalidateWholeLayer ( ) ;
2015-05-13 10:23:46 +03:00
data - > mLayer - > SetEventRegions ( EventRegions ( ) ) ;
2017-04-21 10:27:48 +03:00
for ( auto & item : data - > mAssignedDisplayItems ) {
mLayerBuilder - > StoreOptimizedLayerForFrame ( item . mItem , layer ) ;
}
2011-01-18 00:47:18 +03:00
}
2015-05-13 10:23:46 +03:00
}
2015-07-18 16:35:59 +03:00
2015-05-13 10:23:46 +03:00
if ( ! layer ) {
// We couldn't optimize to an image layer or a color layer above.
2013-04-19 19:17:21 +04:00
layer = data - > mLayer ;
2015-04-12 05:03:00 +03:00
layer - > SetClipRect ( Nothing ( ) ) ;
2014-09-26 21:07:06 +04:00
FLB_LOG_PAINTED_LAYER_DECISION ( data , " Selected painted layer=%p \n " , layer . get ( ) ) ;
2010-07-16 01:08:03 +04:00
}
2014-06-23 08:24:00 +04:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
2015-06-16 20:41:59 +03:00
newLayerEntry - > mVisibleRegion = data - > mVisibleRegion ;
2014-06-23 08:24:00 +04:00
newLayerEntry - > mOpaqueRegion = data - > mOpaqueRegion ;
newLayerEntry - > mHideAllLayersBelow = data - > mHideAllLayersBelow ;
2014-08-31 07:29:24 +04:00
newLayerEntry - > mOpaqueForAnimatedGeometryRootParent = data - > mOpaqueForAnimatedGeometryRootParent ;
2014-06-23 08:24:00 +04:00
} else {
2015-06-16 20:41:59 +03:00
SetOuterVisibleRegionForLayer ( layer , data - > mVisibleRegion ) ;
2010-07-16 01:07:51 +04:00
}
2014-08-22 19:53:24 +04:00
# ifdef MOZ_DUMP_PAINTING
2015-03-09 07:41:11 +03:00
if ( ! data - > mLog . IsEmpty ( ) ) {
if ( PaintedLayerData * containingPld = mLayerBuilder - > GetContainingPaintedLayerData ( ) ) {
containingPld - > mLayer - > AddExtraDumpInfo ( nsCString ( data - > mLog ) ) ;
} else {
layer - > AddExtraDumpInfo ( nsCString ( data - > mLog ) ) ;
}
2015-01-20 17:49:30 +03:00
}
2014-08-22 19:53:24 +04:00
# endif
2010-07-16 01:07:51 +04:00
nsIntRegion transparentRegion ;
2015-06-16 20:41:59 +03:00
transparentRegion . Sub ( data - > mVisibleRegion , data - > mOpaqueRegion ) ;
2011-09-29 10:19:26 +04:00
bool isOpaque = transparentRegion . IsEmpty ( ) ;
2014-09-26 21:06:08 +04:00
// For translucent PaintedLayers, try to find an opaque background
2010-09-02 13:18:39 +04:00
// color that covers the entire area beneath it so we can pull that
// color into this layer to make it opaque.
if ( layer = = data - > mLayer ) {
nscolor backgroundColor = NS_RGBA ( 0 , 0 , 0 , 0 ) ;
if ( ! isOpaque ) {
2015-04-02 21:22:40 +03:00
backgroundColor = aFindOpaqueBackgroundColor ( ) ;
2010-09-02 13:18:39 +04:00
if ( NS_GET_A ( backgroundColor ) = = 255 ) {
2011-10-17 18:59:28 +04:00
isOpaque = true ;
2010-09-02 13:18:39 +04:00
}
}
// Store the background color
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * userData =
GetPaintedDisplayItemLayerUserData ( data - > mLayer ) ;
2010-09-02 13:18:39 +04:00
NS_ASSERTION ( userData , " where did our user data go? " ) ;
if ( userData - > mForcedBackgroundColor ! = backgroundColor ) {
2014-09-26 21:06:08 +04:00
// Invalidate the entire target PaintedLayer since we're changing
2010-09-02 13:18:39 +04:00
// the background color
2014-05-05 12:26:28 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
printf_stderr ( " Forced background color has changed from #%08X to #%08X on layer %p \n " ,
userData - > mForcedBackgroundColor , backgroundColor , data - > mLayer ) ;
nsAutoCString str ;
AppendToString ( str , data - > mLayer - > GetValidRegion ( ) ) ;
printf_stderr ( " Invalidating layer %p: %s \n " , data - > mLayer , str . get ( ) ) ;
}
# endif
2017-06-16 00:29:18 +03:00
data - > mLayer - > InvalidateWholeLayer ( ) ;
2010-09-02 13:18:39 +04:00
}
userData - > mForcedBackgroundColor = backgroundColor ;
2012-02-08 02:27:44 +04:00
2013-12-16 16:16:24 +04:00
// use a mask layer for rounded rect clipping.
// data->mCommonClipCount may be -1 if we haven't put any actual
// drawable items in this layer (i.e. it's only catching events).
2015-09-12 03:00:22 +03:00
int32_t commonClipCount ;
2017-02-01 01:07:35 +03:00
commonClipCount = std : : max ( 0 , data - > mCommonClipCount ) ;
SetupMaskLayer ( layer , data - > mItemClip , commonClipCount ) ;
2012-02-08 02:27:44 +04:00
// copy commonClipCount to the entry
2014-09-26 21:06:08 +04:00
FrameLayerBuilder : : PaintedLayerItemsEntry * entry = mLayerBuilder - >
GetPaintedLayerItemsEntry ( static_cast < PaintedLayer * > ( layer . get ( ) ) ) ;
2012-02-08 02:27:44 +04:00
entry - > mCommonClipCount = commonClipCount ;
} else {
// mask layer for image and color layers
2016-07-25 05:41:25 +03:00
SetupMaskLayer ( layer , data - > mItemClip ) ;
2010-09-02 13:18:39 +04:00
}
2013-12-13 22:53:18 +04:00
uint32_t flags = 0 ;
nsIWidget * widget = mContainerReferenceFrame - > PresContext ( ) - > GetRootWidget ( ) ;
2014-01-20 07:31:02 +04:00
// See bug 941095. Not quite ready to disable this.
bool hidpi = false & & widget & & widget - > GetDefaultScale ( ) . scale > = 2 ;
2013-12-13 22:53:18 +04:00
if ( hidpi ) {
flags | = Layer : : CONTENT_DISABLE_SUBPIXEL_AA ;
}
2010-12-20 04:26:14 +03:00
if ( isOpaque & & ! data - > mForceTransparentSurface ) {
2013-12-13 22:53:18 +04:00
flags | = Layer : : CONTENT_OPAQUE ;
} else if ( data - > mNeedComponentAlpha & & ! hidpi ) {
flags | = Layer : : CONTENT_COMPONENT_ALPHA ;
2010-12-20 04:26:14 +03:00
}
2015-06-27 01:13:50 +03:00
if ( data - > mDisableFlattening ) {
flags | = Layer : : CONTENT_DISABLE_FLATTENING ;
}
2010-09-02 13:18:40 +04:00
layer - > SetContentFlags ( flags ) ;
2010-09-02 13:18:39 +04:00
2014-09-26 21:06:08 +04:00
PaintedLayerData * containingPaintedLayerData =
mLayerBuilder - > GetContainingPaintedLayerData ( ) ;
2017-04-29 03:32:05 +03:00
// If we're building layers for an inactive layer, the event regions are
// clipped to the inactive layer's clip prior to being combined into the
// event regions of the containing PLD.
// For the dispatch-to-content and maybe-hit regions, rounded corners on
// the clip are ignored, since these are approximate regions. For the
// remaining regions, rounded corners in the clip cause the region to
// be combined into the corresponding "imprecise" region of the
// containing's PLD (e.g. the maybe-hit region instead of the hit region).
const DisplayItemClip * inactiveLayerClip = mLayerBuilder - > GetInactiveLayerClip ( ) ;
2014-09-26 21:06:08 +04:00
if ( containingPaintedLayerData ) {
2014-07-03 22:40:13 +04:00
if ( ! data - > mDispatchToContentHitRegion . GetBounds ( ) . IsEmpty ( ) ) {
nsRect rect = nsLayoutUtils : : TransformFrameRectToAncestor (
mContainerReferenceFrame ,
data - > mDispatchToContentHitRegion . GetBounds ( ) ,
2014-09-26 21:06:08 +04:00
containingPaintedLayerData - > mReferenceFrame ) ;
2017-04-29 03:32:05 +03:00
if ( inactiveLayerClip ) {
rect = inactiveLayerClip - > ApplyNonRoundedIntersection ( rect ) ;
}
2014-09-26 21:06:08 +04:00
containingPaintedLayerData - > mDispatchToContentHitRegion . Or (
containingPaintedLayerData - > mDispatchToContentHitRegion , rect ) ;
2014-07-03 22:40:13 +04:00
}
if ( ! data - > mMaybeHitRegion . GetBounds ( ) . IsEmpty ( ) ) {
nsRect rect = nsLayoutUtils : : TransformFrameRectToAncestor (
mContainerReferenceFrame ,
data - > mMaybeHitRegion . GetBounds ( ) ,
2014-09-26 21:06:08 +04:00
containingPaintedLayerData - > mReferenceFrame ) ;
2017-04-29 03:32:05 +03:00
if ( inactiveLayerClip ) {
rect = inactiveLayerClip - > ApplyNonRoundedIntersection ( rect ) ;
}
2014-09-26 21:06:08 +04:00
containingPaintedLayerData - > mMaybeHitRegion . Or (
containingPaintedLayerData - > mMaybeHitRegion , rect ) ;
2016-03-16 22:27:19 +03:00
containingPaintedLayerData - > mMaybeHitRegion . SimplifyOutward ( 8 ) ;
2014-07-03 22:40:13 +04:00
}
2016-05-17 18:05:46 +03:00
Maybe < Matrix4x4 > matrixCache ;
2015-03-24 16:13:24 +03:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 18:05:46 +03:00
data - > mHitRegion ,
2015-03-24 16:13:24 +03:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mHitRegion ,
2016-05-17 18:05:46 +03:00
& containingPaintedLayerData - > mMaybeHitRegion ,
2017-04-29 03:32:05 +03:00
& matrixCache ,
inactiveLayerClip ) ;
2016-07-21 02:02:09 +03:00
// See the comment in nsDisplayList::AddFrame, where the touch action regions
// are handled. The same thing applies here.
bool alreadyHadRegions =
! containingPaintedLayerData - > mNoActionRegion . IsEmpty ( ) | |
! containingPaintedLayerData - > mHorizontalPanRegion . IsEmpty ( ) | |
! containingPaintedLayerData - > mVerticalPanRegion . IsEmpty ( ) ;
2015-03-24 16:13:24 +03:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 18:05:46 +03:00
data - > mNoActionRegion ,
2015-03-24 16:13:24 +03:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mNoActionRegion ,
2016-05-17 18:05:46 +03:00
& containingPaintedLayerData - > mDispatchToContentHitRegion ,
2017-04-29 03:32:05 +03:00
& matrixCache ,
inactiveLayerClip ) ;
2015-03-24 16:13:24 +03:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 18:05:46 +03:00
data - > mHorizontalPanRegion ,
2015-03-24 16:13:24 +03:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mHorizontalPanRegion ,
2016-05-17 18:05:46 +03:00
& containingPaintedLayerData - > mDispatchToContentHitRegion ,
2017-04-29 03:32:05 +03:00
& matrixCache ,
inactiveLayerClip ) ;
2015-03-24 16:13:24 +03:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 18:05:46 +03:00
data - > mVerticalPanRegion ,
2015-03-24 16:13:24 +03:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mVerticalPanRegion ,
2016-05-17 18:05:46 +03:00
& containingPaintedLayerData - > mDispatchToContentHitRegion ,
2017-04-29 03:32:05 +03:00
& matrixCache ,
inactiveLayerClip ) ;
2016-07-21 02:02:09 +03:00
if ( alreadyHadRegions ) {
containingPaintedLayerData - > mDispatchToContentHitRegion . OrWith (
containingPaintedLayerData - > CombinedTouchActionRegion ( ) ) ;
}
2013-12-16 16:16:24 +04:00
} else {
2017-08-18 20:06:30 +03:00
EventRegions regions (
ScaleRegionToOutsidePixels ( data - > mHitRegion ) ,
ScaleRegionToOutsidePixels ( data - > mMaybeHitRegion ) ,
ScaleRegionToOutsidePixels ( data - > mDispatchToContentHitRegion ) ,
ScaleRegionToOutsidePixels ( data - > mNoActionRegion ) ,
ScaleRegionToOutsidePixels ( data - > mHorizontalPanRegion ) ,
ScaleRegionToOutsidePixels ( data - > mVerticalPanRegion ) ) ;
2014-06-20 07:56:36 +04:00
2015-05-07 02:18:00 +03:00
Matrix mat = layer - > GetTransform ( ) . As2D ( ) ;
2015-04-14 23:39:00 +03:00
mat . Invert ( ) ;
regions . ApplyTranslationAndScale ( mat . _31 , mat . _32 , mat . _11 , mat . _22 ) ;
2014-06-20 07:56:36 +04:00
2013-12-16 16:16:24 +04:00
layer - > SetEventRegions ( regions ) ;
}
2015-09-17 04:31:00 +03:00
SetBackfaceHiddenForLayer ( data - > mBackfaceHidden , data - > mLayer ) ;
if ( layer ! = data - > mLayer ) {
SetBackfaceHiddenForLayer ( data - > mBackfaceHidden , layer ) ;
}
2010-07-16 01:07:51 +04:00
}
2011-09-29 10:19:26 +04:00
static bool
2014-07-15 08:23:37 +04:00
IsItemAreaInWindowOpaqueRegion ( nsDisplayListBuilder * aBuilder ,
nsDisplayItem * aItem ,
const nsRect & aComponentAlphaBounds )
2011-01-03 04:48:09 +03:00
{
2014-07-15 08:23:37 +04:00
if ( ! aItem - > Frame ( ) - > PresContext ( ) - > IsChrome ( ) ) {
// Assume that Web content is always in the window opaque region.
return true ;
}
if ( aItem - > ReferenceFrame ( ) ! = aBuilder - > RootReferenceFrame ( ) ) {
// aItem is probably in some transformed subtree.
// We're not going to bother figuring out where this landed, we're just
// going to assume it might have landed over a transparent part of
// the window.
2011-10-17 18:59:28 +04:00
return false ;
2011-01-03 04:48:09 +03:00
}
2014-07-15 08:23:37 +04:00
return aBuilder - > GetWindowOpaqueRegion ( ) . Contains ( aComponentAlphaBounds ) ;
2011-01-03 04:48:09 +03:00
}
2010-07-16 01:07:51 +04:00
void
2014-09-26 21:06:08 +04:00
PaintedLayerData : : Accumulate ( ContainerState * aState ,
2013-12-16 16:11:01 +04:00
nsDisplayItem * aItem ,
const nsIntRect & aVisibleRect ,
2015-03-04 08:21:55 +03:00
const DisplayItemClip & aClip ,
2017-09-12 21:14:27 +03:00
LayerState aLayerState ,
nsDisplayList * aList )
2010-07-16 01:07:51 +04:00
{
2014-11-26 21:58:15 +03:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Accumulating dp=%s(%p), f=%p against pld=%p \n " , aItem - > Name ( ) , aItem , aItem - > Frame ( ) , this ) ;
2014-08-22 19:53:24 +04:00
2012-05-03 08:29:05 +04:00
if ( aState - > mBuilder - > NeedToForceTransparentSurfaceForItem ( aItem ) ) {
mForceTransparentSurface = true ;
}
2012-05-03 08:29:05 +04:00
if ( aState - > mParameters . mDisableSubpixelAntialiasingInDescendants ) {
// Disable component alpha.
2014-09-26 21:06:08 +04:00
// Note that the transform (if any) on the PaintedLayer is always an integer translation so
2012-05-03 08:29:05 +04:00
// we don't have to factor that in here.
aItem - > DisableComponentAlpha ( ) ;
}
2012-05-03 08:29:05 +04:00
2014-02-28 23:52:03 +04:00
bool clipMatches = mItemClip = = aClip ;
2012-02-08 02:27:44 +04:00
mItemClip = aClip ;
2011-10-26 07:24:58 +04:00
2015-03-04 08:21:55 +03:00
mAssignedDisplayItems . AppendElement ( AssignedDisplayItem ( aItem , aClip , aLayerState ) ) ;
2017-07-20 12:34:15 +03:00
if ( aItem - > MustPaintOnContentSide ( ) ) {
mShouldPaintOnContentSide = true ;
}
2015-02-18 21:01:40 +03:00
if ( ! mIsSolidColorInVisibleRegion & & mOpaqueRegion . Contains ( aVisibleRect ) & &
2015-06-16 20:41:59 +03:00
mVisibleRegion . Contains ( aVisibleRect ) & & ! mImage ) {
2014-09-26 21:06:08 +04:00
// A very common case! Most pages have a PaintedLayer with the page
2012-05-03 08:29:05 +04:00
// background (opaque) visible and most or all of the page content over the
// top of that background.
2015-02-18 21:01:40 +03:00
// The rest of this method won't do anything. mVisibleRegion and mOpaqueRegion
// don't need updating. mVisibleRegion contains aVisibleRect already,
// mOpaqueRegion contains aVisibleRect and therefore whatever the opaque
// region of the item is. mVisibleRegion must contain mOpaqueRegion
// and therefore aVisibleRect.
2012-05-03 08:29:05 +04:00
return ;
}
2017-09-12 21:14:27 +03:00
nsIntRegion opaquePixels = aState - > ComputeOpaqueRect ( aItem ,
mAnimatedGeometryRoot , mASR , aClip , aList ,
& mHideAllLayersBelow , & mOpaqueForAnimatedGeometryRootParent ) ;
opaquePixels . AndWith ( aVisibleRect ) ;
2014-09-04 09:02:27 +04:00
/* Mark as available for conversion to image layer if this is a nsDisplayImage and
* it ' s the only thing visible in this layer .
*/
2015-06-16 20:41:59 +03:00
if ( nsIntRegion ( aVisibleRect ) . Contains ( mVisibleRegion ) & &
2017-09-12 21:14:27 +03:00
opaquePixels . Contains ( mVisibleRegion ) & &
2014-09-04 09:02:27 +04:00
aItem - > SupportsOptimizingToImage ( ) ) {
mImage = static_cast < nsDisplayImageContainer * > ( aItem ) ;
2014-09-26 21:07:06 +04:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Tracking image: nsDisplayImageContainer covers the layer \n " ) ;
2014-09-04 09:02:27 +04:00
} else if ( mImage ) {
2014-09-26 21:07:06 +04:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " No longer tracking image \n " ) ;
2014-09-04 09:02:27 +04:00
mImage = nullptr ;
}
2014-10-24 20:32:23 +04:00
bool isFirstVisibleItem = mVisibleRegion . IsEmpty ( ) ;
2016-05-19 11:07:52 +03:00
Maybe < nscolor > uniformColor = aItem - > IsUniform ( aState - > mBuilder ) ;
2014-10-20 00:50:29 +04:00
2011-01-16 13:38:45 +03:00
// Some display items have to exist (so they can set forceTransparentSurface
// below) but don't draw anything. They'll return true for isUniform but
// a color with opacity 0.
2016-05-19 11:07:52 +03:00
if ( ! uniformColor | | NS_GET_A ( * uniformColor ) > 0 ) {
2012-04-10 15:24:18 +04:00
// Make sure that the visible area is covered by uniform pixels. In
// particular this excludes cases where the edges of the item are not
// pixel-aligned (thus the item will not be truly uniform).
2016-05-19 11:07:52 +03:00
if ( uniformColor ) {
2012-04-10 15:24:18 +04:00
bool snap ;
nsRect bounds = aItem - > GetBounds ( aState - > mBuilder , & snap ) ;
if ( ! aState - > ScaleToInsidePixels ( bounds , snap ) . Contains ( aVisibleRect ) ) {
2016-05-19 11:07:52 +03:00
uniformColor = Nothing ( ) ;
2014-09-26 21:07:06 +04:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Display item does not cover the visible rect \n " ) ;
2012-04-10 15:24:18 +04:00
}
2014-10-20 00:50:29 +04:00
}
2016-05-19 11:07:52 +03:00
if ( uniformColor ) {
2014-10-24 20:32:23 +04:00
if ( isFirstVisibleItem ) {
2011-01-16 13:38:45 +03:00
// This color is all we have
2016-05-19 11:07:52 +03:00
mSolidColor = * uniformColor ;
2011-10-17 18:59:28 +04:00
mIsSolidColorInVisibleRegion = true ;
2011-01-16 13:38:45 +03:00
} else if ( mIsSolidColorInVisibleRegion & &
2015-06-16 20:41:59 +03:00
mVisibleRegion . IsEqual ( nsIntRegion ( aVisibleRect ) ) & &
2014-02-28 23:52:03 +04:00
clipMatches ) {
2011-01-16 13:38:45 +03:00
// we can just blend the colors together
2016-05-19 11:07:52 +03:00
mSolidColor = NS_ComposeColors ( mSolidColor , * uniformColor ) ;
2011-01-16 13:38:45 +03:00
} else {
2014-09-26 21:07:06 +04:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Layer not a solid color: Can't blend colors togethers \n " ) ;
2011-10-17 18:59:28 +04:00
mIsSolidColorInVisibleRegion = false ;
2011-01-16 13:38:45 +03:00
}
2010-07-16 01:08:03 +04:00
} else {
2014-09-26 21:07:06 +04:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Layer is not a solid color: Display item is not uniform over the visible bound \n " ) ;
2011-10-17 18:59:28 +04:00
mIsSolidColorInVisibleRegion = false ;
2010-07-16 01:08:03 +04:00
}
2015-06-16 20:41:59 +03:00
mVisibleRegion . Or ( mVisibleRegion , aVisibleRect ) ;
mVisibleRegion . SimplifyOutward ( 4 ) ;
2011-01-16 13:38:45 +03:00
}
2014-02-21 05:11:17 +04:00
2017-09-12 21:14:27 +03:00
if ( ! opaquePixels . IsEmpty ( ) ) {
for ( auto iter = opaquePixels . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
2011-01-03 04:48:09 +03:00
// We don't use SimplifyInward here since it's not defined exactly
// what it will discard. For our purposes the most important case
// is a large opaque background at the bottom of z-order (e.g.,
// a canvas background), so we need to make sure that the first rect
// we see doesn't get discarded.
nsIntRegion tmp ;
2016-01-19 04:20:59 +03:00
tmp . Or ( mOpaqueRegion , iter . Get ( ) ) ;
2011-01-03 04:48:09 +03:00
// Opaque display items in chrome documents whose window is partially
// transparent are always added to the opaque region. This helps ensure
// that we get as much subpixel-AA as possible in the chrome.
2014-06-09 08:48:00 +04:00
if ( tmp . GetNumRects ( ) < = 4 | | aItem - > Frame ( ) - > PresContext ( ) - > IsChrome ( ) ) {
2015-09-14 21:18:20 +03:00
mOpaqueRegion = Move ( tmp ) ;
2011-01-03 04:48:09 +03:00
}
2010-07-16 01:08:11 +04:00
}
2011-01-03 04:48:09 +03:00
}
2012-05-03 08:29:05 +04:00
if ( ! aState - > mParameters . mDisableSubpixelAntialiasingInDescendants ) {
2012-01-11 15:26:33 +04:00
nsRect componentAlpha = aItem - > GetComponentAlphaBounds ( aState - > mBuilder ) ;
if ( ! componentAlpha . IsEmpty ( ) ) {
2012-04-10 15:24:18 +04:00
nsIntRect componentAlphaRect =
aState - > ScaleToOutsidePixels ( componentAlpha , false ) . Intersect ( aVisibleRect ) ;
if ( ! mOpaqueRegion . Contains ( componentAlphaRect ) ) {
2014-07-15 08:23:37 +04:00
if ( IsItemAreaInWindowOpaqueRegion ( aState - > mBuilder , aItem ,
componentAlpha . Intersect ( aItem - > GetVisibleRect ( ) ) ) ) {
2014-07-17 19:24:47 +04:00
mNeedComponentAlpha = true ;
2014-07-15 08:23:37 +04:00
} else {
aItem - > DisableComponentAlpha ( ) ;
2012-01-11 15:26:33 +04:00
}
2011-01-03 04:48:09 +03:00
}
2010-09-02 13:18:40 +04:00
}
2010-07-16 01:07:51 +04:00
}
2015-06-27 01:13:50 +03:00
// Ensure animated text does not get flattened, even if it forces other
// content in the container to be layerized. The content backend might
// not support subpixel positioning of text that animated transforms can
// generate. bug 633097
if ( aState - > mParameters . mInActiveTransformedSubtree & &
( mNeedComponentAlpha | |
! aItem - > GetComponentAlphaBounds ( aState - > mBuilder ) . IsEmpty ( ) ) ) {
mDisableFlattening = true ;
}
2010-07-16 01:07:51 +04:00
}
2016-07-21 02:02:09 +03:00
nsRegion
PaintedLayerData : : CombinedTouchActionRegion ( )
{
nsRegion result ;
result . Or ( mHorizontalPanRegion , mVerticalPanRegion ) ;
result . OrWith ( mNoActionRegion ) ;
return result ;
}
2015-09-01 02:59:22 +03:00
void
2015-09-01 02:53:34 +03:00
PaintedLayerData : : AccumulateEventRegions ( ContainerState * aState , nsDisplayLayerEventRegions * aEventRegions )
2015-09-01 02:59:22 +03:00
{
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Accumulating event regions %p against pld=%p \n " , aEventRegions , this ) ;
2016-07-21 02:02:09 +03:00
mHitRegion . OrWith ( aEventRegions - > HitRegion ( ) ) ;
mMaybeHitRegion . OrWith ( aEventRegions - > MaybeHitRegion ( ) ) ;
mDispatchToContentHitRegion . OrWith ( aEventRegions - > DispatchToContentHitRegion ( ) ) ;
// See the comment in nsDisplayList::AddFrame, where the touch action regions
// are handled. The same thing applies here.
bool alreadyHadRegions = ! mNoActionRegion . IsEmpty ( ) | |
! mHorizontalPanRegion . IsEmpty ( ) | |
! mVerticalPanRegion . IsEmpty ( ) ;
mNoActionRegion . OrWith ( aEventRegions - > NoActionRegion ( ) ) ;
mHorizontalPanRegion . OrWith ( aEventRegions - > HorizontalPanRegion ( ) ) ;
mVerticalPanRegion . OrWith ( aEventRegions - > VerticalPanRegion ( ) ) ;
if ( alreadyHadRegions ) {
mDispatchToContentHitRegion . OrWith ( CombinedTouchActionRegion ( ) ) ;
}
2015-09-01 02:53:34 +03:00
2017-05-13 03:28:12 +03:00
// Avoid quadratic performance as a result of the region growing to include
// and arbitrarily large number of rects, which can happen on some pages.
mMaybeHitRegion . SimplifyOutward ( 8 ) ;
2015-09-04 19:14:28 +03:00
// Calculate scaled versions of the bounds of mHitRegion and mMaybeHitRegion
// for quick access in FindPaintedLayerFor().
mScaledHitRegionBounds = aState - > ScaleToOutsidePixels ( mHitRegion . GetBounds ( ) ) ;
mScaledMaybeHitRegionBounds = aState - > ScaleToOutsidePixels ( mMaybeHitRegion . GetBounds ( ) ) ;
2015-09-01 02:59:22 +03:00
}
2015-04-02 21:22:40 +03:00
PaintedLayerData
ContainerState : : NewPaintedLayerData ( nsDisplayItem * aItem ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * aASR ,
const DisplayItemClipChain * aClipChain ,
const ActiveScrolledRoot * aScrollMetadataASR ,
const nsPoint & aTopLeft )
2014-12-30 17:39:39 +03:00
{
2015-06-16 20:41:59 +03:00
PaintedLayerData data ;
data . mAnimatedGeometryRoot = aAnimatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
data . mASR = aASR ;
2017-04-10 07:11:45 +03:00
data . mClipChain = aClipChain ;
2015-06-16 20:41:59 +03:00
data . mAnimatedGeometryRootOffset = aTopLeft ;
2015-04-02 21:22:40 +03:00
data . mReferenceFrame = aItem - > ReferenceFrame ( ) ;
2016-02-09 01:34:13 +03:00
data . mBackfaceHidden = aItem - > Frame ( ) - > In3DContextAndBackfaceIsHidden ( ) ;
2015-04-02 21:22:40 +03:00
data . mNewChildLayersIndex = mNewChildLayers . Length ( ) ;
NewLayerEntry * newLayerEntry = mNewChildLayers . AppendElement ( ) ;
newLayerEntry - > mAnimatedGeometryRoot = aAnimatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
newLayerEntry - > mASR = aASR ;
newLayerEntry - > mScrollMetadataASR = aScrollMetadataASR ;
2017-04-10 07:11:45 +03:00
newLayerEntry - > mClipChain = aClipChain ;
2015-04-02 21:22:40 +03:00
// newLayerEntry->mOpaqueRegion is filled in later from
// paintedLayerData->mOpaqueRegion, if necessary.
// Allocate another entry for this layer's optimization to ColorLayer/ImageLayer
mNewChildLayers . AppendElement ( ) ;
2014-12-30 17:39:39 +03:00
2015-04-02 21:22:40 +03:00
return data ;
2010-07-16 01:07:51 +04:00
}
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
static void
2014-06-27 15:19:40 +04:00
DumpPaintedImage ( nsDisplayItem * aItem , SourceSurface * aSurface )
2012-03-05 22:09:05 +04:00
{
nsCString string ( aItem - > Name ( ) ) ;
2014-05-22 07:48:52 +04:00
string . Append ( ' - ' ) ;
2012-08-22 19:56:38 +04:00
string . AppendInt ( ( uint64_t ) aItem ) ;
2015-09-26 02:23:13 +03:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " <script>array[ \" %s \" ]= \" " , string . BeginReading ( ) ) ;
2014-06-27 15:19:40 +04:00
gfxUtils : : DumpAsDataURI ( aSurface , gfxUtils : : sDumpPaintFile ) ;
2015-09-26 02:23:13 +03:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " \" ;</script> \n " ) ;
2012-03-05 22:09:05 +04:00
}
# endif
2011-02-10 11:58:11 +03:00
static void
PaintInactiveLayer ( nsDisplayListBuilder * aBuilder ,
2012-08-29 09:47:15 +04:00
LayerManager * aManager ,
2011-02-10 11:58:11 +03:00
nsDisplayItem * aItem ,
2012-07-17 21:03:51 +04:00
gfxContext * aContext ,
2017-06-09 22:14:53 +03:00
gfxContext * aCtx )
2010-08-03 07:33:24 +04:00
{
2014-09-26 21:06:08 +04:00
// This item has an inactive layer. Render it to a PaintedLayer
2011-02-10 11:58:11 +03:00
// using a temporary BasicLayerManager.
2012-08-29 09:47:15 +04:00
BasicLayerManager * basic = static_cast < BasicLayerManager * > ( aManager ) ;
2015-10-18 08:24:48 +03:00
RefPtr < gfxContext > context = aContext ;
2012-08-29 09:47:15 +04:00
# ifdef MOZ_DUMP_PAINTING
2012-08-22 19:56:38 +04:00
int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel ( aItem ) ;
2012-03-05 22:09:05 +04:00
nsIntRect itemVisibleRect =
aItem - > GetVisibleRect ( ) . ToOutsidePixels ( appUnitsPerDevPixel ) ;
2015-10-18 08:24:48 +03:00
RefPtr < DrawTarget > tempDT ;
2015-10-28 16:31:00 +03:00
if ( gfxEnv : : DumpPaint ( ) ) {
2014-06-27 15:19:40 +04:00
tempDT = gfxPlatform : : GetPlatform ( ) - > CreateOffscreenContentDrawTarget (
2015-03-29 17:59:08 +03:00
itemVisibleRect . Size ( ) ,
2014-06-27 15:19:40 +04:00
SurfaceFormat : : B8G8R8A8 ) ;
2015-03-09 22:48:20 +03:00
if ( tempDT ) {
2016-06-07 02:39:56 +03:00
context = gfxContext : : CreateOrNull ( tempDT ) ;
2016-04-12 22:18:11 +03:00
if ( ! context ) {
// Leave this as crash, it's in the debugging code, we want to know
gfxDevCrash ( LogReason : : InvalidContext ) < < " PaintInactive context problem " < < gfx : : hexa ( tempDT ) ;
return ;
}
2015-03-09 22:48:20 +03:00
context - > SetMatrix ( gfxMatrix : : Translation ( - itemVisibleRect . x ,
- itemVisibleRect . y ) ) ;
}
2012-03-05 22:09:05 +04:00
}
# endif
2013-11-06 23:10:49 +04:00
basic - > BeginTransaction ( ) ;
2012-08-29 09:47:15 +04:00
basic - > SetTarget ( context ) ;
2012-03-05 22:09:05 +04:00
2017-08-07 07:07:43 +03:00
if ( aItem - > GetType ( ) = = DisplayItemType : : TYPE_MASK ) {
2016-08-09 22:02:45 +03:00
static_cast < nsDisplayMask * > ( aItem ) - > PaintAsLayer ( aBuilder , aCtx , basic ) ;
2012-08-29 09:47:15 +04:00
if ( basic - > InTransaction ( ) ) {
basic - > AbortTransaction ( ) ;
2012-07-20 08:53:55 +04:00
}
2017-08-07 07:07:43 +03:00
} else if ( aItem - > GetType ( ) = = DisplayItemType : : TYPE_FILTER ) {
2016-09-01 06:14:00 +03:00
static_cast < nsDisplayFilter * > ( aItem ) - > PaintAsLayer ( aBuilder , aCtx , basic ) ;
if ( basic - > InTransaction ( ) ) {
basic - > AbortTransaction ( ) ;
}
2012-07-17 21:03:51 +04:00
} else {
2014-09-26 21:06:08 +04:00
basic - > EndTransaction ( FrameLayerBuilder : : DrawPaintedLayer , aBuilder ) ;
2012-08-29 09:47:15 +04:00
}
FrameLayerBuilder * builder = static_cast < FrameLayerBuilder * > ( basic - > GetUserData ( & gLayerManagerLayerBuilder ) ) ;
if ( builder ) {
builder - > DidEndTransaction ( ) ;
2012-07-17 21:03:51 +04:00
}
2012-10-23 15:05:14 +04:00
2012-11-09 10:01:24 +04:00
basic - > SetTarget ( nullptr ) ;
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
2015-10-28 16:31:00 +03:00
if ( gfxEnv : : DumpPaint ( ) & & tempDT ) {
2015-10-18 08:24:48 +03:00
RefPtr < SourceSurface > surface = tempDT - > Snapshot ( ) ;
2014-06-27 15:19:40 +04:00
DumpPaintedImage ( aItem , surface ) ;
DrawTarget * drawTarget = aContext - > GetDrawTarget ( ) ;
Rect rect ( itemVisibleRect . x , itemVisibleRect . y ,
itemVisibleRect . width , itemVisibleRect . height ) ;
drawTarget - > DrawSurface ( surface , rect , Rect ( Point ( 0 , 0 ) , rect . Size ( ) ) ) ;
2012-07-31 21:28:21 +04:00
2012-03-05 22:09:05 +04:00
aItem - > SetPainted ( ) ;
}
# endif
2010-08-03 07:33:24 +04:00
}
2012-12-04 10:05:22 +04:00
/**
* Chooses a single active scrolled root for the entire display list , used
* when we are flattening layers .
*/
2012-12-12 00:36:22 +04:00
bool
2013-09-26 01:07:26 +04:00
ContainerState : : ChooseAnimatedGeometryRoot ( const nsDisplayList & aList ,
2017-02-01 01:07:35 +03:00
AnimatedGeometryRoot * * aAnimatedGeometryRoot ,
const ActiveScrolledRoot * * aASR )
2012-12-04 10:05:22 +04:00
{
for ( nsDisplayItem * item = aList . GetBottom ( ) ; item ; item = item - > GetAbove ( ) ) {
2012-12-12 00:36:22 +04:00
LayerState layerState = item - > GetLayerState ( mBuilder , mManager , mParameters ) ;
2014-09-26 21:06:08 +04:00
// Don't use an item that won't be part of any PaintedLayers to pick the
2012-12-12 00:36:22 +04:00
// active scrolled root.
if ( layerState = = LAYER_ACTIVE_FORCE ) {
continue ;
}
// Try using the actual active scrolled root of the backmost item, as that
// should result in the least invalidation when scrolling.
2015-11-25 01:53:51 +03:00
* aAnimatedGeometryRoot = item - > GetAnimatedGeometryRoot ( ) ;
2017-02-01 01:07:35 +03:00
* aASR = item - > GetActiveScrolledRoot ( ) ;
2013-09-27 10:01:16 +04:00
return true ;
2012-12-04 10:05:22 +04:00
}
2012-12-12 00:36:22 +04:00
return false ;
2012-12-04 10:05:22 +04:00
}
2017-03-04 18:18:00 +03:00
nsRect
ContainerState : : GetDisplayPortForAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
{
if ( mLastDisplayPortAGR = = aAnimatedGeometryRoot ) {
return mLastDisplayPortRect ;
}
2017-04-19 06:39:17 +03:00
mLastDisplayPortAGR = aAnimatedGeometryRoot ;
2017-03-04 18:18:00 +03:00
nsIScrollableFrame * sf = nsLayoutUtils : : GetScrollableFrameFor ( * aAnimatedGeometryRoot ) ;
2017-04-21 05:02:15 +03:00
if ( sf = = nullptr | | nsLayoutUtils : : UsesAsyncScrolling ( * aAnimatedGeometryRoot ) ) {
2017-04-19 06:39:17 +03:00
mLastDisplayPortRect = nsRect ( ) ;
return mLastDisplayPortRect ;
2017-03-04 18:18:00 +03:00
}
bool usingDisplayport =
2017-04-19 06:39:17 +03:00
nsLayoutUtils : : GetDisplayPort ( ( * aAnimatedGeometryRoot ) - > GetContent ( ) , & mLastDisplayPortRect ,
2017-03-04 18:18:00 +03:00
RelativeTo : : ScrollFrame ) ;
if ( ! usingDisplayport ) {
// No async scrolling, so all that matters is that the layer contents
// cover the scrollport.
2017-04-19 06:39:17 +03:00
mLastDisplayPortRect = sf - > GetScrollPortRect ( ) ;
2017-03-04 18:18:00 +03:00
}
nsIFrame * scrollFrame = do_QueryFrame ( sf ) ;
2017-04-19 06:39:17 +03:00
mLastDisplayPortRect + = scrollFrame - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
return mLastDisplayPortRect ;
2017-03-04 18:18:00 +03:00
}
2014-06-23 08:24:00 +04:00
nsIntRegion
ContainerState : : ComputeOpaqueRect ( nsDisplayItem * aItem ,
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2017-04-21 05:03:40 +03:00
const ActiveScrolledRoot * aASR ,
2014-06-23 08:24:00 +04:00
const DisplayItemClip & aClip ,
nsDisplayList * aList ,
2014-08-31 07:29:24 +04:00
bool * aHideAllLayersBelow ,
bool * aOpaqueForAnimatedGeometryRootParent )
2014-06-23 08:24:00 +04:00
{
bool snapOpaque ;
nsRegion opaque = aItem - > GetOpaqueRegion ( mBuilder , & snapOpaque ) ;
2016-03-10 03:56:52 +03:00
if ( opaque . IsEmpty ( ) ) {
return nsIntRegion ( ) ;
}
2014-06-23 08:24:00 +04:00
nsIntRegion opaquePixels ;
2016-03-10 03:56:52 +03:00
nsRegion opaqueClipped ;
for ( auto iter = opaque . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
opaqueClipped . Or ( opaqueClipped ,
aClip . ApproximateIntersectInward ( iter . Get ( ) ) ) ;
}
if ( aAnimatedGeometryRoot = = mContainerAnimatedGeometryRoot & &
2017-04-21 05:03:40 +03:00
aASR = = mContainerASR & &
2016-03-10 03:56:52 +03:00
opaqueClipped . Contains ( mContainerBounds ) ) {
* aHideAllLayersBelow = true ;
aList - > SetIsOpaque ( ) ;
}
// Add opaque areas to the "exclude glass" region. Only do this when our
// container layer is going to be the rootmost layer, otherwise transforms
// etc will mess us up (and opaque contributions from other containers are
// not needed).
if ( ! nsLayoutUtils : : GetCrossDocParentFrame ( mContainerFrame ) ) {
mBuilder - > AddWindowOpaqueRegion ( opaqueClipped ) ;
}
opaquePixels = ScaleRegionToInsidePixels ( opaqueClipped , snapOpaque ) ;
if ( IsInInactiveLayer ( ) ) {
return opaquePixels ;
}
2017-03-04 18:18:00 +03:00
const nsRect & displayport =
GetDisplayPortForAnimatedGeometryRoot ( aAnimatedGeometryRoot ) ;
if ( ! displayport . IsEmpty ( ) & &
opaquePixels . Contains ( ScaleRegionToNearestPixels ( displayport ) ) ) {
* aOpaqueForAnimatedGeometryRootParent = true ;
2014-06-23 08:24:00 +04:00
}
return opaquePixels ;
}
2016-05-07 02:02:26 +03:00
Maybe < size_t >
ContainerState : : SetupMaskLayerForScrolledClip ( Layer * aLayer ,
const DisplayItemClip & aClip )
{
if ( aClip . GetRoundedRectCount ( ) > 0 ) {
Maybe < size_t > maskLayerIndex = Some ( aLayer - > GetAncestorMaskLayerCount ( ) ) ;
if ( RefPtr < Layer > maskLayer = CreateMaskLayer ( aLayer , aClip , maskLayerIndex ,
aClip . GetRoundedRectCount ( ) ) ) {
aLayer - > AddAncestorMaskLayer ( maskLayer ) ;
return maskLayerIndex ;
}
// Fall through to |return Nothing()|.
}
return Nothing ( ) ;
}
2017-02-01 01:07:35 +03:00
static const ActiveScrolledRoot *
GetASRForPerspective ( const ActiveScrolledRoot * aASR , nsIFrame * aPerspectiveFrame )
{
for ( const ActiveScrolledRoot * asr = aASR ; asr ; asr = asr - > mParent ) {
nsIFrame * scrolledFrame = asr - > mScrollableFrame - > GetScrolledFrame ( ) ;
if ( nsLayoutUtils : : IsAncestorFrameCrossDoc ( scrolledFrame , aPerspectiveFrame ) ) {
return asr ;
}
}
return nullptr ;
}
2017-08-10 09:02:01 +03:00
void
SetCSSMaskLayerUserData ( Layer * aMaskLayer )
{
aMaskLayer - > SetUserData ( & gCSSMaskLayerUserData ,
new CSSMaskLayerUserData ( ) ) ;
}
2016-11-07 17:32:43 +03:00
void
ContainerState : : SetupMaskLayerForCSSMask ( Layer * aLayer ,
nsDisplayMask * aMaskItem )
{
MOZ_ASSERT ( mManager - > IsCompositingCheap ( ) ) ;
RefPtr < ImageLayer > maskLayer =
CreateOrRecycleMaskImageLayerFor ( MaskLayerKey ( aLayer , Nothing ( ) ) ,
2017-08-10 09:02:01 +03:00
SetCSSMaskLayerUserData ) ;
2016-11-07 17:32:43 +03:00
CSSMaskLayerUserData * oldUserData =
static_cast < CSSMaskLayerUserData * > ( maskLayer - > GetUserData ( & gCSSMaskLayerUserData ) ) ;
bool snap ;
nsRect bounds = aMaskItem - > GetBounds ( mBuilder , & snap ) ;
2016-11-11 21:18:28 +03:00
nsIntRect itemRect = ScaleToOutsidePixels ( bounds , snap ) ;
2016-12-19 17:33:36 +03:00
// Setup mask layer offset.
// We do not repaint mask for mask position change, so update base transform
// each time is required.
Matrix4x4 matrix ;
matrix . PreTranslate ( itemRect . x , itemRect . y , 0 ) ;
matrix . PreTranslate ( mParameters . mOffset . x , mParameters . mOffset . y , 0 ) ;
maskLayer - > SetBaseTransform ( matrix ) ;
Bug 1350663 - Repaint mask layer when the offset between mask region and mask layer changed. r=mstange
Let's said we have a div,
<div id="outer" style="width:200px, height:200px;
mask="url(opaque-200X100-transparent-200X100.png)"">
<div id="innter" style="position:fixed;
left:0px; top:0px; width:200px; height:100px;
mask-repeat: no-repeat;
background-color: blue;"></div>
</div>
Some hints:
1. '#inner' is out-of-flow
2. '#outer' itself does not draw any things, no background/ border, etc....
3. Mask applied on '#outer'.
4. opaque-100X200-transparent-100X200.png is a 200X200 image. The upper side of
this image is opaque; the lower side of this image is transparent.
After page load, you will see a 200X100 blue rect on left-top corner. This blue
rect is contributed by 200X100 blue '#inner' and 200X100 opaque upper part of
mask. So far so good.
Then you scroll down 100px. '#inner' is not moved, since it's an out-of-flow
element, mask move up 100px with '#outter'. Ideally, you should see nothing in
the view, since '#inner' is now masked by transparent part of the image mask.
On FF, you will still see a 200X100 blue rect in view as if no scrolling at all,
which is wrong.
Here is the root cause of this bug:
1. At beginning, we create a 200X100 mask layer, which fit the size of '#inner'.
Not 200X200 of '#outer', since '#outer' basically draw nothing, we smartly
choose a more compact draw target for painting the mask.
2. Things go wrong after scrolling down. By scroll down 100px, the size of the
mask layer is still "200X100", so we _think_ cached mask layer is still
reusable, but it is not.
Before scrolling, we paint (0, 0, 200, 100) portion of the 200X200 mask onto
mask layer; after scrolling, we should paint (0, _100_, 200, 100) portion of
mask onto mask layer. We did not keep this kind of offset information in
CSSMaskLayerUserData, so we don't know that the cached mask layer should be
rejected.
It's difficult to create a reftest for this bug as well. With scrollTo, we may
mimic an environment of this error, but since reftest harness will trigger
whole viewport repaint while taking a snapshot, we actually can not repro this
issue on it.
MozReview-Commit-ID: H5xaUSssMRh
--HG--
extra : rebase_source : 47103b6638e50dd2fb39f7b47e9cdc653446cd20
2017-05-14 14:28:01 +03:00
nsPoint maskLayerOffset = aMaskItem - > ToReferenceFrame ( ) - bounds . TopLeft ( ) ;
2017-07-06 15:00:35 +03:00
Bug 1350663 - Repaint mask layer when the offset between mask region and mask layer changed. r=mstange
Let's said we have a div,
<div id="outer" style="width:200px, height:200px;
mask="url(opaque-200X100-transparent-200X100.png)"">
<div id="innter" style="position:fixed;
left:0px; top:0px; width:200px; height:100px;
mask-repeat: no-repeat;
background-color: blue;"></div>
</div>
Some hints:
1. '#inner' is out-of-flow
2. '#outer' itself does not draw any things, no background/ border, etc....
3. Mask applied on '#outer'.
4. opaque-100X200-transparent-100X200.png is a 200X200 image. The upper side of
this image is opaque; the lower side of this image is transparent.
After page load, you will see a 200X100 blue rect on left-top corner. This blue
rect is contributed by 200X100 blue '#inner' and 200X100 opaque upper part of
mask. So far so good.
Then you scroll down 100px. '#inner' is not moved, since it's an out-of-flow
element, mask move up 100px with '#outter'. Ideally, you should see nothing in
the view, since '#inner' is now masked by transparent part of the image mask.
On FF, you will still see a 200X100 blue rect in view as if no scrolling at all,
which is wrong.
Here is the root cause of this bug:
1. At beginning, we create a 200X100 mask layer, which fit the size of '#inner'.
Not 200X200 of '#outer', since '#outer' basically draw nothing, we smartly
choose a more compact draw target for painting the mask.
2. Things go wrong after scrolling down. By scroll down 100px, the size of the
mask layer is still "200X100", so we _think_ cached mask layer is still
reusable, but it is not.
Before scrolling, we paint (0, 0, 200, 100) portion of the 200X200 mask onto
mask layer; after scrolling, we should paint (0, _100_, 200, 100) portion of
mask onto mask layer. We did not keep this kind of offset information in
CSSMaskLayerUserData, so we don't know that the cached mask layer should be
rejected.
It's difficult to create a reftest for this bug as well. With scrollTo, we may
mimic an environment of this error, but since reftest harness will trigger
whole viewport repaint while taking a snapshot, we actually can not repro this
issue on it.
MozReview-Commit-ID: H5xaUSssMRh
--HG--
extra : rebase_source : 47103b6638e50dd2fb39f7b47e9cdc653446cd20
2017-05-14 14:28:01 +03:00
CSSMaskLayerUserData newUserData ( aMaskItem - > Frame ( ) , itemRect , maskLayerOffset ) ;
2016-11-15 07:26:21 +03:00
nsRect dirtyRect ;
2017-05-26 20:38:54 +03:00
if ( ! aMaskItem - > IsInvalid ( dirtyRect ) & & * oldUserData = = newUserData ) {
2016-11-07 17:32:43 +03:00
aLayer - > SetMaskLayer ( maskLayer ) ;
return ;
}
2016-11-11 21:18:28 +03:00
int32_t maxSize = mManager - > GetMaxTextureSize ( ) ;
IntSize surfaceSize ( std : : min ( itemRect . width , maxSize ) ,
std : : min ( itemRect . height , maxSize ) ) ;
2016-11-07 17:32:43 +03:00
2016-11-11 21:18:28 +03:00
if ( surfaceSize . IsEmpty ( ) ) {
2016-12-17 06:06:44 +03:00
// Return early if we know that the size of this mask surface is empty.
2016-11-07 17:32:43 +03:00
return ;
}
2016-11-11 21:18:28 +03:00
MaskImageData imageData ( surfaceSize , mManager ) ;
2016-11-07 17:32:43 +03:00
RefPtr < DrawTarget > dt = imageData . CreateDrawTarget ( ) ;
if ( ! dt | | ! dt - > IsValid ( ) ) {
NS_WARNING ( " Could not create DrawTarget for mask layer. " ) ;
return ;
}
2016-10-30 10:43:43 +03:00
RefPtr < gfxContext > maskCtx = gfxContext : : CreateOrNull ( dt ) ;
2016-11-11 21:18:28 +03:00
maskCtx - > SetMatrix ( gfxMatrix : : Translation ( - itemRect . TopLeft ( ) ) ) ;
maskCtx - > Multiply ( gfxMatrix : : Scaling ( mParameters . mXScale , mParameters . mYScale ) ) ;
2016-10-30 10:43:43 +03:00
2017-05-31 09:38:25 +03:00
bool isPaintFinished = aMaskItem - > PaintMask ( mBuilder , maskCtx ) ;
2016-10-30 10:43:43 +03:00
2016-11-07 17:32:43 +03:00
RefPtr < ImageContainer > imgContainer =
imageData . CreateImageAndImageContainer ( ) ;
if ( ! imgContainer ) {
return ;
}
maskLayer - > SetContainer ( imgContainer ) ;
2017-05-31 09:38:25 +03:00
if ( isPaintFinished ) {
* oldUserData = Move ( newUserData ) ;
}
2016-11-07 17:32:43 +03:00
aLayer - > SetMaskLayer ( maskLayer ) ;
}
2017-05-30 01:05:05 +03:00
static bool
IsScrollThumbLayer ( nsDisplayItem * aItem )
{
2017-08-07 07:07:43 +03:00
return aItem - > GetType ( ) = = DisplayItemType : : TYPE_OWN_LAYER & &
2017-05-30 01:05:05 +03:00
static_cast < nsDisplayOwnLayer * > ( aItem ) - > IsScrollThumbLayer ( ) ;
}
2010-07-16 01:07:51 +04:00
/*
* Iterate through the non - clip items in aList and its descendants .
* For each item we compute the effective clip rect . Each item is assigned
2014-09-26 21:06:08 +04:00
* to a layer . We invalidate the areas in PaintedLayers where an item
* has moved from one PaintedLayer to another . Also ,
2014-09-26 21:07:06 +04:00
* aState - > mInvalidPaintedContent is invalidated in every PaintedLayer .
2012-02-08 02:27:44 +04:00
* We set the clip rect for items that generated their own layer , and
* create a mask layer to do any rounded rect clipping .
2014-09-26 21:06:08 +04:00
* ( PaintedLayers don ' t need a clip rect on the layer , we clip the items
2010-07-16 01:07:51 +04:00
* individually when we draw them . )
* We set the visible rect for all layers , although the actual setting
2014-09-26 21:06:08 +04:00
* of visible rects for some PaintedLayers is deferred until the calling
2010-07-16 01:07:51 +04:00
* of ContainerState : : Finish .
*/
void
2014-09-06 08:16:33 +04:00
ContainerState : : ProcessDisplayItems ( nsDisplayList * aList )
2010-07-16 01:07:51 +04:00
{
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
AUTO_PROFILER_LABEL ( " ContainerState::ProcessDisplayItems " , GRAPHICS ) ;
2012-10-12 03:38:25 +04:00
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * lastAnimatedGeometryRoot = mContainerAnimatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * lastASR = mContainerASR ;
2016-09-08 06:39:04 +03:00
nsPoint lastAGRTopLeft ;
2014-02-18 08:00:35 +04:00
nsPoint topLeft ( 0 , 0 ) ;
2012-10-12 03:38:25 +04:00
2012-12-04 10:05:22 +04:00
// When NO_COMPONENT_ALPHA is set, items will be flattened into a single
// layer, so we need to choose which active scrolled root to use for all
// items.
2014-09-06 08:16:33 +04:00
if ( mFlattenToSingleLayer ) {
2017-02-01 01:07:35 +03:00
if ( ChooseAnimatedGeometryRoot ( * aList , & lastAnimatedGeometryRoot , & lastASR ) ) {
2016-09-08 06:39:04 +03:00
lastAGRTopLeft = ( * lastAnimatedGeometryRoot ) - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2012-12-04 10:05:22 +04:00
}
}
2016-03-04 20:13:57 +03:00
int32_t maxLayers = gfxPrefs : : MaxActiveLayers ( ) ;
2013-07-17 00:17:18 +04:00
int layerCount = 0 ;
2017-10-17 05:16:28 +03:00
FlattenedDisplayItemIterator iter ( mBuilder , aList ) ;
while ( nsDisplayItem * i = iter . GetNext ( ) ) {
2017-08-25 13:34:40 +03:00
nsDisplayItem * item = i ;
MOZ_ASSERT ( item ) ;
2017-08-07 07:07:43 +03:00
DisplayItemType itemType = item - > GetType ( ) ;
2016-06-03 17:20:38 +03:00
// If the item is a event regions item, but is empty (has no regions in it)
// then we should just throw it out
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_LAYER_EVENT_REGIONS ) {
2016-06-03 17:20:38 +03:00
nsDisplayLayerEventRegions * eventRegions =
static_cast < nsDisplayLayerEventRegions * > ( item ) ;
2017-08-23 22:01:28 +03:00
2016-06-03 17:20:38 +03:00
if ( eventRegions - > IsEmpty ( ) ) {
continue ;
}
}
2017-08-23 22:01:28 +03:00
// Peek ahead to the next item and see if it can be merged with the current
// item. We create a list of consecutive items that can be merged together.
AutoTArray < nsDisplayItem * , 1 > mergedItems ;
mergedItems . AppendElement ( item ) ;
2017-10-17 05:16:28 +03:00
while ( nsDisplayItem * peek = iter . PeekNext ( ) ) {
2017-08-23 22:01:28 +03:00
if ( ! item - > CanMerge ( peek ) ) {
2014-06-09 08:48:00 +04:00
break ;
}
2017-08-23 22:01:28 +03:00
mergedItems . AppendElement ( peek ) ;
// Move the iterator forward since we will merge this item.
2017-10-17 05:16:28 +03:00
i = iter . GetNext ( ) ;
2017-08-23 22:01:28 +03:00
}
if ( mergedItems . Length ( ) > 1 ) {
// We have items that can be merged together. Merge them into a temporary
// item and process that item immediately.
item = mBuilder - > MergeItems ( mergedItems ) ;
MOZ_ASSERT ( item & & itemType = = item - > GetType ( ) ) ;
2014-06-09 08:48:00 +04:00
}
2017-08-25 13:34:40 +03:00
MOZ_ASSERT ( item - > GetType ( ) ! = DisplayItemType : : TYPE_WRAP_LIST ) ;
2014-06-09 08:48:00 +04:00
2012-04-10 15:24:18 +04:00
NS_ASSERTION ( mAppUnitsPerDevPixel = = AppUnitsPerDevPixel ( item ) ,
2010-08-08 22:49:07 +04:00
" items in a container layer should all have the same app units per dev pixel " ) ;
2014-08-20 19:25:19 +04:00
if ( mBuilder - > NeedToForceTransparentSurfaceForItem ( item ) ) {
aList - > SetNeedsTransparentSurface ( ) ;
}
2016-08-10 06:15:28 +03:00
if ( mParameters . mForEventsAndPluginsOnly & & ! item - > GetChildren ( ) & &
2017-08-07 07:07:43 +03:00
( itemType ! = DisplayItemType : : TYPE_LAYER_EVENT_REGIONS & &
itemType ! = DisplayItemType : : TYPE_PLUGIN ) ) {
2015-11-11 05:09:21 +03:00
continue ;
}
2015-07-03 00:00:17 +03:00
LayerState layerState = item - > GetLayerState ( mBuilder , mManager , mParameters ) ;
if ( layerState = = LAYER_INACTIVE & &
nsDisplayItem : : ForceActiveLayers ( ) ) {
layerState = LAYER_ACTIVE ;
}
bool forceInactive ;
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * animatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * itemASR = nullptr ;
const DisplayItemClipChain * layerClipChain = nullptr ;
2016-08-25 05:25:57 +03:00
if ( mFlattenToSingleLayer & & layerState ! = LAYER_ACTIVE_FORCE ) {
2015-07-03 00:00:17 +03:00
forceInactive = true ;
2017-10-17 05:16:28 +03:00
animatedGeometryRoot = lastAnimatedGeometryRoot ;
itemASR = lastASR ;
topLeft = lastAGRTopLeft ;
2017-02-01 01:07:35 +03:00
item - > FuseClipChainUpTo ( mBuilder , mContainerASR ) ;
2015-07-03 00:00:17 +03:00
} else {
forceInactive = false ;
if ( mManager - > IsWidgetLayerManager ( ) ) {
2015-12-22 18:54:19 +03:00
animatedGeometryRoot = item - > GetAnimatedGeometryRoot ( ) ;
2017-02-01 01:07:35 +03:00
itemASR = item - > GetActiveScrolledRoot ( ) ;
const DisplayItemClipChain * itemClipChain = item - > GetClipChain ( ) ;
2016-08-26 00:06:49 +03:00
if ( itemClipChain & & itemClipChain - > mASR = = itemASR & &
2017-08-07 07:07:43 +03:00
itemType ! = DisplayItemType : : TYPE_STICKY_POSITION ) {
2017-02-01 01:07:35 +03:00
layerClipChain = itemClipChain - > mParent ;
} else {
layerClipChain = itemClipChain ;
}
2015-07-03 00:00:17 +03:00
} else {
// For inactive layer subtrees, splitting content into PaintedLayers
// based on animated geometry roots is pointless. It's more efficient
// to build the minimum number of layers.
animatedGeometryRoot = mContainerAnimatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
itemASR = mContainerASR ;
item - > FuseClipChainUpTo ( mBuilder , mContainerASR ) ;
2015-07-03 00:00:17 +03:00
}
2017-10-17 05:16:28 +03:00
topLeft = ( * animatedGeometryRoot ) - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2015-07-03 00:00:17 +03:00
}
2016-05-17 00:20:23 +03:00
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * scrollMetadataASR =
layerClipChain ? ActiveScrolledRoot : : PickDescendant ( itemASR , layerClipChain - > mASR ) : itemASR ;
2015-09-12 03:00:22 +03:00
2012-04-10 15:24:18 +04:00
bool snap ;
nsRect itemContent = item - > GetBounds ( mBuilder , & snap ) ;
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_LAYER_EVENT_REGIONS ) {
2015-02-12 02:06:47 +03:00
nsDisplayLayerEventRegions * eventRegions =
static_cast < nsDisplayLayerEventRegions * > ( item ) ;
itemContent = eventRegions - > GetHitRegionBounds ( mBuilder , & snap ) ;
}
2012-04-13 15:44:05 +04:00
nsIntRect itemDrawRect = ScaleToOutsidePixels ( itemContent , snap ) ;
2017-08-07 07:07:43 +03:00
bool prerenderedTransform = itemType = = DisplayItemType : : TYPE_TRANSFORM & &
2016-05-18 06:12:44 +03:00
static_cast < nsDisplayTransform * > ( item ) - > MayBeAnimated ( mBuilder ) ;
2015-04-12 05:03:00 +03:00
ParentLayerIntRect clipRect ;
2013-03-04 13:56:02 +04:00
const DisplayItemClip & itemClip = item - > GetClip ( ) ;
if ( itemClip . HasClip ( ) ) {
itemContent . IntersectRect ( itemContent , itemClip . GetClipRect ( ) ) ;
2015-04-12 05:03:00 +03:00
clipRect = ViewAs < ParentLayerPixel > ( ScaleToNearestPixels ( itemClip . GetClipRect ( ) ) ) ;
2017-08-01 02:09:53 +03:00
if ( ! prerenderedTransform & & ! IsScrollThumbLayer ( item ) ) {
2015-11-07 06:13:40 +03:00
itemDrawRect . IntersectRect ( itemDrawRect , clipRect . ToUnknownRect ( ) ) ;
2014-07-29 16:09:35 +04:00
}
2015-04-12 05:03:00 +03:00
clipRect . MoveBy ( ViewAs < ParentLayerPixel > ( mParameters . mOffset ) ) ;
2010-08-02 07:06:58 +04:00
}
2014-06-09 08:48:00 +04:00
# ifdef DEBUG
2015-02-12 02:06:47 +03:00
nsRect bounds = itemContent ;
bool dummy ;
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_LAYER_EVENT_REGIONS ) {
2015-02-12 02:06:47 +03:00
bounds = item - > GetBounds ( mBuilder , & dummy ) ;
if ( itemClip . HasClip ( ) ) {
bounds . IntersectRect ( bounds , itemClip . GetClipRect ( ) ) ;
}
}
2016-02-22 18:17:16 +03:00
if ( ! bounds . IsEmpty ( ) ) {
2017-02-01 01:07:35 +03:00
if ( itemASR ! = mContainerASR ) {
const DisplayItemClip * clip = DisplayItemClipChain : : ClipForASR ( item - > GetClipChain ( ) , mContainerASR ) ;
2017-01-27 19:38:55 +03:00
MOZ_ASSERT ( clip | | gfxPrefs : : LayoutUseContainersForRootFrames ( ) ,
" the item should have finite bounds with respect to mContainerASR. " ) ;
2017-02-01 01:07:35 +03:00
if ( clip ) {
bounds = clip - > GetClipRect ( ) ;
2016-02-22 18:17:16 +03:00
}
2015-12-22 18:54:19 +03:00
}
}
2015-02-12 02:06:47 +03:00
( ( nsRect & ) mAccumulatedChildBounds ) . UnionRect ( mAccumulatedChildBounds , bounds ) ;
2014-06-09 08:48:00 +04:00
# endif
2015-09-25 15:40:52 +03:00
nsIntRect itemVisibleRect = itemDrawRect ;
2016-05-17 00:14:29 +03:00
// We haven't computed visibility at this point, so item->GetVisibleRect()
// is just the dirty rect that item was initialized with. We intersect it
// with the clipped item bounds to get a tighter visible rect.
2017-06-22 03:41:36 +03:00
if ( ! prerenderedTransform ) {
itemVisibleRect = itemVisibleRect . Intersect (
ScaleToOutsidePixels ( item - > GetVisibleRect ( ) , false ) ) ;
}
2012-04-10 15:24:18 +04:00
2017-10-17 05:16:28 +03:00
if ( maxLayers ! = - 1 & & layerCount > = maxLayers ) {
2013-07-17 00:17:18 +04:00
forceInactive = true ;
}
2010-07-16 01:07:51 +04:00
// Assign the item to a layer
2011-03-16 02:20:19 +03:00
if ( layerState = = LAYER_ACTIVE_FORCE | |
2012-11-14 02:22:21 +04:00
( layerState = = LAYER_INACTIVE & & ! mManager - > IsWidgetLayerManager ( ) ) | |
2012-07-23 07:00:36 +04:00
( ! forceInactive & &
( layerState = = LAYER_ACTIVE_EMPTY | |
layerState = = LAYER_ACTIVE ) ) ) {
2011-04-14 01:12:22 +04:00
2017-10-17 05:16:28 +03:00
layerCount + + ;
2013-07-17 00:17:18 +04:00
2011-04-14 01:12:22 +04:00
// LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
// We should never see an empty layer with any visible content!
NS_ASSERTION ( layerState ! = LAYER_ACTIVE_EMPTY | |
2011-10-26 06:55:51 +04:00
itemVisibleRect . IsEmpty ( ) ,
2011-04-14 01:12:22 +04:00
" State is LAYER_ACTIVE_EMPTY but visible rect is not. " ) ;
2014-09-26 21:06:08 +04:00
// As long as the new layer isn't going to be a PaintedLayer,
2012-10-12 06:39:46 +04:00
// InvalidateForLayerChange doesn't need the new layer pointer.
// We also need to check the old data now, because BuildLayer
// can overwrite it.
2014-07-23 10:03:24 +04:00
InvalidateForLayerChange ( item , nullptr ) ;
2012-10-12 06:39:46 +04:00
2010-07-16 01:08:09 +04:00
// If the item would have its own layer but is invisible, just hide it.
// Note that items without their own layers can't be skipped this
2014-09-26 21:06:08 +04:00
// way, since their PaintedLayer may decide it wants to draw them
2010-07-16 01:08:09 +04:00
// into its buffer even if they're currently covered.
2013-03-19 17:08:29 +04:00
if ( itemVisibleRect . IsEmpty ( ) & &
! item - > ShouldBuildLayerEvenIfInvisible ( mBuilder ) ) {
2010-07-16 01:08:09 +04:00
continue ;
}
2015-02-25 19:47:22 +03:00
// 3D-transformed layers don't necessarily draw in the order in which
// they're added to their parent container layer.
2017-08-07 07:07:43 +03:00
bool mayDrawOutOfOrder = itemType = = DisplayItemType : : TYPE_TRANSFORM & &
2015-09-17 04:31:00 +03:00
( item - > Frame ( ) - > Combines3DTransformWithAncestors ( ) | |
item - > Frame ( ) - > Extend3DContext ( ) ) ;
2015-02-25 19:47:22 +03:00
2015-04-02 21:22:40 +03:00
// Let mPaintedLayerDataTree know about this item, so that
// FindPaintedLayerFor and FindOpaqueBackgroundColor are aware of this
// item, even though it's not in any PaintedLayerDataStack.
// Ideally we'd only need the "else" case here and have
// mPaintedLayerDataTree figure out the right clip from the animated
// geometry root that we give it, but it can't easily figure about
// overflow:hidden clips on ancestors just by looking at the frame.
// So we'll do a little hand holding and pass the clip instead of the
// visible rect for the two important cases.
nscolor uniformColor = NS_RGBA ( 0 , 0 , 0 , 0 ) ;
2016-03-10 03:56:52 +03:00
nscolor * uniformColorPtr = ( mayDrawOutOfOrder | | IsInInactiveLayer ( ) ) ? nullptr :
& uniformColor ;
2015-04-12 05:03:00 +03:00
nsIntRect clipRectUntyped ;
2015-10-28 20:46:40 +03:00
nsIntRect * clipPtr = nullptr ;
2017-02-01 01:07:35 +03:00
if ( itemClip . HasClip ( ) ) {
clipRectUntyped = clipRect . ToUnknownRect ( ) ;
2015-10-28 20:46:40 +03:00
clipPtr = & clipRectUntyped ;
2015-04-12 05:03:00 +03:00
}
2017-02-01 01:07:35 +03:00
bool hasScrolledClip = layerClipChain & & layerClipChain - > mClip . HasClip ( ) & &
2016-08-26 00:06:49 +03:00
( ! ActiveScrolledRoot : : IsAncestor ( layerClipChain - > mASR , itemASR ) | |
2017-08-07 07:07:43 +03:00
itemType = = DisplayItemType : : TYPE_STICKY_POSITION ) ;
2017-02-01 01:07:35 +03:00
if ( hasScrolledClip ) {
// If the clip is scrolled, reserve just the area of the clip for
// layerization, so that elements outside the clip can still merge
// into the same layer.
const ActiveScrolledRoot * clipASR = layerClipChain - > mASR ;
AnimatedGeometryRoot * clipAGR = mBuilder - > AnimatedGeometryRootForASR ( clipASR ) ;
nsIntRect scrolledClipRect =
ScaleToNearestPixels ( layerClipChain - > mClip . GetClipRect ( ) ) + mParameters . mOffset ;
mPaintedLayerDataTree . AddingOwnLayer ( clipAGR ,
& scrolledClipRect ,
uniformColorPtr ) ;
} else if ( item - > ShouldFixToViewport ( mBuilder ) & & itemClip . HasClip ( ) & &
2017-02-03 21:41:37 +03:00
item - > AnimatedGeometryRootForScrollMetadata ( ) ! = animatedGeometryRoot & &
! nsLayoutUtils : : UsesAsyncScrolling ( item - > Frame ( ) ) ) {
2017-02-01 01:07:35 +03:00
// This is basically the same as the case above, but for the non-APZ
// case. At the moment, when APZ is off, there is only the root ASR
// (because scroll frames without display ports don't create ASRs) and
// the whole clip chain is always just one fused clip.
2017-02-03 21:41:37 +03:00
// Bug 1336516 aims to change that and to remove this workaround.
2017-02-01 01:07:35 +03:00
AnimatedGeometryRoot * clipAGR = item - > AnimatedGeometryRootForScrollMetadata ( ) ;
nsIntRect scrolledClipRect =
ScaleToNearestPixels ( itemClip . GetClipRect ( ) ) + mParameters . mOffset ;
mPaintedLayerDataTree . AddingOwnLayer ( clipAGR ,
& scrolledClipRect ,
uniformColorPtr ) ;
2017-06-09 23:26:47 +03:00
} else if ( IsScrollThumbLayer ( item ) & & mManager - > IsWidgetLayerManager ( ) ) {
// For scrollbar thumbs, the clip we care about is the clip added by the
// slider frame.
2015-11-25 01:53:51 +03:00
mPaintedLayerDataTree . AddingOwnLayer ( animatedGeometryRoot - > mParentAGR ,
2016-03-07 23:50:35 +03:00
clipPtr ,
uniformColorPtr ) ;
2017-06-09 23:26:47 +03:00
} else if ( prerenderedTransform & & mManager - > IsWidgetLayerManager ( ) ) {
if ( animatedGeometryRoot - > mParentAGR ) {
mPaintedLayerDataTree . AddingOwnLayer ( animatedGeometryRoot - > mParentAGR ,
clipPtr ,
uniformColorPtr ) ;
} else {
mPaintedLayerDataTree . AddingOwnLayer ( animatedGeometryRoot ,
nullptr ,
uniformColorPtr ) ;
}
2015-04-02 21:22:40 +03:00
} else {
// Using itemVisibleRect here isn't perfect. itemVisibleRect can be
// larger or smaller than the potential bounds of item's contents in
// animatedGeometryRoot: It's too large if there's a clipped display
// port somewhere among item's contents (see bug 1147673), and it can
// be too small if the contents can move, because it only looks at the
// contents' current bounds and doesn't anticipate any animations.
// Time will tell whether this is good enough, or whether we need to do
// something more sophisticated here.
mPaintedLayerDataTree . AddingOwnLayer ( animatedGeometryRoot ,
& itemVisibleRect , uniformColorPtr ) ;
}
2016-03-08 22:43:15 +03:00
ContainerLayerParameters params = mParameters ;
params . mBackgroundColor = uniformColor ;
2016-03-08 22:43:32 +03:00
params . mLayerCreationHint = GetLayerCreationHint ( animatedGeometryRoot ) ;
2017-02-01 01:07:35 +03:00
params . mScrollMetadataASR = ActiveScrolledRoot : : PickDescendant ( mContainerScrollMetadataASR , scrollMetadataASR ) ;
params . mCompositorASR = params . mScrollMetadataASR ! = mContainerScrollMetadataASR
? params . mScrollMetadataASR
: mContainerCompositorASR ;
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_FIXED_POSITION ) {
2017-02-01 01:07:35 +03:00
params . mCompositorASR = itemASR ;
}
2016-02-26 03:29:41 +03:00
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_PERSPECTIVE ) {
2016-02-26 03:29:41 +03:00
// Perspective items have a single child item, an nsDisplayTransform.
// If the perspective item is scrolled, but the perspective-inducing
2017-02-01 01:07:35 +03:00
// frame is outside the scroll frame (indicated by item->Frame()
2016-02-26 03:29:41 +03:00
// being outside that scroll frame), we have to take special care to
// make APZ scrolling work properly. APZ needs us to put the scroll
// frame's FrameMetrics on our child transform ContainerLayer instead.
2017-02-01 01:07:35 +03:00
// It's worth investigating whether this ASR adjustment can be done at
// display item creation time.
scrollMetadataASR = GetASRForPerspective ( scrollMetadataASR , item - > Frame ( ) ) ;
params . mScrollMetadataASR = scrollMetadataASR ;
itemASR = scrollMetadataASR ;
2016-02-26 03:29:41 +03:00
}
2015-02-25 19:47:22 +03:00
2010-07-16 01:08:05 +04:00
// Just use its layer.
2014-07-11 05:17:47 +04:00
// Set layerContentsVisibleRect.width/height to -1 to indicate we
// currently don't know. If BuildContainerLayerFor gets called by
// item->BuildLayer, this will be set to a proper rect.
2014-06-23 08:24:00 +04:00
nsIntRect layerContentsVisibleRect ( 0 , 0 , - 1 , - 1 ) ;
2016-03-08 22:43:15 +03:00
params . mLayerContentsVisibleRect = & layerContentsVisibleRect ;
RefPtr < Layer > ownLayer = item - > BuildLayer ( mBuilder , mManager , params ) ;
2010-07-16 01:08:05 +04:00
if ( ! ownLayer ) {
continue ;
}
2014-09-26 21:06:08 +04:00
NS_ASSERTION ( ! ownLayer - > AsPaintedLayer ( ) ,
2014-09-26 21:07:06 +04:00
" Should never have created a dedicated Painted layer! " ) ;
2012-10-12 06:39:46 +04:00
2015-09-17 04:31:00 +03:00
if ( item - > BackfaceIsHidden ( ) ) {
ownLayer - > SetContentFlags ( ownLayer - > GetContentFlags ( ) |
Layer : : CONTENT_BACKFACE_HIDDEN ) ;
} else {
ownLayer - > SetContentFlags ( ownLayer - > GetContentFlags ( ) &
~ Layer : : CONTENT_BACKFACE_HIDDEN ) ;
}
2012-08-29 09:48:45 +04:00
nsRect invalid ;
if ( item - > IsInvalid ( invalid ) ) {
2012-08-29 09:47:18 +04:00
ownLayer - > SetInvalidRectToVisibleRegion ( ) ;
}
2011-06-22 16:11:27 +04:00
// If it's not a ContainerLayer, we need to apply the scale transform
// ourselves.
if ( ! ownLayer - > AsContainerLayer ( ) ) {
2012-08-04 01:29:22 +04:00
ownLayer - > SetPostScale ( mParameters . mXScale ,
mParameters . mYScale ) ;
2011-06-22 16:11:27 +04:00
}
2010-07-16 01:08:05 +04:00
// Update that layer's clip and visible rects.
2010-07-16 01:07:51 +04:00
NS_ASSERTION ( ownLayer - > Manager ( ) = = mManager , " Wrong manager " ) ;
2010-09-02 13:18:39 +04:00
NS_ASSERTION ( ! ownLayer - > HasUserData ( & gLayerManagerUserData ) ,
2010-07-16 01:07:51 +04:00
" We shouldn't have a FrameLayerBuilder-managed layer here! " ) ;
2017-02-01 01:07:35 +03:00
NS_ASSERTION ( itemClip . HasClip ( ) | |
itemClip . GetRoundedRectCount ( ) = = 0 ,
2012-01-20 00:21:41 +04:00
" If we have rounded rects, we must have a clip rect " ) ;
2016-05-07 02:02:26 +03:00
2010-07-16 01:07:51 +04:00
// It has its own layer. Update that layer's clip and visible rects.
2016-05-07 02:02:26 +03:00
ownLayer - > SetClipRect ( Nothing ( ) ) ;
ownLayer - > SetScrolledClip ( Nothing ( ) ) ;
2017-02-01 01:07:35 +03:00
ownLayer - > SetAncestorMaskLayers ( { } ) ;
if ( itemClip . HasClip ( ) ) {
ownLayer - > SetClipRect ( Some ( clipRect ) ) ;
2016-08-03 20:48:10 +03:00
2017-02-01 01:07:35 +03:00
// rounded rectangle clipping using mask layers
// (must be done after visible rect is set on layer)
if ( itemClip . GetRoundedRectCount ( ) > 0 ) {
SetupMaskLayer ( ownLayer , itemClip ) ;
2016-05-07 02:02:26 +03:00
}
2016-12-19 13:07:39 +03:00
}
2017-02-01 01:07:35 +03:00
if ( hasScrolledClip ) {
const DisplayItemClip & scrolledClip = layerClipChain - > mClip ;
LayerClip scrolledLayerClip ;
scrolledLayerClip . SetClipRect ( ViewAs < ParentLayerPixel > (
ScaleToNearestPixels ( scrolledClip . GetClipRect ( ) ) + mParameters . mOffset ) ) ;
if ( scrolledClip . GetRoundedRectCount ( ) > 0 ) {
scrolledLayerClip . SetMaskLayerIndex (
SetupMaskLayerForScrolledClip ( ownLayer . get ( ) , scrolledClip ) ) ;
2016-05-07 02:02:26 +03:00
}
2017-02-01 01:07:35 +03:00
ownLayer - > SetScrolledClip ( Some ( scrolledLayerClip ) ) ;
2016-12-19 13:07:39 +03:00
}
2017-08-07 07:07:43 +03:00
if ( item - > GetType ( ) = = DisplayItemType : : TYPE_MASK ) {
2017-02-01 01:07:35 +03:00
MOZ_ASSERT ( itemClip . GetRoundedRectCount ( ) = = 0 ) ;
2016-12-19 13:07:39 +03:00
2016-10-30 10:43:43 +03:00
nsDisplayMask * maskItem = static_cast < nsDisplayMask * > ( item ) ;
SetupMaskLayerForCSSMask ( ownLayer , maskItem ) ;
2016-12-15 17:20:33 +03:00
2017-10-17 05:16:28 +03:00
if ( iter . PeekNext ( ) & &
iter . PeekNext ( ) - > GetType ( ) = = DisplayItemType : : TYPE_SCROLL_INFO_LAYER ) {
2016-12-15 17:20:33 +03:00
// Since we do build a layer for mask, there is no need for this
// scroll info layer anymore.
2017-10-17 05:16:28 +03:00
i = iter . GetNext ( ) ;
2016-12-15 17:20:33 +03:00
}
2012-02-08 02:27:44 +04:00
}
2016-11-24 08:11:30 +03:00
// Convert the visible rect to a region and give the item
// a chance to try restrict it further.
nsIntRegion itemVisibleRegion = itemVisibleRect ;
nsRegion tightBounds = item - > GetTightBounds ( mBuilder , & snap ) ;
if ( ! tightBounds . IsEmpty ( ) ) {
itemVisibleRegion . AndWith ( ScaleToOutsidePixels ( tightBounds , snap ) ) ;
}
2010-07-16 01:07:51 +04:00
ContainerLayer * oldContainer = ownLayer - > GetParent ( ) ;
if ( oldContainer & & oldContainer ! = mContainerLayer ) {
oldContainer - > RemoveChild ( ownLayer ) ;
}
2014-06-23 08:24:00 +04:00
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , ownLayer ) < 0 ,
2010-07-16 01:07:51 +04:00
" Layer already in list??? " ) ;
2010-07-16 01:08:05 +04:00
2014-06-23 08:24:00 +04:00
NewLayerEntry * newLayerEntry = mNewChildLayers . AppendElement ( ) ;
newLayerEntry - > mLayer = ownLayer ;
newLayerEntry - > mAnimatedGeometryRoot = animatedGeometryRoot ;
2017-02-01 01:07:35 +03:00
newLayerEntry - > mASR = itemASR ;
newLayerEntry - > mScrollMetadataASR = scrollMetadataASR ;
newLayerEntry - > mClipChain = layerClipChain ;
2016-01-14 02:42:27 +03:00
newLayerEntry - > mLayerState = layerState ;
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_FIXED_POSITION ) {
2017-02-01 01:07:35 +03:00
newLayerEntry - > mIsFixedToRootScrollFrame =
item - > Frame ( ) - > StyleDisplay ( ) - > mPosition = = NS_STYLE_POSITION_FIXED & &
nsLayoutUtils : : IsReallyFixedPos ( item - > Frame ( ) ) ;
}
2014-07-23 02:53:37 +04:00
// Don't attempt to flatten compnent alpha layers that are within
// a forced active layer, or an active transform;
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_TRANSFORM | |
2014-07-23 02:53:37 +04:00
layerState = = LAYER_ACTIVE_FORCE ) {
newLayerEntry - > mPropagateComponentAlphaFlattening = false ;
}
2017-06-14 04:48:28 +03:00
float contentXScale = 1.0f ;
float contentYScale = 1.0f ;
if ( ContainerLayer * ownContainer = ownLayer - > AsContainerLayer ( ) ) {
contentXScale = 1 / ownContainer - > GetPreXScale ( ) ;
contentYScale = 1 / ownContainer - > GetPreYScale ( ) ;
}
2014-07-11 05:17:47 +04:00
// nsDisplayTransform::BuildLayer must set layerContentsVisibleRect.
// We rely on this to ensure 3D transforms compute a reasonable
// layer visible region.
2017-08-07 07:07:43 +03:00
NS_ASSERTION ( itemType ! = DisplayItemType : : TYPE_TRANSFORM | |
2014-07-11 05:17:47 +04:00
layerContentsVisibleRect . width > = 0 ,
" Transform items must set layerContentsVisibleRect! " ) ;
2014-06-23 08:24:00 +04:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
newLayerEntry - > mLayerContentsVisibleRect = layerContentsVisibleRect ;
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_PERSPECTIVE | |
( itemType = = DisplayItemType : : TYPE_TRANSFORM & &
2015-11-26 12:32:36 +03:00
( item - > Frame ( ) - > Extend3DContext ( ) | |
item - > Frame ( ) - > Combines3DTransformWithAncestors ( ) | |
item - > Frame ( ) - > HasPerspective ( ) ) ) ) {
2015-09-17 04:31:00 +03:00
// Give untransformed visible region as outer visible region
// to avoid failure caused by singular transforms.
newLayerEntry - > mUntransformedVisibleRegion = true ;
newLayerEntry - > mVisibleRegion =
2017-06-14 04:48:28 +03:00
item - > GetVisibleRectForChildren ( ) . ScaleToOutsidePixels ( contentXScale , contentYScale , mAppUnitsPerDevPixel ) ;
2015-09-17 04:31:00 +03:00
} else {
2016-11-24 08:11:30 +03:00
newLayerEntry - > mVisibleRegion = itemVisibleRegion ;
2015-09-17 04:31:00 +03:00
}
2014-06-23 08:24:00 +04:00
newLayerEntry - > mOpaqueRegion = ComputeOpaqueRect ( item ,
2017-04-21 05:03:40 +03:00
animatedGeometryRoot , itemASR , itemClip , aList ,
2014-08-31 07:29:24 +04:00
& newLayerEntry - > mHideAllLayersBelow ,
& newLayerEntry - > mOpaqueForAnimatedGeometryRootParent ) ;
2014-06-23 08:24:00 +04:00
} else {
2015-09-17 04:31:00 +03:00
bool useChildrenVisible =
2017-08-07 07:07:43 +03:00
itemType = = DisplayItemType : : TYPE_TRANSFORM & &
2016-04-28 08:05:46 +03:00
( item - > Frame ( ) - > IsPreserve3DLeaf ( ) | |
item - > Frame ( ) - > HasPerspective ( ) ) ;
2015-09-17 04:31:00 +03:00
const nsIntRegion & visible = useChildrenVisible ?
2017-06-14 04:48:28 +03:00
item - > GetVisibleRectForChildren ( ) . ScaleToOutsidePixels ( contentXScale , contentYScale , mAppUnitsPerDevPixel ) :
2016-11-24 08:11:30 +03:00
itemVisibleRegion ;
2015-09-17 04:31:00 +03:00
SetOuterVisibleRegionForLayer ( ownLayer , visible ,
layerContentsVisibleRect . width > = 0 ? & layerContentsVisibleRect : nullptr ,
useChildrenVisible ) ;
2014-06-23 08:24:00 +04:00
}
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_SCROLL_INFO_LAYER ) {
2015-04-21 06:48:10 +03:00
nsDisplayScrollInfoLayer * scrollItem = static_cast < nsDisplayScrollInfoLayer * > ( item ) ;
newLayerEntry - > mOpaqueForAnimatedGeometryRootParent = false ;
2016-03-29 02:14:52 +03:00
newLayerEntry - > mBaseScrollMetadata =
scrollItem - > ComputeScrollMetadata ( ownLayer , mParameters ) ;
2017-08-07 07:07:43 +03:00
} else if ( ( itemType = = DisplayItemType : : TYPE_SUBDOCUMENT | |
itemType = = DisplayItemType : : TYPE_ZOOM | |
itemType = = DisplayItemType : : TYPE_RESOLUTION ) & &
2014-12-18 02:37:28 +03:00
gfxPrefs : : LayoutUseContainersForRootFrames ( ) )
{
2016-03-29 02:14:52 +03:00
newLayerEntry - > mBaseScrollMetadata =
static_cast < nsDisplaySubDocument * > ( item ) - > ComputeScrollMetadata ( ownLayer , mParameters ) ;
2014-06-23 08:24:00 +04:00
}
2012-10-17 12:00:00 +04:00
/**
* No need to allocate geometry for items that aren ' t
2014-09-26 21:06:08 +04:00
* part of a PaintedLayer .
2012-10-17 12:00:00 +04:00
*/
2015-12-16 08:24:06 +03:00
mLayerBuilder - > AddLayerDisplayItem ( ownLayer , item , layerState , nullptr ) ;
2010-05-21 07:20:48 +04:00
} else {
2014-09-26 21:06:08 +04:00
PaintedLayerData * paintedLayerData =
2017-02-01 01:07:35 +03:00
mPaintedLayerDataTree . FindPaintedLayerFor ( animatedGeometryRoot , itemASR , layerClipChain ,
2016-06-02 23:44:32 +03:00
itemVisibleRect ,
2016-02-09 01:34:13 +03:00
item - > Frame ( ) - > In3DContextAndBackfaceIsHidden ( ) ,
2015-09-17 04:31:00 +03:00
[ & ] ( ) {
2017-02-01 01:07:35 +03:00
return NewPaintedLayerData ( item , animatedGeometryRoot , itemASR , layerClipChain , scrollMetadataASR ,
2017-10-17 05:16:28 +03:00
topLeft ) ;
2015-04-02 21:22:40 +03:00
} ) ;
2013-12-16 16:16:24 +04:00
2017-08-07 07:07:43 +03:00
if ( itemType = = DisplayItemType : : TYPE_LAYER_EVENT_REGIONS ) {
2013-12-16 16:16:24 +04:00
nsDisplayLayerEventRegions * eventRegions =
static_cast < nsDisplayLayerEventRegions * > ( item ) ;
2015-09-01 02:53:34 +03:00
paintedLayerData - > AccumulateEventRegions ( this , eventRegions ) ;
2013-12-16 16:16:24 +04:00
} else {
// check to see if the new item has rounded rect clips in common with
// other items in the layer
2015-03-04 01:00:55 +03:00
if ( mManager - > IsWidgetLayerManager ( ) ) {
paintedLayerData - > UpdateCommonClipCount ( itemClip ) ;
}
2017-09-12 21:14:27 +03:00
paintedLayerData - > Accumulate ( this , item , itemVisibleRect , itemClip , layerState , aList ) ;
2017-04-14 09:59:49 +03:00
if ( ! paintedLayerData - > mLayer ) {
// Try to recycle the old layer of this display item.
RefPtr < PaintedLayer > layer =
2017-10-17 05:16:28 +03:00
AttemptToRecyclePaintedLayer ( animatedGeometryRoot , item , topLeft ) ;
2017-04-14 09:59:49 +03:00
if ( layer ) {
paintedLayerData - > mLayer = layer ;
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , layer ) < 0 ,
" Layer already in list??? " ) ;
mNewChildLayers [ paintedLayerData - > mNewChildLayersIndex ] . mLayer = layer . forget ( ) ;
}
2015-03-04 08:18:47 +03:00
}
2014-07-17 19:24:47 +04:00
}
2014-06-09 08:48:00 +04:00
}
2014-06-09 08:48:00 +04:00
2017-10-17 05:16:28 +03:00
nsDisplayList * childItems = item - > GetSameCoordinateSystemChildren ( ) ;
2017-08-25 13:34:40 +03:00
if ( childItems & & childItems - > NeedsTransparentSurface ( ) ) {
2014-06-09 08:48:00 +04:00
aList - > SetNeedsTransparentSurface ( ) ;
}
2010-05-21 07:20:48 +04:00
}
}
2010-07-16 01:08:05 +04:00
void
2014-09-26 21:06:08 +04:00
ContainerState : : InvalidateForLayerChange ( nsDisplayItem * aItem , PaintedLayer * aNewLayer )
2010-07-16 01:08:05 +04:00
{
2012-10-10 09:00:05 +04:00
NS_ASSERTION ( aItem - > GetPerFrameKey ( ) ,
" Display items that render using Thebes must have a key " ) ;
2014-07-23 10:03:24 +04:00
nsDisplayItemGeometry * oldGeometry = nullptr ;
2013-10-08 22:47:21 +04:00
DisplayItemClip * oldClip = nullptr ;
2014-07-23 10:03:24 +04:00
Layer * oldLayer = mLayerBuilder - > GetOldLayerFor ( aItem , & oldGeometry , & oldClip ) ;
2012-08-29 09:47:15 +04:00
if ( aNewLayer ! = oldLayer & & oldLayer ) {
2010-07-16 01:08:05 +04:00
// The item has changed layers.
2012-09-28 15:19:39 +04:00
// Invalidate the old bounds in the old layer and new bounds in the new layer.
2014-09-26 21:06:08 +04:00
PaintedLayer * t = oldLayer - > AsPaintedLayer ( ) ;
2014-07-23 10:03:24 +04:00
if ( t & & oldGeometry ) {
2011-06-22 16:11:27 +04:00
// Note that whenever the layer's scale changes, we invalidate the whole thing,
// so it doesn't matter whether we are using the old scale at last paint
// or a new scale here
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Display item type %s(%p) changed layers %p to %p! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , t , aNewLayer ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
2011-06-22 16:11:27 +04:00
InvalidatePostTransformRegion ( t ,
2012-10-16 05:10:43 +04:00
oldGeometry - > ComputeInvalidationRegion ( ) ,
* oldClip ,
2012-07-17 21:03:51 +04:00
mLayerBuilder - > GetLastPaintOffset ( t ) ) ;
2010-07-16 01:08:05 +04:00
}
2014-07-23 10:03:24 +04:00
// Clear the old geometry so that invalidation thinks the item has been
// added this paint.
mLayerBuilder - > ClearCachedGeometry ( aItem ) ;
2012-12-10 09:34:31 +04:00
aItem - > NotifyRenderingChanged ( ) ;
2012-08-29 09:47:15 +04:00
}
2014-07-23 10:03:24 +04:00
}
2010-07-16 01:08:05 +04:00
2014-07-23 10:03:24 +04:00
void
FrameLayerBuilder : : ComputeGeometryChangeForItem ( DisplayItemData * aData )
{
nsDisplayItem * item = aData - > mItem ;
2014-09-26 21:06:08 +04:00
PaintedLayer * paintedLayer = aData - > mLayer - > AsPaintedLayer ( ) ;
2017-04-21 10:27:48 +03:00
// If aData->mOptLayer is presence, means this item has been optimized to the separate
// layer. Thus, skip geometry change calculation.
if ( aData - > mOptLayer | | ! item | | ! paintedLayer ) {
2014-07-23 10:03:24 +04:00
aData - > EndUpdate ( ) ;
2012-08-29 09:47:15 +04:00
return ;
}
2017-09-29 00:58:54 +03:00
// If we're a reused display item, then we can't be invalid, so no need to
// do an in-depth comparison. If we haven't previously stored geometry
// for this item (if it was an active layer), then we can't skip this
// yet.
2015-11-06 06:57:47 +03:00
nsAutoPtr < nsDisplayItemGeometry > geometry ;
2017-09-29 00:58:54 +03:00
if ( item - > IsReused ( ) & & aData - > mGeometry ) {
aData - > EndUpdate ( geometry ) ;
return ;
}
2014-07-23 10:03:24 +04:00
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * layerData =
static_cast < PaintedDisplayItemLayerUserData * > ( aData - > mLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2014-07-23 10:03:24 +04:00
nsPoint shift = layerData - > mAnimatedGeometryRootOrigin - layerData - > mLastAnimatedGeometryRootOrigin ;
const DisplayItemClip & clip = item - > GetClip ( ) ;
2015-11-06 06:57:47 +03:00
// If the frame is marked as invalidated, and didn't specify a rect to invalidate then we want to
2012-08-29 09:48:45 +04:00
// invalidate both the old and new bounds, otherwise we only want to invalidate the changed areas.
// If we do get an invalid rect, then we want to add this on top of the change areas.
nsRect invalid ;
2012-08-29 09:47:15 +04:00
nsRegion combined ;
2014-04-24 06:56:15 +04:00
bool notifyRenderingChanged = true ;
2014-07-23 10:03:24 +04:00
if ( ! aData - > mGeometry ) {
2012-08-29 09:48:43 +04:00
// This item is being added for the first time, invalidate its entire area.
2015-11-06 06:57:47 +03:00
geometry = item - > AllocateGeometry ( mDisplayListBuilder ) ;
2014-07-23 10:03:24 +04:00
combined = clip . ApplyNonRoundedIntersection ( geometry - > ComputeInvalidationRegion ( ) ) ;
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2014-07-23 10:03:24 +04:00
printf_stderr ( " Display item type %s(%p) added to layer %p! \n " , item - > Name ( ) , item - > Frame ( ) , aData - > mLayer . get ( ) ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
2014-07-23 10:03:24 +04:00
} else if ( aData - > mIsInvalid | | ( item - > IsInvalid ( invalid ) & & invalid . IsEmpty ( ) ) ) {
2015-11-06 06:57:47 +03:00
// Layout marked item/frame as needing repainting (without an explicit rect), invalidate the entire old and new areas.
geometry = item - > AllocateGeometry ( mDisplayListBuilder ) ;
2014-07-23 10:03:24 +04:00
combined = aData - > mClip . ApplyNonRoundedIntersection ( aData - > mGeometry - > ComputeInvalidationRegion ( ) ) ;
2012-10-16 05:10:43 +04:00
combined . MoveBy ( shift ) ;
2014-07-23 10:03:24 +04:00
combined . Or ( combined , clip . ApplyNonRoundedIntersection ( geometry - > ComputeInvalidationRegion ( ) ) ) ;
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2014-07-23 10:03:24 +04:00
printf_stderr ( " Display item type %s(%p) (in layer %p) belongs to an invalidated frame! \n " , item - > Name ( ) , item - > Frame ( ) , aData - > mLayer . get ( ) ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
} else {
2012-08-29 09:48:44 +04:00
// Let the display item check for geometry changes and decide what needs to be
2012-08-29 09:48:43 +04:00
// repainted.
2014-04-24 06:56:15 +04:00
2017-03-21 03:07:49 +03:00
const nsRegion & changedFrameInvalidations = aData - > GetChangedFrameInvalidations ( ) ;
2015-11-06 06:57:47 +03:00
aData - > mGeometry - > MoveBy ( shift ) ;
item - > ComputeInvalidationRegion ( mDisplayListBuilder , aData - > mGeometry , & combined ) ;
2014-07-23 10:03:24 +04:00
2015-11-06 06:57:47 +03:00
// We have an optimization to cache the drawing of background-attachment: fixed canvas
2014-04-24 06:56:15 +04:00
// background images so we can scroll and just blit them when they are flattened into
// the same layer as scrolling content. NotifyRenderingChanged is only used to tell
// the canvas bg image item to purge this cache. We want to be careful not to accidentally
// purge the cache if we are just invalidating due to scrolling (ie the background image
// moves on the scrolling layer but it's rendering stays the same) so if
// AddOffsetAndComputeDifference is the only thing that will invalidate we skip the
// NotifyRenderingChanged call (ComputeInvalidationRegion for background images also calls
// NotifyRenderingChanged if anything changes).
2016-02-09 06:05:20 +03:00
// Only allocate a new geometry object if something actually changed, otherwise the existing
// one should be fine. We always reallocate for inactive layers, since these types don't
// implement ComputeInvalidateRegion (and rely on the ComputeDifferences call in
// AddPaintedDisplayItem instead).
if ( ! combined . IsEmpty ( ) | | aData - > mLayerState = = LAYER_INACTIVE ) {
2015-11-06 06:57:47 +03:00
geometry = item - > AllocateGeometry ( mDisplayListBuilder ) ;
2017-03-21 03:07:49 +03:00
} else if ( aData - > mClip = = clip & & invalid . IsEmpty ( ) & &
changedFrameInvalidations . IsEmpty ( ) = = 0 ) {
2014-04-24 06:56:15 +04:00
notifyRenderingChanged = false ;
}
2017-06-17 01:06:04 +03:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . GetEntry ( paintedLayer ) ;
2014-07-23 10:03:52 +04:00
aData - > mClip . AddOffsetAndComputeDifference ( entry - > mCommonClipCount ,
shift , aData - > mGeometry - > ComputeInvalidationRegion ( ) ,
2015-11-06 06:57:47 +03:00
clip , entry - > mLastCommonClipCount ,
geometry ? geometry - > ComputeInvalidationRegion ( ) :
aData - > mGeometry - > ComputeInvalidationRegion ( ) ,
2014-07-23 10:03:24 +04:00
& combined ) ;
2012-08-29 09:48:45 +04:00
// Add in any rect that the frame specified
2012-10-16 05:10:43 +04:00
combined . Or ( combined , invalid ) ;
2017-03-21 03:07:49 +03:00
combined . Or ( combined , changedFrameInvalidations ) ;
2012-10-16 05:10:43 +04:00
// Restrict invalidation to the clipped region
2014-07-23 10:03:24 +04:00
nsRegion clipRegion ;
if ( clip . ComputeRegionInClips ( & aData - > mClip , shift , & clipRegion ) ) {
combined . And ( combined , clipRegion ) ;
2012-10-16 05:10:43 +04:00
}
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
if ( ! combined . IsEmpty ( ) ) {
2014-07-23 10:03:24 +04:00
printf_stderr ( " Display item type %s(%p) (in layer %p) changed geometry! \n " , item - > Name ( ) , item - > Frame ( ) , aData - > mLayer . get ( ) ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
}
# endif
}
if ( ! combined . IsEmpty ( ) ) {
2014-04-24 06:56:15 +04:00
if ( notifyRenderingChanged ) {
2014-07-23 10:03:24 +04:00
item - > NotifyRenderingChanged ( ) ;
2014-04-24 06:56:15 +04:00
}
2014-09-26 21:06:08 +04:00
InvalidatePostTransformRegion ( paintedLayer ,
2014-07-23 10:03:24 +04:00
combined . ScaleToOutsidePixels ( layerData - > mXScale , layerData - > mYScale , layerData - > mAppUnitsPerDevPixel ) ,
2016-03-29 01:37:07 +03:00
layerData - > mTranslation ) ;
2010-07-16 01:08:05 +04:00
}
2014-07-23 10:03:24 +04:00
aData - > EndUpdate ( geometry ) ;
2010-07-16 01:08:05 +04:00
}
2010-07-16 01:07:51 +04:00
void
2014-09-26 21:07:06 +04:00
FrameLayerBuilder : : AddPaintedDisplayItem ( PaintedLayerData * aLayerData ,
2010-07-16 01:07:51 +04:00
nsDisplayItem * aItem ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2015-01-20 17:49:30 +03:00
ContainerState & aContainerState ,
2012-08-29 09:47:15 +04:00
LayerState aLayerState ,
2014-07-23 10:03:24 +04:00
const nsPoint & aTopLeft )
2010-07-16 01:07:51 +04:00
{
2014-09-26 21:06:08 +04:00
PaintedLayer * layer = aLayerData - > mLayer ;
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * paintedData =
static_cast < PaintedDisplayItemLayerUserData * >
( layer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2015-10-18 08:24:48 +03:00
RefPtr < BasicLayerManager > tempManager ;
2012-10-16 05:10:43 +04:00
nsIntRect intClip ;
bool hasClip = false ;
2012-08-29 09:47:15 +04:00
if ( aLayerState ! = LAYER_NONE ) {
2013-12-16 16:16:24 +04:00
DisplayItemData * data = GetDisplayItemDataForManager ( aItem , layer - > Manager ( ) ) ;
2012-08-29 09:47:15 +04:00
if ( data ) {
tempManager = data - > mInactiveManager ;
}
if ( ! tempManager ) {
2014-06-19 22:22:17 +04:00
tempManager = new BasicLayerManager ( BasicLayerManager : : BLM_INACTIVE ) ;
2012-08-29 09:47:15 +04:00
}
2012-10-23 15:05:14 +04:00
2012-10-16 05:10:43 +04:00
// We need to grab these before calling AddLayerDisplayItem because it will overwrite them.
nsRegion clip ;
2013-03-04 13:55:59 +04:00
DisplayItemClip * oldClip = nullptr ;
2012-10-16 05:10:43 +04:00
GetOldLayerFor ( aItem , nullptr , & oldClip ) ;
2013-03-04 13:56:00 +04:00
hasClip = aClip . ComputeRegionInClips ( oldClip ,
2014-09-26 21:07:06 +04:00
aTopLeft - paintedData - > mLastAnimatedGeometryRootOrigin ,
2013-03-04 13:56:00 +04:00
& clip ) ;
2012-10-16 05:10:43 +04:00
if ( hasClip ) {
2014-09-26 21:07:06 +04:00
intClip = clip . GetBounds ( ) . ScaleToOutsidePixels ( paintedData - > mXScale ,
paintedData - > mYScale ,
paintedData - > mAppUnitsPerDevPixel ) ;
2012-10-16 05:10:43 +04:00
}
2012-08-29 09:47:15 +04:00
}
2015-12-16 08:24:06 +03:00
AddLayerDisplayItem ( layer , aItem , aLayerState , tempManager ) ;
2010-07-16 01:07:51 +04:00
2014-09-26 21:06:08 +04:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . PutEntry ( layer ) ;
2010-07-16 01:07:51 +04:00
if ( entry ) {
2014-06-23 08:24:00 +04:00
entry - > mContainerLayerFrame = aContainerState . GetContainerFrame ( ) ;
2012-09-12 01:17:26 +04:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2012-08-29 09:47:15 +04:00
if ( tempManager ) {
2015-01-20 17:49:30 +03:00
FLB_LOG_PAINTED_LAYER_DECISION ( aLayerData , " Creating nested FLB for item %p \n " , aItem ) ;
2012-08-29 09:47:15 +04:00
FrameLayerBuilder * layerBuilder = new FrameLayerBuilder ( ) ;
2017-10-07 01:32:30 +03:00
layerBuilder - > Init ( mDisplayListBuilder , tempManager , aLayerData , true ,
& aClip ) ;
2012-08-29 09:47:15 +04:00
tempManager - > BeginTransaction ( ) ;
if ( mRetainingManager ) {
layerBuilder - > DidBeginRetainedLayerTransaction ( tempManager ) ;
}
2014-03-20 10:49:27 +04:00
2015-11-03 09:29:06 +03:00
UniquePtr < LayerProperties > props ( LayerProperties : : CloneFrom ( tempManager - > GetRoot ( ) ) ) ;
2015-10-18 08:24:48 +03:00
RefPtr < Layer > tmpLayer =
2013-09-27 10:01:16 +04:00
aItem - > BuildLayer ( mDisplayListBuilder , tempManager , ContainerLayerParameters ( ) ) ;
2012-08-29 09:47:15 +04:00
// We have no easy way of detecting if this transaction will ever actually get finished.
// For now, I've just silenced the warning with nested transactions in BasicLayers.cpp
2013-12-16 16:16:24 +04:00
if ( ! tmpLayer ) {
2012-08-29 09:47:15 +04:00
tempManager - > EndTransaction ( nullptr , nullptr ) ;
tempManager - > SetUserData ( & gLayerManagerLayerBuilder , nullptr ) ;
return ;
}
2014-06-23 08:24:00 +04:00
bool snap ;
nsRect visibleRect =
aItem - > GetVisibleRect ( ) . Intersect ( aItem - > GetBounds ( mDisplayListBuilder , & snap ) ) ;
2014-09-26 21:07:06 +04:00
nsIntRegion rgn = visibleRect . ToOutsidePixels ( paintedData - > mAppUnitsPerDevPixel ) ;
2016-11-24 08:11:30 +03:00
// Convert the visible rect to a region and give the item
// a chance to try restrict it further.
nsRegion tightBounds = aItem - > GetTightBounds ( mDisplayListBuilder , & snap ) ;
if ( ! tightBounds . IsEmpty ( ) ) {
rgn . AndWith ( tightBounds . ToOutsidePixels ( paintedData - > mAppUnitsPerDevPixel ) ) ;
}
2014-06-23 08:24:00 +04:00
SetOuterVisibleRegion ( tmpLayer , & rgn ) ;
2012-08-29 09:47:15 +04:00
// If BuildLayer didn't call BuildContainerLayerFor, then our new layer won't have been
// stored in layerBuilder. Manually add it now.
2012-10-12 03:38:24 +04:00
if ( mRetainingManager ) {
2012-10-12 06:39:46 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-12 03:38:24 +04:00
LayerManagerData * parentLmd = static_cast < LayerManagerData * >
2013-12-16 16:16:24 +04:00
( layer - > Manager ( ) - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-10-12 03:38:24 +04:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( tempManager - > GetUserData ( & gLayerManagerUserData ) ) ;
lmd - > mParent = parentLmd ;
2012-10-12 06:39:46 +04:00
# endif
2013-12-16 16:16:24 +04:00
layerBuilder - > StoreDataForFrame ( aItem , tmpLayer , LAYER_ACTIVE ) ;
2012-10-12 03:38:24 +04:00
}
2012-08-29 09:47:15 +04:00
2013-12-16 16:16:24 +04:00
tempManager - > SetRoot ( tmpLayer ) ;
2012-08-29 09:47:15 +04:00
layerBuilder - > WillEndTransaction ( ) ;
2013-11-06 23:10:49 +04:00
tempManager - > AbortTransaction ( ) ;
2012-08-29 09:47:15 +04:00
2015-09-26 01:37:30 +03:00
# ifdef MOZ_DUMP_PAINTING
2015-10-28 16:31:00 +03:00
if ( gfxUtils : : DumpDisplayList ( ) | | gfxEnv : : DumpPaint ( ) ) {
2015-09-26 01:37:30 +03:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " Basic layer tree for painting contents of display item %s(%p): \n " , aItem - > Name ( ) , aItem - > Frame ( ) ) ;
std : : stringstream stream ;
2015-10-28 16:31:00 +03:00
tempManager - > Dump ( stream , " " , gfxEnv : : DumpPaintToFile ( ) ) ;
2015-09-26 01:37:30 +03:00
fprint_stderr ( gfxUtils : : sDumpPaintFile , stream ) ; // not a typo, fprint_stderr declared in LayersLogging.h
}
# endif
2015-11-03 09:29:06 +03:00
nsIntPoint offset = GetLastPaintOffset ( layer ) - GetTranslationForPaintedLayer ( layer ) ;
props - > MoveBy ( - offset ) ;
2015-11-02 20:28:00 +03:00
// Effective transforms are needed by ComputeDifferences().
tmpLayer - > ComputeEffectiveTransforms ( Matrix4x4 ( ) ) ;
2017-08-04 07:22:48 +03:00
nsIntRegion invalid ;
if ( ! props - > ComputeDifferences ( tmpLayer , invalid , nullptr ) ) {
nsRect visible = aItem - > Frame ( ) - > GetVisualOverflowRect ( ) ;
invalid = visible . ToOutsidePixels ( paintedData - > mAppUnitsPerDevPixel ) ;
}
2015-11-03 09:29:06 +03:00
if ( aLayerState = = LAYER_SVG_EFFECTS ) {
invalid = nsSVGIntegrationUtils : : AdjustInvalidAreaForSVGEffects ( aItem - > Frame ( ) ,
aItem - > ToReferenceFrame ( ) ,
invalid ) ;
}
if ( ! invalid . IsEmpty ( ) ) {
2015-11-03 06:48:42 +03:00
# ifdef MOZ_DUMP_PAINTING
2015-11-03 09:29:06 +03:00
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
printf_stderr ( " Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p \n " , tempManager . get ( ) , aItem - > Name ( ) , aItem - > Frame ( ) , layer ) ;
}
2012-08-29 09:47:18 +04:00
# endif
2015-11-03 09:29:06 +03:00
invalid . ScaleRoundOut ( paintedData - > mXScale , paintedData - > mYScale ) ;
2012-10-16 05:10:43 +04:00
2015-11-03 09:29:06 +03:00
if ( hasClip ) {
invalid . And ( invalid , intClip ) ;
2015-11-03 06:48:42 +03:00
}
2015-11-03 09:29:06 +03:00
InvalidatePostTransformRegion ( layer , invalid ,
2016-03-29 01:37:07 +03:00
GetTranslationForPaintedLayer ( layer ) ) ;
2012-08-29 09:47:18 +04:00
}
2012-08-29 09:47:15 +04:00
}
2010-07-16 01:08:05 +04:00
ClippedDisplayItem * cdi =
2013-03-04 13:56:02 +04:00
entry - > mItems . AppendElement ( ClippedDisplayItem ( aItem ,
2012-07-23 07:00:36 +04:00
mContainerLayerGeneration ) ) ;
2012-10-23 15:05:14 +04:00
cdi - > mInactiveLayerManager = tempManager ;
2010-07-16 01:07:51 +04:00
}
}
2017-05-10 06:07:37 +03:00
DisplayItemData *
2012-10-12 06:39:46 +04:00
FrameLayerBuilder : : StoreDataForFrame ( nsDisplayItem * aItem , Layer * aLayer , LayerState aState )
2012-08-29 14:53:27 +04:00
{
2012-10-12 06:39:46 +04:00
DisplayItemData * oldData = GetDisplayItemDataForManager ( aItem , mRetainingManager ) ;
if ( oldData ) {
if ( ! oldData - > mUsed ) {
2014-07-23 10:03:24 +04:00
oldData - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration , aItem ) ;
2012-10-12 06:39:46 +04:00
}
return oldData ;
2012-10-12 03:38:24 +04:00
}
2014-03-20 10:49:27 +04:00
2012-10-12 06:39:46 +04:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2014-03-20 10:49:27 +04:00
2015-10-18 08:24:48 +03:00
RefPtr < DisplayItemData > data =
2017-05-10 06:07:37 +03:00
new ( aItem - > Frame ( ) - > PresContext ( ) ) DisplayItemData ( lmd , aItem - > GetPerFrameKey ( ) , aLayer ) ;
2012-10-12 06:39:46 +04:00
2014-07-23 10:03:24 +04:00
data - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration , aItem ) ;
2012-10-12 06:39:46 +04:00
lmd - > mDisplayItems . PutEntry ( data ) ;
return data ;
}
void
FrameLayerBuilder : : StoreDataForFrame ( nsIFrame * aFrame ,
uint32_t aDisplayItemKey ,
Layer * aLayer ,
LayerState aState )
{
DisplayItemData * oldData = GetDisplayItemData ( aFrame , aDisplayItemKey ) ;
if ( oldData & & oldData - > mFrameList . Length ( ) = = 1 ) {
2014-07-23 10:03:24 +04:00
oldData - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration ) ;
2012-10-12 06:39:46 +04:00
return ;
}
2014-03-20 10:49:27 +04:00
2012-10-12 06:39:46 +04:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2015-10-18 08:24:48 +03:00
RefPtr < DisplayItemData > data =
2017-05-10 06:07:37 +03:00
new ( aFrame - > PresContext ( ) ) DisplayItemData ( lmd , aDisplayItemKey , aLayer , aFrame ) ;
2012-10-12 06:39:46 +04:00
2014-07-23 10:03:24 +04:00
data - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration ) ;
2012-10-12 06:39:46 +04:00
lmd - > mDisplayItems . PutEntry ( data ) ;
2012-08-29 09:47:15 +04:00
}
2015-10-23 00:00:16 +03:00
FrameLayerBuilder : : ClippedDisplayItem : : ClippedDisplayItem ( nsDisplayItem * aItem ,
uint32_t aGeneration )
: mItem ( aItem )
, mContainerLayerGeneration ( aGeneration )
{
}
2012-08-29 09:47:15 +04:00
FrameLayerBuilder : : ClippedDisplayItem : : ~ ClippedDisplayItem ( )
{
2012-10-23 15:05:14 +04:00
if ( mInactiveLayerManager ) {
2015-03-16 21:19:32 +03:00
mInactiveLayerManager - > SetUserData ( & gLayerManagerLayerBuilder , nullptr ) ;
2012-08-29 14:53:27 +04:00
}
}
2015-10-23 00:00:16 +03:00
FrameLayerBuilder : : PaintedLayerItemsEntry : : PaintedLayerItemsEntry ( const PaintedLayer * aKey )
: nsPtrHashKey < PaintedLayer > ( aKey )
, mContainerLayerFrame ( nullptr )
, mLastCommonClipCount ( 0 )
, mContainerLayerGeneration ( 0 )
, mHasExplicitLastPaintOffset ( false )
, mCommonClipCount ( 0 )
{
}
FrameLayerBuilder : : PaintedLayerItemsEntry : : PaintedLayerItemsEntry ( const PaintedLayerItemsEntry & aOther )
: nsPtrHashKey < PaintedLayer > ( aOther . mKey )
, mItems ( aOther . mItems )
{
NS_ERROR ( " Should never be called, since we ALLOW_MEMMOVE " ) ;
}
FrameLayerBuilder : : PaintedLayerItemsEntry : : ~ PaintedLayerItemsEntry ( )
{
}
2012-12-14 02:50:57 +04:00
void
2010-07-16 01:07:51 +04:00
FrameLayerBuilder : : AddLayerDisplayItem ( Layer * aLayer ,
2011-05-19 02:54:31 +04:00
nsDisplayItem * aItem ,
2012-08-29 09:47:15 +04:00
LayerState aLayerState ,
2014-07-23 10:03:24 +04:00
BasicLayerManager * aManager )
2010-07-16 01:07:51 +04:00
{
if ( aLayer - > Manager ( ) ! = mRetainingManager )
2012-12-14 02:50:57 +04:00
return ;
2012-10-12 03:38:24 +04:00
2012-10-12 06:39:46 +04:00
DisplayItemData * data = StoreDataForFrame ( aItem , aLayer , aLayerState ) ;
2012-08-29 09:47:15 +04:00
data - > mInactiveManager = aManager ;
2010-07-16 01:07:51 +04:00
}
2011-05-18 09:48:43 +04:00
nsIntPoint
2014-09-26 21:06:08 +04:00
FrameLayerBuilder : : GetLastPaintOffset ( PaintedLayer * aLayer )
2011-05-17 03:05:56 +04:00
{
2014-09-26 21:06:08 +04:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . PutEntry ( aLayer ) ;
2012-07-23 07:00:36 +04:00
if ( entry ) {
2012-09-12 01:17:26 +04:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2012-07-23 07:00:36 +04:00
if ( entry - > mHasExplicitLastPaintOffset )
return entry - > mLastPaintOffset ;
}
2014-09-26 21:06:08 +04:00
return GetTranslationForPaintedLayer ( aLayer ) ;
2011-05-17 03:05:56 +04:00
}
void
2014-09-26 21:06:08 +04:00
FrameLayerBuilder : : SavePreviousDataForLayer ( PaintedLayer * aLayer , uint32_t aClipCount )
2011-05-17 03:05:56 +04:00
{
2014-09-26 21:06:08 +04:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . PutEntry ( aLayer ) ;
2011-05-17 03:05:56 +04:00
if ( entry ) {
2012-09-12 01:17:26 +04:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2014-09-26 21:06:08 +04:00
entry - > mLastPaintOffset = GetTranslationForPaintedLayer ( aLayer ) ;
2011-10-17 18:59:28 +04:00
entry - > mHasExplicitLastPaintOffset = true ;
2014-07-23 10:03:52 +04:00
entry - > mLastCommonClipCount = aClipCount ;
2011-05-17 03:05:56 +04:00
}
}
2014-01-30 09:41:17 +04:00
bool
FrameLayerBuilder : : CheckInLayerTreeCompressionMode ( )
{
if ( mInLayerTreeCompressionMode ) {
2014-03-20 10:49:27 +04:00
return true ;
2014-01-30 09:41:17 +04:00
}
// If we wanted to be in layer tree compression mode, but weren't, then scheduled
// a delayed repaint where we will be.
2017-09-29 00:51:49 +03:00
mRootPresContext - > PresShell ( ) - > GetRootFrame ( ) - > SchedulePaint ( nsIFrame : : PAINT_DELAYED_COMPRESS , false ) ;
2014-01-30 09:41:17 +04:00
return false ;
}
2010-07-16 01:07:51 +04:00
void
2010-07-16 01:08:03 +04:00
ContainerState : : CollectOldLayers ( )
2010-07-16 01:07:51 +04:00
{
for ( Layer * layer = mContainerLayer - > GetFirstChild ( ) ; layer ;
layer = layer - > GetNextSibling ( ) ) {
2012-02-08 02:26:40 +04:00
NS_ASSERTION ( ! layer - > HasUserData ( & gMaskLayerUserData ) ,
2016-08-05 05:00:04 +03:00
" Mask layers should not be part of the layer tree. " ) ;
2014-09-26 21:07:06 +04:00
if ( layer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
2014-09-26 21:06:08 +04:00
NS_ASSERTION ( layer - > AsPaintedLayer ( ) , " Wrong layer type " ) ;
2015-03-04 08:21:00 +03:00
mPaintedLayersAvailableForRecycling . PutEntry ( static_cast < PaintedLayer * > ( layer ) ) ;
2010-07-16 01:07:51 +04:00
}
2012-02-08 02:26:40 +04:00
if ( Layer * maskLayer = layer - > GetMaskLayer ( ) ) {
NS_ASSERTION ( maskLayer - > GetType ( ) = = Layer : : TYPE_IMAGE ,
" Could not recycle mask layer, unsupported layer type. " ) ;
2015-06-21 19:28:10 +03:00
mRecycledMaskImageLayers . Put ( MaskLayerKey ( layer , Nothing ( ) ) , static_cast < ImageLayer * > ( maskLayer ) ) ;
}
for ( size_t i = 0 ; i < layer - > GetAncestorMaskLayerCount ( ) ; i + + ) {
Layer * maskLayer = layer - > GetAncestorMaskLayerAt ( i ) ;
NS_ASSERTION ( maskLayer - > GetType ( ) = = Layer : : TYPE_IMAGE ,
" Could not recycle mask layer, unsupported layer type. " ) ;
mRecycledMaskImageLayers . Put ( MaskLayerKey ( layer , Some ( i ) ) , static_cast < ImageLayer * > ( maskLayer ) ) ;
2012-02-08 02:26:40 +04:00
}
2010-07-16 01:07:51 +04:00
}
}
2014-06-23 08:24:00 +04:00
struct OpaqueRegionEntry {
2015-11-25 01:53:51 +03:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2017-04-21 05:03:40 +03:00
const ActiveScrolledRoot * mASR ;
2014-06-23 08:24:00 +04:00
nsIntRegion mOpaqueRegion ;
} ;
static OpaqueRegionEntry *
FindOpaqueRegionEntry ( nsTArray < OpaqueRegionEntry > & aEntries ,
2017-04-21 05:03:40 +03:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
const ActiveScrolledRoot * aASR )
2014-06-23 08:24:00 +04:00
{
for ( uint32_t i = 0 ; i < aEntries . Length ( ) ; + + i ) {
OpaqueRegionEntry * d = & aEntries [ i ] ;
2017-04-21 05:03:40 +03:00
if ( d - > mAnimatedGeometryRoot = = aAnimatedGeometryRoot & &
d - > mASR = = aASR ) {
2014-06-23 08:24:00 +04:00
return d ;
}
}
return nullptr ;
}
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot *
FindDirectChildASR ( const ActiveScrolledRoot * aParent , const ActiveScrolledRoot * aDescendant )
{
MOZ_ASSERT ( aDescendant , " can't start at the root when looking for a child " ) ;
MOZ_ASSERT ( ActiveScrolledRoot : : IsAncestor ( aParent , aDescendant ) ) ;
const ActiveScrolledRoot * directChild = aDescendant ;
while ( directChild - > mParent ! = aParent ) {
directChild = directChild - > mParent ;
MOZ_RELEASE_ASSERT ( directChild , " this must not be null " ) ;
}
return directChild ;
}
static void
FixUpFixedPositionLayer ( Layer * aLayer ,
const ActiveScrolledRoot * aTargetASR ,
const ActiveScrolledRoot * aLeafScrollMetadataASR ,
const ActiveScrolledRoot * aContainerScrollMetadataASR ,
const ActiveScrolledRoot * aContainerCompositorASR ,
bool aIsFixedToRootScrollFrame )
{
if ( ! aLayer - > GetIsFixedPosition ( ) ) {
return ;
}
// Analyze ASRs to figure out if we need to fix up fixedness annotations on
// the layer. Fixed annotations are required in multiple cases:
// - Sometimes we set scroll metadata on a layer for a scroll frame that we
// don't want the layer to be moved by. (We have to do this if there is a
// scrolled clip that is moved by that scroll frame.) So we set the fixed
// annotation so that the compositor knows that it should ignore that
// scroll metadata when determining the layer's position.
// - Sometimes there is a scroll meta data on aLayer's parent layer for a
// scroll frame that we don't want aLayer to be moved by. The most common
// way for this to happen is with containerful root scrolling, where the
// scroll metadata for the root scroll frame is on a container layer that
// wraps the whole document's contents.
// - Sometimes it's just needed for hit testing, i.e. figuring out what
// scroll frame should be scrolled by events over the layer.
// A fixed layer needs to be annotated with the scroll ID of the scroll frame
// that it is *fixed with respect to*, i.e. the outermost scroll frame which
// does not move the layer. nsDisplayFixedPosition only ever annotates layers
// with the scroll ID of the presshell's root scroll frame, which is
// sometimes the wrong thing to do, so we correct it here. Specifically,
// it's the wrong thing to do if the fixed frame's containing block is a
// transformed frame - in that case, the fixed frame needs to scroll along
// with the transformed frame instead of being fixed with respect to the rsf.
// (It would be nice to compute the annotation only in one place and get it
// right, instead of fixing it up after the fact like this, but this will
// need to do for now.)
// compositorASR is the ASR that the layer would move with on the compositor
// if there were no fixed annotation on it.
const ActiveScrolledRoot * compositorASR =
aLeafScrollMetadataASR = = aContainerScrollMetadataASR
? aContainerCompositorASR
: aLeafScrollMetadataASR ;
// The goal of the annotation is to have the layer move with aTargetASR.
if ( compositorASR & & aTargetASR ! = compositorASR ) {
// Mark this layer as fixed with respect to the child scroll frame of aTargetASR.
aLayer - > SetFixedPositionData (
2017-07-20 19:33:09 +03:00
nsLayoutUtils : : ViewIDForASR ( FindDirectChildASR ( aTargetASR , compositorASR ) ) ,
2017-02-01 01:07:35 +03:00
aLayer - > GetFixedPositionAnchor ( ) ,
aLayer - > GetFixedPositionSides ( ) ) ;
} else {
// Remove the fixed annotation from the layer, unless this layers is fixed
// to the document's root scroll frame - in that case, the annotation is
// needed for hit testing, because fixed layers in iframes should scroll
// the iframe, even though their position is not affected by scrolling in
// the iframe. (The APZ hit testing code has a special case for this.)
// nsDisplayFixedPosition has annotated this layer with the document's
// root scroll frame's scroll id.
aLayer - > SetIsFixedPosition ( aIsFixedToRootScrollFrame ) ;
}
}
2014-06-23 08:24:00 +04:00
void
2014-08-31 07:29:24 +04:00
ContainerState : : SetupScrollingMetadata ( NewLayerEntry * aEntry )
{
2014-09-06 08:16:33 +04:00
if ( mFlattenToSingleLayer ) {
// animated geometry roots are forced to all match, so we can't
// use them and we don't get async scrolling.
return ;
}
2015-11-03 11:03:47 +03:00
if ( ! mBuilder - > IsPaintingToWindow ( ) ) {
// async scrolling not possible, and async scrolling info not computed
// for this paint.
return ;
}
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * startASR = aEntry - > mScrollMetadataASR ;
const ActiveScrolledRoot * stopASR = mContainerScrollMetadataASR ;
if ( ! ActiveScrolledRoot : : IsAncestor ( stopASR , startASR ) ) {
if ( ActiveScrolledRoot : : IsAncestor ( startASR , stopASR ) ) {
// startASR and stopASR are in the same branch of the ASR tree, but
// startASR is closer to the root. Just start at stopASR so that the loop
// below doesn't actually do anything.
startASR = stopASR ;
} else {
// startASR and stopASR are in different branches of the
// ASR tree. Find a common ancestor and make that the stopASR.
// This can happen when there's a scrollable frame inside a fixed layer
// which has a scrolled clip. As far as scroll metadata is concerned,
// the scroll frame's scroll metadata will be a child of the scroll ID
// that scrolls the clip on the fixed layer. But as far as ASRs are
// concerned, those two ASRs are siblings, parented to the ASR of the
// fixed layer.
do {
stopASR = stopASR - > mParent ;
} while ( ! ActiveScrolledRoot : : IsAncestor ( stopASR , startASR ) ) ;
}
}
FixUpFixedPositionLayer ( aEntry - > mLayer , aEntry - > mASR , startASR ,
mContainerScrollMetadataASR , mContainerCompositorASR ,
aEntry - > mIsFixedToRootScrollFrame ) ;
2016-03-29 02:14:52 +03:00
AutoTArray < ScrollMetadata , 2 > metricsArray ;
if ( aEntry - > mBaseScrollMetadata ) {
metricsArray . AppendElement ( * aEntry - > mBaseScrollMetadata ) ;
2015-06-21 19:27:31 +03:00
// The base FrameMetrics was not computed by the nsIScrollableframe, so it
// should not have a mask layer.
2016-04-29 23:14:21 +03:00
MOZ_ASSERT ( ! aEntry - > mBaseScrollMetadata - > HasMaskLayer ( ) ) ;
2014-08-31 07:29:24 +04:00
}
2016-05-07 02:34:16 +03:00
// Any extra mask layers we need to attach to ScrollMetadatas.
// The list may already contain an entry added for the layer's scrolled clip
// so add to it rather than overwriting it (we clear the list when recycling
// a layer).
nsTArray < RefPtr < Layer > > maskLayers ( aEntry - > mLayer - > GetAllAncestorMaskLayers ( ) ) ;
2015-06-21 19:27:31 +03:00
2017-02-01 01:07:35 +03:00
// Iterate over the ASR chain and create the corresponding scroll metadatas.
// This loop is slightly tricky because the scrollframe-to-clip relationship
// is reversed between DisplayItemClipChain and ScrollMetadata:
// - DisplayItemClipChain associates the clip with the scroll frame that
// this clip is *moved by*, i.e. the clip is moving inside the scroll
// frame.
// - ScrollMetaData associates the scroll frame with the clip that's
// *just outside* the scroll frame, i.e. not moved by the scroll frame
// itself.
// This discrepancy means that the leaf clip item of the clip chain is never
// applied to any scroll meta data. Instead, it was applied earlier as the
// layer's clip (or fused with the painted layer contents), or it was applied
// as a ScrolledClip on the layer.
const DisplayItemClipChain * clipChain = aEntry - > mClipChain ;
for ( const ActiveScrolledRoot * asr = startASR ; asr ! = stopASR ; asr = asr - > mParent ) {
if ( ! asr ) {
MOZ_ASSERT_UNREACHABLE ( " Should have encountered stopASR on the way up. " ) ;
break ;
}
if ( clipChain & & clipChain - > mASR = = asr ) {
clipChain = clipChain - > mParent ;
2015-12-16 13:52:37 +03:00
}
2015-12-12 18:58:37 +03:00
2017-02-01 01:07:35 +03:00
nsIScrollableFrame * scrollFrame = asr - > mScrollableFrame ;
const DisplayItemClip * clip =
( clipChain & & clipChain - > mASR = = asr - > mParent ) ? & clipChain - > mClip : nullptr ;
2015-12-22 18:54:19 +03:00
2016-03-29 02:14:52 +03:00
Maybe < ScrollMetadata > metadata =
2017-02-01 01:07:35 +03:00
scrollFrame - > ComputeScrollMetadata ( aEntry - > mLayer , mContainerReferenceFrame ,
mParameters , clip ) ;
2016-03-29 02:14:52 +03:00
if ( ! metadata ) {
2015-06-21 19:27:31 +03:00
continue ;
}
if ( clip & &
clip - > HasClip ( ) & &
clip - > GetRoundedRectCount ( ) > 0 )
{
// The clip in between this scrollframe and its ancestor scrollframe
// requires a mask layer. Since this mask layer should not move with
// the APZC associated with this FrameMetrics, we attach the mask
// layer as an additional, separate clip.
Maybe < size_t > nextIndex = Some ( maskLayers . Length ( ) ) ;
2015-10-18 08:24:48 +03:00
RefPtr < Layer > maskLayer =
2016-01-06 03:08:17 +03:00
CreateMaskLayer ( aEntry - > mLayer , * clip , nextIndex , clip - > GetRoundedRectCount ( ) ) ;
2015-06-21 19:27:31 +03:00
if ( maskLayer ) {
2016-04-29 23:14:21 +03:00
MOZ_ASSERT ( metadata - > HasScrollClip ( ) ) ;
metadata - > ScrollClip ( ) . SetMaskLayerIndex ( nextIndex ) ;
2015-06-21 19:27:31 +03:00
maskLayers . AppendElement ( maskLayer ) ;
}
}
2016-03-29 02:14:52 +03:00
metricsArray . AppendElement ( * metadata ) ;
2014-08-31 07:29:24 +04:00
}
2015-06-21 19:27:31 +03:00
2014-08-31 07:29:24 +04:00
// Watch out for FrameMetrics copies in profiles
2016-03-29 02:14:52 +03:00
aEntry - > mLayer - > SetScrollMetadata ( metricsArray ) ;
2015-06-21 19:27:31 +03:00
aEntry - > mLayer - > SetAncestorMaskLayers ( maskLayers ) ;
2014-08-31 07:29:24 +04:00
}
2016-04-29 23:14:21 +03:00
static inline Maybe < ParentLayerIntRect >
2015-06-03 02:34:28 +03:00
GetStationaryClipInContainer ( Layer * aLayer )
{
2016-03-29 02:14:52 +03:00
if ( size_t metricsCount = aLayer - > GetScrollMetadataCount ( ) ) {
return aLayer - > GetScrollMetadata ( metricsCount - 1 ) . GetClipRect ( ) ;
2015-06-03 02:34:28 +03:00
}
return aLayer - > GetClipRect ( ) ;
}
2014-08-31 07:29:24 +04:00
void
ContainerState : : PostprocessRetainedLayers ( nsIntRegion * aOpaqueRegionForContainer )
2014-06-23 08:24:00 +04:00
{
2016-02-02 18:36:30 +03:00
AutoTArray < OpaqueRegionEntry , 4 > opaqueRegions ;
2014-06-23 08:24:00 +04:00
bool hideAll = false ;
int32_t opaqueRegionForContainer = - 1 ;
for ( int32_t i = mNewChildLayers . Length ( ) - 1 ; i > = 0 ; - - i ) {
NewLayerEntry * e = & mNewChildLayers . ElementAt ( i ) ;
if ( ! e - > mLayer ) {
continue ;
}
2017-04-21 05:03:40 +03:00
OpaqueRegionEntry * data = FindOpaqueRegionEntry ( opaqueRegions , e - > mAnimatedGeometryRoot , e - > mASR ) ;
2014-06-23 08:24:00 +04:00
2014-09-06 08:16:33 +04:00
SetupScrollingMetadata ( e ) ;
2014-06-23 08:24:00 +04:00
if ( hideAll ) {
e - > mVisibleRegion . SetEmpty ( ) ;
2015-01-14 10:55:17 +03:00
} else if ( ! e - > mLayer - > IsScrollbarContainer ( ) ) {
2016-04-29 23:14:21 +03:00
Maybe < ParentLayerIntRect > clipRect = GetStationaryClipInContainer ( e - > mLayer ) ;
2014-09-06 08:16:33 +04:00
if ( clipRect & & opaqueRegionForContainer > = 0 & &
2015-11-07 06:13:40 +03:00
opaqueRegions [ opaqueRegionForContainer ] . mOpaqueRegion . Contains ( clipRect - > ToUnknownRect ( ) ) ) {
2014-09-06 08:16:33 +04:00
e - > mVisibleRegion . SetEmpty ( ) ;
} else if ( data ) {
e - > mVisibleRegion . Sub ( e - > mVisibleRegion , data - > mOpaqueRegion ) ;
}
2014-06-23 08:24:00 +04:00
}
2015-09-17 04:31:00 +03:00
SetOuterVisibleRegionForLayer ( e - > mLayer ,
e - > mVisibleRegion ,
e - > mLayerContentsVisibleRect . width > = 0 ? & e - > mLayerContentsVisibleRect : nullptr ,
e - > mUntransformedVisibleRegion ) ;
2014-08-31 07:29:24 +04:00
2014-06-23 08:24:00 +04:00
if ( ! e - > mOpaqueRegion . IsEmpty ( ) ) {
2016-08-25 05:25:57 +03:00
AnimatedGeometryRoot * animatedGeometryRootToCover = e - > mAnimatedGeometryRoot ;
2017-04-21 05:03:40 +03:00
const ActiveScrolledRoot * asrToCover = e - > mASR ;
2014-06-23 08:24:00 +04:00
if ( e - > mOpaqueForAnimatedGeometryRootParent & &
2015-11-25 01:53:51 +03:00
e - > mAnimatedGeometryRoot - > mParentAGR = = mContainerAnimatedGeometryRoot ) {
2014-06-23 08:24:00 +04:00
animatedGeometryRootToCover = mContainerAnimatedGeometryRoot ;
2017-04-21 05:03:40 +03:00
asrToCover = mContainerASR ;
data = FindOpaqueRegionEntry ( opaqueRegions , animatedGeometryRootToCover , asrToCover ) ;
2014-06-23 08:24:00 +04:00
}
if ( ! data ) {
2017-04-21 05:03:40 +03:00
if ( animatedGeometryRootToCover = = mContainerAnimatedGeometryRoot & &
asrToCover = = mContainerASR ) {
2014-06-23 08:24:00 +04:00
NS_ASSERTION ( opaqueRegionForContainer = = - 1 , " Already found it? " ) ;
opaqueRegionForContainer = opaqueRegions . Length ( ) ;
}
data = opaqueRegions . AppendElement ( ) ;
data - > mAnimatedGeometryRoot = animatedGeometryRootToCover ;
2017-04-21 05:03:40 +03:00
data - > mASR = asrToCover ;
2014-06-23 08:24:00 +04:00
}
2014-10-22 05:33:12 +04:00
nsIntRegion clippedOpaque = e - > mOpaqueRegion ;
2015-06-03 02:34:28 +03:00
Maybe < ParentLayerIntRect > clipRect = e - > mLayer - > GetCombinedClipRect ( ) ;
2014-10-22 05:33:12 +04:00
if ( clipRect ) {
2015-11-07 06:13:40 +03:00
clippedOpaque . AndWith ( clipRect - > ToUnknownRect ( ) ) ;
2014-10-22 05:33:12 +04:00
}
2017-02-01 01:07:35 +03:00
if ( e - > mLayer - > GetScrolledClip ( ) ) {
2015-09-25 16:47:41 +03:00
// The clip can move asynchronously, so we can't rely on opaque parts
2017-02-01 01:07:35 +03:00
// staying visible.
2015-09-25 16:47:41 +03:00
clippedOpaque . SetEmpty ( ) ;
2016-08-05 05:40:56 +03:00
} else if ( e - > mHideAllLayersBelow ) {
2014-06-23 08:24:00 +04:00
hideAll = true ;
}
2016-08-05 05:40:56 +03:00
data - > mOpaqueRegion . Or ( data - > mOpaqueRegion , clippedOpaque ) ;
2014-06-23 08:24:00 +04:00
}
if ( e - > mLayer - > GetType ( ) = = Layer : : TYPE_READBACK ) {
// ReadbackLayers need to accurately read what's behind them. So,
// we don't want to do any occlusion culling of layers behind them.
// Theoretically we could just punch out the ReadbackLayer's rectangle
// from all mOpaqueRegions, but that's probably not worth doing.
opaqueRegions . Clear ( ) ;
opaqueRegionForContainer = - 1 ;
}
}
if ( opaqueRegionForContainer > = 0 ) {
aOpaqueRegionForContainer - > Or ( * aOpaqueRegionForContainer ,
opaqueRegions [ opaqueRegionForContainer ] . mOpaqueRegion ) ;
}
}
2014-06-23 08:24:00 +04:00
void
2015-12-16 08:24:06 +03:00
ContainerState : : Finish ( uint32_t * aTextContentFlags ,
2014-06-23 08:24:00 +04:00
const nsIntRect & aContainerPixelBounds ,
2016-01-14 02:42:27 +03:00
nsDisplayList * aChildItems , bool * aHasComponentAlphaChildren )
2010-07-16 01:07:51 +04:00
{
2015-04-02 21:22:40 +03:00
mPaintedLayerDataTree . Finish ( ) ;
2014-03-20 10:49:27 +04:00
2017-02-03 22:55:51 +03:00
if ( ! mParameters . mForEventsAndPluginsOnly & & ! gfxPrefs : : LayoutUseContainersForRootFrames ( ) ) {
// Bug 1336544 tracks re-enabling this assertion in the
// gfxPrefs::LayoutUseContainersForRootFrames() case.
2015-12-22 18:54:19 +03:00
NS_ASSERTION ( mContainerBounds . IsEqualInterior ( mAccumulatedChildBounds ) ,
" Bounds computation mismatch " ) ;
}
2014-06-09 08:48:00 +04:00
2014-06-23 08:24:00 +04:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
nsIntRegion containerOpaqueRegion ;
2014-08-31 07:29:24 +04:00
PostprocessRetainedLayers ( & containerOpaqueRegion ) ;
2014-06-23 08:24:00 +04:00
if ( containerOpaqueRegion . Contains ( aContainerPixelBounds ) ) {
aChildItems - > SetIsOpaque ( ) ;
}
}
2012-08-22 19:56:38 +04:00
uint32_t textContentFlags = 0 ;
2010-12-20 04:26:14 +03:00
2012-08-29 14:53:06 +04:00
// Make sure that current/existing layers are added to the parent and are
// in the correct order.
Layer * layer = nullptr ;
2014-06-23 08:24:00 +04:00
Layer * prevChild = nullptr ;
for ( uint32_t i = 0 ; i < mNewChildLayers . Length ( ) ; + + i , prevChild = layer ) {
if ( ! mNewChildLayers [ i ] . mLayer ) {
continue ;
}
layer = mNewChildLayers [ i ] . mLayer ;
2014-03-20 10:49:27 +04:00
2012-08-29 14:53:06 +04:00
if ( ! layer - > GetVisibleRegion ( ) . IsEmpty ( ) ) {
2014-07-18 10:48:23 +04:00
textContentFlags | =
layer - > GetContentFlags ( ) & ( Layer : : CONTENT_COMPONENT_ALPHA |
2015-06-27 01:13:50 +03:00
Layer : : CONTENT_COMPONENT_ALPHA_DESCENDANT |
Layer : : CONTENT_DISABLE_FLATTENING ) ;
2014-07-18 10:48:23 +04:00
// Notify the parent of component alpha children unless it's coming from
2014-07-23 02:53:37 +04:00
// within a child that has asked not to contribute to layer flattening.
2016-01-14 02:42:27 +03:00
if ( aHasComponentAlphaChildren & &
mNewChildLayers [ i ] . mPropagateComponentAlphaFlattening & &
2014-07-23 02:53:37 +04:00
( layer - > GetContentFlags ( ) & Layer : : CONTENT_COMPONENT_ALPHA ) ) {
2016-01-14 02:42:27 +03:00
for ( int32_t j = i - 1 ; j > = 0 ; j - - ) {
if ( mNewChildLayers [ j ] . mVisibleRegion . Intersects ( mNewChildLayers [ i ] . mVisibleRegion . GetBounds ( ) ) ) {
if ( mNewChildLayers [ j ] . mLayerState ! = LAYER_ACTIVE_FORCE ) {
* aHasComponentAlphaChildren = true ;
}
break ;
}
}
2014-07-18 10:48:23 +04:00
}
2010-07-16 01:07:51 +04:00
}
2012-08-29 14:53:06 +04:00
if ( ! layer - > GetParent ( ) ) {
// This is not currently a child of the container, so just add it
// now.
mContainerLayer - > InsertAfter ( layer , prevChild ) ;
2015-03-17 01:37:04 +03:00
} else {
NS_ASSERTION ( layer - > GetParent ( ) = = mContainerLayer ,
" Layer shouldn't be the child of some other container " ) ;
if ( layer - > GetPrevSibling ( ) ! = prevChild ) {
mContainerLayer - > RepositionChild ( layer , prevChild ) ;
}
2010-07-16 01:07:51 +04:00
}
2012-08-29 14:53:06 +04:00
}
// Remove old layers that have become unused.
if ( ! layer ) {
layer = mContainerLayer - > GetFirstChild ( ) ;
} else {
layer = layer - > GetNextSibling ( ) ;
}
while ( layer ) {
Layer * layerToRemove = layer ;
layer = layer - > GetNextSibling ( ) ;
mContainerLayer - > RemoveChild ( layerToRemove ) ;
2010-07-16 01:07:51 +04:00
}
2010-12-20 04:26:14 +03:00
* aTextContentFlags = textContentFlags ;
2010-07-16 01:07:51 +04:00
}
2010-05-21 07:20:48 +04:00
2013-05-13 03:12:19 +04:00
static inline gfxSize RoundToFloatPrecision ( const gfxSize & aSize )
{
return gfxSize ( float ( aSize . width ) , float ( aSize . height ) ) ;
}
2014-07-09 06:01:54 +04:00
static void RestrictScaleToMaxLayerSize ( gfxSize & aScale ,
const nsRect & aVisibleRect ,
nsIFrame * aContainerFrame ,
Layer * aContainerLayer )
{
if ( ! aContainerLayer - > Manager ( ) - > IsWidgetLayerManager ( ) ) {
return ;
}
nsIntRect pixelSize =
aVisibleRect . ScaleToOutsidePixels ( aScale . width , aScale . height ,
aContainerFrame - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ) ;
int32_t maxLayerSize = aContainerLayer - > GetMaxLayerSize ( ) ;
if ( pixelSize . width > maxLayerSize ) {
float scale = ( float ) pixelSize . width / maxLayerSize ;
scale = gfxUtils : : ClampToScaleFactor ( scale ) ;
aScale . width / = scale ;
}
if ( pixelSize . height > maxLayerSize ) {
float scale = ( float ) pixelSize . height / maxLayerSize ;
scale = gfxUtils : : ClampToScaleFactor ( scale ) ;
aScale . height / = scale ;
}
}
2017-07-26 07:55:11 +03:00
static nsSize
ComputeDesiredDisplaySizeForAnimation ( nsIFrame * aContainerFrame )
{
// Use the size of the nearest widget as the maximum size. This
// is important since it might be a popup that is bigger than the
// pres context's size.
nsPresContext * presContext = aContainerFrame - > PresContext ( ) ;
nsIWidget * widget = aContainerFrame - > GetNearestWidget ( ) ;
if ( widget ) {
return LayoutDevicePixel : : ToAppUnits ( widget - > GetClientSize ( ) ,
presContext - > AppUnitsPerDevPixel ( ) ) ;
} else {
return presContext - > GetVisibleArea ( ) . Size ( ) ;
}
}
2013-03-21 06:33:00 +04:00
static bool
2011-06-22 16:11:27 +04:00
ChooseScaleAndSetTransform ( FrameLayerBuilder * aLayerBuilder ,
2012-09-17 02:25:33 +04:00
nsDisplayListBuilder * aDisplayListBuilder ,
2011-06-22 16:11:27 +04:00
nsIFrame * aContainerFrame ,
2015-06-30 02:46:16 +03:00
nsDisplayItem * aContainerItem ,
2014-07-09 06:01:54 +04:00
const nsRect & aVisibleRect ,
2014-08-01 16:31:49 +04:00
const Matrix4x4 * aTransform ,
2013-09-27 10:01:16 +04:00
const ContainerLayerParameters & aIncomingScale ,
2012-09-17 02:25:33 +04:00
ContainerLayer * aLayer ,
2013-03-21 06:33:00 +04:00
LayerState aState ,
2013-09-27 10:01:16 +04:00
ContainerLayerParameters & aOutgoingScale )
2011-06-22 16:11:27 +04:00
{
2012-09-17 02:25:33 +04:00
nsIntPoint offset ;
2014-08-01 16:31:49 +04:00
Matrix4x4 transform =
2014-10-08 07:43:00 +04:00
Matrix4x4 : : Scaling ( aIncomingScale . mXScale , aIncomingScale . mYScale , 1.0 ) ;
2011-06-22 16:11:27 +04:00
if ( aTransform ) {
// aTransform is applied first, then the scale is applied to the result
transform = ( * aTransform ) * transform ;
2016-03-21 23:16:52 +03:00
// Set any matrix entries close to integers to be those exact integers.
// This protects against floating-point inaccuracies causing problems
// in the checks below.
// We use the fixed epsilon version here because we don't want the nudging
// to depend on the scroll position.
transform . NudgeToIntegersFixedEpsilon ( ) ;
2012-12-04 10:04:20 +04:00
}
2014-08-01 16:31:49 +04:00
Matrix transform2d ;
2012-12-04 10:04:20 +04:00
if ( aContainerFrame & &
2013-09-06 13:28:02 +04:00
( aState = = LAYER_INACTIVE | | aState = = LAYER_SVG_EFFECTS ) & &
2012-12-04 10:04:20 +04:00
( ! aTransform | | ( aTransform - > Is2D ( & transform2d ) & &
! transform2d . HasNonTranslation ( ) ) ) ) {
2012-09-17 02:25:33 +04:00
// When we have an inactive ContainerLayer, translate the container by the offset to the
// reference frame (and offset all child layers by the reverse) so that the coordinate
// space of the child layers isn't affected by scrolling.
2012-12-04 10:04:20 +04:00
// This gets confusing for complicated transform (since we'd have to compute the scale
// factors for the matrix), so we don't bother. Any frames that are building an nsDisplayTransform
// for a css transform would have 0,0 as their offset to the reference frame, so this doesn't
// matter.
2012-09-17 02:25:33 +04:00
nsPoint appUnitOffset = aDisplayListBuilder - > ToReferenceFrame ( aContainerFrame ) ;
nscoord appUnitsPerDevPixel = aContainerFrame - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
offset = nsIntPoint (
2013-09-06 13:28:34 +04:00
NS_lround ( NSAppUnitsToDoublePixels ( appUnitOffset . x , appUnitsPerDevPixel ) * aIncomingScale . mXScale ) ,
NS_lround ( NSAppUnitsToDoublePixels ( appUnitOffset . y , appUnitsPerDevPixel ) * aIncomingScale . mYScale ) ) ;
2012-09-17 02:25:33 +04:00
}
2014-10-08 07:43:00 +04:00
transform . PostTranslate ( offset . x + aIncomingScale . mOffset . x ,
offset . y + aIncomingScale . mOffset . y ,
0 ) ;
2012-12-04 10:04:20 +04:00
2013-03-21 06:33:00 +04:00
if ( transform . IsSingular ( ) ) {
return false ;
}
2011-06-22 16:11:27 +04:00
2012-02-23 22:03:27 +04:00
bool canDraw2D = transform . CanDraw2D ( & transform2d ) ;
2011-06-22 16:11:27 +04:00
gfxSize scale ;
2012-01-11 15:26:33 +04:00
// XXX Should we do something for 3D transforms?
2015-11-26 12:32:36 +03:00
if ( canDraw2D & &
! aContainerFrame - > Combines3DTransformWithAncestors ( ) & &
! aContainerFrame - > HasPerspective ( ) ) {
2014-02-18 18:58:01 +04:00
// If the container's transform is animated off main thread, fix a suitable scale size
// for animation
2015-07-01 18:55:51 +03:00
if ( aContainerItem & &
2017-08-07 07:07:43 +03:00
aContainerItem - > GetType ( ) = = DisplayItemType : : TYPE_TRANSFORM & &
2015-12-10 00:28:10 +03:00
EffectCompositor : : HasAnimationsForCompositor (
2015-07-01 18:55:51 +03:00
aContainerFrame , eCSSProperty_transform ) ) {
2017-07-26 07:55:11 +03:00
nsSize displaySize = ComputeDesiredDisplaySizeForAnimation ( aContainerFrame ) ;
2015-06-30 02:46:16 +03:00
// compute scale using the animation on the container (ignoring
// its ancestors)
2015-05-06 09:52:20 +03:00
scale = nsLayoutUtils : : ComputeSuitableScaleForAnimation (
2015-07-01 18:55:51 +03:00
aContainerFrame , aVisibleRect . Size ( ) ,
2015-06-30 02:46:17 +03:00
displaySize ) ;
2016-03-23 23:18:00 +03:00
// multiply by the scale inherited from ancestors--we use a uniform
// scale factor to prevent blurring when the layer is rotated.
float incomingScale = std : : max ( aIncomingScale . mXScale , aIncomingScale . mYScale ) ;
scale . width * = incomingScale ;
scale . height * = incomingScale ;
2012-12-22 01:58:17 +04:00
} else {
2013-09-04 15:30:57 +04:00
// Scale factors are normalized to a power of 2 to reduce the number of resolution changes
2014-08-01 16:31:49 +04:00
scale = RoundToFloatPrecision ( ThebesMatrix ( transform2d ) . ScaleFactors ( true ) ) ;
2017-07-27 13:52:27 +03:00
// For frames with a changing scale transform round scale factors up to
// nearest power-of-2 boundary so that we don't keep having to redraw
// the content as it scales up and down. Rounding up to nearest
2012-12-22 01:58:17 +04:00
// power-of-2 boundary ensures we never scale up, only down --- avoiding
// jaggies. It also ensures we never scale down by more than a factor of 2,
// avoiding bad downscaling quality.
2014-08-01 16:31:49 +04:00
Matrix frameTransform ;
2017-07-27 13:52:27 +03:00
if ( ActiveLayerTracker : : IsScaleSubjectToAnimation ( aContainerFrame ) ) {
scale . width = gfxUtils : : ClampToScaleFactor ( scale . width ) ;
scale . height = gfxUtils : : ClampToScaleFactor ( scale . height ) ;
// Limit animated scale factors to not grow excessively beyond the display size.
nsSize maxScale ( 4 , 4 ) ;
if ( ! aVisibleRect . IsEmpty ( ) ) {
nsSize displaySize = ComputeDesiredDisplaySizeForAnimation ( aContainerFrame ) ;
maxScale = Max ( maxScale , displaySize / aVisibleRect . Size ( ) ) ;
2012-12-07 03:58:12 +04:00
}
2017-07-27 13:52:27 +03:00
if ( scale . width > maxScale . width ) {
scale . width = gfxUtils : : ClampToScaleFactor ( maxScale . width , true ) ;
}
if ( scale . height > maxScale . height ) {
scale . height = gfxUtils : : ClampToScaleFactor ( maxScale . height , true ) ;
2012-12-22 01:58:17 +04:00
}
} else {
2016-03-21 23:16:52 +03:00
// XXX Do we need to move nearly-integer values to integers here?
2011-12-08 03:12:41 +04:00
}
2011-06-22 16:11:27 +04:00
}
// If the scale factors are too small, just use 1.0. The content is being
// scaled out of sight anyway.
2011-06-22 16:11:28 +04:00
if ( fabs ( scale . width ) < 1e-8 | | fabs ( scale . height ) < 1e-8 ) {
2012-04-30 01:41:13 +04:00
scale = gfxSize ( 1.0 , 1.0 ) ;
2011-06-22 16:11:27 +04:00
}
2014-07-09 06:01:54 +04:00
// If this is a transform container layer, then pre-rendering might
2015-09-21 12:56:52 +03:00
// mean we try render a layer bigger than the max texture size. If we have
// tiling, that's not a problem, since we'll automatically choose a tiled
// layer for layers of that size. If not, we need to apply clamping to
// prevent this.
if ( aTransform & & ! gfxPrefs : : LayersTilesEnabled ( ) ) {
2014-07-09 06:01:54 +04:00
RestrictScaleToMaxLayerSize ( scale , aVisibleRect , aContainerFrame , aLayer ) ;
}
2011-06-22 16:11:27 +04:00
} else {
scale = gfxSize ( 1.0 , 1.0 ) ;
}
2012-08-04 01:29:22 +04:00
// Store the inverse of our resolution-scale on the layer
2014-08-01 16:31:49 +04:00
aLayer - > SetBaseTransform ( transform ) ;
2012-08-04 01:29:22 +04:00
aLayer - > SetPreScale ( 1.0f / float ( scale . width ) ,
1.0f / float ( scale . height ) ) ;
2013-01-08 13:39:12 +04:00
aLayer - > SetInheritedScale ( aIncomingScale . mXScale ,
aIncomingScale . mYScale ) ;
2011-06-22 16:11:28 +04:00
2013-09-27 10:01:16 +04:00
aOutgoingScale =
ContainerLayerParameters ( scale . width , scale . height , - offset , aIncomingScale ) ;
2011-06-22 16:11:28 +04:00
if ( aTransform ) {
2013-03-21 06:33:00 +04:00
aOutgoingScale . mInTransformedSubtree = true ;
2014-10-22 05:54:32 +04:00
if ( ActiveLayerTracker : : IsStyleAnimated ( aDisplayListBuilder , aContainerFrame ,
eCSSProperty_transform ) ) {
2013-03-21 06:33:00 +04:00
aOutgoingScale . mInActiveTransformedSubtree = true ;
2011-06-22 16:11:28 +04:00
}
}
2015-09-17 04:31:00 +03:00
if ( ( aLayerBuilder - > IsBuildingRetainedLayers ( ) & &
( ! canDraw2D | | transform2d . HasNonIntegerTranslation ( ) ) ) | |
aContainerFrame - > Extend3DContext ( ) | |
2017-03-29 16:38:00 +03:00
aContainerFrame - > Combines3DTransformWithAncestors ( ) | |
// For async transform animation, the value would be changed at
// any time, integer translation is not always true.
aContainerFrame - > HasAnimationOfTransform ( ) ) {
2013-03-21 06:33:00 +04:00
aOutgoingScale . mDisableSubpixelAntialiasingInDescendants = true ;
2012-01-11 15:26:33 +04:00
}
2013-03-21 06:33:00 +04:00
return true ;
2011-06-22 16:11:27 +04:00
}
2010-09-04 00:10:45 +04:00
already_AddRefed < ContainerLayer >
2010-07-16 01:07:51 +04:00
FrameLayerBuilder : : BuildContainerLayerFor ( nsDisplayListBuilder * aBuilder ,
LayerManager * aManager ,
nsIFrame * aContainerFrame ,
nsDisplayItem * aContainerItem ,
2014-06-09 08:48:00 +04:00
nsDisplayList * aChildren ,
2013-09-27 10:01:16 +04:00
const ContainerLayerParameters & aParameters ,
2014-08-01 16:31:49 +04:00
const Matrix4x4 * aTransform ,
2013-03-22 06:17:29 +04:00
uint32_t aFlags )
2010-07-16 01:07:51 +04:00
{
2012-08-22 19:56:38 +04:00
uint32_t containerDisplayItemKey =
2017-08-07 07:07:43 +03:00
aContainerItem ? aContainerItem - > GetPerFrameKey ( ) : 0 ;
2010-07-16 01:07:51 +04:00
NS_ASSERTION ( aContainerFrame , " Container display items here should have a frame " ) ;
NS_ASSERTION ( ! aContainerItem | |
2013-04-19 16:02:13 +04:00
aContainerItem - > Frame ( ) = = aContainerFrame ,
2010-07-16 01:07:51 +04:00
" Container display item must match given frame " ) ;
2013-03-06 00:04:40 +04:00
if ( ! aParameters . mXScale | | ! aParameters . mYScale ) {
return nullptr ;
}
2015-10-18 08:24:48 +03:00
RefPtr < ContainerLayer > containerLayer ;
2012-07-04 04:24:55 +04:00
if ( aManager = = mRetainingManager ) {
2012-08-29 14:53:27 +04:00
// Using GetOldLayerFor will search merged frames, as well as the underlying
// frame. The underlying frame can change when a page scrolls, so this
// avoids layer recreation in the situation that a new underlying frame is
// picked for a layer.
2012-08-29 09:47:15 +04:00
Layer * oldLayer = nullptr ;
if ( aContainerItem ) {
oldLayer = GetOldLayerFor ( aContainerItem ) ;
} else {
DisplayItemData * data = GetOldLayerForFrame ( aContainerFrame , containerDisplayItemKey ) ;
if ( data ) {
oldLayer = data - > mLayer ;
}
}
2012-08-29 14:53:20 +04:00
2012-07-04 04:24:55 +04:00
if ( oldLayer ) {
NS_ASSERTION ( oldLayer - > Manager ( ) = = aManager , " Wrong manager " ) ;
2014-09-26 21:07:06 +04:00
if ( oldLayer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
2014-09-26 21:06:08 +04:00
// The old layer for this item is actually our PaintedLayer
// because we rendered its layer into that PaintedLayer. So we
2012-07-04 04:24:55 +04:00
// don't actually have a retained container layer.
} else {
NS_ASSERTION ( oldLayer - > GetType ( ) = = Layer : : TYPE_CONTAINER ,
" Wrong layer type " ) ;
containerLayer = static_cast < ContainerLayer * > ( oldLayer ) ;
2016-07-08 23:30:47 +03:00
ResetLayerStateForRecycling ( containerLayer ) ;
2012-07-04 04:24:55 +04:00
}
2010-07-16 01:07:51 +04:00
}
}
if ( ! containerLayer ) {
// No suitable existing layer was found.
containerLayer = aManager - > CreateContainerLayer ( ) ;
if ( ! containerLayer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2010-05-21 07:20:48 +04:00
2012-09-17 02:25:33 +04:00
LayerState state = aContainerItem ? aContainerItem - > GetLayerState ( aBuilder , aManager , aParameters ) : LAYER_ACTIVE ;
2012-11-23 03:29:05 +04:00
if ( state = = LAYER_INACTIVE & &
nsDisplayItem : : ForceActiveLayers ( ) ) {
state = LAYER_ACTIVE ;
}
2012-09-17 02:25:33 +04:00
if ( aContainerItem & & state = = LAYER_ACTIVE_EMPTY ) {
2011-05-19 02:54:31 +04:00
// Empty layers only have metadata and should never have display items. We
// early exit because later, invalidation will walk up the frame tree to
2014-09-26 21:06:08 +04:00
// determine which painted layer gets invalidated. Since an empty layer
2011-05-19 02:54:31 +04:00
// should never have anything to paint, it should never be invalidated.
2014-06-09 08:48:00 +04:00
NS_ASSERTION ( aChildren - > IsEmpty ( ) , " Should have no children " ) ;
2011-05-19 02:54:31 +04:00
return containerLayer . forget ( ) ;
}
2017-02-01 01:07:35 +03:00
const ActiveScrolledRoot * containerASR = aContainerItem ? aContainerItem - > GetActiveScrolledRoot ( ) : nullptr ;
const ActiveScrolledRoot * containerScrollMetadataASR = aParameters . mScrollMetadataASR ;
const ActiveScrolledRoot * containerCompositorASR = aParameters . mCompositorASR ;
2015-12-22 18:54:19 +03:00
2017-01-27 19:38:55 +03:00
if ( ! aContainerItem & & gfxPrefs : : LayoutUseContainersForRootFrames ( ) ) {
containerASR = aBuilder - > ActiveScrolledRootForRootScrollframe ( ) ;
containerScrollMetadataASR = containerASR ;
containerCompositorASR = containerASR ;
}
2015-12-22 18:54:19 +03:00
2013-09-27 10:01:16 +04:00
ContainerLayerParameters scaleParameters ;
2017-02-01 01:07:35 +03:00
nsRect bounds = aChildren - > GetClippedBoundsWithRespectToASR ( aBuilder , containerASR ) ;
2014-07-15 15:49:38 +04:00
nsRect childrenVisible =
aContainerItem ? aContainerItem - > GetVisibleRectForChildren ( ) :
aContainerFrame - > GetVisualOverflowRectRelativeToSelf ( ) ;
if ( ! ChooseScaleAndSetTransform ( this , aBuilder , aContainerFrame ,
2015-06-30 02:46:16 +03:00
aContainerItem ,
2014-07-15 15:49:38 +04:00
bounds . Intersect ( childrenVisible ) ,
aTransform , aParameters ,
containerLayer , state , scaleParameters ) ) {
2013-03-21 06:33:00 +04:00
return nullptr ;
}
2010-05-21 07:20:48 +04:00
2012-08-22 19:56:38 +04:00
uint32_t oldGeneration = mContainerLayerGeneration ;
2012-07-23 07:00:36 +04:00
mContainerLayerGeneration = + + mMaxContainerLayerGeneration ;
2012-08-29 09:47:15 +04:00
if ( mRetainingManager ) {
2012-10-12 03:38:24 +04:00
if ( aContainerItem ) {
2012-10-12 06:39:46 +04:00
StoreDataForFrame ( aContainerItem , containerLayer , LAYER_ACTIVE ) ;
} else {
StoreDataForFrame ( aContainerFrame , containerDisplayItemKey , containerLayer , LAYER_ACTIVE ) ;
2012-10-12 03:38:24 +04:00
}
2012-07-23 07:00:36 +04:00
}
2014-03-20 10:49:27 +04:00
2012-10-12 06:39:46 +04:00
LayerManagerData * data = static_cast < LayerManagerData * >
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-07-23 07:00:36 +04:00
nsIntRect pixBounds ;
2014-06-23 08:24:00 +04:00
nscoord appUnitsPerDevPixel ;
2014-09-06 08:16:33 +04:00
bool flattenToSingleLayer = false ;
2012-11-22 09:34:32 +04:00
if ( ( aContainerFrame - > GetStateBits ( ) & NS_FRAME_NO_COMPONENT_ALPHA ) & &
2015-02-11 07:54:18 +03:00
mRetainingManager & &
mRetainingManager - > ShouldAvoidComponentAlphaLayers ( ) & &
2015-06-04 23:51:10 +03:00
! nsLayoutUtils : : AsyncPanZoomEnabled ( aContainerFrame ) )
2015-02-11 07:54:18 +03:00
{
2014-09-06 08:16:33 +04:00
flattenToSingleLayer = true ;
2012-11-22 09:34:32 +04:00
}
2015-02-25 19:47:22 +03:00
nscolor backgroundColor = NS_RGBA ( 0 , 0 , 0 , 0 ) ;
if ( aFlags & CONTAINER_ALLOW_PULL_BACKGROUND_COLOR ) {
backgroundColor = aParameters . mBackgroundColor ;
}
2012-08-22 19:56:38 +04:00
uint32_t flags ;
2012-07-23 07:00:36 +04:00
while ( true ) {
2012-08-21 08:06:46 +04:00
ContainerState state ( aBuilder , aManager , aManager - > GetLayerBuilder ( ) ,
2014-06-09 08:48:00 +04:00
aContainerFrame , aContainerItem , bounds ,
2015-02-25 19:47:22 +03:00
containerLayer , scaleParameters , flattenToSingleLayer ,
2017-02-01 01:07:35 +03:00
backgroundColor , containerASR , containerScrollMetadataASR ,
containerCompositorASR ) ;
2014-03-20 10:49:27 +04:00
2014-09-06 08:16:33 +04:00
state . ProcessDisplayItems ( aChildren ) ;
2012-08-04 01:29:22 +04:00
2012-07-23 07:00:36 +04:00
// Set CONTENT_COMPONENT_ALPHA if any of our children have it.
// This is suboptimal ... a child could have text that's over transparent
// pixels in its own layer, but over opaque parts of previous siblings.
2014-07-18 10:48:23 +04:00
bool hasComponentAlphaChildren = false ;
2016-01-14 02:42:27 +03:00
bool mayFlatten =
mRetainingManager & &
mRetainingManager - > ShouldAvoidComponentAlphaLayers ( ) & &
! flattenToSingleLayer & &
! nsLayoutUtils : : AsyncPanZoomEnabled ( aContainerFrame ) ;
2012-07-23 07:00:36 +04:00
pixBounds = state . ScaleToOutsidePixels ( bounds , false ) ;
appUnitsPerDevPixel = state . GetAppUnitsPerDevPixel ( ) ;
2016-01-14 02:42:27 +03:00
state . Finish ( & flags , pixBounds , aChildren , mayFlatten ? & hasComponentAlphaChildren : nullptr ) ;
2012-07-23 07:00:36 +04:00
2014-07-18 10:48:23 +04:00
if ( hasComponentAlphaChildren & &
2015-06-27 01:13:50 +03:00
! ( flags & Layer : : CONTENT_DISABLE_FLATTENING ) & &
2016-01-14 02:42:27 +03:00
containerLayer - > HasMultipleChildren ( ) )
2015-02-11 07:54:18 +03:00
{
2012-07-23 07:00:36 +04:00
// Since we don't want any component alpha layers on BasicLayers, we repeat
// the layer building process with this explicitely forced off.
// We restore the previous FrameLayerBuilder state since the first set
// of layer building will have changed it.
2014-09-06 08:16:33 +04:00
flattenToSingleLayer = true ;
2015-07-15 12:05:06 +03:00
// Restore DisplayItemData
for ( auto iter = data - > mDisplayItems . Iter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
DisplayItemData * data = iter . Get ( ) - > GetKey ( ) ;
if ( data - > mUsed & & data - > mContainerLayerGeneration > = mContainerLayerGeneration ) {
iter . Remove ( ) ;
}
}
// Restore PaintedLayerItemEntries
for ( auto iter = mPaintedLayerItems . Iter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
PaintedLayerItemsEntry * entry = iter . Get ( ) ;
if ( entry - > mContainerLayerGeneration > = mContainerLayerGeneration ) {
// We can just remove these items rather than attempting to revert them
// because we're going to want to invalidate everything when transitioning
// to component alpha flattening.
iter . Remove ( ) ;
continue ;
}
for ( uint32_t i = 0 ; i < entry - > mItems . Length ( ) ; i + + ) {
if ( entry - > mItems [ i ] . mContainerLayerGeneration > = mContainerLayerGeneration ) {
entry - > mItems . TruncateLength ( i ) ;
break ;
}
}
}
2012-07-23 07:00:36 +04:00
aContainerFrame - > AddStateBits ( NS_FRAME_NO_COMPONENT_ALPHA ) ;
continue ;
}
break ;
}
2010-12-20 04:26:14 +03:00
2014-07-18 10:48:23 +04:00
// CONTENT_COMPONENT_ALPHA is propogated up to the nearest CONTENT_OPAQUE
// ancestor so that BasicLayerManager knows when to copy the background into
// pushed groups. Accelerated layers managers can't necessarily do this (only
// when the visible region is a simple rect), so we propogate
// CONTENT_COMPONENT_ALPHA_DESCENDANT all the way to the root.
if ( flags & Layer : : CONTENT_COMPONENT_ALPHA ) {
flags | = Layer : : CONTENT_COMPONENT_ALPHA_DESCENDANT ;
}
2011-02-23 08:38:09 +03:00
// Make sure that rounding the visible region out didn't add any area
// we won't paint
2014-06-09 08:48:00 +04:00
if ( aChildren - > IsOpaque ( ) & & ! aChildren - > NeedsTransparentSurface ( ) ) {
2011-06-22 16:11:27 +04:00
bounds . ScaleRoundIn ( scaleParameters . mXScale , scaleParameters . mYScale ) ;
2015-04-21 18:04:57 +03:00
if ( bounds . Contains ( ToAppUnits ( pixBounds , appUnitsPerDevPixel ) ) ) {
2014-07-18 10:48:23 +04:00
// Clear CONTENT_COMPONENT_ALPHA and add CONTENT_OPAQUE instead.
flags & = ~ Layer : : CONTENT_COMPONENT_ALPHA ;
flags | = Layer : : CONTENT_OPAQUE ;
2011-06-22 16:11:27 +04:00
}
2010-12-20 04:26:14 +03:00
}
2010-09-02 13:18:40 +04:00
containerLayer - > SetContentFlags ( flags ) ;
2014-06-23 08:24:00 +04:00
// If aContainerItem is non-null some BuildContainerLayer further up the
// call stack is responsible for setting containerLayer's visible region.
if ( ! aContainerItem ) {
2015-11-29 10:07:55 +03:00
containerLayer - > SetVisibleRegion ( LayerIntRegion : : FromUnknownRegion ( pixBounds ) ) ;
2014-06-23 08:24:00 +04:00
}
if ( aParameters . mLayerContentsVisibleRect ) {
* aParameters . mLayerContentsVisibleRect = pixBounds + scaleParameters . mOffset ;
}
2010-12-20 04:26:14 +03:00
2012-07-23 07:00:36 +04:00
mContainerLayerGeneration = oldGeneration ;
2013-08-14 15:33:03 +04:00
nsPresContext : : ClearNotifySubDocInvalidationData ( containerLayer ) ;
2012-08-29 09:47:18 +04:00
2010-08-06 02:11:23 +04:00
return containerLayer . forget ( ) ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:46 +04:00
Layer *
FrameLayerBuilder : : GetLeafLayerFor ( nsDisplayListBuilder * aBuilder ,
nsDisplayItem * aItem )
{
2012-08-29 09:47:15 +04:00
Layer * layer = GetOldLayerFor ( aItem ) ;
2010-07-16 01:07:51 +04:00
if ( ! layer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2014-09-26 21:07:06 +04:00
if ( layer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
2010-07-16 01:07:51 +04:00
// This layer was created to render Thebes-rendered content for this
// display item. The display item should not use it for its own
// layer rendering.
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2016-07-09 00:24:48 +03:00
ResetLayerStateForRecycling ( layer ) ;
2010-07-16 01:07:51 +04:00
return layer ;
2010-07-16 01:07:46 +04:00
}
2012-09-27 19:34:46 +04:00
/* static */ void
FrameLayerBuilder : : InvalidateAllLayers ( LayerManager * aManager )
{
LayerManagerData * data = static_cast < LayerManagerData * >
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-08-29 09:48:45 +04:00
if ( data ) {
data - > mInvalidateAllLayers = true ;
}
}
2012-08-29 09:48:45 +04:00
/* static */ void
FrameLayerBuilder : : InvalidateAllLayersForFrame ( nsIFrame * aFrame )
{
2017-05-10 06:07:38 +03:00
const SmallPointerArray < DisplayItemData > & array = aFrame - > DisplayItemData ( ) ;
for ( uint32_t i = 0 ; i < array . Length ( ) ; i + + ) {
DisplayItemData : : AssertDisplayItemData ( array . ElementAt ( i ) ) - > mParent - > mInvalidateAllLayers = true ;
2012-08-29 09:48:45 +04:00
}
}
2010-07-16 01:07:53 +04:00
/* static */
2011-03-28 03:59:47 +04:00
Layer *
2017-08-07 07:07:43 +03:00
FrameLayerBuilder : : GetDedicatedLayer ( nsIFrame * aFrame , DisplayItemType aDisplayItemKey )
2010-07-16 01:07:53 +04:00
{
2012-08-29 09:48:41 +04:00
//TODO: This isn't completely correct, since a frame could exist as a layer
// in the normal widget manager, and as a different layer (or no layer)
// in the secondary manager
2017-05-10 06:07:38 +03:00
const SmallPointerArray < DisplayItemData > & array = aFrame - > DisplayItemData ( ) ; ;
for ( uint32_t i = 0 ; i < array . Length ( ) ; i + + ) {
DisplayItemData * element = DisplayItemData : : AssertDisplayItemData ( array . ElementAt ( i ) ) ;
if ( ! element - > mParent - > mLayerManager - > IsWidgetLayerManager ( ) ) {
continue ;
}
2017-08-07 07:07:43 +03:00
if ( GetDisplayItemTypeFromKey ( element - > mDisplayItemKey ) = = aDisplayItemKey ) {
2017-05-10 06:07:38 +03:00
if ( element - > mOptLayer ) {
return element - > mOptLayer ;
2012-10-12 06:39:46 +04:00
}
2012-09-25 00:31:30 +04:00
2017-05-10 06:07:38 +03:00
Layer * layer = element - > mLayer ;
if ( ! layer - > HasUserData ( & gColorLayerUserData ) & &
! layer - > HasUserData ( & gImageLayerUserData ) & &
! layer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
return layer ;
2012-10-12 03:38:24 +04:00
}
}
2010-07-16 01:07:53 +04:00
}
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:53 +04:00
}
2012-08-04 16:26:38 +04:00
gfxSize
2014-09-26 21:06:08 +04:00
FrameLayerBuilder : : GetPaintedLayerScaleForFrame ( nsIFrame * aFrame )
2012-08-04 16:26:38 +04:00
{
2014-06-24 21:52:18 +04:00
MOZ_ASSERT ( aFrame , " need a frame " ) ;
2014-03-20 10:49:27 +04:00
2017-08-25 01:21:55 +03:00
nsPresContext * presCtx = aFrame - > PresContext ( ) - > GetRootPresContext ( ) ;
2012-10-12 03:38:24 +04:00
2017-08-25 01:21:55 +03:00
if ( ! presCtx ) {
presCtx = aFrame - > PresContext ( ) ;
MOZ_ASSERT ( presCtx ) ;
2012-08-05 17:35:08 +04:00
}
2017-08-25 01:21:55 +03:00
nsIFrame * root = presCtx - > PresShell ( ) - > GetRootFrame ( ) ;
MOZ_ASSERT ( root ) ;
float resolution = presCtx - > PresShell ( ) - > GetResolution ( ) ;
Matrix4x4 transform = Matrix4x4 : : Scaling ( resolution , resolution , 1.0 ) ;
if ( aFrame ! = root ) {
// aTransform is applied first, then the scale is applied to the result
transform = nsLayoutUtils : : GetTransformToAncestor ( aFrame , root ) * transform ;
}
Matrix transform2d ;
if ( transform . CanDraw2D ( & transform2d ) ) {
return ThebesMatrix ( transform2d ) . ScaleFactors ( true ) ;
}
return gfxSize ( 1.0 , 1.0 ) ;
2012-05-10 09:24:18 +04:00
}
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
2014-10-29 20:07:11 +03:00
static void DebugPaintItem ( DrawTarget & aDrawTarget ,
2014-06-20 10:42:30 +04:00
nsPresContext * aPresContext ,
nsDisplayItem * aItem ,
nsDisplayListBuilder * aBuilder )
2012-03-05 22:09:05 +04:00
{
2012-04-10 15:24:18 +04:00
bool snap ;
2014-10-29 20:07:11 +03:00
Rect bounds = NSRectToRect ( aItem - > GetBounds ( aBuilder , & snap ) ,
aPresContext - > AppUnitsPerDevPixel ( ) ) ;
2012-03-05 22:09:05 +04:00
2015-10-18 08:24:48 +03:00
RefPtr < DrawTarget > tempDT =
2016-07-26 17:48:30 +03:00
aDrawTarget . CreateSimilarDrawTarget ( IntSize : : Truncate ( bounds . width , bounds . height ) ,
2014-10-29 20:07:11 +03:00
SurfaceFormat : : B8G8R8A8 ) ;
2016-06-07 02:39:56 +03:00
RefPtr < gfxContext > context = gfxContext : : CreateOrNull ( tempDT ) ;
2016-04-12 22:18:11 +03:00
if ( ! context ) {
// Leave this as crash, it's in the debugging code, we want to know
gfxDevCrash ( LogReason : : InvalidContext ) < < " DebugPaintItem context problem " < < gfx : : hexa ( tempDT ) ;
return ;
}
2014-10-29 20:07:11 +03:00
context - > SetMatrix ( gfxMatrix : : Translation ( - bounds . x , - bounds . y ) ) ;
2012-03-05 22:09:05 +04:00
2017-06-09 22:14:53 +03:00
aItem - > Paint ( aBuilder , context ) ;
2015-10-18 08:24:48 +03:00
RefPtr < SourceSurface > surface = tempDT - > Snapshot ( ) ;
2014-06-27 15:19:40 +04:00
DumpPaintedImage ( aItem , surface ) ;
2012-07-31 21:28:21 +04:00
2014-10-29 20:07:11 +03:00
aDrawTarget . DrawSurface ( surface , bounds , Rect ( Point ( 0 , 0 ) , bounds . Size ( ) ) ) ;
2014-06-27 15:19:40 +04:00
aItem - > SetPainted ( ) ;
2012-03-05 22:09:05 +04:00
}
# endif
2010-05-21 07:20:48 +04:00
/* static */ void
2013-11-06 23:10:49 +04:00
FrameLayerBuilder : : RecomputeVisibilityForItems ( nsTArray < ClippedDisplayItem > & aItems ,
nsDisplayListBuilder * aBuilder ,
const nsIntRegion & aRegionToDraw ,
const nsIntPoint & aOffset ,
int32_t aAppUnitsPerDevPixel ,
float aXScale ,
float aYScale )
2010-05-21 07:20:48 +04:00
{
2012-08-22 19:56:38 +04:00
uint32_t i ;
2014-06-09 08:48:01 +04:00
// Update visible regions. We perform visibility analysis to take account
// of occlusion culling.
2013-11-06 23:10:49 +04:00
nsRegion visible = aRegionToDraw . ToAppUnits ( aAppUnitsPerDevPixel ) ;
visible . MoveBy ( NSIntPixelsToAppUnits ( aOffset . x , aAppUnitsPerDevPixel ) ,
NSIntPixelsToAppUnits ( aOffset . y , aAppUnitsPerDevPixel ) ) ;
visible . ScaleInverseRoundOut ( aXScale , aYScale ) ;
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:49 +04:00
for ( i = aItems . Length ( ) ; i > 0 ; - - i ) {
ClippedDisplayItem * cdi = & aItems [ i - 1 ] ;
2013-03-04 13:56:02 +04:00
const DisplayItemClip & clip = cdi - > mItem - > GetClip ( ) ;
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:49 +04:00
NS_ASSERTION ( AppUnitsPerDevPixel ( cdi - > mItem ) = = aAppUnitsPerDevPixel ,
2014-09-26 21:06:08 +04:00
" a painted layer should contain items only at the same zoom " ) ;
2010-07-16 01:07:51 +04:00
2015-02-10 01:34:50 +03:00
MOZ_ASSERT ( clip . HasClip ( ) | | clip . GetRoundedRectCount ( ) = = 0 ,
" If we have rounded rects, we must have a clip rect " ) ;
2010-09-09 19:21:46 +04:00
2013-03-04 13:56:02 +04:00
if ( ! clip . IsRectAffectedByClip ( visible . GetBounds ( ) ) ) {
2013-11-06 23:10:49 +04:00
cdi - > mItem - > RecomputeVisibility ( aBuilder , & visible ) ;
2012-12-14 02:50:57 +04:00
continue ;
}
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped ;
2013-03-04 13:56:02 +04:00
clipped . And ( visible , clip . NonRoundedIntersection ( ) ) ;
2012-12-14 02:50:57 +04:00
nsRegion finalClipped = clipped ;
2013-11-06 23:10:49 +04:00
cdi - > mItem - > RecomputeVisibility ( aBuilder , & finalClipped ) ;
2012-12-14 02:50:57 +04:00
// If we have rounded clip rects, don't subtract from the visible
// region since we aren't displaying everything inside the rect.
2013-03-04 13:56:02 +04:00
if ( clip . GetRoundedRectCount ( ) = = 0 ) {
2012-12-14 02:50:57 +04:00
nsRegion removed ;
removed . Sub ( clipped , finalClipped ) ;
nsRegion newVisible ;
newVisible . Sub ( visible , removed ) ;
// Don't let the visible region get too complex.
if ( newVisible . GetNumRects ( ) < = 15 ) {
visible = newVisible ;
2010-09-09 19:21:46 +04:00
}
2011-01-26 21:36:11 +03:00
}
2010-07-16 01:07:51 +04:00
}
2013-11-06 23:10:49 +04:00
}
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:49 +04:00
void
FrameLayerBuilder : : PaintItems ( nsTArray < ClippedDisplayItem > & aItems ,
2013-11-06 23:10:50 +04:00
const nsIntRect & aRect ,
2013-11-06 23:10:49 +04:00
gfxContext * aContext ,
nsDisplayListBuilder * aBuilder ,
nsPresContext * aPresContext ,
2013-11-06 23:10:50 +04:00
const nsIntPoint & aOffset ,
float aXScale , float aYScale ,
2013-11-06 23:10:49 +04:00
int32_t aCommonClipCount )
{
2017-09-13 05:17:43 +03:00
DrawTarget & aDrawTarget = * aContext - > GetDrawTarget ( ) ;
2015-02-25 07:59:43 +03:00
2013-11-06 23:10:50 +04:00
int32_t appUnitsPerDevPixel = aPresContext - > AppUnitsPerDevPixel ( ) ;
2015-04-21 18:04:57 +03:00
nsRect boundRect = ToAppUnits ( aRect , appUnitsPerDevPixel ) ;
2013-11-06 23:10:50 +04:00
boundRect . MoveBy ( NSIntPixelsToAppUnits ( aOffset . x , appUnitsPerDevPixel ) ,
NSIntPixelsToAppUnits ( aOffset . y , appUnitsPerDevPixel ) ) ;
boundRect . ScaleInverseRoundOut ( aXScale , aYScale ) ;
2013-03-04 13:55:59 +04:00
DisplayItemClip currentClip ;
2013-03-04 13:56:00 +04:00
bool currentClipIsSetInContext = false ;
2013-03-04 13:56:02 +04:00
DisplayItemClip tmpClip ;
2010-08-08 22:49:07 +04:00
2013-11-06 23:10:49 +04:00
for ( uint32_t i = 0 ; i < aItems . Length ( ) ; + + i ) {
ClippedDisplayItem * cdi = & aItems [ i ] ;
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:50 +04:00
nsRect paintRect = cdi - > mItem - > GetVisibleRect ( ) . Intersect ( boundRect ) ;
if ( paintRect . IsEmpty ( ) )
2010-07-16 01:07:51 +04:00
continue ;
2014-07-09 23:11:51 +04:00
# ifdef MOZ_DUMP_PAINTING
2017-10-13 08:12:57 +03:00
AUTO_PROFILER_LABEL_DYNAMIC_CSTR ( " FrameLayerBuilder::PaintItems " , GRAPHICS ,
cdi - > mItem - > Name ( ) ) ;
2014-07-09 23:11:51 +04:00
# else
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
AUTO_PROFILER_LABEL ( " FrameLayerBuilder::PaintItems " , GRAPHICS ) ;
2014-07-09 23:11:51 +04:00
# endif
2010-05-21 07:20:48 +04:00
// If the new desired clip state is different from the current state,
// update the clip.
2013-03-04 13:56:02 +04:00
const DisplayItemClip * clip = & cdi - > mItem - > GetClip ( ) ;
if ( clip - > GetRoundedRectCount ( ) > 0 & &
! clip - > IsRectClippedByRoundedCorner ( cdi - > mItem - > GetVisibleRect ( ) ) ) {
tmpClip = * clip ;
tmpClip . RemoveRoundedCorners ( ) ;
clip = & tmpClip ;
}
if ( currentClipIsSetInContext ! = clip - > HasClip ( ) | |
( clip - > HasClip ( ) & & * clip ! = currentClip ) ) {
2013-03-04 13:56:00 +04:00
if ( currentClipIsSetInContext ) {
2010-05-21 07:20:48 +04:00
aContext - > Restore ( ) ;
}
2013-03-04 13:56:02 +04:00
currentClipIsSetInContext = clip - > HasClip ( ) ;
2013-03-04 13:56:00 +04:00
if ( currentClipIsSetInContext ) {
2013-03-04 13:56:02 +04:00
currentClip = * clip ;
2010-05-21 07:20:48 +04:00
aContext - > Save ( ) ;
2013-11-06 23:10:49 +04:00
NS_ASSERTION ( aCommonClipCount < 100 ,
2012-02-08 02:27:44 +04:00
" Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong. " ) ;
2013-11-06 23:10:49 +04:00
currentClip . ApplyTo ( aContext , aPresContext , aCommonClipCount ) ;
2013-09-19 09:23:30 +04:00
aContext - > NewPath ( ) ;
2010-05-21 07:20:48 +04:00
}
}
2010-07-16 01:07:51 +04:00
2012-10-23 15:05:14 +04:00
if ( cdi - > mInactiveLayerManager ) {
2015-02-25 07:59:43 +03:00
bool saved = aDrawTarget . GetPermitSubpixelAA ( ) ;
2017-09-13 05:17:43 +03:00
PaintInactiveLayer ( aBuilder , cdi - > mInactiveLayerManager , cdi - > mItem , aContext , aContext ) ;
2015-02-25 07:59:43 +03:00
aDrawTarget . SetPermitSubpixelAA ( saved ) ;
2010-07-16 01:08:05 +04:00
} else {
2013-04-19 16:02:13 +04:00
nsIFrame * frame = cdi - > mItem - > Frame ( ) ;
2016-05-06 17:31:11 +03:00
if ( aBuilder - > IsPaintingToWindow ( ) ) {
frame - > AddStateBits ( NS_FRAME_PAINTED_THEBES ) ;
}
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
2015-10-28 16:31:00 +03:00
if ( gfxEnv : : DumpPaintItems ( ) ) {
2014-10-29 20:07:11 +03:00
DebugPaintItem ( aDrawTarget , aPresContext , cdi - > mItem , aBuilder ) ;
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
} else
2012-03-05 22:09:05 +04:00
# endif
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
{
2017-09-13 05:17:43 +03:00
cdi - > mItem - > Paint ( aBuilder , aContext ) ;
2012-03-05 22:09:05 +04:00
}
2010-05-21 07:20:48 +04:00
}
2010-09-17 23:09:08 +04:00
2013-11-06 23:10:49 +04:00
if ( CheckDOMModified ( ) )
2010-09-17 23:09:08 +04:00
break ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:51 +04:00
2013-03-04 13:56:00 +04:00
if ( currentClipIsSetInContext ) {
2010-05-21 07:20:48 +04:00
aContext - > Restore ( ) ;
}
2013-11-06 23:10:49 +04:00
}
2013-11-06 23:10:50 +04:00
/**
* Returns true if it is preferred to draw the list of display
* items separately for each rect in the visible region rather
* than clipping to a complex region .
*/
2015-12-18 06:36:09 +03:00
static bool
ShouldDrawRectsSeparately ( DrawTarget * aDrawTarget , DrawRegionClip aClip )
2013-11-06 23:10:50 +04:00
{
2014-05-08 06:56:48 +04:00
if ( ! gfxPrefs : : LayoutPaintRectsSeparately ( ) | |
2014-10-01 09:25:25 +04:00
aClip = = DrawRegionClip : : NONE ) {
2013-11-06 23:10:50 +04:00
return false ;
}
2013-11-14 04:46:19 +04:00
2015-12-18 06:36:09 +03:00
return ! aDrawTarget - > SupportsRegionClipping ( ) ;
2013-11-06 23:10:50 +04:00
}
2014-11-24 03:04:33 +03:00
static void DrawForcedBackgroundColor ( DrawTarget & aDrawTarget ,
2016-05-06 20:53:56 +03:00
const IntRect & aBounds ,
nscolor aBackgroundColor )
2013-11-06 23:10:50 +04:00
{
if ( NS_GET_A ( aBackgroundColor ) > 0 ) {
2014-11-24 03:04:33 +03:00
ColorPattern color ( ToDeviceColor ( aBackgroundColor ) ) ;
2016-05-06 20:53:56 +03:00
aDrawTarget . FillRect ( Rect ( aBounds ) , color ) ;
2013-11-06 23:10:50 +04:00
}
}
2013-11-06 23:10:49 +04:00
/*
* A note on residual transforms :
*
2014-09-26 21:06:08 +04:00
* In a transformed subtree we sometimes apply the PaintedLayer ' s
* " residual transform " when drawing content into the PaintedLayer .
2013-11-06 23:10:49 +04:00
* This is a translation by components in the range [ - 0.5 , 0.5 ) provided
* by the layer system ; applying the residual transform followed by the
* transforms used by layer compositing ensures that the subpixel alignment
2014-09-26 21:06:08 +04:00
* of the content of the PaintedLayer exactly matches what it would be if
2013-11-06 23:10:49 +04:00
* we used cairo / Thebes to draw directly to the screen without going through
* retained layer buffers .
*
2014-09-26 21:06:08 +04:00
* The visible and valid regions of the PaintedLayer are computed without
2013-11-06 23:10:49 +04:00
* knowing the residual transform ( because we don ' t know what the residual
* transform is going to be until we ' ve built the layer tree ! ) . So we have to
* consider whether content painted in the range [ x , xmost ) might be painted
* outside the visible region we computed for that content . The visible region
* would be [ floor ( x ) , ceil ( xmost ) ) . The content would be rendered at
* [ x + r , xmost + r ) , where - 0.5 < = r < 0.5 . So some half - rendered pixels could
* indeed fall outside the computed visible region , which is not a big deal ;
* similar issues already arise when we snap cliprects to nearest pixels .
* Note that if the rendering of the content is snapped to nearest pixels - - -
* which it often is - - - then the content is actually rendered at
* [ snap ( x + r ) , snap ( xmost + r ) ) . It turns out that floor ( x ) < = snap ( x + r )
* and ceil ( xmost ) > = snap ( xmost + r ) , so the rendering of snapped content
* always falls within the visible region we computed .
*/
/* static */ void
2014-09-26 21:06:08 +04:00
FrameLayerBuilder : : DrawPaintedLayer ( PaintedLayer * aLayer ,
2013-11-06 23:10:49 +04:00
gfxContext * aContext ,
const nsIntRegion & aRegionToDraw ,
2015-09-15 16:41:42 +03:00
const nsIntRegion & aDirtyRegion ,
2013-11-06 23:10:50 +04:00
DrawRegionClip aClip ,
2013-11-06 23:10:49 +04:00
const nsIntRegion & aRegionToInvalidate ,
void * aCallbackData )
{
2014-11-24 03:04:33 +03:00
DrawTarget & aDrawTarget = * aContext - > GetDrawTarget ( ) ;
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
AUTO_PROFILER_LABEL ( " FrameLayerBuilder::DrawPaintedLayer " , GRAPHICS ) ;
2013-11-06 23:10:49 +04:00
nsDisplayListBuilder * builder = static_cast < nsDisplayListBuilder * >
( aCallbackData ) ;
FrameLayerBuilder * layerBuilder = aLayer - > Manager ( ) - > GetLayerBuilder ( ) ;
NS_ASSERTION ( layerBuilder , " Unexpectedly null layer builder! " ) ;
if ( layerBuilder - > CheckDOMModified ( ) )
return ;
2014-09-26 21:06:08 +04:00
PaintedLayerItemsEntry * entry = layerBuilder - > mPaintedLayerItems . GetEntry ( aLayer ) ;
2013-11-06 23:10:49 +04:00
NS_ASSERTION ( entry , " We shouldn't be drawing into a layer with no items! " ) ;
if ( ! entry - > mContainerLayerFrame ) {
return ;
}
2013-11-06 23:10:50 +04:00
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * userData =
static_cast < PaintedDisplayItemLayerUserData * >
( aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2013-11-06 23:10:49 +04:00
NS_ASSERTION ( userData , " where did our user data go? " ) ;
2013-11-06 23:10:50 +04:00
2015-12-18 06:36:09 +03:00
bool shouldDrawRectsSeparately =
ShouldDrawRectsSeparately ( & aDrawTarget , aClip ) ;
2013-11-06 23:10:50 +04:00
if ( ! shouldDrawRectsSeparately ) {
2014-10-01 09:25:25 +04:00
if ( aClip = = DrawRegionClip : : DRAW ) {
2013-11-06 23:10:50 +04:00
gfxUtils : : ClipToRegion ( aContext , aRegionToDraw ) ;
}
2016-05-06 20:53:56 +03:00
DrawForcedBackgroundColor ( aDrawTarget , aRegionToDraw . GetBounds ( ) ,
2014-11-24 03:04:33 +03:00
userData - > mForcedBackgroundColor ) ;
2013-11-06 23:10:49 +04:00
}
// make the origin of the context coincide with the origin of the
2014-09-26 21:06:08 +04:00
// PaintedLayer
2013-11-06 23:10:49 +04:00
gfxContextMatrixAutoSaveRestore saveMatrix ( aContext ) ;
2014-09-26 21:06:08 +04:00
nsIntPoint offset = GetTranslationForPaintedLayer ( aLayer ) ;
2013-11-06 23:10:49 +04:00
nsPresContext * presContext = entry - > mContainerLayerFrame - > PresContext ( ) ;
2015-09-15 16:41:42 +03:00
if ( ! userData - > mVisibilityComputedRegion . Contains ( aDirtyRegion ) & &
2015-07-21 11:19:25 +03:00
! layerBuilder - > GetContainingPaintedLayerData ( ) ) {
2015-09-15 16:41:42 +03:00
// Recompute visibility of items in our PaintedLayer, if required. Note
// that this recomputes visibility for all descendants of our display
// items too, so there's no need to do this for the items in inactive
// PaintedLayers. If aDirtyRegion has not changed since the previous call
// then we can skip this.
2014-06-23 08:24:14 +04:00
int32_t appUnitsPerDevPixel = presContext - > AppUnitsPerDevPixel ( ) ;
2015-09-15 16:41:42 +03:00
RecomputeVisibilityForItems ( entry - > mItems , builder , aDirtyRegion ,
2014-06-23 08:24:14 +04:00
offset , appUnitsPerDevPixel ,
userData - > mXScale , userData - > mYScale ) ;
2015-09-15 16:41:42 +03:00
userData - > mVisibilityComputedRegion = aDirtyRegion ;
2014-06-23 08:24:14 +04:00
}
2013-11-06 23:10:49 +04:00
2013-11-06 23:10:50 +04:00
if ( shouldDrawRectsSeparately ) {
2016-01-19 04:20:59 +03:00
for ( auto iter = aRegionToDraw . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
const nsIntRect & iterRect = iter . Get ( ) ;
2013-11-06 23:10:50 +04:00
gfxContextAutoSaveRestore save ( aContext ) ;
aContext - > NewPath ( ) ;
2016-01-19 04:20:59 +03:00
aContext - > Rectangle ( ThebesRect ( iterRect ) ) ;
2013-11-06 23:10:50 +04:00
aContext - > Clip ( ) ;
2016-05-06 20:53:56 +03:00
DrawForcedBackgroundColor ( aDrawTarget , iterRect ,
2014-11-24 03:04:33 +03:00
userData - > mForcedBackgroundColor ) ;
2013-11-06 23:10:50 +04:00
// Apply the residual transform if it has been enabled, to ensure that
// snapping when we draw into aContext exactly matches the ideal transform.
// See above for why this is OK.
2014-09-11 10:57:38 +04:00
aContext - > SetMatrix (
2017-07-05 18:18:49 +03:00
aContext - > CurrentMatrix ( ) . PreTranslate ( aLayer - > GetResidualTranslation ( ) - gfxPoint ( offset . x , offset . y ) ) .
PreScale ( userData - > mXScale , userData - > mYScale ) ) ;
2013-11-06 23:10:50 +04:00
2017-09-13 05:17:43 +03:00
layerBuilder - > PaintItems ( entry - > mItems , iterRect , aContext ,
2013-11-06 23:10:50 +04:00
builder , presContext ,
2013-11-06 23:10:50 +04:00
offset , userData - > mXScale , userData - > mYScale ,
2013-11-06 23:10:50 +04:00
entry - > mCommonClipCount ) ;
2016-04-20 00:07:57 +03:00
if ( gfxPrefs : : GfxLoggingPaintedPixelCountEnabled ( ) ) {
aLayer - > Manager ( ) - > AddPaintedPixelCount ( iterRect . Area ( ) ) ;
}
2013-11-06 23:10:50 +04:00
}
} else {
// Apply the residual transform if it has been enabled, to ensure that
// snapping when we draw into aContext exactly matches the ideal transform.
// See above for why this is OK.
2014-09-11 10:57:38 +04:00
aContext - > SetMatrix (
2017-07-05 18:18:49 +03:00
aContext - > CurrentMatrix ( ) . PreTranslate ( aLayer - > GetResidualTranslation ( ) - gfxPoint ( offset . x , offset . y ) ) .
PreScale ( userData - > mXScale , userData - > mYScale ) ) ;
2013-11-06 23:10:50 +04:00
2017-09-13 05:17:43 +03:00
layerBuilder - > PaintItems ( entry - > mItems , aRegionToDraw . GetBounds ( ) , aContext ,
2013-11-06 23:10:50 +04:00
builder , presContext ,
2013-11-06 23:10:50 +04:00
offset , userData - > mXScale , userData - > mYScale ,
2013-11-06 23:10:50 +04:00
entry - > mCommonClipCount ) ;
2016-04-20 00:07:57 +03:00
if ( gfxPrefs : : GfxLoggingPaintedPixelCountEnabled ( ) ) {
aLayer - > Manager ( ) - > AddPaintedPixelCount (
aRegionToDraw . GetBounds ( ) . Area ( ) ) ;
}
2013-11-06 23:10:50 +04:00
}
2011-11-15 08:59:03 +04:00
2014-09-09 22:54:08 +04:00
bool isActiveLayerManager = ! aLayer - > Manager ( ) - > IsInactiveLayerManager ( ) ;
if ( presContext - > GetPaintFlashing ( ) & & isActiveLayerManager ) {
2014-05-22 06:36:26 +04:00
gfxContextAutoSaveRestore save ( aContext ) ;
if ( shouldDrawRectsSeparately ) {
2014-10-01 09:25:25 +04:00
if ( aClip = = DrawRegionClip : : DRAW ) {
2014-05-22 06:36:26 +04:00
gfxUtils : : ClipToRegion ( aContext , aRegionToDraw ) ;
}
}
2013-03-12 22:01:00 +04:00
FlashPaint ( aContext ) ;
}
2015-12-17 02:18:00 +03:00
if ( presContext - > GetDocShell ( ) & & isActiveLayerManager ) {
2014-09-09 22:54:08 +04:00
nsDocShell * docShell = static_cast < nsDocShell * > ( presContext - > GetDocShell ( ) ) ;
2015-10-22 00:10:05 +03:00
RefPtr < TimelineConsumers > timelines = TimelineConsumers : : Get ( ) ;
if ( timelines & & timelines - > HasConsumer ( docShell ) ) {
timelines - > AddMarkerForDocShell ( docShell , Move (
MakeUnique < LayerTimelineMarker > ( aRegionToDraw ) ) ) ;
2014-12-11 18:40:00 +03:00
}
2014-09-09 22:54:08 +04:00
}
2012-08-29 09:47:18 +04:00
if ( ! aRegionToInvalidate . IsEmpty ( ) ) {
aLayer - > AddInvalidRect ( aRegionToInvalidate . GetBounds ( ) ) ;
}
2010-05-21 07:20:48 +04:00
}
2011-09-29 10:19:26 +04:00
bool
2010-09-17 23:09:08 +04:00
FrameLayerBuilder : : CheckDOMModified ( )
{
2010-09-18 22:43:17 +04:00
if ( ! mRootPresContext | |
2010-09-17 23:09:08 +04:00
mInitialDOMGeneration = = mRootPresContext - > GetDOMGeneration ( ) )
2011-10-17 18:59:28 +04:00
return false ;
2010-09-17 23:09:08 +04:00
if ( mDetectedDOMModification ) {
// Don't spam the console with extra warnings
2011-10-17 18:59:28 +04:00
return true ;
2010-09-17 23:09:08 +04:00
}
2011-10-17 18:59:28 +04:00
mDetectedDOMModification = true ;
2010-09-17 23:09:08 +04:00
// Painting is not going to complete properly. There's not much
// we can do here though. Invalidating the window to get another repaint
// is likely to lead to an infinite repaint loop.
NS_WARNING ( " Detected DOM modification during paint, bailing out! " ) ;
2011-10-17 18:59:28 +04:00
return true ;
2010-09-17 23:09:08 +04:00
}
2012-07-17 21:03:51 +04:00
/* static */ void
2014-06-20 02:36:25 +04:00
FrameLayerBuilder : : DumpRetainedLayerTree ( LayerManager * aManager , std : : stringstream & aStream , bool aDumpHtml )
2010-07-16 01:07:51 +04:00
{
2014-06-20 02:36:25 +04:00
aManager - > Dump ( aStream , " " , aDumpHtml ) ;
2010-07-16 01:07:51 +04:00
}
2015-02-05 00:50:56 +03:00
nsDisplayItemGeometry *
FrameLayerBuilder : : GetMostRecentGeometry ( nsDisplayItem * aItem )
{
2017-05-10 06:07:38 +03:00
typedef SmallPointerArray < DisplayItemData > DataArray ;
2015-02-05 00:50:56 +03:00
// Retrieve the array of DisplayItemData associated with our frame.
2017-05-10 06:07:38 +03:00
const DataArray & dataArray = aItem - > Frame ( ) - > DisplayItemData ( ) ;
2015-02-05 00:50:56 +03:00
// Find our display item data, if it exists, and return its geometry.
uint32_t itemPerFrameKey = aItem - > GetPerFrameKey ( ) ;
2017-05-10 06:07:38 +03:00
for ( uint32_t i = 0 ; i < dataArray . Length ( ) ; i + + ) {
DisplayItemData * data = DisplayItemData : : AssertDisplayItemData ( dataArray . ElementAt ( i ) ) ;
2015-02-05 00:50:56 +03:00
if ( data - > GetDisplayItemKey ( ) = = itemPerFrameKey ) {
return data - > GetGeometry ( ) ;
}
}
return nullptr ;
}
2017-05-11 06:38:00 +03:00
static gfx : : Rect
CalculateBounds ( const nsTArray < DisplayItemClip : : RoundedRect > & aRects , int32_t aAppUnitsPerDevPixel )
2012-02-08 02:27:44 +04:00
{
2012-06-26 06:43:30 +04:00
nsRect bounds = aRects [ 0 ] . mRect ;
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 1 ; i < aRects . Length ( ) ; + + i ) {
2012-06-26 06:43:30 +04:00
bounds . UnionRect ( bounds , aRects [ i ] . mRect ) ;
}
2013-12-30 03:35:53 +04:00
2017-05-11 06:38:00 +03:00
return gfx : : Rect ( bounds . ToNearestPixels ( aAppUnitsPerDevPixel ) ) ;
2012-02-08 02:27:44 +04:00
}
2012-09-04 05:02:56 +04:00
static void
2014-09-26 21:07:06 +04:00
SetClipCount ( PaintedDisplayItemLayerUserData * apaintedData ,
2012-09-04 05:02:56 +04:00
uint32_t aClipCount )
{
2014-09-26 21:07:06 +04:00
if ( apaintedData ) {
apaintedData - > mMaskClipCount = aClipCount ;
2012-09-04 05:02:56 +04:00
}
}
2012-02-08 02:27:44 +04:00
void
2014-06-23 08:24:00 +04:00
ContainerState : : SetupMaskLayer ( Layer * aLayer ,
const DisplayItemClip & aClip ,
2012-08-22 19:56:38 +04:00
uint32_t aRoundedRectClipCount )
2012-02-08 02:27:44 +04:00
{
2012-09-04 05:02:56 +04:00
// if the number of clips we are going to mask has decreased, then aLayer might have
// cached graphics which assume the existence of a soon-to-be non-existent mask layer
// in that case, invalidate the whole layer.
2014-09-26 21:07:06 +04:00
PaintedDisplayItemLayerUserData * paintedData = GetPaintedDisplayItemLayerUserData ( aLayer ) ;
if ( paintedData & &
aRoundedRectClipCount < paintedData - > mMaskClipCount ) {
PaintedLayer * painted = aLayer - > AsPaintedLayer ( ) ;
2017-06-16 00:29:18 +03:00
painted - > InvalidateWholeLayer ( ) ;
2012-09-04 05:02:56 +04:00
}
2012-02-08 02:27:44 +04:00
// don't build an unnecessary mask
2013-03-04 13:56:00 +04:00
if ( aClip . GetRoundedRectCount ( ) = = 0 | |
2016-07-25 05:41:25 +03:00
aRoundedRectClipCount = = 0 ) {
2014-09-26 21:07:06 +04:00
SetClipCount ( paintedData , 0 ) ;
2012-02-08 02:27:44 +04:00
return ;
}
2015-10-18 08:24:48 +03:00
RefPtr < Layer > maskLayer =
2016-01-06 03:08:17 +03:00
CreateMaskLayer ( aLayer , aClip , Nothing ( ) , aRoundedRectClipCount ) ;
2015-06-21 02:47:57 +03:00
if ( ! maskLayer ) {
SetClipCount ( paintedData , 0 ) ;
return ;
}
aLayer - > SetMaskLayer ( maskLayer ) ;
SetClipCount ( paintedData , aRoundedRectClipCount ) ;
}
2017-08-10 09:02:01 +03:00
void
SetMaskLayerUserData ( Layer * aMaskLayer )
{
aMaskLayer - > SetUserData ( & gMaskLayerUserData ,
new MaskLayerUserData ( ) ) ;
}
2015-06-21 02:47:57 +03:00
already_AddRefed < Layer >
ContainerState : : CreateMaskLayer ( Layer * aLayer ,
const DisplayItemClip & aClip ,
const Maybe < size_t > & aForAncestorMaskLayer ,
uint32_t aRoundedRectClipCount )
{
2016-11-07 17:32:43 +03:00
// aLayer will never be the container layer created by an nsDisplayMask
// because nsDisplayMask propagates the DisplayItemClip to its contents
// and is not clipped itself.
// This assertion will fail if that ever stops being the case.
MOZ_ASSERT ( ! aLayer - > GetUserData ( & gCSSMaskLayerUserData ) ,
" A layer contains round clips should not have css-mask on it. " ) ;
2012-02-08 02:27:44 +04:00
// check if we can re-use the mask layer
2015-06-21 19:28:10 +03:00
MaskLayerKey recycleKey ( aLayer , aForAncestorMaskLayer ) ;
2016-11-07 17:32:43 +03:00
RefPtr < ImageLayer > maskLayer =
2017-08-10 09:02:01 +03:00
CreateOrRecycleMaskImageLayerFor ( recycleKey , SetMaskLayerUserData ) ;
2012-02-08 02:27:44 +04:00
MaskLayerUserData * userData = GetMaskLayerUserData ( maskLayer ) ;
2012-06-26 06:43:30 +04:00
2016-11-07 18:27:35 +03:00
int32_t A2D = mContainerFrame - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
MaskLayerUserData newData ( aClip , aRoundedRectClipCount , A2D , mParameters ) ;
2012-06-26 06:43:30 +04:00
if ( * userData = = newData ) {
2015-06-21 02:47:57 +03:00
return maskLayer . forget ( ) ;
2012-06-26 02:54:05 +04:00
}
2012-07-31 21:28:21 +04:00
2013-12-30 03:35:53 +04:00
gfx : : Rect boundingRect = CalculateBounds ( newData . mRoundedClipRects ,
newData . mAppUnitsPerDevPixel ) ;
2012-06-26 06:43:30 +04:00
boundingRect . Scale ( mParameters . mXScale , mParameters . mYScale ) ;
2012-08-22 19:56:38 +04:00
uint32_t maxSize = mManager - > GetMaxTextureSize ( ) ;
2012-05-17 02:30:10 +04:00
NS_ASSERTION ( maxSize > 0 , " Invalid max texture size " ) ;
2016-08-18 12:19:55 +03:00
# ifdef MOZ_GFX_OPTIMIZE_MOBILE
// Make mask image width aligned to 4. See Bug 1245552.
2016-08-25 20:57:39 +03:00
gfx : : Size surfaceSize ( std : : min < gfx : : Float > ( GetAlignedStride < 4 > ( NSToIntCeil ( boundingRect . Width ( ) ) , 1 ) , maxSize ) ,
2016-08-18 12:19:55 +03:00
std : : min < gfx : : Float > ( boundingRect . Height ( ) , maxSize ) ) ;
# else
2016-08-15 18:54:43 +03:00
gfx : : Size surfaceSize ( std : : min < gfx : : Float > ( boundingRect . Width ( ) , maxSize ) ,
2013-12-30 03:35:53 +04:00
std : : min < gfx : : Float > ( boundingRect . Height ( ) , maxSize ) ) ;
2016-08-18 12:19:55 +03:00
# endif
2012-05-17 02:30:10 +04:00
2012-06-26 06:43:30 +04:00
// maskTransform is applied to the clip when it is painted into the mask (as a
// component of imageTransform), and its inverse used when the mask is used for
// masking.
// It is the transform from the masked layer's space to mask space
2014-09-10 17:26:12 +04:00
gfx : : Matrix maskTransform =
Matrix : : Scaling ( surfaceSize . width / boundingRect . Width ( ) ,
surfaceSize . height / boundingRect . Height ( ) ) ;
2016-12-17 06:06:44 +03:00
if ( surfaceSize . IsEmpty ( ) ) {
// Return early if we know that the size of this mask surface is empty.
return nullptr ;
}
2013-12-30 03:35:53 +04:00
gfx : : Point p = boundingRect . TopLeft ( ) ;
2014-09-10 21:29:35 +04:00
maskTransform . PreTranslate ( - p . x , - p . y ) ;
2012-06-26 06:43:30 +04:00
// imageTransform is only used when the clip is painted to the mask
2013-12-30 03:35:53 +04:00
gfx : : Matrix imageTransform = maskTransform ;
2014-09-10 21:29:35 +04:00
imageTransform . PreScale ( mParameters . mXScale , mParameters . mYScale ) ;
2012-06-26 06:43:30 +04:00
2012-09-04 05:02:56 +04:00
nsAutoPtr < MaskLayerImageCache : : MaskLayerImageKey > newKey (
2012-12-12 01:57:52 +04:00
new MaskLayerImageCache : : MaskLayerImageKey ( ) ) ;
2012-09-04 05:02:56 +04:00
2012-06-26 06:43:30 +04:00
// copy and transform the rounded rects
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < newData . mRoundedClipRects . Length ( ) ; + + i ) {
2012-09-04 05:02:56 +04:00
newKey - > mRoundedClipRects . AppendElement (
2012-06-26 06:43:30 +04:00
MaskLayerImageCache : : PixelRoundedRect ( newData . mRoundedClipRects [ i ] ,
mContainerFrame - > PresContext ( ) ) ) ;
2012-09-04 05:02:56 +04:00
newKey - > mRoundedClipRects [ i ] . ScaleAndTranslate ( imageTransform ) ;
2012-02-08 02:27:44 +04:00
}
2017-08-10 05:43:11 +03:00
newKey - > mKnowsCompositor = mManager - > AsKnowsCompositor ( ) ;
2013-12-30 03:35:53 +04:00
2012-09-04 05:02:56 +04:00
const MaskLayerImageCache : : MaskLayerImageKey * lookupKey = newKey ;
2012-09-03 14:47:51 +04:00
2012-09-04 05:02:56 +04:00
// check to see if we can reuse a mask image
2015-10-18 08:24:48 +03:00
RefPtr < ImageContainer > container =
2012-06-26 06:43:30 +04:00
GetMaskLayerImageCache ( ) - > FindImageFor ( & lookupKey ) ;
2012-09-04 05:02:56 +04:00
if ( ! container ) {
2016-08-18 12:19:55 +03:00
IntSize surfaceSizeInt ( NSToIntCeil ( surfaceSize . width ) ,
2013-12-31 13:06:12 +04:00
NSToIntCeil ( surfaceSize . height ) ) ;
2012-06-26 06:43:30 +04:00
// no existing mask image, so build a new one
2016-05-10 13:18:11 +03:00
MaskImageData imageData ( surfaceSizeInt , mManager ) ;
RefPtr < DrawTarget > dt = imageData . CreateDrawTarget ( ) ;
2012-06-26 06:43:30 +04:00
// fail if we can't get the right surface
2016-04-12 22:18:11 +03:00
if ( ! dt | | ! dt - > IsValid ( ) ) {
2014-04-10 12:49:49 +04:00
NS_WARNING ( " Could not create DrawTarget for mask layer. " ) ;
2015-06-21 02:47:57 +03:00
return nullptr ;
2012-06-26 06:43:30 +04:00
}
2012-02-08 02:27:44 +04:00
2016-06-07 02:39:56 +03:00
RefPtr < gfxContext > context = gfxContext : : CreateOrNull ( dt ) ;
2016-04-12 22:18:11 +03:00
MOZ_ASSERT ( context ) ; // already checked the draw target above
2013-12-30 03:35:53 +04:00
context - > Multiply ( ThebesMatrix ( imageTransform ) ) ;
2012-02-08 02:27:44 +04:00
2012-06-26 06:43:30 +04:00
// paint the clipping rects with alpha to create the mask
2014-11-24 03:04:33 +03:00
aClip . FillIntersectionOfRoundedRectClips ( context ,
Color ( 1.f , 1.f , 1.f , 1.f ) ,
newData . mAppUnitsPerDevPixel ,
0 ,
aRoundedRectClipCount ) ;
2012-02-08 02:27:44 +04:00
2012-06-26 06:43:30 +04:00
// build the image and container
2016-10-26 17:17:24 +03:00
MOZ_ASSERT ( aLayer - > Manager ( ) = = mManager ) ;
container = imageData . CreateImageAndImageContainer ( ) ;
2012-06-26 06:43:30 +04:00
NS_ASSERTION ( container , " Could not create image container for mask layer. " ) ;
2014-04-10 12:49:49 +04:00
2016-10-26 17:17:24 +03:00
if ( ! container ) {
2016-05-10 13:18:11 +03:00
return nullptr ;
}
2012-06-26 02:54:05 +04:00
2012-09-04 05:02:56 +04:00
GetMaskLayerImageCache ( ) - > PutImage ( newKey . forget ( ) , container ) ;
2012-06-26 06:43:30 +04:00
}
2012-06-26 01:44:41 +04:00
2012-06-26 02:54:05 +04:00
maskLayer - > SetContainer ( container ) ;
2013-12-30 03:35:53 +04:00
maskTransform . Invert ( ) ;
2014-01-27 19:28:33 +04:00
Matrix4x4 matrix = Matrix4x4 : : From2D ( maskTransform ) ;
2014-10-16 13:51:12 +04:00
matrix . PreTranslate ( mParameters . mOffset . x , mParameters . mOffset . y , 0 ) ;
2012-09-17 02:25:33 +04:00
maskLayer - > SetBaseTransform ( matrix ) ;
2012-06-26 06:43:30 +04:00
2012-02-08 02:27:44 +04:00
// save the details of the clip in user data
2016-11-07 18:27:35 +03:00
* userData = Move ( newData ) ;
2015-07-13 07:09:57 +03:00
userData - > mImageKey . Reset ( lookupKey ) ;
2012-02-08 02:27:44 +04:00
2015-06-21 02:47:57 +03:00
return maskLayer . forget ( ) ;
2012-02-08 02:27:44 +04:00
}
2010-05-21 07:20:48 +04:00
} // namespace mozilla