2010-05-21 03:20:48 +00:00
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2012-05-21 11:12:37 +00: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 03:20:48 +00:00
2012-12-14 23:58:45 +00:00
# include "mozilla/DebugOnly.h"
2010-05-21 03:20:48 +00:00
# include "FrameLayerBuilder.h"
2015-04-12 02:03:00 +00:00
# include "mozilla/LookAndFeel.h"
# include "mozilla/Maybe.h"
# include "mozilla/dom/ProfileTimelineMarkerBinding.h"
2014-06-27 11:19:40 +00:00
# include "mozilla/gfx/Matrix.h"
2015-04-12 02:03:00 +00:00
# include "ActiveLayerTracker.h"
2010-07-15 21:08:05 +00:00
# include "BasicLayers.h"
2015-12-22 15:54:19 +00:00
# include "DisplayItemScrollClip.h"
2013-10-02 00:57:50 +00:00
# include "ImageContainer.h"
2015-10-22 21:02:14 +00:00
# include "ImageLayers.h"
2015-04-12 02:03:00 +00:00
# include "LayerTreeInvalidation.h"
# include "Layers.h"
2015-10-22 20:04:35 +00:00
# include "LayerUserData.h"
2015-04-12 02:03:00 +00:00
# include "MaskLayerImageCache.h"
# include "UnitTransforms.h"
# include "Units.h"
2013-12-29 23:35:53 +00:00
# include "gfx2DGlue.h"
2015-10-28 13:31:00 +00:00
# include "gfxEnv.h"
2015-04-12 02:03:00 +00:00
# include "gfxUtils.h"
2016-06-07 20:10:18 +00:00
# include "nsAutoPtr.h"
2015-09-10 10:24:34 +00:00
# include "nsAnimationManager.h"
2015-04-12 02:03:00 +00:00
# include "nsDisplayList.h"
2014-09-09 18:54:08 +00:00
# include "nsDocShell.h"
2015-04-12 02:03:00 +00:00
# include "nsIScrollableFrame.h"
2014-09-04 05:02:27 +00:00
# include "nsImageFrame.h"
2015-04-12 02:03:00 +00:00
# include "nsLayoutUtils.h"
# include "nsPresContext.h"
# include "nsPrintfCString.h"
# include "nsRenderingContext.h"
# include "nsSVGIntegrationUtils.h"
2015-09-10 10:24:34 +00:00
# include "nsTransitionManager.h"
2015-08-31 12:56:37 +00:00
# include "mozilla/LayerTimelineMarker.h"
2010-07-15 21:07:51 +00:00
2015-12-09 21:28:10 +00:00
# include "mozilla/EffectCompositor.h"
2015-04-12 02:03:00 +00:00
# include "mozilla/Move.h"
# include "mozilla/ReverseIterator.h"
2013-11-06 19:10:50 +00:00
# include "mozilla/gfx/2D.h"
2015-04-12 02:03:00 +00:00
# include "mozilla/gfx/Tools.h"
2016-05-10 10:18:11 +00:00
# include "mozilla/layers/ShadowLayers.h"
# include "mozilla/layers/TextureClient.h"
# include "mozilla/layers/TextureWrapperImage.h"
2016-08-23 04:09:32 +00:00
# include "mozilla/Unused.h"
2015-04-12 02:03:00 +00:00
# include "GeckoProfiler.h"
# include "LayersLogging.h"
# include "gfxPrefs.h"
2011-11-15 04:59:03 +00:00
2013-01-15 12:22:03 +00:00
# include <algorithm>
2012-07-31 17:28:21 +00:00
2010-05-21 03:20:48 +00:00
using namespace mozilla : : layers ;
2012-10-02 04:00:09 +00:00
using namespace mozilla : : gfx ;
2010-05-21 03:20:48 +00:00
namespace mozilla {
2015-03-02 23:43:58 +00:00
class PaintedDisplayItemLayerUserData ;
2015-04-21 18:13:54 +00:00
static nsTHashtable < nsPtrHashKey < FrameLayerBuilder : : DisplayItemData > > * sAliveDisplayItemDatas ;
2015-07-15 09:05:06 +00: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-05-10 10:18:11 +00: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-22 21:00:16 +00:00
FrameLayerBuilder : : FrameLayerBuilder ( )
: mRetainingManager ( nullptr )
, mDetectedDOMModification ( false )
, mInvalidateAllLayers ( false )
, mInLayerTreeCompressionMode ( false )
, mContainerLayerGeneration ( 0 )
, mMaxContainerLayerGeneration ( 0 )
{
MOZ_COUNT_CTOR ( FrameLayerBuilder ) ;
}
FrameLayerBuilder : : ~ FrameLayerBuilder ( )
{
2016-05-10 10:18:11 +00:00
GetMaskLayerImageCache ( ) - > Sweep ( ) ;
2015-10-22 21:00:16 +00:00
MOZ_COUNT_DTOR ( FrameLayerBuilder ) ;
}
2014-03-20 06:49:27 +00:00
FrameLayerBuilder : : DisplayItemData : : DisplayItemData ( LayerManagerData * aParent , uint32_t aKey ,
2015-04-10 21:11:04 +00:00
Layer * aLayer , nsIFrame * aFrame )
2012-10-11 23:38:24 +00:00
: mParent ( aParent )
2015-04-10 21:11:04 +00:00
, mLayer ( aLayer )
2012-08-21 04:06:46 +00:00
, mDisplayItemKey ( aKey )
2014-07-23 06:03:24 +00:00
, mItem ( nullptr )
2012-10-12 02:39:46 +00:00
, mUsed ( true )
2012-11-06 22:04:53 +00:00
, mIsInvalid ( false )
2012-10-11 23:38:24 +00:00
{
2015-04-21 18:13:54 +00:00
MOZ_COUNT_CTOR ( FrameLayerBuilder : : DisplayItemData ) ;
if ( ! sAliveDisplayItemDatas ) {
sAliveDisplayItemDatas = new nsTHashtable < nsPtrHashKey < FrameLayerBuilder : : DisplayItemData > > ( ) ;
}
MOZ_RELEASE_ASSERT ( ! sAliveDisplayItemDatas - > Contains ( this ) ) ;
sAliveDisplayItemDatas - > PutEntry ( this ) ;
2015-04-10 21:30:09 +00:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2014-07-23 06:03:24 +00:00
if ( aFrame ) {
AddFrame ( aFrame ) ;
}
2015-04-21 18:13:54 +00:00
2012-10-11 23:38:24 +00:00
}
2012-08-21 04:06:46 +00:00
2012-10-11 23:38:24 +00:00
void
2012-10-12 02:39:46 +00:00
FrameLayerBuilder : : DisplayItemData : : AddFrame ( nsIFrame * aFrame )
2012-10-11 23:38:24 +00:00
{
2015-04-10 21:30:09 +00:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2012-10-12 02:39:46 +00:00
mFrameList . AppendElement ( aFrame ) ;
2015-04-10 21:42:42 +00:00
nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( FrameLayerBuilder : : LayerManagerDataProperty ( ) ) ;
2012-10-12 02:39:46 +00:00
if ( ! array ) {
array = new nsTArray < DisplayItemData * > ( ) ;
aFrame - > Properties ( ) . Set ( FrameLayerBuilder : : LayerManagerDataProperty ( ) , array ) ;
2012-10-11 23:38:24 +00:00
}
2012-10-12 02:39:46 +00:00
array - > AppendElement ( this ) ;
2012-08-29 05:47:15 +00:00
}
2012-10-11 23:38:24 +00:00
void
2012-10-16 01:23:07 +00:00
FrameLayerBuilder : : DisplayItemData : : RemoveFrame ( nsIFrame * aFrame )
{
2015-03-16 20:04:00 +00:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2015-04-10 21:34:04 +00:00
bool result = mFrameList . RemoveElement ( aFrame ) ;
MOZ_RELEASE_ASSERT ( result , " Can't remove a frame that wasn't added! " ) ;
2012-10-16 01:23:07 +00:00
2015-04-10 21:42:42 +00:00
nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( FrameLayerBuilder : : LayerManagerDataProperty ( ) ) ;
2015-04-10 21:34:04 +00:00
MOZ_RELEASE_ASSERT ( array , " Must be already stored on the frame! " ) ;
2012-10-16 01:23:07 +00:00
array - > RemoveElement ( this ) ;
}
void
2014-07-23 06:03:24 +00:00
FrameLayerBuilder : : DisplayItemData : : EndUpdate ( )
{
2015-03-16 20:04:00 +00:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2014-07-23 06:03:24 +00:00
MOZ_ASSERT ( ! mItem ) ;
mIsInvalid = false ;
mUsed = false ;
}
void
FrameLayerBuilder : : DisplayItemData : : EndUpdate ( nsAutoPtr < nsDisplayItemGeometry > aGeometry )
{
2015-03-16 20:04:00 +00:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2014-07-23 06:03:24 +00:00
MOZ_ASSERT ( mItem ) ;
2015-11-06 03:57:47 +00:00
MOZ_ASSERT ( mGeometry | | aGeometry ) ;
2014-07-23 06:03:24 +00:00
2015-11-06 03:57:47 +00:00
if ( aGeometry ) {
mGeometry = aGeometry ;
}
2014-07-23 06:03:24 +00:00
mClip = mItem - > GetClip ( ) ;
mFrameListChanges . Clear ( ) ;
mItem = nullptr ;
EndUpdate ( ) ;
}
void
FrameLayerBuilder : : DisplayItemData : : BeginUpdate ( Layer * aLayer , LayerState aState ,
uint32_t aContainerLayerGeneration ,
nsDisplayItem * aItem /* = nullptr */ )
2012-10-11 23:38:24 +00:00
{
2015-04-10 21:30:09 +00:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2015-03-16 20:04:00 +00:00
MOZ_RELEASE_ASSERT ( aLayer ) ;
2012-10-12 02:39:46 +00:00
mLayer = aLayer ;
mOptLayer = nullptr ;
mInactiveManager = nullptr ;
mLayerState = aState ;
mContainerLayerGeneration = aContainerLayerGeneration ;
mUsed = true ;
2012-10-16 01:23:07 +00:00
2014-09-26 17:06:08 +00:00
if ( aLayer - > AsPaintedLayer ( ) ) {
2014-07-23 06:03:24 +00:00
mItem = aItem ;
}
2012-10-16 01:23:07 +00:00
if ( ! aItem ) {
return ;
}
2014-07-23 06:03:24 +00:00
// We avoid adding or removing element unnecessarily
// since we have to modify userdata each time
2016-02-02 15:36:30 +00:00
AutoTArray < nsIFrame * , 4 > copy ( mFrameList ) ;
2013-04-19 12:02:13 +00:00
if ( ! copy . RemoveElement ( aItem - > Frame ( ) ) ) {
AddFrame ( aItem - > Frame ( ) ) ;
2014-07-23 06:03:24 +00:00
mFrameListChanges . AppendElement ( aItem - > Frame ( ) ) ;
2012-10-16 01:23:07 +00:00
}
2016-02-02 15:36:30 +00:00
AutoTArray < nsIFrame * , 4 > mergedFrames ;
2012-10-16 01:23:07 +00:00
aItem - > GetMergedFrames ( & mergedFrames ) ;
for ( uint32_t i = 0 ; i < mergedFrames . Length ( ) ; + + i ) {
if ( ! copy . RemoveElement ( mergedFrames [ i ] ) ) {
AddFrame ( mergedFrames [ i ] ) ;
2014-07-23 06:03:24 +00:00
mFrameListChanges . AppendElement ( mergedFrames [ i ] ) ;
2012-10-16 01:23:07 +00:00
}
}
for ( uint32_t i = 0 ; i < copy . Length ( ) ; i + + ) {
2014-03-20 06:49:27 +00:00
RemoveFrame ( copy [ i ] ) ;
2014-07-23 06:03:24 +00:00
mFrameListChanges . AppendElement ( copy [ i ] ) ;
2012-10-16 01:23:07 +00:00
}
2012-10-11 23:38:24 +00:00
}
2016-01-28 03:23:59 +00:00
static const nsIFrame * sDestroyedFrame = nullptr ;
2012-08-21 04:06:46 +00:00
FrameLayerBuilder : : DisplayItemData : : ~ DisplayItemData ( )
2012-10-11 23:38:24 +00:00
{
2015-04-21 18:13:54 +00:00
MOZ_COUNT_DTOR ( FrameLayerBuilder : : DisplayItemData ) ;
2015-04-10 21:30:09 +00:00
MOZ_RELEASE_ASSERT ( mLayer ) ;
2012-10-11 23:38:24 +00:00
for ( uint32_t i = 0 ; i < mFrameList . Length ( ) ; i + + ) {
2012-10-12 02:39:46 +00:00
nsIFrame * frame = mFrameList [ i ] ;
if ( frame = = sDestroyedFrame ) {
2012-10-11 23:38:24 +00:00
continue ;
}
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-12 02:39:46 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( frame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
array - > RemoveElement ( this ) ;
2012-10-11 23:38:24 +00:00
}
2015-04-21 18:13:54 +00:00
MOZ_RELEASE_ASSERT ( sAliveDisplayItemDatas & & sAliveDisplayItemDatas - > Contains ( this ) ) ;
sAliveDisplayItemDatas - > RemoveEntry ( this ) ;
if ( sAliveDisplayItemDatas - > Count ( ) = = 0 ) {
delete sAliveDisplayItemDatas ;
sAliveDisplayItemDatas = nullptr ;
}
2012-10-11 23:38:24 +00:00
}
2012-08-21 04:06:46 +00:00
2015-09-16 14:05:00 +00:00
void
FrameLayerBuilder : : DisplayItemData : : ClearAnimationCompositorState ( )
{
if ( mDisplayItemKey ! = nsDisplayItem : : TYPE_TRANSFORM & &
mDisplayItemKey ! = nsDisplayItem : : TYPE_OPACITY ) {
return ;
}
for ( nsIFrame * frame : mFrameList ) {
2016-08-09 23:28:19 +00:00
nsCSSPropertyID prop = mDisplayItemKey = = nsDisplayItem : : TYPE_TRANSFORM ?
2015-09-16 14:05:00 +00:00
eCSSProperty_transform : eCSSProperty_opacity ;
2016-01-12 22:54:56 +00:00
EffectCompositor : : ClearIsRunningOnCompositor ( frame , prop ) ;
2015-09-16 14:05:00 +00:00
}
}
2014-07-23 06:03:24 +00:00
const nsTArray < nsIFrame * > &
FrameLayerBuilder : : DisplayItemData : : GetFrameListChanges ( )
2012-08-29 05:47:15 +00:00
{
2014-07-23 06:03:24 +00:00
return mFrameListChanges ;
2012-08-29 05:47:15 +00:00
}
2010-05-21 03:20:48 +00:00
/**
2010-07-15 21:07:51 +00:00
* This is the userdata we associate with a layer manager .
2010-05-21 03:20:48 +00:00
*/
2010-09-02 09:18:39 +00:00
class LayerManagerData : public LayerUserData {
2010-05-21 03:20:48 +00:00
public :
2014-09-01 03:36:37 +00:00
explicit LayerManagerData ( LayerManager * aManager )
2012-10-11 23:38:24 +00:00
: mLayerManager ( aManager )
2012-10-12 02:39:46 +00:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-11 23:38:24 +00:00
, mParent ( nullptr )
2012-10-12 02:39:46 +00:00
# endif
2012-10-11 23:38:24 +00:00
, mInvalidateAllLayers ( false )
2010-05-21 03:20:48 +00:00
{
2010-09-02 09:18:39 +00:00
MOZ_COUNT_CTOR ( LayerManagerData ) ;
2010-05-21 03:20:48 +00:00
}
2010-09-02 09:18:39 +00:00
~ LayerManagerData ( ) {
2012-08-29 05:48:41 +00:00
MOZ_COUNT_DTOR ( LayerManagerData ) ;
2010-09-02 09:18:39 +00:00
}
2014-03-20 06:49:27 +00:00
2012-10-11 23:38:25 +00:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
void Dump ( const char * aPrefix = " " ) {
2013-11-23 22:44:18 +00:00
printf_stderr ( " %sLayerManagerData %p \n " , aPrefix , this ) ;
2015-07-15 09:05:06 +00: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 ;
}
uint32_t mask = ( 1 < < nsDisplayItem : : TYPE_BITS ) - 1 ;
nsAutoCString str ;
str + = prefix ;
str + = nsPrintfCString ( " Frame %p " , data - > mFrameList [ 0 ] ) ;
str + = nsDisplayItem : : DisplayItemTypeName ( static_cast < nsDisplayItem : : Type > ( data - > mDisplayItemKey & mask ) ) ;
if ( ( data - > mDisplayItemKey > > nsDisplayItem : : TYPE_BITS ) ) {
str + = nsPrintfCString ( " (%i) " , data - > mDisplayItemKey > > nsDisplayItem : : TYPE_BITS ) ;
}
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-11 23:38:25 +00:00
}
# endif
2010-07-15 21:07:51 +00:00
/**
* Tracks which frames have layers associated with them .
*/
2012-10-11 23:38:24 +00:00
LayerManager * mLayerManager ;
2012-10-12 02:39:46 +00:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-11 23:38:24 +00:00
LayerManagerData * mParent ;
2012-10-12 02:39:46 +00:00
# endif
2012-10-11 23:38:24 +00:00
nsTHashtable < nsRefPtrHashKey < FrameLayerBuilder : : DisplayItemData > > mDisplayItems ;
2011-09-29 06:19:26 +00:00
bool mInvalidateAllLayers ;
2010-07-15 21:07:51 +00:00
} ;
2012-08-29 05:48:41 +00:00
/* static */ void
FrameLayerBuilder : : DestroyDisplayItemDataFor ( nsIFrame * aFrame )
{
FrameProperties props = aFrame - > Properties ( ) ;
props . Delete ( LayerManagerDataProperty ( ) ) ;
}
2015-03-04 05:21:55 +00: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 12:11:01 +00:00
/**
2014-09-26 17:06:08 +00:00
* We keep a stack of these to represent the PaintedLayers that are
2013-12-16 12:11:01 +00: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 17:06:08 +00: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 12:11:01 +00: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 17:06:08 +00:00
class PaintedLayerData {
2013-12-16 12:11:01 +00:00
public :
2015-06-16 17:41:59 +00:00
PaintedLayerData ( ) :
mAnimatedGeometryRoot ( nullptr ) ,
2015-12-22 15:54:19 +00:00
mScrollClip ( nullptr ) ,
2014-02-26 04:17:18 +00:00
mReferenceFrame ( nullptr ) ,
2013-12-16 12:11:01 +00:00
mLayer ( nullptr ) ,
2015-12-14 03:06:00 +00:00
mSolidColor ( NS_RGBA ( 0 , 0 , 0 , 0 ) ) ,
2013-12-16 12:11:01 +00:00
mIsSolidColorInVisibleRegion ( false ) ,
2014-10-24 16:32:23 +00:00
mFontSmoothingBackgroundColor ( NS_RGBA ( 0 , 0 , 0 , 0 ) ) ,
2016-08-03 17:48:10 +00:00
mSingleItemFixedToViewport ( false ) ,
2013-12-16 12:11:01 +00:00
mNeedComponentAlpha ( false ) ,
mForceTransparentSurface ( false ) ,
2014-06-23 04:24:00 +00:00
mHideAllLayersBelow ( false ) ,
2014-08-31 03:29:24 +00:00
mOpaqueForAnimatedGeometryRootParent ( false ) ,
2015-06-26 22:13:50 +00:00
mDisableFlattening ( false ) ,
2015-09-17 01:31:00 +00:00
mBackfaceHidden ( false ) ,
2013-12-16 12:11:01 +00:00
mImage ( nullptr ) ,
mCommonClipCount ( - 1 ) ,
2015-06-16 17:41:59 +00:00
mNewChildLayersIndex ( - 1 )
2014-02-21 01:11:17 +00:00
{ }
2014-11-25 22:05:39 +00:00
# ifdef MOZ_DUMP_PAINTING
/**
* Keep track of important decisions for debugging .
*/
2015-05-10 14:18:52 +00:00
nsCString mLog ;
2014-11-25 22:05:39 +00:00
2014-11-26 18:58:15 +00:00
# define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
2014-12-31 20:21:58 +00:00
if ( gfxPrefs : : LayersDumpDecision ( ) ) { \
pld - > mLog . AppendPrintf ( " \t \t \t \t " ) ; \
pld - > mLog . AppendPrintf ( __VA_ARGS__ ) ; \
}
2014-11-25 22:05:39 +00:00
# else
# define FLB_LOG_PAINTED_LAYER_DECISION(...)
# endif
2013-12-16 12:11:01 +00:00
/**
2014-09-26 17:06:08 +00:00
* Record that an item has been added to the PaintedLayer , so we
2013-12-16 12:11:01 +00: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 ,
2014-06-09 04:48:00 +00:00
const nsIntRegion & aClippedOpaqueRegion ,
2013-12-16 12:11:01 +00:00
const nsIntRect & aVisibleRect ,
2015-03-04 05:21:55 +00:00
const DisplayItemClip & aClip ,
LayerState aLayerState ) ;
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * GetAnimatedGeometryRoot ( ) { return mAnimatedGeometryRoot ; }
2013-12-16 12:11:01 +00:00
2016-07-20 23:02:09 +00:00
/**
* A region including the horizontal pan , vertical pan , and no action regions .
*/
nsRegion CombinedTouchActionRegion ( ) ;
2013-12-16 12:16:24 +00:00
/**
2014-11-25 22:05:39 +00:00
* Add the given hit regions to the hit regions to the hit retions for this
* PaintedLayer .
2013-12-16 12:16:24 +00:00
*/
2015-08-31 23:53:34 +00:00
void AccumulateEventRegions ( ContainerState * aState , nsDisplayLayerEventRegions * aEventRegions ) ;
2013-12-16 12:16:24 +00:00
2013-12-16 12:11:01 +00:00
/**
2015-05-13 07:23:46 +00:00
* If this represents only a nsDisplayImage , and the image type supports being
* optimized to an ImageLayer , returns true .
2013-12-16 12:11:01 +00:00
*/
2015-05-13 07:23:46 +00: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 12:11:01 +00:00
2015-02-18 18:01:40 +00:00
bool VisibleAboveRegionIntersects ( const nsIntRegion & aRegion ) const
2015-04-02 18:22:40 +00:00
{ return ! mVisibleAboveRegion . Intersect ( aRegion ) . IsEmpty ( ) ; }
bool VisibleRegionIntersects ( const nsIntRegion & aRegion ) const
{ return ! mVisibleRegion . Intersect ( aRegion ) . IsEmpty ( ) ; }
2014-02-26 04:17:18 +00:00
2013-12-16 12:11:01 +00: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 17:41:59 +00:00
nsIntRegion mVisibleRegion ;
2013-12-16 12:11:01 +00:00
/**
* The region of visible content in the layer that is opaque .
* Same coordinate system as mVisibleRegion .
*/
nsIntRegion mOpaqueRegion ;
2013-12-16 12:16:24 +00:00
/**
2014-09-26 17:06:08 +00:00
* The definitely - hit region for this PaintedLayer .
2013-12-16 12:16:24 +00:00
*/
2014-06-20 03:56:36 +00:00
nsRegion mHitRegion ;
2013-12-16 12:16:24 +00:00
/**
2014-09-26 17:06:08 +00:00
* The maybe - hit region for this PaintedLayer .
2013-12-16 12:16:24 +00:00
*/
2014-06-20 03:56:36 +00:00
nsRegion mMaybeHitRegion ;
2013-12-16 12:16:24 +00:00
/**
2014-09-26 17:06:08 +00:00
* The dispatch - to - content hit region for this PaintedLayer .
2013-12-16 12:16:24 +00:00
*/
2014-06-20 03:56:36 +00:00
nsRegion mDispatchToContentHitRegion ;
2015-03-24 13:13:24 +00: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-08-31 23:53:34 +00:00
/**
2015-09-04 16:14:28 +00:00
* Scaled versions of the bounds of mHitRegion and mMaybeHitRegion .
2015-08-31 23:53:34 +00:00
* We store these because FindPaintedLayerFor ( ) needs to consume them
2015-09-04 16:14:28 +00:00
* in this form , and it ' s a hot code path so we don ' t want to scale
2015-08-31 23:53:34 +00:00
* them inside that function .
*/
2015-09-04 16:14:28 +00:00
nsIntRect mScaledHitRegionBounds ;
nsIntRect mScaledMaybeHitRegionBounds ;
2013-12-16 12:11:01 +00:00
/**
* The " active scrolled root " for all content in the layer . Must
2014-09-26 17:06:08 +00:00
* be non - null ; all content in a PaintedLayer must have the same
2013-12-16 12:11:01 +00:00
* active scrolled root .
*/
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2015-08-26 22:16:51 +00:00
/**
2015-12-22 15:54:19 +00:00
* The scroll clip for this layer .
2015-08-26 22:16:51 +00:00
*/
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * mScrollClip ;
2015-03-04 05:21:55 +00:00
/**
* The offset between mAnimatedGeometryRoot and the reference frame .
*/
nsPoint mAnimatedGeometryRootOffset ;
2014-02-26 04:17:18 +00: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 12:11:01 +00:00
const nsIFrame * mReferenceFrame ;
2014-09-26 17:06:08 +00:00
PaintedLayer * mLayer ;
2013-12-16 12:11:01 +00: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 ;
2014-10-24 16:32:23 +00:00
/**
* The target background color for smoothing fonts that are drawn on top of
* transparent parts of the layer .
*/
nscolor mFontSmoothingBackgroundColor ;
2014-02-21 01:11:17 +00:00
/**
2016-08-03 17:48:10 +00:00
* True if the layer contains exactly one item that returned true for
* ShouldFixToViewport .
2014-02-21 01:11:17 +00:00
*/
2016-08-03 17:48:10 +00:00
bool mSingleItemFixedToViewport ;
2013-12-16 12:11:01 +00:00
/**
* 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 04:24:00 +00:00
/**
2014-09-26 17:06:08 +00:00
* Set if all layers below this PaintedLayer should be hidden .
2014-06-23 04:24:00 +00:00
*/
bool mHideAllLayersBelow ;
2014-08-31 03:29:24 +00: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 17:06:08 +00: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 03:29:24 +00:00
*/
bool mOpaqueForAnimatedGeometryRootParent ;
2015-06-26 22:13:50 +00:00
/**
* Set if there is content in the layer that must avoid being flattened .
*/
bool mDisableFlattening ;
2015-09-17 01:31:00 +00: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 ;
2013-12-16 12:11:01 +00: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 17:07:06 +00:00
* by PaintedDisplayItemLayerUserData : : GetCommonClipCount ( ) - which may even be
2013-12-16 12:11:01 +00: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 04:24:00 +00:00
/**
* Index of this layer in mNewChildLayers .
*/
int32_t mNewChildLayersIndex ;
2013-12-16 12:11:01 +00: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 ) ;
2014-09-15 20:09:52 +00:00
/**
* The union of all the bounds of the display items in this layer .
*/
2014-12-12 16:25:36 +00:00
nsIntRect mBounds ;
2013-12-16 12:11:01 +00:00
/**
* The region of visible content above the layer and below the
2015-04-02 18:22:40 +00:00
* next PaintedLayerData currently in the stack , if any .
2013-12-16 12:11:01 +00:00
* This is a conservative approximation : it contains the true region .
*/
2015-06-16 17:41:59 +00:00
nsIntRegion mVisibleAboveRegion ;
2015-03-04 05:21:55 +00: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 15:53:24 +00:00
2013-12-16 12:11:01 +00:00
} ;
2014-06-23 04:24:00 +00:00
struct NewLayerEntry {
NewLayerEntry ( )
: mAnimatedGeometryRoot ( nullptr )
2015-12-22 15:54:19 +00:00
, mScrollClip ( nullptr )
2014-06-23 04:24:00 +00:00
, mLayerContentsVisibleRect ( 0 , 0 , - 1 , - 1 )
2016-01-13 23:42:27 +00:00
, mLayerState ( LAYER_INACTIVE )
2014-06-23 04:24:00 +00:00
, mHideAllLayersBelow ( false )
, mOpaqueForAnimatedGeometryRootParent ( false )
2014-07-22 22:53:37 +00:00
, mPropagateComponentAlphaFlattening ( true )
2015-09-17 01:31:00 +00:00
, mUntransformedVisibleRegion ( false )
2014-06-23 04:24:00 +00:00
{ }
2014-09-26 17:06:08 +00:00
// mLayer is null if the previous entry is for a PaintedLayer that hasn't
2014-06-23 04:24:00 +00:00
// been optimized to some other form (yet).
2015-10-18 05:24:48 +00:00
RefPtr < Layer > mLayer ;
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * mScrollClip ;
2016-03-28 23:14:52 +00:00
// If non-null, this ScrollMetadata is set to the be the first ScrollMetadata
2014-08-31 03:29:24 +00:00
// on the layer.
2016-03-28 23:14:52 +00:00
UniquePtr < ScrollMetadata > mBaseScrollMetadata ;
2014-06-23 04:24:00 +00: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-13 23:42:27 +00:00
LayerState mLayerState ;
2014-06-23 04:24:00 +00: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-22 22:53:37 +00: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 01:31:00 +00:00
// mVisibleRegion is relative to the associated frame before
// transform.
bool mUntransformedVisibleRegion ;
2014-06-23 04:24:00 +00:00
} ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00:00
~ PaintedLayerDataNode ( ) ;
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * GetAnimatedGeometryRoot ( ) const { return mAnimatedGeometryRoot ; }
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerDataNode * AddChildNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00: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 01:31:00 +00:00
bool aBackfaceHidden ,
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * aScrollClip ,
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2015-04-02 18:22:40 +00: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 17:41:59 +00:00
nsIntRegion mVisibleAboveBackgroundRegion ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
void AddingOwnLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerData * FindPaintedLayerFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * aScrollClip ,
2015-04-02 18:22:40 +00:00
const nsIntRect & aVisibleRect ,
2015-09-17 01:31:00 +00:00
bool aBackfaceidden ,
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
AnimatedGeometryRoot * GetParentAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
bool IsClippedWithRespectToParentAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 18:22:40 +00:00
nsIntRect * aOutClip ) ;
/**
* Called by PaintedLayerDataNode when it is finished , so that we can drop
* our pointers to it .
*/
2015-11-24 22:53:51 +00:00
void NodeWasFinished ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
void FinishPotentiallyIntersectingNodes ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerDataNode * EnsureNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
FindNodeForAncestorAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
AnimatedGeometryRoot * * aOutAncestorChild ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
nsDataHashtable < nsPtrHashKey < AnimatedGeometryRoot > , PaintedLayerDataNode * > mNodes ;
2015-04-02 18:22:40 +00:00
} ;
2010-07-15 21:07:51 +00: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 17:03:51 +00:00
FrameLayerBuilder * aLayerBuilder ,
2010-07-15 21:07:51 +00:00
nsIFrame * aContainerFrame ,
2012-09-28 11:19:39 +00:00
nsDisplayItem * aContainerItem ,
2014-06-09 04:48:00 +00:00
const nsRect & aContainerBounds ,
2011-06-22 12:11:27 +00:00
ContainerLayer * aContainerLayer ,
2014-09-06 04:16:33 +00:00
const ContainerLayerParameters & aParameters ,
2015-02-25 16:47:22 +00:00
bool aFlattenToSingleLayer ,
2015-12-22 15:54:19 +00:00
nscolor aBackgroundColor ,
const DisplayItemScrollClip * aContainerScrollClip ) :
2010-07-15 21:07:51 +00:00
mBuilder ( aBuilder ) , mManager ( aManager ) ,
2012-07-17 17:03:51 +00:00
mLayerBuilder ( aLayerBuilder ) ,
2012-09-28 11:19:39 +00:00
mContainerFrame ( aContainerFrame ) ,
mContainerLayer ( aContainerLayer ) ,
2014-06-09 04:48:00 +00:00
mContainerBounds ( aContainerBounds ) ,
2015-12-22 15:54:19 +00:00
mContainerScrollClip ( aContainerScrollClip ) ,
2016-02-26 00:29:41 +00:00
mScrollClipForPerspectiveChild ( aParameters . mScrollClipForPerspectiveChild ) ,
2011-06-22 12:11:27 +00:00
mParameters ( aParameters ) ,
2015-04-02 18:22:40 +00:00
mPaintedLayerDataTree ( * this , aBackgroundColor ) ,
2014-09-06 04:16:33 +00:00
mFlattenToSingleLayer ( aFlattenToSingleLayer )
2010-05-21 03:20:48 +00:00
{
2012-04-10 11:24:18 +00:00
nsPresContext * presContext = aContainerFrame - > PresContext ( ) ;
mAppUnitsPerDevPixel = presContext - > AppUnitsPerDevPixel ( ) ;
2014-06-20 03:56:36 +00:00
mContainerReferenceFrame =
const_cast < nsIFrame * > ( aContainerItem ? aContainerItem - > ReferenceFrameForChildren ( ) :
mBuilder - > FindReferenceFrameFor ( mContainerFrame ) ) ;
2015-04-02 18:22:40 +00:00
bool isAtRoot = ! aContainerItem | | ( aContainerItem - > Frame ( ) = = mBuilder - > RootReferenceFrame ( ) ) ;
MOZ_ASSERT_IF ( isAtRoot , mContainerReferenceFrame = = mBuilder - > RootReferenceFrame ( ) ) ;
mContainerAnimatedGeometryRoot = isAtRoot
2015-11-24 22:53:51 +00:00
? aBuilder - > GetRootAnimatedGeometryRoot ( )
: aContainerItem - > GetAnimatedGeometryRoot ( ) ;
2015-11-03 08:03:47 +00:00
MOZ_ASSERT ( ! mBuilder - > IsPaintingToWindow ( ) | |
nsLayoutUtils : : IsAncestorFrameCrossDoc ( mBuilder - > RootReferenceFrame ( ) ,
2015-11-24 22:53:51 +00:00
* mContainerAnimatedGeometryRoot ) ) ;
2012-04-10 11:24:18 +00: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-15 21:08:03 +00:00
CollectOldLayers ( ) ;
2010-05-21 03:20:48 +00:00
}
2010-07-15 21:07:51 +00:00
/**
* This is the method that actually walks a display list and builds
2013-03-04 09:56:02 +00:00
* the child layers .
2010-07-15 21:07:51 +00:00
*/
2014-09-06 04:16:33 +00:00
void ProcessDisplayItems ( nsDisplayList * aList ) ;
2010-07-15 21:07:51 +00:00
/**
2014-09-26 17:06:08 +00:00
* This finalizes all the open PaintedLayers by popping every element off
* mPaintedLayerDataStack , then sets the children of the container layer
2010-07-15 21:07:51 +00: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 01:26:14 +00:00
* @ param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA ,
* set * aTextContentFlags to CONTENT_COMPONENT_ALPHA
2010-07-15 21:07:51 +00:00
*/
2015-12-16 05:24:06 +00:00
void Finish ( uint32_t * aTextContentFlags ,
2014-06-23 04:24:00 +00:00
const nsIntRect & aContainerPixelBounds ,
2016-01-13 23:42:27 +00:00
nsDisplayList * aChildItems , bool * aHasComponentAlphaChildren ) ;
2014-07-17 15:24:47 +00:00
2012-04-10 11:24:18 +00:00
nscoord GetAppUnitsPerDevPixel ( ) { return mAppUnitsPerDevPixel ; }
2015-03-25 22:08:56 +00:00
nsIntRect ScaleToNearestPixels ( const nsRect & aRect ) const
2012-04-10 11:24:18 +00:00
{
return aRect . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-25 22:08:56 +00:00
nsIntRegion ScaleRegionToNearestPixels ( const nsRegion & aRegion ) const
2012-07-23 03:00:36 +00:00
{
return aRegion . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-25 22:08:56 +00:00
nsIntRect ScaleToOutsidePixels ( const nsRect & aRect , bool aSnap = false ) const
2012-04-10 11:24:18 +00:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-25 22:08:56 +00:00
nsIntRect ScaleToInsidePixels ( const nsRect & aRect , bool aSnap = false ) const
2012-04-10 11:24:18 +00:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToInsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2015-03-25 22:08:56 +00:00
nsIntRegion ScaleRegionToInsidePixels ( const nsRegion & aRegion , bool aSnap = false ) const
2012-07-23 03:00:36 +00:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleRegionToNearestPixels ( aRegion ) ;
}
return aRegion . ScaleToInsidePixels ( mParameters . mXScale , mParameters . mYScale ,
2013-12-16 12:11:59 +00:00
mAppUnitsPerDevPixel ) ;
}
2015-03-25 22:08:56 +00:00
nsIntRegion ScaleRegionToOutsidePixels ( const nsRegion & aRegion , bool aSnap = false ) const
2013-12-16 12:11:59 +00:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleRegionToNearestPixels ( aRegion ) ;
}
return aRegion . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
2012-07-23 03:00:36 +00:00
mAppUnitsPerDevPixel ) ;
}
2014-06-23 04:24:00 +00:00
nsIFrame * GetContainerFrame ( ) const { return mContainerFrame ; }
2015-04-02 18:22:40 +00:00
nsDisplayListBuilder * Builder ( ) const { return mBuilder ; }
2014-06-23 04:24:00 +00:00
2015-06-26 21:26:06 +00:00
/**
* Check if we are currently inside an inactive layer .
*/
bool IsInInactiveLayer ( ) const {
return mLayerBuilder - > GetContainingPaintedLayerData ( ) ;
}
2014-06-23 04:24:00 +00:00
/**
2015-09-17 01:31:00 +00: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 04:24:00 +00:00
*/
void SetOuterVisibleRegionForLayer ( Layer * aLayer ,
const nsIntRegion & aOuterVisibleRegion ,
2015-09-17 01:31:00 +00:00
const nsIntRect * aLayerContentsVisibleRect = nullptr ,
bool aOuterUntransformed = false ) const ;
2014-06-23 04:24:00 +00:00
2015-04-02 18:22:40 +00: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-15 21:07:51 +00:00
protected :
2014-09-26 17:06:08 +00:00
friend class PaintedLayerData ;
2010-05-21 03:20:48 +00:00
2015-03-03 00:24:18 +00:00
LayerManager : : PaintedLayerCreationHint
2015-11-24 22:53:51 +00:00
GetLayerCreationHint ( AnimatedGeometryRoot * aAnimatedGeometryRoot ) ;
2015-03-03 00:24:18 +00:00
2010-07-15 21:07:51 +00:00
/**
2015-03-04 05:18:47 +00:00
* Creates a new PaintedLayer and sets up the transform on the PaintedLayer
2010-07-15 21:08:03 +00:00
* to account for scrolling .
2010-07-15 21:07:51 +00:00
*/
2015-03-04 05:18:47 +00:00
already_AddRefed < PaintedLayer > CreatePaintedLayer ( PaintedLayerData * aData ) ;
2015-03-02 23:43:58 +00:00
2015-03-03 00:25:13 +00:00
/**
* Find a PaintedLayer for recycling , recycle it and prepare it for use , or
* return null if no suitable layer was found .
*/
2015-11-24 22:53:51 +00:00
already_AddRefed < PaintedLayer > AttemptToRecyclePaintedLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-04 05:21:00 +00:00
nsDisplayItem * aItem ,
2015-03-03 00:25:13 +00:00
const nsPoint & aTopLeft ) ;
2015-03-02 23:43:58 +00:00
/**
* Recycle aLayer and do any necessary invalidation .
*/
PaintedDisplayItemLayerUserData * RecyclePaintedLayer ( PaintedLayer * aLayer ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-02 23:43:58 +00:00
bool & didResetScrollPositionForLayerPixelAlignment ) ;
/**
2015-03-04 05:18:47 +00: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-02 23:43:58 +00:00
*/
void PreparePaintedLayerForUse ( PaintedLayer * aLayer ,
PaintedDisplayItemLayerUserData * aData ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-02 23:43:58 +00:00
const nsIFrame * aReferenceFrame ,
const nsPoint & aTopLeft ,
bool aDidResetScrollPositionForLayerPixelAlignment ) ;
2015-05-13 07:23:46 +00: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-15 21:07:51 +00:00
/**
2010-07-15 21:08:03 +00:00
* Grab the next recyclable ColorLayer , or create one if there are no
* more recyclable ColorLayers .
*/
2014-09-26 17:07:06 +00:00
already_AddRefed < ColorLayer > CreateOrRecycleColorLayer ( PaintedLayer * aPainted ) ;
2011-01-17 21:47:18 +00:00
/**
* Grab the next recyclable ImageLayer , or create one if there are no
* more recyclable ImageLayers .
*/
2014-09-26 17:07:06 +00:00
already_AddRefed < ImageLayer > CreateOrRecycleImageLayer ( PaintedLayer * aPainted ) ;
2012-02-07 22:26:40 +00: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 16:28:10 +00: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-07 22:26:40 +00:00
*/
2015-06-21 16:28:10 +00:00
struct MaskLayerKey ;
already_AddRefed < ImageLayer > CreateOrRecycleMaskImageLayerFor ( const MaskLayerKey & aKey ) ;
2010-07-15 21:08:03 +00:00
/**
2014-09-26 17:06:08 +00:00
* Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes them
2010-07-15 21:07:51 +00:00
* available for recycling .
*/
2010-07-15 21:08:03 +00:00
void CollectOldLayers ( ) ;
2010-07-15 21:08:05 +00:00
/**
2014-09-26 17:06:08 +00: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-15 21:08:05 +00:00
* aItem in that layer .
*/
2014-03-20 06:49:27 +00:00
void InvalidateForLayerChange ( nsDisplayItem * aItem ,
2014-09-26 17:06:08 +00:00
PaintedLayer * aNewLayer ) ;
2014-06-23 04:24:00 +00: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 ) ;
/**
2014-08-31 03:29:24 +00:00
* Set FrameMetrics and scroll - induced clipping on aEntry ' s layer .
*/
void SetupScrollingMetadata ( NewLayerEntry * aEntry ) ;
/**
* Applies occlusion culling .
2014-06-23 04:24:00 +00: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 03:29:24 +00:00
*
* Also sets scroll metadata on the layers .
2014-06-23 04:24:00 +00:00
*/
2014-08-31 03:29:24 +00:00
void PostprocessRetainedLayers ( nsIntRegion * aOpaqueRegionForContainer ) ;
2014-06-23 04:24:00 +00: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-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2014-06-23 04:24:00 +00:00
const DisplayItemClip & aClip ,
nsDisplayList * aList ,
2014-08-31 03:29:24 +00:00
bool * aHideAllLayersBelow ,
bool * aOpaqueForAnimatedGeometryRootParent ) ;
2014-06-23 04:24:00 +00:00
2010-07-15 21:07:51 +00:00
/**
2015-04-02 18:22:40 +00: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 .
2015-12-22 15:54:19 +00:00
* @ param aScrollClip The scroll clip for this PaintedLayer .
2015-04-02 18:22:40 +00:00
* @ param aTopLeft The offset between aAnimatedGeometryRoot and
* the reference frame .
* @ param aShouldFixToViewport If true , aAnimatedGeometryRoot is the
* viewport and we will be adding fixed - pos
* metadata for this layer because the display
* item returned true from ShouldFixToViewport .
2010-07-15 21:07:51 +00:00
*/
2015-04-02 18:22:40 +00:00
PaintedLayerData NewPaintedLayerData ( nsDisplayItem * aItem ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * aScrollClip ,
2015-04-02 18:22:40 +00:00
const nsPoint & aTopLeft ,
bool aShouldFixToViewport ) ;
2010-05-21 03:20:48 +00:00
2012-02-07 22:27:44 +00: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 04:24:00 +00:00
* relative to the container reference frame
2014-09-26 17:06:08 +00:00
* aRoundedRectClipCount is used when building mask layers for PaintedLayers ,
2012-02-07 22:27:44 +00:00
* SetupMaskLayer will build a mask layer for only the first
* aRoundedRectClipCount rounded rects in aClip
*/
2013-03-04 09:55:59 +00:00
void SetupMaskLayer ( Layer * aLayer , const DisplayItemClip & aClip ,
2012-09-28 06:57:33 +00:00
uint32_t aRoundedRectClipCount = UINT32_MAX ) ;
2012-02-07 22:27:44 +00:00
2016-05-06 23:02:26 +00: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 ) ;
2015-06-20 23:47:57 +00:00
already_AddRefed < Layer > CreateMaskLayer (
Layer * aLayer , const DisplayItemClip & aClip ,
const Maybe < size_t > & aForAncestorMaskLayer ,
uint32_t aRoundedRectClipCount = UINT32_MAX ) ;
2013-09-25 21:07:26 +00:00
bool ChooseAnimatedGeometryRoot ( const nsDisplayList & aList ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * * aAnimatedGeometryRoot ) ;
2012-12-11 20:36:22 +00:00
2010-07-15 21:07:51 +00:00
nsDisplayListBuilder * mBuilder ;
LayerManager * mManager ;
2012-07-17 17:03:51 +00:00
FrameLayerBuilder * mLayerBuilder ;
2010-07-15 21:07:51 +00:00
nsIFrame * mContainerFrame ;
2014-06-20 03:56:36 +00:00
nsIFrame * mContainerReferenceFrame ;
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * mContainerAnimatedGeometryRoot ;
2010-07-15 21:07:51 +00:00
ContainerLayer * mContainerLayer ;
2014-06-09 04:48:00 +00:00
nsRect mContainerBounds ;
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * mContainerScrollClip ;
2016-02-26 00:29:41 +00:00
const DisplayItemScrollClip * mScrollClipForPerspectiveChild ;
2016-02-26 15:52:07 +00:00
# ifdef DEBUG
nsRect mAccumulatedChildBounds ;
# endif
2013-09-27 06:01:16 +00:00
ContainerLayerParameters mParameters ;
2010-07-15 21:07:51 +00:00
/**
2014-09-26 17:06:08 +00:00
* The region of PaintedLayers that should be invalidated every time
2010-07-15 21:07:51 +00:00
* we recycle one .
*/
2014-09-26 17:07:06 +00:00
nsIntRegion mInvalidPaintedContent ;
2015-04-02 18:22:40 +00:00
PaintedLayerDataTree mPaintedLayerDataTree ;
2010-07-15 21:07:51 +00: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 17:06:08 +00: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-15 21:07:51 +00:00
*/
2016-02-02 15:36:30 +00:00
typedef AutoTArray < NewLayerEntry , 1 > AutoLayersArray ;
2010-11-09 02:48:59 +00:00
AutoLayersArray mNewChildLayers ;
2015-03-04 05:21:00 +00:00
nsTHashtable < nsRefPtrHashKey < PaintedLayer > > mPaintedLayersAvailableForRecycling ;
2012-04-10 11:24:18 +00:00
nscoord mAppUnitsPerDevPixel ;
bool mSnappingEnabled ;
2014-09-06 04:16:33 +00:00
bool mFlattenToSingleLayer ;
2015-06-21 16:28:10 +00: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 05:24:48 +00:00
nsDataHashtable < nsGenericHashKey < MaskLayerKey > , RefPtr < ImageLayer > >
2015-06-21 16:28:10 +00:00
mRecycledMaskImageLayers ;
2010-05-21 03:20:48 +00:00
} ;
2014-09-26 17:07:06 +00:00
class PaintedDisplayItemLayerUserData : public LayerUserData
2010-09-02 09:18:39 +00:00
{
public :
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData ( ) :
2012-09-06 04:07:53 +00:00
mMaskClipCount ( 0 ) ,
2011-06-22 12:11:28 +00:00
mForcedBackgroundColor ( NS_RGBA ( 0 , 0 , 0 , 0 ) ) ,
2014-10-24 16:32:23 +00:00
mFontSmoothingBackgroundColor ( NS_RGBA ( 0 , 0 , 0 , 0 ) ) ,
2011-06-22 12:11:28 +00:00
mXScale ( 1.f ) , mYScale ( 1.f ) ,
2012-08-29 05:47:15 +00:00
mAppUnitsPerDevPixel ( 0 ) ,
2012-09-16 22:25:33 +00:00
mTranslation ( 0 , 0 ) ,
2015-09-15 13:41:42 +00:00
mAnimatedGeometryRootPosition ( 0 , 0 ) { }
2010-09-02 09:18:39 +00:00
2012-09-04 01:02:56 +00:00
/**
2014-09-26 17:07:06 +00:00
* Record the number of clips in the PaintedLayer ' s mask layer .
2012-09-04 01:02:56 +00: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 10:35:57 +00: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 09:18:39 +00:00
nscolor mForcedBackgroundColor ;
2012-09-04 01:02:56 +00:00
2014-10-24 16:32:23 +00:00
/**
* The target background color for smoothing fonts that are drawn on top of
* transparent parts of the layer .
*/
nscolor mFontSmoothingBackgroundColor ;
2011-06-22 12:11:27 +00:00
/**
* The resolution scale used .
*/
float mXScale , mYScale ;
2012-02-07 22:27:44 +00:00
2012-08-29 05:47:15 +00:00
/**
* The appunits per dev pixel for the items in this layer .
*/
nscoord mAppUnitsPerDevPixel ;
2012-09-16 22:25:33 +00:00
/**
2014-09-26 17:06:08 +00:00
* The offset from the PaintedLayer ' s 0 , 0 to the
2012-09-16 22:25:33 +00:00
* reference frame . This isn ' t necessarily the same as the transform
2014-09-26 17:06:08 +00:00
* set on the PaintedLayer since we might also be applying an extra
2012-09-16 22:25:33 +00:00
* offset specified by the parent ContainerLayer /
*/
nsIntPoint mTranslation ;
2011-06-22 12:11:28 +00:00
/**
2014-09-26 17:06:08 +00:00
* We try to make 0 , 0 of the PaintedLayer be the top - left of the
2011-06-22 12:11:28 +00: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 17:06:08 +00: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 12:11:28 +00:00
* 0 , 0 may not be exactly the top - left of the active scrolled root . Here we
2014-09-26 17:06:08 +00:00
* store the coordinates in PaintedLayer space of the top - left of the
2011-06-22 12:11:28 +00:00
* active scrolled root .
*/
2013-09-25 21:07:26 +00:00
gfxPoint mAnimatedGeometryRootPosition ;
2012-08-20 10:00:49 +00:00
2012-08-29 05:47:15 +00:00
nsIntRegion mRegionToInvalidate ;
2012-09-28 11:19:39 +00:00
// The offset between the active scrolled root of this layer
2014-03-20 06:49:27 +00:00
// and the root of the container for the previous and current
2012-09-28 11:19:39 +00:00
// paints respectively.
2013-09-25 21:07:26 +00:00
nsPoint mLastAnimatedGeometryRootOrigin ;
nsPoint mAnimatedGeometryRootOrigin ;
2012-08-29 05:47:15 +00:00
2015-10-18 05:24:48 +00:00
RefPtr < ColorLayer > mColorLayer ;
RefPtr < ImageLayer > mImageLayer ;
2015-07-21 08:19:25 +00:00
2015-09-15 13:41:42 +00: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 ;
2010-09-02 09:18:39 +00:00
} ;
2012-02-07 22:26:33 +00:00
/*
* User data for layers which will be used as masks .
*/
struct MaskLayerUserData : public LayerUserData
{
2014-03-10 22:12:48 +00:00
MaskLayerUserData ( )
: mScaleX ( - 1.0f )
, mScaleY ( - 1.0f )
, mAppUnitsPerDevPixel ( - 1 )
{ }
2012-06-26 02:43:30 +00:00
bool
operator = = ( const MaskLayerUserData & aOther ) const
{
return mRoundedClipRects = = aOther . mRoundedClipRects & &
mScaleX = = aOther . mScaleX & &
2013-04-04 02:59:24 +00:00
mScaleY = = aOther . mScaleY & &
2013-08-09 09:42:05 +00:00
mOffset = = aOther . mOffset & &
mAppUnitsPerDevPixel = = aOther . mAppUnitsPerDevPixel ;
2012-06-26 02:43:30 +00:00
}
2015-07-13 04:09:57 +00:00
// Keeps a MaskLayerImageKey alive by managing its mLayerCount member-var
MaskLayerImageCache : : MaskLayerImageKeyRef mImageKey ;
2012-02-07 22:26:33 +00:00
// properties of the mask layer; the mask layer may be re-used if these
// remain unchanged.
2013-03-04 09:55:59 +00:00
nsTArray < DisplayItemClip : : RoundedRect > mRoundedClipRects ;
2012-06-26 02:43:30 +00:00
// scale from the masked layer which is applied to the mask
float mScaleX , mScaleY ;
2013-09-27 06:01:16 +00:00
// The ContainerLayerParameters offset which is applied to the mask's transform.
2013-04-04 02:59:24 +00:00
nsIntPoint mOffset ;
2013-08-09 09:42:05 +00:00
int32_t mAppUnitsPerDevPixel ;
2012-02-07 22:26:33 +00:00
} ;
2016-05-10 10:18:11 +00:00
class MaskImageData
{
public :
MaskImageData ( const gfx : : IntSize & aSize , LayerManager * aLayerManager )
: mTextureClientLocked ( false )
, mSize ( aSize )
, mLayerManager ( aLayerManager )
{
}
~ MaskImageData ( )
{
if ( mTextureClientLocked ) {
MOZ_ASSERT ( mTextureClient ) ;
// Clear DrawTarget before Unlock.
mDrawTarget = nullptr ;
mTextureClient - > Unlock ( ) ;
}
}
gfx : : DrawTarget * CreateDrawTarget ( )
{
MOZ_ASSERT ( mLayerManager ) ;
if ( mDrawTarget ) {
return mDrawTarget ;
}
if ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_BASIC ) {
mDrawTarget = mLayerManager - > CreateOptimalMaskDrawTarget ( mSize ) ;
return mDrawTarget ;
}
MOZ_ASSERT ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_CLIENT ) ;
ShadowLayerForwarder * fwd = mLayerManager - > AsShadowForwarder ( ) ;
if ( ! fwd ) {
return nullptr ;
}
mTextureClient =
TextureClient : : CreateForDrawing ( fwd ,
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 ;
}
already_AddRefed < Image > CreateImage ( )
{
if ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_BASIC & &
mDrawTarget ) {
RefPtr < SourceSurface > surface = mDrawTarget - > Snapshot ( ) ;
RefPtr < SourceSurfaceImage > image = new SourceSurfaceImage ( mSize , surface ) ;
2016-09-22 21:43:11 +00:00
// Disallow BIGIMAGE (splitting into multiple textures) for mask
// layer images
image - > SetTextureFlags ( TextureFlags : : DISALLOW_BIGIMAGE ) ;
2016-05-10 10:18:11 +00:00
return image . forget ( ) ;
}
if ( mLayerManager - > GetBackendType ( ) = = LayersBackend : : LAYERS_CLIENT & &
mTextureClient & &
mDrawTarget ) {
RefPtr < TextureWrapperImage > image =
new TextureWrapperImage ( mTextureClient , gfx : : IntRect ( gfx : : IntPoint ( 0 , 0 ) , mSize ) ) ;
return image . forget ( ) ;
}
return nullptr ;
}
private :
bool mTextureClientLocked ;
gfx : : IntSize mSize ;
LayerManager * mLayerManager ;
RefPtr < gfx : : DrawTarget > mDrawTarget ;
RefPtr < TextureClient > mTextureClient ;
} ;
2012-02-07 22:27:44 +00: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 17:07:06 +00:00
PaintedDisplayItemLayerUserData * GetPaintedDisplayItemLayerUserData ( Layer * aLayer )
2012-02-07 22:27:44 +00:00
{
2014-09-26 17:07:06 +00:00
return static_cast < PaintedDisplayItemLayerUserData * > (
aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2012-02-07 22:27:44 +00:00
}
2012-06-26 02:43:30 +00:00
/* static */ void
FrameLayerBuilder : : Shutdown ( )
{
if ( gMaskLayerImageCache ) {
delete gMaskLayerImageCache ;
2012-07-30 14:20:58 +00:00
gMaskLayerImageCache = nullptr ;
2012-06-26 02:43:30 +00:00
}
}
2010-09-17 19:09:08 +00:00
void
2013-12-16 12:16:24 +00:00
FrameLayerBuilder : : Init ( nsDisplayListBuilder * aBuilder , LayerManager * aManager ,
2015-04-30 18:54:48 +00:00
PaintedLayerData * aLayerData )
2010-09-17 19:09:08 +00:00
{
2012-08-29 05:47:15 +00:00
mDisplayListBuilder = aBuilder ;
2012-09-16 10:32:59 +00:00
mRootPresContext = aBuilder - > RootReferenceFrame ( ) - > PresContext ( ) - > GetRootPresContext ( ) ;
2010-09-17 19:09:08 +00:00
if ( mRootPresContext ) {
mInitialDOMGeneration = mRootPresContext - > GetDOMGeneration ( ) ;
}
2014-09-26 17:06:08 +00:00
mContainingPaintedLayer = aLayerData ;
2012-08-29 05:48:15 +00:00
aManager - > SetUserData ( & gLayerManagerLayerBuilder , this ) ;
2010-09-17 19:09:08 +00:00
}
2011-11-15 04:59:03 +00:00
void
FrameLayerBuilder : : FlashPaint ( gfxContext * aContext )
{
2013-03-12 18:01:00 +00:00
float r = float ( rand ( ) ) / RAND_MAX ;
float g = float ( rand ( ) ) / RAND_MAX ;
float b = float ( rand ( ) ) / RAND_MAX ;
2015-09-24 06:42:58 +00:00
aContext - > SetColor ( Color ( r , g , b , 0.4f ) ) ;
2013-03-12 18:01:00 +00:00
aContext - > Paint ( ) ;
2011-11-15 04:59:03 +00:00
}
2015-04-21 18:13:54 +00:00
static FrameLayerBuilder : : DisplayItemData *
AssertDisplayItemData ( FrameLayerBuilder : : DisplayItemData * aData )
{
MOZ_RELEASE_ASSERT ( aData ) ;
MOZ_RELEASE_ASSERT ( sAliveDisplayItemDatas & & sAliveDisplayItemDatas - > Contains ( aData ) ) ;
MOZ_RELEASE_ASSERT ( aData - > mLayer ) ;
return aData ;
}
2012-10-11 23:38:24 +00:00
FrameLayerBuilder : : DisplayItemData *
FrameLayerBuilder : : GetDisplayItemData ( nsIFrame * aFrame , uint32_t aKey )
{
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-10-11 23:38:24 +00:00
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
DisplayItemData * item = AssertDisplayItemData ( array - > ElementAt ( i ) ) ;
2012-10-11 23:38:24 +00:00
if ( item - > mDisplayItemKey = = aKey & &
item - > mLayer - > Manager ( ) = = mRetainingManager ) {
return item ;
}
}
2012-08-29 05:47:15 +00:00
}
2012-10-11 23:38:24 +00:00
return nullptr ;
2010-07-15 21:07:51 +00:00
}
2012-08-29 05:47:15 +00: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 01:20:59 +00:00
for ( auto iter = r . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
AppendToString ( s , iter . Get ( ) ) + = " ; " ;
2012-08-29 05:47:15 +00: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-28 22:37:07 +00:00
static void
InvalidatePostTransformRegion ( PaintedLayer * aLayer , const nsIntRegion & aRegion ,
const nsIntPoint & aTranslation )
2012-08-29 05:47:15 +00: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 17:06:08 +00:00
// to the PaintedLayer's own coordinates
2016-03-28 22:37:07 +00:00
nsIntRegion rgn = aRegion ;
2012-08-29 05:47:15 +00:00
rgn . MoveBy ( - aTranslation ) ;
2016-03-28 22:37:07 +00:00
aLayer - > InvalidateRegion ( rgn ) ;
2015-05-28 21:39:34 +00:00
# ifdef MOZ_DUMP_PAINTING
2016-03-28 22:37:07 +00:00
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
nsAutoCString str ;
AppendToString ( str , rgn ) ;
printf_stderr ( " Invalidating layer %p: %s \n " , aLayer , str . get ( ) ) ;
2015-05-28 21:39:34 +00:00
}
2016-03-28 22:37:07 +00:00
# endif
2012-08-29 05:47:15 +00:00
}
2012-10-16 01:10:43 +00:00
static void
2014-09-26 17:06:08 +00:00
InvalidatePostTransformRegion ( PaintedLayer * aLayer , const nsRect & aRect ,
2013-03-04 09:55:59 +00:00
const DisplayItemClip & aClip ,
2012-10-16 01:10:43 +00:00
const nsIntPoint & aTranslation )
{
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * > ( aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2012-10-16 01:10:43 +00:00
nsRect rect = aClip . ApplyNonRoundedIntersection ( aRect ) ;
nsIntRect pixelRect = rect . ScaleToOutsidePixels ( data - > mXScale , data - > mYScale , data - > mAppUnitsPerDevPixel ) ;
2016-03-28 22:37:07 +00:00
InvalidatePostTransformRegion ( aLayer , pixelRect , aTranslation ) ;
2012-10-16 01:10:43 +00:00
}
2012-08-29 05:47:15 +00:00
static nsIntPoint
2014-09-26 17:06:08 +00:00
GetTranslationForPaintedLayer ( PaintedLayer * aLayer )
2012-08-29 05:47:15 +00:00
{
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * >
( aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2014-09-26 17:06:08 +00:00
NS_ASSERTION ( data , " Must be a tracked painted layer! " ) ;
2012-08-29 05:47:15 +00: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 06:49:27 +00:00
* the layer manager destroys the LayerManagerData and calls into
2012-10-12 02:39:46 +00:00
* the DisplayItemData destructor . If the inner layer manager had any
2012-08-29 05:47:15 +00: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-15 21:07:51 +00:00
/* static */ void
2016-01-28 03:23:59 +00:00
FrameLayerBuilder : : RemoveFrameFromLayerManager ( const nsIFrame * aFrame ,
2016-01-28 03:23:59 +00:00
nsTArray < DisplayItemData * > * aArray )
2010-07-15 21:07:51 +00:00
{
2015-04-10 21:34:28 +00:00
MOZ_RELEASE_ASSERT ( ! sDestroyedFrame ) ;
2012-10-11 23:38:24 +00:00
sDestroyedFrame = aFrame ;
// Hold a reference to all the items so that they don't get
// deleted from under us.
2015-10-18 05:24:48 +00:00
nsTArray < RefPtr < DisplayItemData > > arrayCopy ;
2016-01-28 03:23:59 +00:00
for ( DisplayItemData * data : * aArray ) {
arrayCopy . AppendElement ( data ) ;
2012-10-11 23:38:24 +00:00
}
2012-08-29 05:47:15 +00:00
2012-10-11 23:38:25 +00:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2016-01-28 03:23:59 +00:00
if ( aArray - > Length ( ) ) {
LayerManagerData * rootData = aArray - > ElementAt ( 0 ) - > mParent ;
2012-10-11 23:38:25 +00:00
while ( rootData - > mParent ) {
rootData = rootData - > mParent ;
}
2013-11-23 22:44:18 +00:00
printf_stderr ( " Removing frame %p - dumping display data \n " , aFrame ) ;
2012-10-11 23:38:25 +00:00
rootData - > Dump ( ) ;
}
# endif
2016-01-28 03:23:59 +00:00
for ( DisplayItemData * data : * aArray ) {
2014-09-26 17:06:08 +00:00
PaintedLayer * t = data - > mLayer - > AsPaintedLayer ( ) ;
2012-08-29 05:47:15 +00:00
if ( t ) {
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * paintedData =
static_cast < PaintedDisplayItemLayerUserData * > ( t - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
if ( paintedData ) {
2012-10-11 23:38:24 +00:00
nsRegion old = data - > mGeometry - > ComputeInvalidationRegion ( ) ;
2014-09-26 17:07:06 +00:00
nsIntRegion rgn = old . ScaleToOutsidePixels ( paintedData - > mXScale , paintedData - > mYScale , paintedData - > mAppUnitsPerDevPixel ) ;
2014-09-26 17:06:08 +00:00
rgn . MoveBy ( - GetTranslationForPaintedLayer ( t ) ) ;
2014-09-26 17:07:06 +00:00
paintedData - > mRegionToInvalidate . Or ( paintedData - > mRegionToInvalidate , rgn ) ;
paintedData - > mRegionToInvalidate . SimplifyOutward ( 8 ) ;
2012-08-29 05:47:15 +00:00
}
}
2012-10-11 23:38:24 +00:00
data - > mParent - > mDisplayItems . RemoveEntry ( data ) ;
2012-09-27 15:34:46 +00:00
}
2012-09-28 11:19:39 +00:00
2012-10-11 23:38:24 +00:00
arrayCopy . Clear ( ) ;
2016-01-28 03:23:59 +00:00
delete aArray ;
2013-10-08 18:47:21 +00:00
sDestroyedFrame = nullptr ;
2010-07-15 21:07:51 +00:00
}
void
2011-01-19 08:27:54 +00:00
FrameLayerBuilder : : DidBeginRetainedLayerTransaction ( LayerManager * aManager )
2010-07-15 21:07:51 +00:00
{
mRetainingManager = aManager ;
LayerManagerData * data = static_cast < LayerManagerData * >
2010-09-02 09:18:39 +00:00
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2010-07-15 21:07:51 +00:00
if ( data ) {
mInvalidateAllLayers = data - > mInvalidateAllLayers ;
2012-08-29 05:48:41 +00:00
} else {
2012-10-11 23:38:24 +00:00
data = new LayerManagerData ( aManager ) ;
2012-08-29 05:48:41 +00:00
aManager - > SetUserData ( & gLayerManagerUserData , data ) ;
2010-05-21 03:20:48 +00:00
}
2010-07-15 21:07:51 +00:00
}
2010-05-21 03:20:48 +00:00
2012-09-24 20:31:30 +00:00
void
2012-10-12 02:39:46 +00:00
FrameLayerBuilder : : StoreOptimizedLayerForFrame ( nsDisplayItem * aItem , Layer * aLayer )
2012-09-24 20:31:30 +00:00
{
2012-10-12 02:39:46 +00:00
if ( ! mRetainingManager ) {
2012-09-24 20:31:30 +00:00
return ;
2012-10-12 02:39:46 +00:00
}
2012-09-24 20:31:30 +00:00
2012-10-12 02:39:46 +00:00
DisplayItemData * data = GetDisplayItemDataForManager ( aItem , aLayer - > Manager ( ) ) ;
NS_ASSERTION ( data , " Must have already stored data for this item! " ) ;
data - > mOptLayer = aLayer ;
2012-09-24 20:31:30 +00:00
}
2010-07-15 21:07:51 +00:00
void
2012-08-29 05:47:15 +00:00
FrameLayerBuilder : : DidEndTransaction ( )
2010-07-15 21:07:51 +00:00
{
2012-06-26 02:43:30 +00:00
GetMaskLayerImageCache ( ) - > Sweep ( ) ;
2010-07-15 21:08:11 +00:00
}
void
2012-08-29 05:47:15 +00:00
FrameLayerBuilder : : WillEndTransaction ( )
2010-07-15 21:08:11 +00:00
{
2012-08-29 05:47:15 +00:00
if ( ! mRetainingManager ) {
2010-07-15 21:08:11 +00:00
return ;
2012-08-29 05:47:15 +00:00
}
2010-05-21 03:20:48 +00:00
2012-08-29 05:47:15 +00:00
// We need to save the data we'll need to support retaining.
2010-07-15 21:07:51 +00:00
LayerManagerData * data = static_cast < LayerManagerData * >
2010-09-02 09:18:39 +00:00
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-08-29 05:48:41 +00:00
NS_ASSERTION ( data , " Must have data! " ) ;
2012-12-12 20:47:05 +00:00
2015-07-15 09:05:06 +00: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-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
2015-07-15 09:05:06 +00: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-12 20:47:05 +00:00
# endif
2015-07-15 09:05:06 +00:00
InvalidatePostTransformRegion ( t ,
data - > mGeometry - > ComputeInvalidationRegion ( ) ,
data - > mClip ,
GetLastPaintOffset ( t ) ) ;
}
2015-09-16 14:05:00 +00:00
data - > ClearAnimationCompositorState ( ) ;
2015-07-15 09:05:06 +00:00
iter . Remove ( ) ;
} else {
ComputeGeometryChangeForItem ( data ) ;
2012-12-12 20:47:05 +00:00
}
2010-07-15 21:07:51 +00:00
}
2015-07-15 09:05:06 +00:00
data - > mInvalidateAllLayers = false ;
2012-10-11 23:38:25 +00:00
}
2012-08-29 05:48:45 +00:00
/* static */ FrameLayerBuilder : : DisplayItemData *
2014-03-20 06:49:27 +00:00
FrameLayerBuilder : : GetDisplayItemDataForManager ( nsDisplayItem * aItem ,
2012-08-29 05:48:45 +00:00
LayerManager * aManager )
2012-08-29 05:47:15 +00:00
{
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aItem - > Frame ( ) - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-10-11 23:38:24 +00:00
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
DisplayItemData * item = AssertDisplayItemData ( array - > ElementAt ( i ) ) ;
2012-10-11 23:38:24 +00:00
if ( item - > mDisplayItemKey = = aItem - > GetPerFrameKey ( ) & &
2012-10-16 01:23:07 +00:00
item - > mLayer - > Manager ( ) = = aManager ) {
2012-10-11 23:38:24 +00:00
return item ;
}
2012-08-29 05:47:15 +00:00
}
}
return nullptr ;
}
2012-08-29 05:48:45 +00:00
bool
2012-12-13 22:51:00 +00:00
FrameLayerBuilder : : HasRetainedDataFor ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2012-08-29 05:48:45 +00:00
{
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-10-11 23:38:24 +00:00
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
if ( AssertDisplayItemData ( array - > ElementAt ( i ) ) - > mDisplayItemKey = = aDisplayItemKey ) {
2012-10-11 23:38:24 +00:00
return true ;
}
}
2012-08-29 05:48:45 +00:00
}
return false ;
}
2012-11-06 22:04:53 +00:00
void
2012-12-13 22:50:57 +00:00
FrameLayerBuilder : : IterateRetainedDataFor ( nsIFrame * aFrame , DisplayItemDataCallback aCallback )
2012-11-06 22:04:53 +00:00
{
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-11-06 22:04:53 +00:00
if ( ! array ) {
return ;
}
2014-03-20 06:49:27 +00:00
2012-11-06 22:04:53 +00:00
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
DisplayItemData * data = AssertDisplayItemData ( array - > ElementAt ( i ) ) ;
2012-12-13 22:50:57 +00:00
if ( data - > mDisplayItemKey ! = nsDisplayItem : : TYPE_ZERO ) {
2012-11-19 10:54:50 +00:00
aCallback ( aFrame , data ) ;
}
2012-11-06 22:04:53 +00:00
}
}
2012-08-29 05:47:15 +00:00
FrameLayerBuilder : : DisplayItemData *
2012-08-29 10:53:27 +00:00
FrameLayerBuilder : : GetOldLayerForFrame ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2010-07-15 21:07:51 +00:00
{
// If we need to build a new layer tree, then just refuse to recycle
// anything.
if ( ! mRetainingManager | | mInvalidateAllLayers )
2012-07-30 14:20:58 +00:00
return nullptr ;
2010-07-15 21:07:51 +00:00
2012-10-11 23:38:24 +00:00
DisplayItemData * data = GetDisplayItemData ( aFrame , aDisplayItemKey ) ;
2010-07-15 21:07:51 +00:00
2012-10-11 23:38:24 +00:00
if ( data & & data - > mLayer - > Manager ( ) = = mRetainingManager ) {
return data ;
2010-05-21 03:20:48 +00:00
}
2012-07-30 14:20:58 +00:00
return nullptr ;
2010-05-21 03:20:48 +00:00
}
2012-08-29 10:53:27 +00:00
Layer *
2014-03-20 06:49:27 +00:00
FrameLayerBuilder : : GetOldLayerFor ( nsDisplayItem * aItem ,
nsDisplayItemGeometry * * aOldGeometry ,
2014-07-23 06:03:24 +00:00
DisplayItemClip * * aOldClip )
2012-08-29 10:53:27 +00:00
{
uint32_t key = aItem - > GetPerFrameKey ( ) ;
2013-04-19 12:02:13 +00:00
nsIFrame * frame = aItem - > Frame ( ) ;
2012-08-29 10:53:27 +00:00
2013-04-19 12:01:41 +00:00
DisplayItemData * oldData = GetOldLayerForFrame ( frame , key ) ;
if ( oldData ) {
if ( aOldGeometry ) {
* aOldGeometry = oldData - > mGeometry . get ( ) ;
2012-08-29 10:53:27 +00:00
}
2013-04-19 12:01:41 +00:00
if ( aOldClip ) {
* aOldClip = & oldData - > mClip ;
}
return oldData - > mLayer ;
2012-08-29 10:53:27 +00:00
}
return nullptr ;
2014-03-20 06:49:27 +00:00
}
2012-08-29 10:53:27 +00:00
2014-07-23 06:03:24 +00: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 ;
}
}
2012-07-17 17:03:51 +00:00
/* static */ Layer *
2012-08-22 15:56:38 +00:00
FrameLayerBuilder : : GetDebugOldLayerFor ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2012-07-17 17:03:51 +00:00
{
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-07-17 17:03:51 +00:00
2012-10-11 23:38:24 +00:00
if ( ! array ) {
2012-07-30 14:20:58 +00:00
return nullptr ;
2012-07-17 17:03:51 +00:00
}
2012-10-11 23:38:24 +00:00
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
DisplayItemData * data = AssertDisplayItemData ( array - > ElementAt ( i ) ) ;
2012-08-29 05:47:15 +00:00
2012-10-11 23:38:24 +00:00
if ( data - > mDisplayItemKey = = aDisplayItemKey ) {
2014-03-20 06:49:27 +00:00
return data - > mLayer ;
2012-08-29 05:47:15 +00:00
}
}
2012-10-11 23:38:24 +00:00
return nullptr ;
2010-07-15 21:07:51 +00:00
}
2016-01-26 00:36:48 +00:00
/* static */ PaintedLayer *
FrameLayerBuilder : : GetDebugSingleOldPaintedLayerForFrame ( nsIFrame * aFrame )
2015-03-11 18:51:59 +00:00
{
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2015-03-11 18:51:59 +00:00
if ( ! array ) {
return nullptr ;
}
Layer * layer = nullptr ;
for ( DisplayItemData * data : * array ) {
2015-04-21 18:13:54 +00:00
AssertDisplayItemData ( data ) ;
2016-01-26 00:36:48 +00:00
if ( ! data - > mLayer - > AsPaintedLayer ( ) ) {
continue ;
}
2015-03-11 18:51:59 +00:00
if ( layer & & layer ! = data - > mLayer ) {
// More than one layer assigned, bail.
return nullptr ;
}
layer = data - > mLayer ;
}
2016-08-08 00:41:50 +00:00
if ( ! layer ) {
return nullptr ;
}
2016-01-26 00:36:48 +00:00
return layer - > AsPaintedLayer ( ) ;
2015-03-11 18:51:59 +00:00
}
2016-07-08 20:30:47 +00: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-15 21:08:03 +00:00
already_AddRefed < ColorLayer >
2014-09-26 17:07:06 +00:00
ContainerState : : CreateOrRecycleColorLayer ( PaintedLayer * aPainted )
2010-07-15 21:08:03 +00:00
{
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * > ( aPainted - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2015-10-18 05:24:48 +00:00
RefPtr < ColorLayer > layer = data - > mColorLayer ;
2012-08-20 10:00:49 +00:00
if ( layer ) {
2016-07-08 21:25:09 +00:00
ResetLayerStateForRecycling ( layer ) ;
2014-08-22 15:53:24 +00:00
layer - > ClearExtraDumpInfo ( ) ;
2010-07-15 21:08:03 +00:00
} else {
// Create a new layer
layer = mManager - > CreateColorLayer ( ) ;
if ( ! layer )
2012-07-30 14:20:58 +00:00
return nullptr ;
2014-09-26 17:07:06 +00:00
// Mark this layer as being used for painting display items
2012-08-20 10:00:49 +00:00
data - > mColorLayer = layer ;
2012-07-30 14:20:58 +00:00
layer - > SetUserData ( & gColorLayerUserData , nullptr ) ;
2014-03-20 06:49:27 +00:00
2014-09-26 17:06:08 +00:00
// Remove other layer types we might have stored for this PaintedLayer
2012-08-20 10:00:49 +00:00
data - > mImageLayer = nullptr ;
2010-07-15 21:08:03 +00:00
}
return layer . forget ( ) ;
}
2011-01-17 21:47:18 +00:00
already_AddRefed < ImageLayer >
2014-09-26 17:07:06 +00:00
ContainerState : : CreateOrRecycleImageLayer ( PaintedLayer * aPainted )
2011-01-17 21:47:18 +00:00
{
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * > ( aPainted - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2015-10-18 05:24:48 +00:00
RefPtr < ImageLayer > layer = data - > mImageLayer ;
2012-08-20 10:00:49 +00:00
if ( layer ) {
2016-07-08 21:25:09 +00:00
ResetLayerStateForRecycling ( layer ) ;
2014-08-22 15:53:24 +00:00
layer - > ClearExtraDumpInfo ( ) ;
2011-01-17 21:47:18 +00:00
} else {
// Create a new layer
layer = mManager - > CreateImageLayer ( ) ;
if ( ! layer )
2012-07-30 14:20:58 +00:00
return nullptr ;
2014-09-26 17:07:06 +00:00
// Mark this layer as being used for painting display items
2012-08-20 10:00:49 +00:00
data - > mImageLayer = layer ;
2012-07-30 14:20:58 +00:00
layer - > SetUserData ( & gImageLayerUserData , nullptr ) ;
2012-08-20 10:00:49 +00:00
2014-09-26 17:06:08 +00:00
// Remove other layer types we might have stored for this PaintedLayer
2012-08-20 10:00:49 +00:00
data - > mColorLayer = nullptr ;
2011-01-17 21:47:18 +00:00
}
return layer . forget ( ) ;
}
2012-02-07 22:26:40 +00:00
already_AddRefed < ImageLayer >
2015-06-21 16:28:10 +00:00
ContainerState : : CreateOrRecycleMaskImageLayerFor ( const MaskLayerKey & aKey )
2012-02-07 22:26:40 +00:00
{
2015-10-18 05:24:48 +00:00
RefPtr < ImageLayer > result = mRecycledMaskImageLayers . Get ( aKey ) ;
2015-06-21 16:28:10 +00:00
if ( result ) {
mRecycledMaskImageLayers . Remove ( aKey ) ;
aKey . mLayer - > ClearExtraDumpInfo ( ) ;
2012-06-26 02:43:30 +00:00
// XXX if we use clip on mask layers, null it out here
2012-02-07 22:26:40 +00:00
} else {
// Create a new layer
result = mManager - > CreateImageLayer ( ) ;
if ( ! result )
2012-07-30 14:20:58 +00:00
return nullptr ;
2012-02-07 22:26:40 +00:00
result - > SetUserData ( & gMaskLayerUserData , new MaskLayerUserData ( ) ) ;
}
2014-03-20 06:49:27 +00:00
2012-02-07 22:26:40 +00:00
return result . forget ( ) ;
}
2012-05-10 05:24:20 +00: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 15:56:38 +00:00
static int32_t
2012-05-10 05:24:20 +00:00
RoundToMatchResidual ( double aValue , double aOldResidual )
{
2012-08-22 15:56:38 +00:00
int32_t v = NSToIntRoundUp ( aValue ) ;
2012-05-10 05:24:20 +00: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 15:56:38 +00:00
return int32_t ( ceil ( aValue ) ) ;
2012-05-10 05:24:20 +00:00
}
} else if ( aOldResidual > 0 ) {
if ( residual < 0 & & fabs ( residual + 1.0 - aOldResidual ) < SUBPIXEL_OFFSET_EPSILON ) {
// Round down instead
2012-08-22 15:56:38 +00:00
return int32_t ( floor ( aValue ) ) ;
2012-05-10 05:24:20 +00:00
}
}
return v ;
2012-05-10 05:24:18 +00:00
}
2012-08-16 23:40:10 +00:00
static void
2015-11-24 22:53:51 +00:00
ResetScrollPositionForLayerPixelAlignment ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2012-08-16 23:40:10 +00:00
{
2015-11-24 22:53:51 +00:00
nsIScrollableFrame * sf = nsLayoutUtils : : GetScrollableFrameFor ( * aAnimatedGeometryRoot ) ;
2012-08-16 23:40:10 +00:00
if ( sf ) {
sf - > ResetScrollPositionForLayerPixelAlignment ( ) ;
}
}
static void
2015-11-24 22:53:51 +00:00
InvalidateEntirePaintedLayer ( PaintedLayer * aLayer , AnimatedGeometryRoot * aAnimatedGeometryRoot , const char * aReason )
2012-08-16 23:40:10 +00:00
{
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2015-02-03 22:18:44 +00:00
printf_stderr ( " Invalidating entire layer %p: %s \n " , aLayer , aReason ) ;
2013-05-13 23:47:02 +00:00
}
2012-08-29 05:47:15 +00:00
# endif
2012-08-16 23:40:10 +00:00
nsIntRect invalidate = aLayer - > GetValidRegion ( ) . GetBounds ( ) ;
aLayer - > InvalidateRegion ( invalidate ) ;
2014-03-06 23:31:47 +00:00
aLayer - > SetInvalidRectToVisibleRegion ( ) ;
2013-09-25 21:07:26 +00:00
ResetScrollPositionForLayerPixelAlignment ( aAnimatedGeometryRoot ) ;
2012-08-16 23:40:10 +00:00
}
2015-03-03 00:24:18 +00:00
LayerManager : : PaintedLayerCreationHint
2015-11-24 22:53:51 +00:00
ContainerState : : GetLayerCreationHint ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-03-03 00:24:18 +00: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 16:28:18 +00:00
2016-03-08 19:43:32 +00:00
// Check creation hint inherited from our parent.
if ( mParameters . mLayerCreationHint = = LayerManager : : SCROLLABLE ) {
return LayerManager : : SCROLLABLE ;
}
2015-09-20 16:28:18 +00:00
// Check whether there's any active scroll frame on the animated geometry
// root chain.
2015-11-24 22:53:51 +00:00
for ( AnimatedGeometryRoot * agr = aAnimatedGeometryRoot ;
2016-08-11 05:52:56 +00:00
agr & & agr ! = mContainerAnimatedGeometryRoot ;
2015-11-24 22:53:51 +00:00
agr = agr - > mParentAGR ) {
nsIFrame * fParent = nsLayoutUtils : : GetCrossDocParentFrame ( * agr ) ;
2015-09-20 16:28:18 +00:00
if ( ! fParent ) {
break ;
}
nsIScrollableFrame * scrollable = do_QueryFrame ( fParent ) ;
if ( scrollable
# ifdef MOZ_B2G
& & scrollable - > WantAsyncScroll ( )
# endif
) {
// WantAsyncScroll() returns false when the frame has overflow:hidden,
// so we won't create tiled layers for overflow:hidden frames even if
// they have a display port. The main purpose of the WantAsyncScroll check
// is to allow the B2G camera app to use hardware composer for compositing.
return LayerManager : : SCROLLABLE ;
}
2015-03-03 00:24:18 +00:00
}
return LayerManager : : NONE ;
}
2015-03-03 00:25:13 +00:00
already_AddRefed < PaintedLayer >
2015-11-24 22:53:51 +00:00
ContainerState : : AttemptToRecyclePaintedLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-04 05:21:00 +00:00
nsDisplayItem * aItem ,
2015-03-03 00:25:13 +00:00
const nsPoint & aTopLeft )
{
2015-03-04 05:21:00 +00:00
Layer * oldLayer = mLayerBuilder - > GetOldLayerFor ( aItem ) ;
if ( ! oldLayer | | ! oldLayer - > AsPaintedLayer ( ) | |
! mPaintedLayersAvailableForRecycling . Contains ( oldLayer - > AsPaintedLayer ( ) ) ) {
2015-03-03 00:25:13 +00:00
return nullptr ;
}
// Try to recycle a layer
2015-10-18 05:24:48 +00:00
RefPtr < PaintedLayer > layer = oldLayer - > AsPaintedLayer ( ) ;
2015-03-04 05:21:00 +00:00
mPaintedLayersAvailableForRecycling . RemoveEntry ( layer ) ;
2015-03-03 00:25:13 +00:00
// Check if the layer hint has changed and whether or not the layer should
// be recreated because of it.
2015-07-29 16:03:01 +00:00
if ( ! layer - > IsOptimizedFor ( GetLayerCreationHint ( aAnimatedGeometryRoot ) ) ) {
2015-03-03 00:25:13 +00:00
return nullptr ;
}
bool didResetScrollPositionForLayerPixelAlignment = false ;
PaintedDisplayItemLayerUserData * data =
RecyclePaintedLayer ( layer , aAnimatedGeometryRoot ,
didResetScrollPositionForLayerPixelAlignment ) ;
2015-03-04 05:21:00 +00:00
PreparePaintedLayerForUse ( layer , data , aAnimatedGeometryRoot , aItem - > ReferenceFrame ( ) ,
2015-03-03 00:25:13 +00:00
aTopLeft ,
didResetScrollPositionForLayerPixelAlignment ) ;
return layer . forget ( ) ;
}
2014-09-26 17:06:08 +00:00
already_AddRefed < PaintedLayer >
2015-03-04 05:18:47 +00:00
ContainerState : : CreatePaintedLayer ( PaintedLayerData * aData )
2010-07-15 21:07:51 +00:00
{
2015-03-03 00:24:18 +00:00
LayerManager : : PaintedLayerCreationHint creationHint =
2015-03-04 05:21:00 +00:00
GetLayerCreationHint ( aData - > mAnimatedGeometryRoot ) ;
2014-06-13 16:11:08 +00:00
2015-03-03 00:25:13 +00:00
// Create a new painted layer
2015-10-18 05:24:48 +00:00
RefPtr < PaintedLayer > layer = mManager - > CreatePaintedLayerWithHint ( creationHint ) ;
2015-03-03 00:25:13 +00:00
if ( ! layer ) {
return nullptr ;
2014-06-13 16:11:08 +00:00
}
2015-03-03 00:25:13 +00:00
// Mark this layer as being used for painting display items
2015-03-04 05:21:00 +00:00
PaintedDisplayItemLayerUserData * userData = new PaintedDisplayItemLayerUserData ( ) ;
layer - > SetUserData ( & gPaintedDisplayItemLayerUserData , userData ) ;
ResetScrollPositionForLayerPixelAlignment ( aData - > mAnimatedGeometryRoot ) ;
2015-03-02 23:43:58 +00:00
2015-03-04 05:21:00 +00:00
PreparePaintedLayerForUse ( layer , userData , aData - > mAnimatedGeometryRoot ,
aData - > mReferenceFrame ,
aData - > mAnimatedGeometryRootOffset , true ) ;
2015-03-02 23:43:58 +00:00
return layer . forget ( ) ;
}
PaintedDisplayItemLayerUserData *
ContainerState : : RecyclePaintedLayer ( PaintedLayer * aLayer ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-02 23:43:58 +00: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 20:30:47 +00:00
ResetLayerStateForRecycling ( aLayer ) ;
2015-03-02 23:43:58 +00: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-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-03-02 23:43:58 +00:00
const nsIFrame * aReferenceFrame ,
const nsPoint & aTopLeft ,
bool didResetScrollPositionForLayerPixelAlignment )
{
2015-03-04 17:08:28 +00: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-02 23:43:58 +00:00
2015-03-04 17:08:28 +00:00
mLayerBuilder - > SavePreviousDataForLayer ( aLayer , aData - > mMaskClipCount ) ;
2010-07-15 21:07:51 +00:00
2015-03-04 17:08:28 +00:00
// Set up transform so that 0,0 in the PaintedLayer corresponds to the
2013-09-25 21:07:26 +00:00
// (pixel-snapped) top-left of the aAnimatedGeometryRoot.
2015-11-24 22:53:51 +00:00
nsPoint offset = ( * aAnimatedGeometryRoot ) - > GetOffsetToCrossDoc ( aReferenceFrame ) ;
nscoord appUnitsPerDevPixel = ( * aAnimatedGeometryRoot ) - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2011-06-22 12:11:28 +00:00
gfxPoint scaledOffset (
NSAppUnitsToDoublePixels ( offset . x , appUnitsPerDevPixel ) * mParameters . mXScale ,
NSAppUnitsToDoublePixels ( offset . y , appUnitsPerDevPixel ) * mParameters . mYScale ) ;
2012-05-10 05:24:20 +00:00
// We call RoundToMatchResidual here so that the residual after rounding
2015-03-04 17:08:28 +00: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-16 22:25:33 +00:00
pixOffset + = mParameters . mOffset ;
2014-09-10 13:26:12 +00:00
Matrix matrix = Matrix : : Translation ( pixOffset . x , pixOffset . y ) ;
2015-03-04 17:08:28 +00:00
aLayer - > SetBaseTransform ( Matrix4x4 : : From2D ( matrix ) ) ;
2010-07-15 21:07:51 +00:00
2015-09-15 13:41:42 +00:00
aData - > mVisibilityComputedRegion . SetEmpty ( ) ;
2015-07-21 08:19:25 +00:00
2014-06-30 10:31:07 +00:00
// FIXME: Temporary workaround for bug 681192 and bug 724786.
2014-08-22 19:26:56 +00:00
# ifndef MOZ_WIDGET_ANDROID
2011-06-22 12:11:28 +00: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 15:28:33 +00:00
gfxPoint animatedGeometryRootTopLeft = scaledOffset - ThebesPoint ( matrix . GetTranslation ( ) ) + mParameters . mOffset ;
2011-06-22 12:11:28 +00: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 17:08:28 +00:00
if ( ! animatedGeometryRootTopLeft . WithinEpsilonOf ( aData - > mAnimatedGeometryRootPosition , SUBPIXEL_OFFSET_EPSILON ) ) {
aData - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
InvalidateEntirePaintedLayer ( aLayer , aAnimatedGeometryRoot , " subpixel offset " ) ;
2012-08-16 23:40:10 +00:00
} else if ( didResetScrollPositionForLayerPixelAlignment ) {
2015-03-04 17:08:28 +00:00
aData - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
2011-06-22 12:11:28 +00:00
}
2015-03-02 23:29:12 +00:00
# else
2015-11-02 05:53:26 +00:00
Unused < < didResetScrollPositionForLayerPixelAlignment ;
2014-06-30 10:31:07 +00:00
# endif
2010-07-15 21:07:51 +00:00
}
2013-11-17 20:33:21 +00:00
# if defined(DEBUG) || defined(MOZ_DUMP_PAINTING)
2010-07-15 21:07:51 +00:00
/**
2013-03-04 09:56:02 +00:00
* Returns the appunits per dev pixel for the item ' s frame
2010-07-15 21:07:51 +00:00
*/
2012-08-22 15:56:38 +00:00
static int32_t
2010-07-15 21:07:51 +00:00
AppUnitsPerDevPixel ( nsDisplayItem * aItem )
{
2010-08-08 18:49:06 +00: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.
if ( aItem - > GetType ( ) = = nsDisplayItem : : TYPE_ZOOM ) {
return static_cast < nsDisplayZoom * > ( aItem ) - > GetParentAppUnitsPerDevPixel ( ) ;
}
2013-04-19 12:02:13 +00:00
return aItem - > Frame ( ) - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2010-07-15 21:07:51 +00:00
}
2012-10-10 05:00:05 +00:00
# endif
2010-07-15 21:07:51 +00:00
/**
2014-06-23 04:24:00 +00:00
* Set the visible region for aLayer .
* aOuterVisibleRegion is the visible region relative to the parent layer .
2014-07-11 01:17:47 +00: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 04:24:00 +00:00
* Consumes * aOuterVisibleRegion .
2010-07-15 21:07:51 +00:00
*/
static void
2014-06-23 04:24:00 +00:00
SetOuterVisibleRegion ( Layer * aLayer , nsIntRegion * aOuterVisibleRegion ,
2015-09-17 01:31:00 +00:00
const nsIntRect * aLayerContentsVisibleRect = nullptr ,
bool aOuterUntransformed = false )
2010-07-15 21:07:51 +00:00
{
2014-08-22 13:40:02 +00:00
Matrix4x4 transform = aLayer - > GetTransform ( ) ;
Matrix transform2D ;
2015-09-17 01:31:00 +00:00
if ( aOuterUntransformed ) {
if ( aLayerContentsVisibleRect ) {
aOuterVisibleRegion - > And ( * aOuterVisibleRegion ,
* aLayerContentsVisibleRect ) ;
}
} else if ( transform . Is2D ( & transform2D ) & & ! transform2D . HasNonIntegerTranslation ( ) ) {
2014-06-23 04:24:00 +00:00
aOuterVisibleRegion - > MoveBy ( - int ( transform2D . _31 ) , - int ( transform2D . _32 ) ) ;
2014-07-11 01:17:47 +00:00
if ( aLayerContentsVisibleRect ) {
aOuterVisibleRegion - > And ( * aOuterVisibleRegion , * aLayerContentsVisibleRect ) ;
}
2013-03-22 02:17:29 +00:00
} else {
2014-06-23 04:24:00 +00: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 13:40:02 +00:00
Rect outerVisible ( outerRect . x , outerRect . y , outerRect . width , outerRect . height ) ;
transform . Invert ( ) ;
2015-03-13 20:42:00 +00:00
Rect layerContentsVisible ( - float ( INT32_MAX ) / 2 , - float ( INT32_MAX ) / 2 ,
float ( INT32_MAX ) , float ( INT32_MAX ) ) ;
2014-07-11 01:17:47 +00: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 20:42:00 +00:00
layerContentsVisible = Rect (
2014-07-11 01:17:47 +00:00
aLayerContentsVisibleRect - > x , aLayerContentsVisibleRect - > y ,
aLayerContentsVisibleRect - > width , aLayerContentsVisibleRect - > height ) ;
}
2015-03-13 20:42:00 +00:00
gfxRect layerVisible = ThebesRect ( transform . ProjectRectBounds ( outerVisible , layerContentsVisible ) ) ;
2014-06-23 04:24:00 +00:00
layerVisible . RoundOut ( ) ;
nsIntRect visRect ;
if ( gfxUtils : : GfxRectToIntRect ( layerVisible , & visRect ) ) {
* aOuterVisibleRegion = visRect ;
} else {
aOuterVisibleRegion - > SetEmpty ( ) ;
2014-06-18 03:12:55 +00:00
}
2010-07-15 21:07:51 +00:00
}
2014-06-23 04:24:00 +00:00
2015-11-29 07:07:55 +00:00
aLayer - > SetVisibleRegion ( LayerIntRegion : : FromUnknownRegion ( * aOuterVisibleRegion ) ) ;
2014-06-23 04:24:00 +00:00
}
void
ContainerState : : SetOuterVisibleRegionForLayer ( Layer * aLayer ,
const nsIntRegion & aOuterVisibleRegion ,
2015-09-17 01:31:00 +00:00
const nsIntRect * aLayerContentsVisibleRect ,
bool aOuterUntransformed ) const
2014-06-23 04:24:00 +00:00
{
nsIntRegion visRegion = aOuterVisibleRegion ;
2015-09-17 01:31:00 +00:00
if ( ! aOuterUntransformed ) {
visRegion . MoveBy ( mParameters . mOffset ) ;
}
SetOuterVisibleRegion ( aLayer , & visRegion , aLayerContentsVisibleRect ,
aOuterUntransformed ) ;
2010-07-15 21:07:51 +00:00
}
2010-09-02 09:18:39 +00:00
nscolor
2015-04-02 18:22:40 +00:00
ContainerState : : FindOpaqueBackgroundColorInLayer ( const PaintedLayerData * aData ,
const nsIntRect & aRect ,
bool * aOutIntersectsLayer ) const
2010-09-02 09:18:39 +00:00
{
2015-04-02 18:22:40 +00:00
* aOutIntersectsLayer = true ;
2010-09-02 09:18:39 +00:00
2015-04-02 18:22:40 +00:00
// Scan the candidate's display items.
nsIntRect deviceRect = aRect ;
2015-04-21 15:04:57 +00:00
nsRect appUnitRect = ToAppUnits ( deviceRect , mAppUnitsPerDevPixel ) ;
2015-04-02 18:22:40 +00:00
appUnitRect . ScaleInverseRoundOut ( mParameters . mXScale , mParameters . mYScale ) ;
2011-06-22 12:11:27 +00:00
2015-04-02 18:22:40 +00: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 02:53:17 +00:00
2015-04-02 18:22:40 +00:00
if ( ! snappedBounds . Contains ( deviceRect ) )
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
2012-12-05 02:53:17 +00:00
2015-04-02 18:22:40 +00: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 02:53:17 +00:00
2015-04-02 18:22:40 +00:00
if ( ! bounds . Contains ( appUnitRect ) )
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2012-12-05 02:53:17 +00:00
2015-04-02 18:22:40 +00:00
if ( item - > IsInvisibleInRect ( appUnitRect ) ) {
continue ;
}
2012-12-05 02:53:17 +00:00
2015-04-02 18:22:40 +00:00
if ( assignedItem . mClip . IsRectAffectedByClip ( deviceRect ,
mParameters . mXScale ,
mParameters . mYScale ,
mAppUnitsPerDevPixel ) ) {
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2014-06-03 12:50:42 +00:00
2016-05-19 08:07:52 +00:00
Maybe < nscolor > color = item - > IsUniform ( mBuilder ) ;
if ( color & & NS_GET_A ( * color ) = = 255 )
return * color ;
2015-04-02 18:22:40 +00:00
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2014-07-23 06:12:08 +00:00
2015-04-02 18:22:40 +00:00
* aOutIntersectsLayer = false ;
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2012-12-05 02:53:17 +00:00
2015-04-02 18:22:40 +00: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 19:46:09 +00:00
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
2012-12-05 02:53:17 +00:00
}
2015-04-02 18:22:40 +00: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 09:18:39 +00:00
}
2015-04-02 18:22:40 +00:00
if ( mAllDrawingAboveBackground | |
! mVisibleAboveBackgroundRegion . Intersect ( aTargetVisibleRegion ) . IsEmpty ( ) ) {
// Some non-PaintedLayer content is between this node's background and target.
2015-02-25 16:47:22 +00:00
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2015-04-02 18:22:40 +00:00
return FindOpaqueBackgroundColorInParentNode ( ) ;
}
nscolor
PaintedLayerDataNode : : FindOpaqueBackgroundColorCoveringEverything ( ) const
{
if ( ! mPaintedLayerDataStack . IsEmpty ( ) | |
2015-04-05 18:05:44 +00:00
mAllDrawingAboveBackground | |
2015-04-02 18:22:40 +00: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 09:18:39 +00:00
}
2012-02-07 22:27:44 +00:00
void
2014-09-26 17:06:08 +00:00
PaintedLayerData : : UpdateCommonClipCount (
2013-03-04 09:55:59 +00:00
const DisplayItemClip & aCurrentClip )
2012-02-07 22:27:44 +00:00
{
if ( mCommonClipCount > = 0 ) {
2013-03-04 09:56:00 +00:00
mCommonClipCount = mItemClip . GetCommonRoundedRectCount ( aCurrentClip , mCommonClipCount ) ;
2012-02-07 22:27:44 +00:00
} else {
// first item in the layer
2013-03-04 09:56:00 +00:00
mCommonClipCount = aCurrentClip . GetRoundedRectCount ( ) ;
2012-07-31 17:28:21 +00:00
}
2012-02-07 22:27:44 +00:00
}
2015-05-13 07:23:46 +00:00
bool
PaintedLayerData : : CanOptimizeToImageLayer ( nsDisplayListBuilder * aBuilder )
{
if ( ! mImage ) {
2015-05-13 21:23:52 +00:00
return false ;
2015-05-13 07:23:46 +00:00
}
return mImage - > CanOptimizeToImageLayer ( mLayer - > Manager ( ) , aBuilder ) ;
}
2012-01-30 05:16:54 +00:00
already_AddRefed < ImageContainer >
2015-05-13 07:23:46 +00:00
PaintedLayerData : : GetContainerForImageLayer ( nsDisplayListBuilder * aBuilder )
2011-01-17 21:47:18 +00:00
{
2012-02-07 22:27:44 +00:00
if ( ! mImage ) {
2012-07-30 14:20:58 +00:00
return nullptr ;
2011-01-17 21:47:18 +00:00
}
2012-11-28 02:34:45 +00:00
return mImage - > GetContainer ( mLayer - > Manager ( ) , aBuilder ) ;
2011-01-17 21:47:18 +00:00
}
2015-04-02 18:22:40 +00:00
PaintedLayerDataNode : : PaintedLayerDataNode ( PaintedLayerDataTree & aTree ,
PaintedLayerDataNode * aParent ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 18:22:40 +00:00
: mTree ( aTree )
, mParent ( aParent )
, mAnimatedGeometryRoot ( aAnimatedGeometryRoot )
, mAllDrawingAboveBackground ( false )
{
2015-11-24 22:53:51 +00:00
MOZ_ASSERT ( nsLayoutUtils : : IsAncestorFrameCrossDoc ( mTree . Builder ( ) - > RootReferenceFrame ( ) , * mAnimatedGeometryRoot ) ) ;
2015-04-02 18:22:40 +00:00
mHasClip = mTree . IsClippedWithRespectToParentAnimatedGeometryRoot ( mAnimatedGeometryRoot , & mClipRect ) ;
}
PaintedLayerDataNode : : ~ PaintedLayerDataNode ( )
{
MOZ_ASSERT ( mPaintedLayerDataStack . IsEmpty ( ) ) ;
MOZ_ASSERT ( mChildren . IsEmpty ( ) ) ;
}
PaintedLayerDataNode *
2015-11-24 22:53:51 +00:00
PaintedLayerDataNode : : AddChildNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 18:22:40 +00:00
{
2015-11-24 22:53:51 +00:00
MOZ_ASSERT ( aAnimatedGeometryRoot - > mParentAGR = = mAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00:00
UniquePtr < PaintedLayerDataNode > child =
2015-06-16 17:41:59 +00:00
MakeUnique < PaintedLayerDataNode > ( mTree , this , aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00:00
mChildren . AppendElement ( Move ( child ) ) ;
return mChildren . LastElement ( ) . get ( ) ;
}
template < typename NewPaintedLayerCallbackType >
PaintedLayerData *
PaintedLayerDataNode : : FindPaintedLayerFor ( const nsIntRect & aVisibleRect ,
2015-09-17 01:31:00 +00:00
bool aBackfaceHidden ,
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * aScrollClip ,
2015-04-02 18:22:40 +00:00
NewPaintedLayerCallbackType aNewPaintedLayerCallback )
{
if ( ! mPaintedLayerDataStack . IsEmpty ( ) ) {
2016-06-02 20:44:32 +00:00
PaintedLayerData * lowestUsableLayer = nullptr ;
for ( auto & data : Reversed ( mPaintedLayerDataStack ) ) {
if ( data . mVisibleAboveRegion . Intersects ( aVisibleRect ) ) {
break ;
2015-04-02 18:22:40 +00:00
}
2016-06-02 20:44:32 +00:00
if ( data . mBackfaceHidden = = aBackfaceHidden & &
data . mScrollClip = = aScrollClip ) {
lowestUsableLayer = & data ;
}
nsIntRegion visibleRegion = data . mVisibleRegion ;
// 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 ;
}
if ( visibleRegion . Intersects ( aVisibleRect ) ) {
break ;
2015-04-02 18:22:40 +00:00
}
}
2016-06-02 20:44:32 +00:00
if ( lowestUsableLayer ) {
return lowestUsableLayer ;
}
2015-04-02 18:22:40 +00: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 17:41:59 +00:00
nsIntRegion & visibleAboveRegion = mPaintedLayerDataStack . IsEmpty ( )
2015-04-02 18:22:40 +00:00
? mVisibleAboveBackgroundRegion
: mPaintedLayerDataStack . LastElement ( ) . mVisibleAboveRegion ;
2015-06-16 17:41:59 +00:00
visibleAboveRegion . Or ( visibleAboveRegion , aRect ) ;
visibleAboveRegion . SimplifyOutward ( 8 ) ;
2015-04-02 18:22:40 +00: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 17:41:59 +00:00
return this - > FindOpaqueBackgroundColor ( data . mVisibleRegion , lastIndex ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerDataTree : : NodeWasFinished ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 18:22:40 +00:00
{
mNodes . Remove ( aAnimatedGeometryRoot ) ;
}
void
2015-11-24 22:53:51 +00:00
PaintedLayerDataTree : : AddingOwnLayer ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerDataTree : : FindPaintedLayerFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * aScrollClip ,
2015-04-02 18:22:40 +00:00
const nsIntRect & aVisibleRect ,
2015-09-17 01:31:00 +00:00
bool aBackfaceHidden ,
2015-04-02 18:22:40 +00:00
NewPaintedLayerCallbackType aNewPaintedLayerCallback )
{
2016-06-02 20:44:32 +00:00
const nsIntRect * bounds = & aVisibleRect ;
2015-04-02 18:22:40 +00:00
FinishPotentiallyIntersectingNodes ( aAnimatedGeometryRoot , bounds ) ;
2016-05-27 15:29:19 +00:00
PaintedLayerDataNode * node = EnsureNodeFor ( aAnimatedGeometryRoot ) ;
2016-01-07 15:50:23 +00:00
2015-07-02 02:08:20 +00:00
PaintedLayerData * data =
2015-12-22 15:54:19 +00:00
node - > FindPaintedLayerFor ( aVisibleRect , aBackfaceHidden , aScrollClip ,
2015-09-17 01:31:00 +00:00
aNewPaintedLayerCallback ) ;
2015-07-02 02:08:20 +00:00
return data ;
2015-04-02 18:22:40 +00:00
}
void
2015-11-24 22:53:51 +00:00
PaintedLayerDataTree : : FinishPotentiallyIntersectingNodes ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 18:22:40 +00:00
const nsIntRect * aRect )
{
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * ancestorThatIsChildOfCommonAncestor = nullptr ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
if ( ancestorNode - > GetAnimatedGeometryRoot ( ) = = aAnimatedGeometryRoot ) {
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
MOZ_ASSERT ( nsLayoutUtils : : IsAncestorFrameCrossDoc ( * ancestorThatIsChildOfCommonAncestor , * aAnimatedGeometryRoot ) ) ;
MOZ_ASSERT ( ancestorThatIsChildOfCommonAncestor - > mParentAGR = = ancestorNode - > GetAnimatedGeometryRoot ( ) ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerDataTree : : EnsureNodeFor ( AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-04-02 18:22:40 +00:00
{
MOZ_ASSERT ( aAnimatedGeometryRoot ) ;
PaintedLayerDataNode * node = mNodes . Get ( aAnimatedGeometryRoot ) ;
if ( node ) {
return node ;
}
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * parentAnimatedGeometryRoot = aAnimatedGeometryRoot - > mParentAGR ;
2015-04-02 18:22:40 +00:00
if ( ! parentAnimatedGeometryRoot ) {
MOZ_ASSERT ( ! mRoot ) ;
2015-11-24 22:53:51 +00:00
MOZ_ASSERT ( * aAnimatedGeometryRoot = = Builder ( ) - > RootReferenceFrame ( ) ) ;
2015-06-16 17:41:59 +00:00
mRoot = MakeUnique < PaintedLayerDataNode > ( * this , nullptr , aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerDataTree : : IsClippedWithRespectToParentAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-04-02 18:22:40 +00:00
nsIntRect * aOutClip )
{
2015-11-24 22:53:51 +00:00
nsIScrollableFrame * scrollableFrame = nsLayoutUtils : : GetScrollableFrameFor ( * aAnimatedGeometryRoot ) ;
2015-04-02 18:22:40 +00: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-24 22:53:51 +00:00
PaintedLayerDataTree : : FindNodeForAncestorAnimatedGeometryRoot ( AnimatedGeometryRoot * aAnimatedGeometryRoot ,
AnimatedGeometryRoot * * aOutAncestorChild )
2015-04-02 18:22:40 +00:00
{
if ( ! aAnimatedGeometryRoot ) {
return nullptr ;
}
PaintedLayerDataNode * node = mNodes . Get ( aAnimatedGeometryRoot ) ;
if ( node ) {
return node ;
}
* aOutAncestorChild = aAnimatedGeometryRoot ;
2015-11-24 22:53:51 +00:00
return FindNodeForAncestorAnimatedGeometryRoot ( aAnimatedGeometryRoot - > mParentAGR , aOutAncestorChild ) ;
2015-04-02 18:22:40 +00:00
}
2014-04-22 14:27:44 +00:00
static bool
2014-09-26 17:06:08 +00:00
CanOptimizeAwayPaintedLayer ( PaintedLayerData * aData ,
2014-04-22 14:27:44 +00:00
FrameLayerBuilder * aLayerBuilder )
{
2014-06-23 04:24:00 +00:00
if ( ! aLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
2014-04-22 14:27:44 +00:00
return false ;
}
2014-09-26 17:06:08 +00:00
// If there's no painted layer with valid content in it that we can reuse,
2014-04-22 14:27:44 +00:00
// always create a color or image layer (and potentially throw away an
2014-09-26 17:06:08 +00:00
// existing completely invalid painted layer).
2014-04-22 14:27:44 +00:00
if ( aData - > mLayer - > GetValidRegion ( ) . IsEmpty ( ) ) {
return true ;
}
2014-09-26 17:06:08 +00:00
// There is an existing painted layer we can reuse. Throwing it away can make
2014-04-22 14:27:44 +00:00
// compositing cheaper (see bug 946952), but it might cause us to re-allocate
2014-09-26 17:06:08 +00:00
// the painted layer frequently due to an animation. So we only discard it if
2014-04-22 14:27:44 +00:00
// we're in tree compression mode, which is triggered at a low frequency.
return aLayerBuilder - > CheckInLayerTreeCompressionMode ( ) ;
}
2014-06-23 04:24:00 +00: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 07:23:46 +00:00
already_AddRefed < Layer >
ContainerState : : PrepareImageLayer ( PaintedLayerData * aData )
{
2015-10-18 05:24:48 +00:00
RefPtr < ImageContainer > imageContainer =
2015-05-13 07:23:46 +00:00
aData - > GetContainerForImageLayer ( mBuilder ) ;
if ( ! imageContainer ) {
return nullptr ;
}
2015-10-18 05:24:48 +00:00
RefPtr < ImageLayer > imageLayer = CreateOrRecycleImageLayer ( aData - > mLayer ) ;
2015-05-13 07:23:46 +00: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 ( ) ) ;
}
mLayerBuilder - > StoreOptimizedLayerForFrame ( aData - > mImage , imageLayer ) ;
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 05:24:48 +00:00
RefPtr < ColorLayer > colorLayer = CreateOrRecycleColorLayer ( aData - > mLayer ) ;
2015-09-25 01:16:45 +00:00
colorLayer - > SetColor ( Color : : FromABGR ( aData - > mSolidColor ) ) ;
2015-05-13 07:23:46 +00: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-15 21:07:51 +00:00
2015-09-17 01:31:00 +00: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 18:22:40 +00:00
template < typename FindOpaqueBackgroundColorCallbackType >
void ContainerState : : FinishPaintedLayerData ( PaintedLayerData & aData , FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor )
{
PaintedLayerData * data = & aData ;
2010-07-15 21:07:51 +00:00
2015-03-04 05:18:47 +00:00
if ( ! data - > mLayer ) {
// No layer was recycled, so we create a new one.
2015-10-18 05:24:48 +00:00
RefPtr < PaintedLayer > paintedLayer = CreatePaintedLayer ( data ) ;
2015-03-04 05:18:47 +00:00
data - > mLayer = paintedLayer ;
2015-03-04 02:32:08 +00:00
2015-03-04 05:18:47 +00:00
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , paintedLayer ) < 0 ,
" Layer already in list??? " ) ;
mNewChildLayers [ data - > mNewChildLayersIndex ] . mLayer = paintedLayer . forget ( ) ;
}
2015-03-04 02:32:08 +00:00
2015-03-04 05:21:55 +00:00
for ( auto & item : data - > mAssignedDisplayItems ) {
MOZ_ASSERT ( item . mItem - > GetType ( ) ! = nsDisplayItem : : TYPE_LAYER_EVENT_REGIONS ) ;
InvalidateForLayerChange ( item . mItem , data - > mLayer ) ;
mLayerBuilder - > AddPaintedDisplayItem ( data , item . mItem , item . mClip ,
* this , item . mLayerState ,
data - > mAnimatedGeometryRootOffset ) ;
}
2014-06-23 04:24:00 +00:00
NewLayerEntry * newLayerEntry = & mNewChildLayers [ data - > mNewChildLayersIndex ] ;
2015-03-16 22:37:04 +00:00
2015-10-18 05:24:48 +00:00
RefPtr < Layer > layer ;
2015-05-13 07:23:46 +00:00
bool canOptimizeToImageLayer = data - > CanOptimizeToImageLayer ( mBuilder ) ;
2014-08-22 15:53:24 +00:00
2014-11-26 18:58:15 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( data , " Selecting layer for pld=%p \n " , data ) ;
2015-05-13 07:23:46 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( data , " Solid=%i, hasImage=%c, canOptimizeAwayPaintedLayer=%i \n " ,
data - > mIsSolidColorInVisibleRegion , canOptimizeToImageLayer ? ' y ' : ' n ' ,
2014-09-26 17:06:08 +00:00
CanOptimizeAwayPaintedLayer ( data , mLayerBuilder ) ) ;
2014-08-22 15:53:24 +00:00
2015-05-13 07:23:46 +00:00
if ( ( data - > mIsSolidColorInVisibleRegion | | canOptimizeToImageLayer ) & &
2014-09-26 17:06:08 +00:00
CanOptimizeAwayPaintedLayer ( data , mLayerBuilder ) ) {
2015-05-13 07:23:46 +00:00
NS_ASSERTION ( ! ( data - > mIsSolidColorInVisibleRegion & & canOptimizeToImageLayer ) ,
2011-01-17 21:47:18 +00:00
" Can't be a solid color as well as an image! " ) ;
2015-05-13 07:23:46 +00: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
newLayerEntry = & mNewChildLayers [ data - > mNewChildLayersIndex + 1 ] ;
NS_ASSERTION ( ! newLayerEntry - > mLayer , " Slot already occupied? " ) ;
newLayerEntry - > mLayer = layer ;
newLayerEntry - > mAnimatedGeometryRoot = data - > mAnimatedGeometryRoot ;
2015-12-22 15:54:19 +00:00
newLayerEntry - > mScrollClip = data - > mScrollClip ;
2015-05-13 07:23:46 +00: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 07:07:55 +00:00
data - > mLayer - > SetVisibleRegion ( LayerIntRegion ( ) ) ;
2015-05-13 07:23:46 +00:00
data - > mLayer - > InvalidateRegion ( data - > mLayer - > GetValidRegion ( ) . GetBounds ( ) ) ;
data - > mLayer - > SetEventRegions ( EventRegions ( ) ) ;
2011-01-17 21:47:18 +00:00
}
2015-05-13 07:23:46 +00:00
}
2015-07-18 13:35:59 +00:00
2015-05-13 07:23:46 +00:00
if ( ! layer ) {
// We couldn't optimize to an image layer or a color layer above.
2013-04-19 15:17:21 +00:00
layer = data - > mLayer ;
2015-04-12 02:03:00 +00:00
layer - > SetClipRect ( Nothing ( ) ) ;
2014-09-26 17:07:06 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( data , " Selected painted layer=%p \n " , layer . get ( ) ) ;
2010-07-15 21:08:03 +00:00
}
2016-01-06 18:48:37 +00:00
// If the layer is a fixed background layer, the clip on the fixed background
// display item was not applied to the opaque region in
// ContainerState::ComputeOpaqueRect(), but was saved in data->mItemClip.
// Apply it to the opaque region now. Note that it's important to do this
// before the opaque region is propagated to the NewLayerEntry below.
2016-08-03 17:48:10 +00:00
if ( data - > mSingleItemFixedToViewport & & data - > mItemClip . HasClip ( ) ) {
2016-01-06 18:48:37 +00:00
nsRect clipRect = data - > mItemClip . GetClipRect ( ) ;
nsRect insideRoundedCorners = data - > mItemClip . ApproximateIntersectInward ( clipRect ) ;
nsIntRect insideRoundedCornersScaled = ScaleToInsidePixels ( insideRoundedCorners ) ;
data - > mOpaqueRegion . AndWith ( insideRoundedCornersScaled ) ;
}
2014-06-23 04:24:00 +00:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
2015-06-16 17:41:59 +00:00
newLayerEntry - > mVisibleRegion = data - > mVisibleRegion ;
2014-06-23 04:24:00 +00:00
newLayerEntry - > mOpaqueRegion = data - > mOpaqueRegion ;
newLayerEntry - > mHideAllLayersBelow = data - > mHideAllLayersBelow ;
2014-08-31 03:29:24 +00:00
newLayerEntry - > mOpaqueForAnimatedGeometryRootParent = data - > mOpaqueForAnimatedGeometryRootParent ;
2014-06-23 04:24:00 +00:00
} else {
2015-06-16 17:41:59 +00:00
SetOuterVisibleRegionForLayer ( layer , data - > mVisibleRegion ) ;
2010-07-15 21:07:51 +00:00
}
2014-12-12 16:25:36 +00:00
nsIntRect layerBounds = data - > mBounds ;
2014-09-26 17:06:08 +00:00
layerBounds . MoveBy ( - GetTranslationForPaintedLayer ( data - > mLayer ) ) ;
2014-09-15 20:09:52 +00:00
layer - > SetLayerBounds ( layerBounds ) ;
2014-08-22 15:53:24 +00:00
# ifdef MOZ_DUMP_PAINTING
2015-03-09 04:41:11 +00: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 14:49:30 +00:00
}
2014-08-22 15:53:24 +00:00
# endif
2010-07-15 21:07:51 +00:00
nsIntRegion transparentRegion ;
2015-06-16 17:41:59 +00:00
transparentRegion . Sub ( data - > mVisibleRegion , data - > mOpaqueRegion ) ;
2011-09-29 06:19:26 +00:00
bool isOpaque = transparentRegion . IsEmpty ( ) ;
2014-09-26 17:06:08 +00:00
// For translucent PaintedLayers, try to find an opaque background
2010-09-02 09:18:39 +00: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 18:22:40 +00:00
backgroundColor = aFindOpaqueBackgroundColor ( ) ;
2010-09-02 09:18:39 +00:00
if ( NS_GET_A ( backgroundColor ) = = 255 ) {
2011-10-17 14:59:28 +00:00
isOpaque = true ;
2010-09-02 09:18:39 +00:00
}
}
// Store the background color
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * userData =
GetPaintedDisplayItemLayerUserData ( data - > mLayer ) ;
2010-09-02 09:18:39 +00:00
NS_ASSERTION ( userData , " where did our user data go? " ) ;
if ( userData - > mForcedBackgroundColor ! = backgroundColor ) {
2014-09-26 17:06:08 +00:00
// Invalidate the entire target PaintedLayer since we're changing
2010-09-02 09:18:39 +00:00
// the background color
2014-05-05 08:26:28 +00: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
2010-09-02 09:18:39 +00:00
data - > mLayer - > InvalidateRegion ( data - > mLayer - > GetValidRegion ( ) ) ;
}
userData - > mForcedBackgroundColor = backgroundColor ;
2012-02-07 22:27:44 +00:00
2014-10-24 16:32:23 +00:00
userData - > mFontSmoothingBackgroundColor = data - > mFontSmoothingBackgroundColor ;
2013-12-16 12:16:24 +00: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 00:00:22 +00:00
int32_t commonClipCount ;
// If the layer contains a single item fixed to the viewport, we removed
// its clip in ProcessDisplayItems() and saved it to set on the layer instead.
// Set the clip on the layer now.
2016-08-03 17:48:10 +00:00
if ( data - > mSingleItemFixedToViewport & & data - > mItemClip . HasClip ( ) ) {
2015-09-25 16:55:00 +00:00
nsIntRect layerClipRect = ScaleToNearestPixels ( data - > mItemClip . GetClipRect ( ) ) ;
layerClipRect . MoveBy ( mParameters . mOffset ) ;
2016-05-06 23:02:26 +00:00
// The clip from such an item becomes part of the layer's scrolled clip,
// and the associated mask layer one of the layer's "ancestor mask layers".
LayerClip scrolledClip ;
scrolledClip . SetClipRect ( ViewAs < ParentLayerPixel > ( layerClipRect ) ) ;
scrolledClip . SetMaskLayerIndex (
SetupMaskLayerForScrolledClip ( data - > mLayer , data - > mItemClip ) ) ;
data - > mLayer - > SetScrolledClip ( Some ( scrolledClip ) ) ;
2015-09-12 00:00:22 +00:00
// There is only one item, so all of the clips are in common to all items.
// data->mCommonClipCount will be zero because we removed the clip from
// the display item. (It could also be -1 if we're inside an inactive
// layer tree in which we don't call UpdateCommonClipCount() at all.)
MOZ_ASSERT ( data - > mCommonClipCount = = - 1 | | data - > mCommonClipCount = = 0 ) ;
commonClipCount = data - > mItemClip . GetRoundedRectCount ( ) ;
} else {
commonClipCount = std : : max ( 0 , data - > mCommonClipCount ) ;
2016-07-25 02:41:25 +00:00
SetupMaskLayer ( layer , data - > mItemClip , commonClipCount ) ;
2015-09-12 00:00:22 +00:00
}
2012-02-07 22:27:44 +00:00
// copy commonClipCount to the entry
2014-09-26 17:06:08 +00:00
FrameLayerBuilder : : PaintedLayerItemsEntry * entry = mLayerBuilder - >
GetPaintedLayerItemsEntry ( static_cast < PaintedLayer * > ( layer . get ( ) ) ) ;
2012-02-07 22:27:44 +00:00
entry - > mCommonClipCount = commonClipCount ;
} else {
// mask layer for image and color layers
2016-07-25 02:41:25 +00:00
SetupMaskLayer ( layer , data - > mItemClip ) ;
2010-09-02 09:18:39 +00:00
}
2013-12-13 18:53:18 +00:00
uint32_t flags = 0 ;
nsIWidget * widget = mContainerReferenceFrame - > PresContext ( ) - > GetRootWidget ( ) ;
2014-01-20 03:31:02 +00:00
// See bug 941095. Not quite ready to disable this.
bool hidpi = false & & widget & & widget - > GetDefaultScale ( ) . scale > = 2 ;
2013-12-13 18:53:18 +00:00
if ( hidpi ) {
flags | = Layer : : CONTENT_DISABLE_SUBPIXEL_AA ;
}
2010-12-20 01:26:14 +00:00
if ( isOpaque & & ! data - > mForceTransparentSurface ) {
2013-12-13 18:53:18 +00:00
flags | = Layer : : CONTENT_OPAQUE ;
} else if ( data - > mNeedComponentAlpha & & ! hidpi ) {
flags | = Layer : : CONTENT_COMPONENT_ALPHA ;
2010-12-20 01:26:14 +00:00
}
2015-06-26 22:13:50 +00:00
if ( data - > mDisableFlattening ) {
flags | = Layer : : CONTENT_DISABLE_FLATTENING ;
}
2010-09-02 09:18:40 +00:00
layer - > SetContentFlags ( flags ) ;
2010-09-02 09:18:39 +00:00
2014-09-26 17:06:08 +00:00
PaintedLayerData * containingPaintedLayerData =
mLayerBuilder - > GetContainingPaintedLayerData ( ) ;
if ( containingPaintedLayerData ) {
2014-07-03 18:40:13 +00:00
if ( ! data - > mDispatchToContentHitRegion . GetBounds ( ) . IsEmpty ( ) ) {
nsRect rect = nsLayoutUtils : : TransformFrameRectToAncestor (
mContainerReferenceFrame ,
data - > mDispatchToContentHitRegion . GetBounds ( ) ,
2014-09-26 17:06:08 +00:00
containingPaintedLayerData - > mReferenceFrame ) ;
containingPaintedLayerData - > mDispatchToContentHitRegion . Or (
containingPaintedLayerData - > mDispatchToContentHitRegion , rect ) ;
2014-07-03 18:40:13 +00:00
}
if ( ! data - > mMaybeHitRegion . GetBounds ( ) . IsEmpty ( ) ) {
nsRect rect = nsLayoutUtils : : TransformFrameRectToAncestor (
mContainerReferenceFrame ,
data - > mMaybeHitRegion . GetBounds ( ) ,
2014-09-26 17:06:08 +00:00
containingPaintedLayerData - > mReferenceFrame ) ;
containingPaintedLayerData - > mMaybeHitRegion . Or (
containingPaintedLayerData - > mMaybeHitRegion , rect ) ;
2016-03-16 19:27:19 +00:00
containingPaintedLayerData - > mMaybeHitRegion . SimplifyOutward ( 8 ) ;
2014-07-03 18:40:13 +00:00
}
2016-05-17 15:05:46 +00:00
Maybe < Matrix4x4 > matrixCache ;
2015-03-24 13:13:24 +00:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 15:05:46 +00:00
data - > mHitRegion ,
2015-03-24 13:13:24 +00:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mHitRegion ,
2016-05-17 15:05:46 +00:00
& containingPaintedLayerData - > mMaybeHitRegion ,
& matrixCache ) ;
2016-07-20 23:02:09 +00: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 13:13:24 +00:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 15:05:46 +00:00
data - > mNoActionRegion ,
2015-03-24 13:13:24 +00:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mNoActionRegion ,
2016-05-17 15:05:46 +00:00
& containingPaintedLayerData - > mDispatchToContentHitRegion ,
& matrixCache ) ;
2015-03-24 13:13:24 +00:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 15:05:46 +00:00
data - > mHorizontalPanRegion ,
2015-03-24 13:13:24 +00:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mHorizontalPanRegion ,
2016-05-17 15:05:46 +00:00
& containingPaintedLayerData - > mDispatchToContentHitRegion ,
& matrixCache ) ;
2015-03-24 13:13:24 +00:00
nsLayoutUtils : : TransformToAncestorAndCombineRegions (
2016-05-17 15:05:46 +00:00
data - > mVerticalPanRegion ,
2015-03-24 13:13:24 +00:00
mContainerReferenceFrame ,
containingPaintedLayerData - > mReferenceFrame ,
& containingPaintedLayerData - > mVerticalPanRegion ,
2016-05-17 15:05:46 +00:00
& containingPaintedLayerData - > mDispatchToContentHitRegion ,
& matrixCache ) ;
2016-07-20 23:02:09 +00:00
if ( alreadyHadRegions ) {
containingPaintedLayerData - > mDispatchToContentHitRegion . OrWith (
containingPaintedLayerData - > CombinedTouchActionRegion ( ) ) ;
}
2013-12-16 12:16:24 +00:00
} else {
EventRegions regions ;
2015-05-06 23:18:00 +00:00
regions . mHitRegion = ScaleRegionToOutsidePixels ( data - > mHitRegion ) ;
regions . mNoActionRegion = ScaleRegionToOutsidePixels ( data - > mNoActionRegion ) ;
regions . mHorizontalPanRegion = ScaleRegionToOutsidePixels ( data - > mHorizontalPanRegion ) ;
regions . mVerticalPanRegion = ScaleRegionToOutsidePixels ( data - > mVerticalPanRegion ) ;
2013-12-16 12:16:24 +00:00
// Points whose hit-region status we're not sure about need to be dispatched
2015-01-21 14:16:38 +00:00
// to the content thread. If a point is in both maybeHitRegion and hitRegion
// then it's not a "maybe" any more, and doesn't go into the dispatch-to-
// content region.
2015-05-06 23:18:00 +00:00
nsIntRegion maybeHitRegion = ScaleRegionToOutsidePixels ( data - > mMaybeHitRegion ) ;
2014-06-20 03:56:36 +00:00
regions . mDispatchToContentHitRegion . Sub ( maybeHitRegion , regions . mHitRegion ) ;
2015-01-21 14:16:38 +00:00
regions . mDispatchToContentHitRegion . OrWith (
2015-05-06 23:18:00 +00:00
ScaleRegionToOutsidePixels ( data - > mDispatchToContentHitRegion ) ) ;
2015-01-21 14:16:38 +00:00
regions . mHitRegion . OrWith ( maybeHitRegion ) ;
2014-06-20 03:56:36 +00:00
2015-05-06 23:18:00 +00:00
Matrix mat = layer - > GetTransform ( ) . As2D ( ) ;
2015-04-14 20:39:00 +00:00
mat . Invert ( ) ;
regions . ApplyTranslationAndScale ( mat . _31 , mat . _32 , mat . _11 , mat . _22 ) ;
2014-06-20 03:56:36 +00:00
2013-12-16 12:16:24 +00:00
layer - > SetEventRegions ( regions ) ;
}
2015-09-17 01:31:00 +00:00
SetBackfaceHiddenForLayer ( data - > mBackfaceHidden , data - > mLayer ) ;
if ( layer ! = data - > mLayer ) {
SetBackfaceHiddenForLayer ( data - > mBackfaceHidden , layer ) ;
}
2010-07-15 21:07:51 +00:00
}
2011-09-29 06:19:26 +00:00
static bool
2014-07-15 04:23:37 +00:00
IsItemAreaInWindowOpaqueRegion ( nsDisplayListBuilder * aBuilder ,
nsDisplayItem * aItem ,
const nsRect & aComponentAlphaBounds )
2011-01-03 01:48:09 +00:00
{
2014-07-15 04:23:37 +00: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 14:59:28 +00:00
return false ;
2011-01-03 01:48:09 +00:00
}
2014-07-15 04:23:37 +00:00
return aBuilder - > GetWindowOpaqueRegion ( ) . Contains ( aComponentAlphaBounds ) ;
2011-01-03 01:48:09 +00:00
}
2010-07-15 21:07:51 +00:00
void
2014-09-26 17:06:08 +00:00
PaintedLayerData : : Accumulate ( ContainerState * aState ,
2013-12-16 12:11:01 +00:00
nsDisplayItem * aItem ,
2014-06-09 04:48:00 +00:00
const nsIntRegion & aClippedOpaqueRegion ,
2013-12-16 12:11:01 +00:00
const nsIntRect & aVisibleRect ,
2015-03-04 05:21:55 +00:00
const DisplayItemClip & aClip ,
LayerState aLayerState )
2010-07-15 21:07:51 +00:00
{
2014-11-26 18:58:15 +00: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 15:53:24 +00:00
2014-09-15 20:09:52 +00:00
bool snap ;
nsRect itemBounds = aItem - > GetBounds ( aState - > mBuilder , & snap ) ;
2014-12-12 16:25:36 +00:00
mBounds = mBounds . Union ( aState - > ScaleToOutsidePixels ( itemBounds , snap ) ) ;
2014-09-15 20:09:52 +00:00
2012-05-03 04:29:05 +00:00
if ( aState - > mBuilder - > NeedToForceTransparentSurfaceForItem ( aItem ) ) {
mForceTransparentSurface = true ;
}
2012-05-03 04:29:05 +00:00
if ( aState - > mParameters . mDisableSubpixelAntialiasingInDescendants ) {
// Disable component alpha.
2014-09-26 17:06:08 +00:00
// Note that the transform (if any) on the PaintedLayer is always an integer translation so
2012-05-03 04:29:05 +00:00
// we don't have to factor that in here.
aItem - > DisableComponentAlpha ( ) ;
}
2012-05-03 04:29:05 +00:00
2014-02-28 19:52:03 +00:00
bool clipMatches = mItemClip = = aClip ;
2012-02-07 22:27:44 +00:00
mItemClip = aClip ;
2011-10-26 03:24:58 +00:00
2015-03-04 05:21:55 +00:00
mAssignedDisplayItems . AppendElement ( AssignedDisplayItem ( aItem , aClip , aLayerState ) ) ;
2015-02-18 18:01:40 +00:00
if ( ! mIsSolidColorInVisibleRegion & & mOpaqueRegion . Contains ( aVisibleRect ) & &
2015-06-16 17:41:59 +00:00
mVisibleRegion . Contains ( aVisibleRect ) & & ! mImage ) {
2014-09-26 17:06:08 +00:00
// A very common case! Most pages have a PaintedLayer with the page
2012-05-03 04:29:05 +00:00
// background (opaque) visible and most or all of the page content over the
// top of that background.
2015-02-18 18:01:40 +00: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 04:29:05 +00:00
return ;
}
2014-09-04 05:02:27 +00: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 17:41:59 +00:00
if ( nsIntRegion ( aVisibleRect ) . Contains ( mVisibleRegion ) & &
aClippedOpaqueRegion . Contains ( mVisibleRegion ) & &
2014-09-04 05:02:27 +00:00
aItem - > SupportsOptimizingToImage ( ) ) {
mImage = static_cast < nsDisplayImageContainer * > ( aItem ) ;
2014-09-26 17:07:06 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Tracking image: nsDisplayImageContainer covers the layer \n " ) ;
2014-09-04 05:02:27 +00:00
} else if ( mImage ) {
2014-09-26 17:07:06 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " No longer tracking image \n " ) ;
2014-09-04 05:02:27 +00:00
mImage = nullptr ;
}
2014-10-24 16:32:23 +00:00
bool isFirstVisibleItem = mVisibleRegion . IsEmpty ( ) ;
if ( isFirstVisibleItem ) {
nscolor fontSmoothingBGColor ;
2016-01-06 00:08:17 +00:00
if ( aItem - > ProvidesFontSmoothingBackgroundColor ( & fontSmoothingBGColor ) ) {
2014-10-24 16:32:23 +00:00
mFontSmoothingBackgroundColor = fontSmoothingBGColor ;
}
}
2016-05-19 08:07:52 +00:00
Maybe < nscolor > uniformColor = aItem - > IsUniform ( aState - > mBuilder ) ;
2014-10-19 20:50:29 +00:00
2011-01-16 10:38:45 +00: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 08:07:52 +00:00
if ( ! uniformColor | | NS_GET_A ( * uniformColor ) > 0 ) {
2012-04-10 11:24:18 +00: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 08:07:52 +00:00
if ( uniformColor ) {
2012-04-10 11:24:18 +00:00
bool snap ;
nsRect bounds = aItem - > GetBounds ( aState - > mBuilder , & snap ) ;
if ( ! aState - > ScaleToInsidePixels ( bounds , snap ) . Contains ( aVisibleRect ) ) {
2016-05-19 08:07:52 +00:00
uniformColor = Nothing ( ) ;
2014-09-26 17:07:06 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Display item does not cover the visible rect \n " ) ;
2012-04-10 11:24:18 +00:00
}
2014-10-19 20:50:29 +00:00
}
2016-05-19 08:07:52 +00:00
if ( uniformColor ) {
2014-10-24 16:32:23 +00:00
if ( isFirstVisibleItem ) {
2011-01-16 10:38:45 +00:00
// This color is all we have
2016-05-19 08:07:52 +00:00
mSolidColor = * uniformColor ;
2011-10-17 14:59:28 +00:00
mIsSolidColorInVisibleRegion = true ;
2011-01-16 10:38:45 +00:00
} else if ( mIsSolidColorInVisibleRegion & &
2015-06-16 17:41:59 +00:00
mVisibleRegion . IsEqual ( nsIntRegion ( aVisibleRect ) ) & &
2014-02-28 19:52:03 +00:00
clipMatches ) {
2011-01-16 10:38:45 +00:00
// we can just blend the colors together
2016-05-19 08:07:52 +00:00
mSolidColor = NS_ComposeColors ( mSolidColor , * uniformColor ) ;
2011-01-16 10:38:45 +00:00
} else {
2014-09-26 17:07:06 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Layer not a solid color: Can't blend colors togethers \n " ) ;
2011-10-17 14:59:28 +00:00
mIsSolidColorInVisibleRegion = false ;
2011-01-16 10:38:45 +00:00
}
2010-07-15 21:08:03 +00:00
} else {
2014-09-26 17:07:06 +00: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 14:59:28 +00:00
mIsSolidColorInVisibleRegion = false ;
2010-07-15 21:08:03 +00:00
}
2015-06-16 17:41:59 +00:00
mVisibleRegion . Or ( mVisibleRegion , aVisibleRect ) ;
mVisibleRegion . SimplifyOutward ( 4 ) ;
2011-01-16 10:38:45 +00:00
}
2014-02-21 01:11:17 +00:00
2014-06-09 04:48:00 +00:00
if ( ! aClippedOpaqueRegion . IsEmpty ( ) ) {
2016-01-19 01:20:59 +00:00
for ( auto iter = aClippedOpaqueRegion . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
2011-01-03 01:48:09 +00: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 01:20:59 +00:00
tmp . Or ( mOpaqueRegion , iter . Get ( ) ) ;
2011-01-03 01:48:09 +00: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 04:48:00 +00:00
if ( tmp . GetNumRects ( ) < = 4 | | aItem - > Frame ( ) - > PresContext ( ) - > IsChrome ( ) ) {
2015-09-14 18:18:20 +00:00
mOpaqueRegion = Move ( tmp ) ;
2011-01-03 01:48:09 +00:00
}
2010-07-15 21:08:11 +00:00
}
2011-01-03 01:48:09 +00:00
}
2012-05-03 04:29:05 +00:00
if ( ! aState - > mParameters . mDisableSubpixelAntialiasingInDescendants ) {
2012-01-11 11:26:33 +00:00
nsRect componentAlpha = aItem - > GetComponentAlphaBounds ( aState - > mBuilder ) ;
if ( ! componentAlpha . IsEmpty ( ) ) {
2012-04-10 11:24:18 +00:00
nsIntRect componentAlphaRect =
aState - > ScaleToOutsidePixels ( componentAlpha , false ) . Intersect ( aVisibleRect ) ;
if ( ! mOpaqueRegion . Contains ( componentAlphaRect ) ) {
2014-07-15 04:23:37 +00:00
if ( IsItemAreaInWindowOpaqueRegion ( aState - > mBuilder , aItem ,
componentAlpha . Intersect ( aItem - > GetVisibleRect ( ) ) ) ) {
2014-07-17 15:24:47 +00:00
mNeedComponentAlpha = true ;
2014-07-15 04:23:37 +00:00
} else {
aItem - > DisableComponentAlpha ( ) ;
2012-01-11 11:26:33 +00:00
}
2011-01-03 01:48:09 +00:00
}
2010-09-02 09:18:40 +00:00
}
2010-07-15 21:07:51 +00:00
}
2015-06-26 22:13:50 +00: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-15 21:07:51 +00:00
}
2016-07-20 23:02:09 +00:00
nsRegion
PaintedLayerData : : CombinedTouchActionRegion ( )
{
nsRegion result ;
result . Or ( mHorizontalPanRegion , mVerticalPanRegion ) ;
result . OrWith ( mNoActionRegion ) ;
return result ;
}
2015-08-31 23:59:22 +00:00
void
2015-08-31 23:53:34 +00:00
PaintedLayerData : : AccumulateEventRegions ( ContainerState * aState , nsDisplayLayerEventRegions * aEventRegions )
2015-08-31 23:59:22 +00:00
{
FLB_LOG_PAINTED_LAYER_DECISION ( this , " Accumulating event regions %p against pld=%p \n " , aEventRegions , this ) ;
2016-07-20 23:02:09 +00: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-08-31 23:53:34 +00:00
2015-09-04 16:14:28 +00: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-08-31 23:59:22 +00:00
}
2015-04-02 18:22:40 +00:00
PaintedLayerData
ContainerState : : NewPaintedLayerData ( nsDisplayItem * aItem ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * aScrollClip ,
2015-04-02 18:22:40 +00:00
const nsPoint & aTopLeft ,
2016-08-03 17:48:10 +00:00
bool aShouldFixToViewport )
2014-12-30 14:39:39 +00:00
{
2015-06-16 17:41:59 +00:00
PaintedLayerData data ;
data . mAnimatedGeometryRoot = aAnimatedGeometryRoot ;
2015-12-22 15:54:19 +00:00
data . mScrollClip = aScrollClip ;
2015-06-16 17:41:59 +00:00
data . mAnimatedGeometryRootOffset = aTopLeft ;
2015-04-02 18:22:40 +00:00
data . mReferenceFrame = aItem - > ReferenceFrame ( ) ;
2016-08-03 17:48:10 +00:00
data . mSingleItemFixedToViewport = aShouldFixToViewport ;
2016-02-08 22:34:13 +00:00
data . mBackfaceHidden = aItem - > Frame ( ) - > In3DContextAndBackfaceIsHidden ( ) ;
2015-04-02 18:22:40 +00:00
data . mNewChildLayersIndex = mNewChildLayers . Length ( ) ;
NewLayerEntry * newLayerEntry = mNewChildLayers . AppendElement ( ) ;
newLayerEntry - > mAnimatedGeometryRoot = aAnimatedGeometryRoot ;
2015-12-22 15:54:19 +00:00
newLayerEntry - > mScrollClip = aScrollClip ;
2015-04-02 18:22:40 +00: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 14:39:39 +00:00
2015-04-02 18:22:40 +00:00
return data ;
2010-07-15 21:07:51 +00:00
}
2012-03-05 18:09:05 +00:00
# ifdef MOZ_DUMP_PAINTING
static void
2014-06-27 11:19:40 +00:00
DumpPaintedImage ( nsDisplayItem * aItem , SourceSurface * aSurface )
2012-03-05 18:09:05 +00:00
{
nsCString string ( aItem - > Name ( ) ) ;
2014-05-22 03:48:52 +00:00
string . Append ( ' - ' ) ;
2012-08-22 15:56:38 +00:00
string . AppendInt ( ( uint64_t ) aItem ) ;
2015-09-25 23:23:13 +00:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " <script>array[ \" %s \" ]= \" " , string . BeginReading ( ) ) ;
2014-06-27 11:19:40 +00:00
gfxUtils : : DumpAsDataURI ( aSurface , gfxUtils : : sDumpPaintFile ) ;
2015-09-25 23:23:13 +00:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " \" ;</script> \n " ) ;
2012-03-05 18:09:05 +00:00
}
# endif
2011-02-10 08:58:11 +00:00
static void
PaintInactiveLayer ( nsDisplayListBuilder * aBuilder ,
2012-08-29 05:47:15 +00:00
LayerManager * aManager ,
2011-02-10 08:58:11 +00:00
nsDisplayItem * aItem ,
2012-07-17 17:03:51 +00:00
gfxContext * aContext ,
2012-08-29 05:47:15 +00:00
nsRenderingContext * aCtx )
2010-08-03 03:33:24 +00:00
{
2014-09-26 17:06:08 +00:00
// This item has an inactive layer. Render it to a PaintedLayer
2011-02-10 08:58:11 +00:00
// using a temporary BasicLayerManager.
2012-08-29 05:47:15 +00:00
BasicLayerManager * basic = static_cast < BasicLayerManager * > ( aManager ) ;
2015-10-18 05:24:48 +00:00
RefPtr < gfxContext > context = aContext ;
2012-08-29 05:47:15 +00:00
# ifdef MOZ_DUMP_PAINTING
2012-08-22 15:56:38 +00:00
int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel ( aItem ) ;
2012-03-05 18:09:05 +00:00
nsIntRect itemVisibleRect =
aItem - > GetVisibleRect ( ) . ToOutsidePixels ( appUnitsPerDevPixel ) ;
2015-10-18 05:24:48 +00:00
RefPtr < DrawTarget > tempDT ;
2015-10-28 13:31:00 +00:00
if ( gfxEnv : : DumpPaint ( ) ) {
2014-06-27 11:19:40 +00:00
tempDT = gfxPlatform : : GetPlatform ( ) - > CreateOffscreenContentDrawTarget (
2015-03-29 14:59:08 +00:00
itemVisibleRect . Size ( ) ,
2014-06-27 11:19:40 +00:00
SurfaceFormat : : B8G8R8A8 ) ;
2015-03-09 19:48:20 +00:00
if ( tempDT ) {
2016-06-06 23:39:56 +00:00
context = gfxContext : : CreateOrNull ( tempDT ) ;
2016-04-12 19:18:11 +00: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 19:48:20 +00:00
context - > SetMatrix ( gfxMatrix : : Translation ( - itemVisibleRect . x ,
- itemVisibleRect . y ) ) ;
}
2012-03-05 18:09:05 +00:00
}
# endif
2013-11-06 19:10:49 +00:00
basic - > BeginTransaction ( ) ;
2012-08-29 05:47:15 +00:00
basic - > SetTarget ( context ) ;
2012-03-05 18:09:05 +00:00
2016-08-09 19:02:45 +00:00
if ( aItem - > GetType ( ) = = nsDisplayItem : : TYPE_MASK ) {
static_cast < nsDisplayMask * > ( aItem ) - > PaintAsLayer ( aBuilder , aCtx , basic ) ;
2012-08-29 05:47:15 +00:00
if ( basic - > InTransaction ( ) ) {
basic - > AbortTransaction ( ) ;
2012-07-20 04:53:55 +00:00
}
2016-09-01 03:14:00 +00:00
} else if ( aItem - > GetType ( ) = = nsDisplayItem : : TYPE_FILTER ) {
static_cast < nsDisplayFilter * > ( aItem ) - > PaintAsLayer ( aBuilder , aCtx , basic ) ;
if ( basic - > InTransaction ( ) ) {
basic - > AbortTransaction ( ) ;
}
2012-07-17 17:03:51 +00:00
} else {
2014-09-26 17:06:08 +00:00
basic - > EndTransaction ( FrameLayerBuilder : : DrawPaintedLayer , aBuilder ) ;
2012-08-29 05:47:15 +00:00
}
FrameLayerBuilder * builder = static_cast < FrameLayerBuilder * > ( basic - > GetUserData ( & gLayerManagerLayerBuilder ) ) ;
if ( builder ) {
builder - > DidEndTransaction ( ) ;
2012-07-17 17:03:51 +00:00
}
2012-10-23 11:05:14 +00:00
2012-11-09 06:01:24 +00:00
basic - > SetTarget ( nullptr ) ;
2012-03-05 18:09:05 +00:00
# ifdef MOZ_DUMP_PAINTING
2015-10-28 13:31:00 +00:00
if ( gfxEnv : : DumpPaint ( ) & & tempDT ) {
2015-10-18 05:24:48 +00:00
RefPtr < SourceSurface > surface = tempDT - > Snapshot ( ) ;
2014-06-27 11:19:40 +00: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 17:28:21 +00:00
2012-03-05 18:09:05 +00:00
aItem - > SetPainted ( ) ;
}
# endif
2010-08-03 03:33:24 +00:00
}
2012-12-04 06:05:22 +00:00
/**
* Chooses a single active scrolled root for the entire display list , used
* when we are flattening layers .
*/
2012-12-11 20:36:22 +00:00
bool
2013-09-25 21:07:26 +00:00
ContainerState : : ChooseAnimatedGeometryRoot ( const nsDisplayList & aList ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * * aAnimatedGeometryRoot )
2012-12-04 06:05:22 +00:00
{
for ( nsDisplayItem * item = aList . GetBottom ( ) ; item ; item = item - > GetAbove ( ) ) {
2012-12-11 20:36:22 +00:00
LayerState layerState = item - > GetLayerState ( mBuilder , mManager , mParameters ) ;
2014-09-26 17:06:08 +00:00
// Don't use an item that won't be part of any PaintedLayers to pick the
2012-12-11 20:36:22 +00: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-24 22:53:51 +00:00
* aAnimatedGeometryRoot = item - > GetAnimatedGeometryRoot ( ) ;
2013-09-27 06:01:16 +00:00
return true ;
2012-12-04 06:05:22 +00:00
}
2012-12-11 20:36:22 +00:00
return false ;
2012-12-04 06:05:22 +00:00
}
2014-06-23 04:24:00 +00:00
nsIntRegion
ContainerState : : ComputeOpaqueRect ( nsDisplayItem * aItem ,
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot ,
2014-06-23 04:24:00 +00:00
const DisplayItemClip & aClip ,
nsDisplayList * aList ,
2014-08-31 03:29:24 +00:00
bool * aHideAllLayersBelow ,
bool * aOpaqueForAnimatedGeometryRootParent )
2014-06-23 04:24:00 +00:00
{
bool snapOpaque ;
nsRegion opaque = aItem - > GetOpaqueRegion ( mBuilder , & snapOpaque ) ;
2016-03-10 00:56:52 +00:00
if ( opaque . IsEmpty ( ) ) {
return nsIntRegion ( ) ;
}
2014-06-23 04:24:00 +00:00
nsIntRegion opaquePixels ;
2016-03-10 00:56:52 +00:00
nsRegion opaqueClipped ;
for ( auto iter = opaque . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
opaqueClipped . Or ( opaqueClipped ,
aClip . ApproximateIntersectInward ( iter . Get ( ) ) ) ;
}
if ( aAnimatedGeometryRoot = = mContainerAnimatedGeometryRoot & &
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 ;
}
nsIScrollableFrame * sf = nsLayoutUtils : : GetScrollableFrameFor ( * aAnimatedGeometryRoot ) ;
if ( sf ) {
nsRect displayport ;
bool usingDisplayport =
nsLayoutUtils : : GetDisplayPort ( ( * aAnimatedGeometryRoot ) - > GetContent ( ) , & displayport ,
RelativeTo : : ScrollFrame ) ;
if ( ! usingDisplayport ) {
// No async scrolling, so all that matters is that the layer contents
// cover the scrollport.
displayport = sf - > GetScrollPortRect ( ) ;
}
nsIFrame * scrollFrame = do_QueryFrame ( sf ) ;
displayport + = scrollFrame - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
Bug 1012752 - Snap scrolled area to layer pixels. r=tnikkel
We want the maximum scroll position to be aligned with layer pixels. That way
we don't have to re-rasterize the scrolled contents once scrolling hits the
edge of the scrollable area.
Here's how we determine the maximum scroll position: We get the scroll port
rect, snapped to layer pixels. Then we get the scrolled rect and also snap
that to layer pixels. The maximum scroll position is set to the difference
between right/bottom edges of these rectangles.
Now the scrollable area is computed by adding this maximum scroll position
to the unsnapped scroll port size.
The underlying idea here is: Pretend we have overflow:visible so that the
scrolled contents start at (0, 0) relative to the scroll port and spill over
the scroll port edges. When these contents are rendered, their rendering is
snapped to layer pixels. We want those exact pixels to be accessible by
scrolling.
This way of computing the snapped scrollable area ensures that, if you scroll
to the maximum scroll position, the right/bottom edges of the rendered
scrolled contents line up exactly with the right/bottom edges of the scroll
port. The scrolled contents are neither cut off nor are they moved too far.
(This is something that no other browser engine gets completely right, see the
testcase in bug 1012752.)
There are also a few disadvantages to this solution. We snap to layer pixels,
and the size of a layer pixel can depend on the zoom level, the document
resolution, the current screen's scale factor, and CSS transforms. The snap
origin is the position of the reference frame. So a change to any of these
things can influence the scrollable area and the maximum scroll position.
This patch does not make us adjust the current scroll position in the event
that the maximum scroll position changes such that the current scroll position
would be out of range, unless there's a reflow of the scrolled contents. This
means that we can sometimes render a slightly inconsistent state where the
current scroll position exceeds the maximum scroll position. We can fix this
once it turns out to be a problem; I doubt that it will be a problem because
none of the other browsers seems to prevent this problem either.
The size of the scrollable area is exposed through the DOM properties
scrollWidth and scrollHeight. At the moment, these are integer properties, so
their value is rounded to the nearest CSS pixel. Before this patch, the
returned value would always be within 0.5 CSS pixels of the value that layout
computed for the content's scrollable overflow based on the CSS styles of the
contents.
Now that scrollWidth and scrollHeight also depend on pixel snapping, their
values can deviate by up to one layer pixel from what the page might expect
based on the styles of the contents. This change requires a few changes to
existing tests.
The fact that scrollWidth and scrollHeight can change based on the position of
the scrollable element and the zoom level / resolution may surprise some web
pages. However, this also seems to happen in Edge. Edge seems to always round
scrollWidth and scrollHeight upwards, possibly to their equivalent of layout
device pixels.
MozReview-Commit-ID: 3LFV7Lio4tG
--HG--
extra : rebase_source : 3e4e0b60493397e61283aa1d7fd93d7c197dec29
extra : source : d43c2d5e87f31ff47d7f3ada66c3f5f27cef84a9
2016-08-05 03:51:58 +00:00
if ( opaquePixels . Contains ( ScaleRegionToNearestPixels ( displayport ) ) ) {
2016-03-10 00:56:52 +00:00
* aOpaqueForAnimatedGeometryRootParent = true ;
2014-08-31 03:29:24 +00:00
}
2014-06-23 04:24:00 +00:00
}
return opaquePixels ;
}
2015-12-22 15:54:19 +00:00
static const DisplayItemScrollClip *
InnermostScrollClipApplicableToAGR ( const DisplayItemScrollClip * aItemScrollClip ,
AnimatedGeometryRoot * aAnimatedGeometryRoot )
2015-07-02 21:04:14 +00:00
{
2015-12-22 15:54:19 +00:00
// "Applicable" scroll clips are those that are for nsIScrollableFrames
// that are ancestors of aAnimatedGeometryRoot or ancestors of aContainerScrollClip.
// They can be applied to all items sharing this animated geometry root, so
// instead of applying to the items individually, they can be applied to the
// whole layer.
for ( const DisplayItemScrollClip * scrollClip = aItemScrollClip ;
scrollClip ;
scrollClip = scrollClip - > mParent ) {
nsIFrame * scrolledFrame = scrollClip - > mScrollableFrame - > GetScrolledFrame ( ) ;
if ( nsLayoutUtils : : IsAncestorFrameCrossDoc ( scrolledFrame , * aAnimatedGeometryRoot ) ) {
// scrollClip and all its ancestors are applicable.
return scrollClip ;
2015-07-02 21:04:14 +00:00
}
}
2015-12-22 15:54:19 +00:00
return nullptr ;
2015-07-02 21:04:14 +00:00
}
2016-05-06 23:02:26 +00: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 ( ) ;
}
2010-07-15 21:07:51 +00: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 17:06:08 +00:00
* to a layer . We invalidate the areas in PaintedLayers where an item
* has moved from one PaintedLayer to another . Also ,
2014-09-26 17:07:06 +00:00
* aState - > mInvalidPaintedContent is invalidated in every PaintedLayer .
2012-02-07 22:27:44 +00: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 17:06:08 +00:00
* ( PaintedLayers don ' t need a clip rect on the layer , we clip the items
2010-07-15 21:07:51 +00:00
* individually when we draw them . )
* We set the visible rect for all layers , although the actual setting
2014-09-26 17:06:08 +00:00
* of visible rects for some PaintedLayers is deferred until the calling
2010-07-15 21:07:51 +00:00
* of ContainerState : : Finish .
*/
void
2014-09-06 04:16:33 +00:00
ContainerState : : ProcessDisplayItems ( nsDisplayList * aList )
2010-07-15 21:07:51 +00:00
{
2014-05-23 21:12:29 +00:00
PROFILER_LABEL ( " ContainerState " , " ProcessDisplayItems " ,
js : : ProfileEntry : : Category : : GRAPHICS ) ;
2012-10-11 23:38:25 +00:00
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * lastAnimatedGeometryRoot = mContainerAnimatedGeometryRoot ;
2016-09-08 03:39:04 +00:00
nsPoint lastAGRTopLeft ;
2014-02-18 04:00:35 +00:00
nsPoint topLeft ( 0 , 0 ) ;
2012-10-11 23:38:25 +00:00
2012-12-04 06:05:22 +00: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 04:16:33 +00:00
if ( mFlattenToSingleLayer ) {
2014-06-09 04:48:00 +00:00
if ( ChooseAnimatedGeometryRoot ( * aList , & lastAnimatedGeometryRoot ) ) {
2016-09-08 03:39:04 +00:00
lastAGRTopLeft = ( * lastAnimatedGeometryRoot ) - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2012-12-04 06:05:22 +00:00
}
}
2016-03-04 17:13:57 +00:00
int32_t maxLayers = gfxPrefs : : MaxActiveLayers ( ) ;
2013-07-16 20:17:18 +00:00
int layerCount = 0 ;
2014-06-09 04:48:00 +00:00
nsDisplayList savedItems ;
nsDisplayItem * item ;
while ( ( item = aList - > RemoveBottom ( ) ) ! = nullptr ) {
2016-06-03 14:20:38 +00:00
nsDisplayItem : : Type itemType = item - > GetType ( ) ;
// If the item is a event regions item, but is empty (has no regions in it)
// then we should just throw it out
if ( itemType = = nsDisplayItem : : TYPE_LAYER_EVENT_REGIONS ) {
nsDisplayLayerEventRegions * eventRegions =
static_cast < nsDisplayLayerEventRegions * > ( item ) ;
if ( eventRegions - > IsEmpty ( ) ) {
item - > ~ nsDisplayItem ( ) ;
continue ;
}
}
2014-06-09 04:48:00 +00:00
// Peek ahead to the next item and try merging with it or swapping with it
// if necessary.
nsDisplayItem * aboveItem ;
while ( ( aboveItem = aList - > GetBottom ( ) ) ! = nullptr ) {
2016-01-06 00:08:17 +00:00
if ( aboveItem - > TryMerge ( item ) ) {
2014-06-09 04:48:00 +00:00
aList - > RemoveBottom ( ) ;
item - > ~ nsDisplayItem ( ) ;
item = aboveItem ;
2016-06-03 14:20:38 +00:00
itemType = item - > GetType ( ) ;
2014-06-09 04:48:00 +00:00
} else {
break ;
}
}
2015-04-21 03:48:10 +00:00
nsDisplayList * itemSameCoordinateSystemChildren
= item - > GetSameCoordinateSystemChildren ( ) ;
if ( item - > ShouldFlattenAway ( mBuilder ) ) {
aList - > AppendToBottom ( itemSameCoordinateSystemChildren ) ;
item - > ~ nsDisplayItem ( ) ;
continue ;
}
2014-06-09 04:48:00 +00:00
savedItems . AppendToTop ( item ) ;
2012-04-10 11:24:18 +00:00
NS_ASSERTION ( mAppUnitsPerDevPixel = = AppUnitsPerDevPixel ( item ) ,
2010-08-08 18:49:07 +00:00
" items in a container layer should all have the same app units per dev pixel " ) ;
2014-08-20 15:25:19 +00:00
if ( mBuilder - > NeedToForceTransparentSurfaceForItem ( item ) ) {
aList - > SetNeedsTransparentSurface ( ) ;
}
2016-08-10 03:15:28 +00:00
if ( mParameters . mForEventsAndPluginsOnly & & ! item - > GetChildren ( ) & &
( itemType ! = nsDisplayItem : : TYPE_LAYER_EVENT_REGIONS & &
itemType ! = nsDisplayItem : : TYPE_PLUGIN ) ) {
2015-11-11 02:09:21 +00:00
continue ;
}
2015-07-02 21:00:17 +00:00
LayerState layerState = item - > GetLayerState ( mBuilder , mManager , mParameters ) ;
if ( layerState = = LAYER_INACTIVE & &
nsDisplayItem : : ForceActiveLayers ( ) ) {
layerState = LAYER_ACTIVE ;
}
bool forceInactive ;
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * animatedGeometryRoot ;
2015-12-22 15:54:19 +00:00
AnimatedGeometryRoot * animatedGeometryRootForClip = nullptr ;
2016-08-25 02:25:57 +00:00
if ( mFlattenToSingleLayer & & layerState ! = LAYER_ACTIVE_FORCE ) {
2015-07-02 21:00:17 +00:00
forceInactive = true ;
animatedGeometryRoot = lastAnimatedGeometryRoot ;
2016-09-08 03:39:04 +00:00
topLeft = lastAGRTopLeft ;
2015-07-02 21:00:17 +00:00
} else {
forceInactive = false ;
if ( mManager - > IsWidgetLayerManager ( ) ) {
2015-12-22 15:54:19 +00:00
animatedGeometryRoot = item - > GetAnimatedGeometryRoot ( ) ;
animatedGeometryRootForClip = item - > AnimatedGeometryRootForScrollMetadata ( ) ;
2015-07-02 21:00:17 +00: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 ;
}
2015-11-24 22:53:51 +00:00
topLeft = ( * animatedGeometryRoot ) - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2015-07-02 21:00:17 +00:00
}
2015-12-22 15:54:19 +00:00
if ( ! animatedGeometryRootForClip ) {
animatedGeometryRootForClip = animatedGeometryRoot ;
}
const DisplayItemScrollClip * itemScrollClip = item - > ScrollClip ( ) ;
// Now we need to separate the item's scroll clip chain into those scroll
// clips that can be applied to the whole layer (i.e. to all items
// sharing the item's animated geometry root), and those that need to be
// applied to the item itself.
const DisplayItemScrollClip * agrScrollClip =
InnermostScrollClipApplicableToAGR ( itemScrollClip , animatedGeometryRootForClip ) ;
MOZ_ASSERT ( DisplayItemScrollClip : : IsAncestor ( agrScrollClip , itemScrollClip ) ) ;
if ( agrScrollClip ! = itemScrollClip ) {
2015-07-02 21:04:14 +00:00
// Pick up any scroll clips that should apply to the item and apply them.
2015-12-22 15:54:19 +00:00
DisplayItemClip clip = item - > GetClip ( ) ;
for ( const DisplayItemScrollClip * scrollClip = itemScrollClip ;
scrollClip & & scrollClip ! = agrScrollClip & & scrollClip ! = mContainerScrollClip ;
scrollClip = scrollClip - > mParent ) {
if ( scrollClip - > mClip ) {
clip . IntersectWith ( * scrollClip - > mClip ) ;
}
}
2015-07-02 21:04:14 +00:00
item - > SetClip ( mBuilder , clip ) ;
}
2016-05-16 21:20:23 +00:00
bool clipMovesWithLayer = ( animatedGeometryRoot = = animatedGeometryRootForClip ) ;
2016-08-03 17:48:10 +00:00
bool shouldFixToViewport = ! clipMovesWithLayer & &
! ( * animatedGeometryRoot ) - > GetParent ( ) & &
item - > ShouldFixToViewport ( mBuilder ) ;
// For items that are fixed to the viewport, remove their clip at the
// display item level because additional areas could be brought into
// view by async scrolling. Save the clip so we can set it on the layer
// instead later.
DisplayItemClip fixedToViewportClip = DisplayItemClip : : NoClip ( ) ;
if ( shouldFixToViewport ) {
fixedToViewportClip = item - > GetClip ( ) ;
2015-09-12 00:00:22 +00:00
item - > SetClip ( mBuilder , DisplayItemClip : : NoClip ( ) ) ;
}
2012-04-10 11:24:18 +00:00
bool snap ;
nsRect itemContent = item - > GetBounds ( mBuilder , & snap ) ;
2015-02-11 23:06:47 +00:00
if ( itemType = = nsDisplayItem : : TYPE_LAYER_EVENT_REGIONS ) {
nsDisplayLayerEventRegions * eventRegions =
static_cast < nsDisplayLayerEventRegions * > ( item ) ;
itemContent = eventRegions - > GetHitRegionBounds ( mBuilder , & snap ) ;
}
2012-04-13 11:44:05 +00:00
nsIntRect itemDrawRect = ScaleToOutsidePixels ( itemContent , snap ) ;
2014-07-29 12:09:35 +00:00
bool prerenderedTransform = itemType = = nsDisplayItem : : TYPE_TRANSFORM & &
2016-05-18 03:12:44 +00:00
static_cast < nsDisplayTransform * > ( item ) - > MayBeAnimated ( mBuilder ) ;
2015-04-12 02:03:00 +00:00
ParentLayerIntRect clipRect ;
2013-03-04 09:56:02 +00:00
const DisplayItemClip & itemClip = item - > GetClip ( ) ;
if ( itemClip . HasClip ( ) ) {
itemContent . IntersectRect ( itemContent , itemClip . GetClipRect ( ) ) ;
2015-04-12 02:03:00 +00:00
clipRect = ViewAs < ParentLayerPixel > ( ScaleToNearestPixels ( itemClip . GetClipRect ( ) ) ) ;
2014-07-29 12:09:35 +00:00
if ( ! prerenderedTransform ) {
2015-11-07 03:13:40 +00:00
itemDrawRect . IntersectRect ( itemDrawRect , clipRect . ToUnknownRect ( ) ) ;
2014-07-29 12:09:35 +00:00
}
2015-04-12 02:03:00 +00:00
clipRect . MoveBy ( ViewAs < ParentLayerPixel > ( mParameters . mOffset ) ) ;
2010-08-02 03:06:58 +00:00
}
2014-06-09 04:48:00 +00:00
# ifdef DEBUG
2015-02-11 23:06:47 +00:00
nsRect bounds = itemContent ;
bool dummy ;
if ( itemType = = nsDisplayItem : : TYPE_LAYER_EVENT_REGIONS ) {
bounds = item - > GetBounds ( mBuilder , & dummy ) ;
if ( itemClip . HasClip ( ) ) {
bounds . IntersectRect ( bounds , itemClip . GetClipRect ( ) ) ;
}
}
2016-08-03 17:48:10 +00:00
bounds = fixedToViewportClip . ApplyNonRoundedIntersection ( bounds ) ;
2016-02-22 15:17:16 +00:00
if ( ! bounds . IsEmpty ( ) ) {
for ( const DisplayItemScrollClip * scrollClip = itemScrollClip ;
scrollClip & & scrollClip ! = mContainerScrollClip ;
scrollClip = scrollClip - > mParent ) {
if ( scrollClip - > mClip ) {
if ( scrollClip - > mIsAsyncScrollable ) {
bounds = scrollClip - > mClip - > GetClipRect ( ) ;
} else {
bounds = scrollClip - > mClip - > ApplyNonRoundedIntersection ( bounds ) ;
}
}
2015-12-22 15:54:19 +00:00
}
}
2015-02-11 23:06:47 +00:00
( ( nsRect & ) mAccumulatedChildBounds ) . UnionRect ( mAccumulatedChildBounds , bounds ) ;
2014-06-09 04:48:00 +00:00
# endif
2015-09-25 12:40:52 +00:00
nsIntRect itemVisibleRect = itemDrawRect ;
2016-05-16 21:14:29 +00: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.
itemVisibleRect = itemVisibleRect . Intersect (
ScaleToOutsidePixels ( item - > GetVisibleRect ( ) , false ) ) ;
2012-04-10 11:24:18 +00:00
2013-07-16 20:17:18 +00:00
if ( maxLayers ! = - 1 & & layerCount > = maxLayers ) {
forceInactive = true ;
}
2010-07-15 21:07:51 +00:00
// Assign the item to a layer
2011-03-15 23:20:19 +00:00
if ( layerState = = LAYER_ACTIVE_FORCE | |
2012-11-13 22:22:21 +00:00
( layerState = = LAYER_INACTIVE & & ! mManager - > IsWidgetLayerManager ( ) ) | |
2012-07-23 03:00:36 +00:00
( ! forceInactive & &
( layerState = = LAYER_ACTIVE_EMPTY | |
layerState = = LAYER_ACTIVE ) ) ) {
2011-04-13 21:12:22 +00:00
2013-07-16 20:17:18 +00:00
layerCount + + ;
2011-04-13 21:12:22 +00: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 02:55:51 +00:00
itemVisibleRect . IsEmpty ( ) ,
2011-04-13 21:12:22 +00:00
" State is LAYER_ACTIVE_EMPTY but visible rect is not. " ) ;
2014-09-26 17:06:08 +00:00
// As long as the new layer isn't going to be a PaintedLayer,
2012-10-12 02:39:46 +00: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 06:03:24 +00:00
InvalidateForLayerChange ( item , nullptr ) ;
2012-10-12 02:39:46 +00:00
2010-07-15 21:08:09 +00: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 17:06:08 +00:00
// way, since their PaintedLayer may decide it wants to draw them
2010-07-15 21:08:09 +00:00
// into its buffer even if they're currently covered.
2013-03-19 13:08:29 +00:00
if ( itemVisibleRect . IsEmpty ( ) & &
! item - > ShouldBuildLayerEvenIfInvisible ( mBuilder ) ) {
2010-07-15 21:08:09 +00:00
continue ;
}
2016-02-26 00:29:41 +00:00
if ( mScrollClipForPerspectiveChild ) {
// We are the single transform child item of an nsDisplayPerspective.
// Our parent forwarded a scroll clip to us. Pick it up.
// We do this after any clipping has been applied, because this
// forwarded scroll clip is only used for scrolling (in the form of
// APZ frame metrics), not for clipping - the clip still belongs on
// the perspective item.
MOZ_ASSERT ( itemType = = nsDisplayItem : : TYPE_TRANSFORM ) ;
MOZ_ASSERT ( ! itemScrollClip ) ;
MOZ_ASSERT ( ! agrScrollClip ) ;
MOZ_ASSERT ( DisplayItemScrollClip : : IsAncestor ( mContainerScrollClip ,
mScrollClipForPerspectiveChild ) ) ;
itemScrollClip = mScrollClipForPerspectiveChild ;
agrScrollClip = mScrollClipForPerspectiveChild ;
}
2015-02-25 16:47:22 +00:00
// 3D-transformed layers don't necessarily draw in the order in which
// they're added to their parent container layer.
bool mayDrawOutOfOrder = itemType = = nsDisplayItem : : TYPE_TRANSFORM & &
2015-09-17 01:31:00 +00:00
( item - > Frame ( ) - > Combines3DTransformWithAncestors ( ) | |
item - > Frame ( ) - > Extend3DContext ( ) ) ;
2015-02-25 16:47:22 +00:00
2015-04-02 18:22:40 +00: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 00:56:52 +00:00
nscolor * uniformColorPtr = ( mayDrawOutOfOrder | | IsInInactiveLayer ( ) ) ? nullptr :
& uniformColor ;
2015-04-12 02:03:00 +00:00
nsIntRect clipRectUntyped ;
2016-08-03 17:48:10 +00:00
const DisplayItemClip & layerClip = shouldFixToViewport ? fixedToViewportClip : itemClip ;
2015-10-28 17:46:40 +00:00
ParentLayerIntRect layerClipRect ;
nsIntRect * clipPtr = nullptr ;
if ( layerClip . HasClip ( ) ) {
layerClipRect = ViewAs < ParentLayerPixel > (
ScaleToNearestPixels ( layerClip . GetClipRect ( ) ) + mParameters . mOffset ) ;
2015-11-07 03:13:40 +00:00
clipRectUntyped = layerClipRect . ToUnknownRect ( ) ;
2015-10-28 17:46:40 +00:00
clipPtr = & clipRectUntyped ;
2015-04-12 02:03:00 +00:00
}
2015-11-24 22:53:51 +00:00
if ( * animatedGeometryRoot = = item - > Frame ( ) & &
* animatedGeometryRoot ! = mBuilder - > RootReferenceFrame ( ) ) {
2015-04-02 18:22:40 +00:00
// This is the case for scrollbar thumbs, for example. In that case the
// clip we care about is the overflow:hidden clip on the scrollbar.
2015-11-24 22:53:51 +00:00
mPaintedLayerDataTree . AddingOwnLayer ( animatedGeometryRoot - > mParentAGR ,
2016-03-07 20:50:35 +00:00
clipPtr ,
uniformColorPtr ) ;
2015-04-02 18:22:40 +00:00
} else if ( prerenderedTransform ) {
mPaintedLayerDataTree . AddingOwnLayer ( animatedGeometryRoot ,
2016-03-07 20:50:35 +00:00
clipPtr ,
uniformColorPtr ) ;
2016-08-03 17:48:10 +00:00
} else if ( shouldFixToViewport ) {
2016-06-03 00:55:02 +00:00
mPaintedLayerDataTree . AddingOwnLayer ( animatedGeometryRootForClip ,
clipPtr ,
uniformColorPtr ) ;
2015-04-02 18:22:40 +00: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 19:43:15 +00:00
ContainerLayerParameters params = mParameters ;
params . mBackgroundColor = uniformColor ;
2016-03-08 19:43:32 +00:00
params . mLayerCreationHint = GetLayerCreationHint ( animatedGeometryRoot ) ;
2016-03-08 19:43:15 +00:00
params . mScrollClip = agrScrollClip ;
params . mScrollClipForPerspectiveChild = nullptr ;
2016-02-26 00:29:41 +00:00
if ( itemType = = nsDisplayItem : : TYPE_PERSPECTIVE ) {
// Perspective items have a single child item, an nsDisplayTransform.
// If the perspective item is scrolled, but the perspective-inducing
// frame is outside the scroll frame (indicated by this items AGR
// 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.
// Our agrScrollClip is the scroll clip that's applicable to our
// perspective frame, so it won't be the scroll clip for the scrolled
// frame in the case that we care about, and we'll forward that scroll
// clip to our child.
2016-03-08 19:43:15 +00:00
params . mScrollClipForPerspectiveChild = itemScrollClip ;
2016-02-26 00:29:41 +00:00
}
2015-02-25 16:47:22 +00:00
2010-07-15 21:08:05 +00:00
// Just use its layer.
2014-07-11 01:17:47 +00: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 04:24:00 +00:00
nsIntRect layerContentsVisibleRect ( 0 , 0 , - 1 , - 1 ) ;
2016-03-08 19:43:15 +00:00
params . mLayerContentsVisibleRect = & layerContentsVisibleRect ;
RefPtr < Layer > ownLayer = item - > BuildLayer ( mBuilder , mManager , params ) ;
2010-07-15 21:08:05 +00:00
if ( ! ownLayer ) {
continue ;
}
2014-09-26 17:06:08 +00:00
NS_ASSERTION ( ! ownLayer - > AsPaintedLayer ( ) ,
2014-09-26 17:07:06 +00:00
" Should never have created a dedicated Painted layer! " ) ;
2012-10-12 02:39:46 +00:00
2015-09-17 01:31:00 +00:00
if ( item - > BackfaceIsHidden ( ) ) {
ownLayer - > SetContentFlags ( ownLayer - > GetContentFlags ( ) |
Layer : : CONTENT_BACKFACE_HIDDEN ) ;
} else {
ownLayer - > SetContentFlags ( ownLayer - > GetContentFlags ( ) &
~ Layer : : CONTENT_BACKFACE_HIDDEN ) ;
}
2012-08-29 05:48:45 +00:00
nsRect invalid ;
if ( item - > IsInvalid ( invalid ) ) {
2012-08-29 05:47:18 +00:00
ownLayer - > SetInvalidRectToVisibleRegion ( ) ;
}
2011-06-22 12:11:27 +00:00
// If it's not a ContainerLayer, we need to apply the scale transform
// ourselves.
if ( ! ownLayer - > AsContainerLayer ( ) ) {
2012-08-03 21:29:22 +00:00
ownLayer - > SetPostScale ( mParameters . mXScale ,
mParameters . mYScale ) ;
2011-06-22 12:11:27 +00:00
}
2010-07-15 21:08:05 +00:00
// Update that layer's clip and visible rects.
2010-07-15 21:07:51 +00:00
NS_ASSERTION ( ownLayer - > Manager ( ) = = mManager , " Wrong manager " ) ;
2010-09-02 09:18:39 +00:00
NS_ASSERTION ( ! ownLayer - > HasUserData ( & gLayerManagerUserData ) ,
2010-07-15 21:07:51 +00:00
" We shouldn't have a FrameLayerBuilder-managed layer here! " ) ;
2015-10-28 17:46:40 +00:00
NS_ASSERTION ( layerClip . HasClip ( ) | |
layerClip . GetRoundedRectCount ( ) = = 0 ,
2012-01-19 20:21:41 +00:00
" If we have rounded rects, we must have a clip rect " ) ;
2016-05-06 23:02:26 +00:00
2010-07-15 21:07:51 +00:00
// It has its own layer. Update that layer's clip and visible rects.
2016-05-06 23:02:26 +00:00
ownLayer - > SetClipRect ( Nothing ( ) ) ;
ownLayer - > SetScrolledClip ( Nothing ( ) ) ;
2015-10-28 17:46:40 +00:00
if ( layerClip . HasClip ( ) ) {
2016-08-03 17:48:10 +00:00
// For layers fixed to the viewport, the clip becomes part of the
// layer's scrolled clip. Otherwise, it becomes part of the layer clip.
if ( shouldFixToViewport ) {
2016-05-16 23:49:49 +00:00
LayerClip scrolledClip ;
scrolledClip . SetClipRect ( layerClipRect ) ;
2016-07-25 02:41:25 +00:00
if ( layerClip . GetRoundedRectCount ( ) > 0 ) {
2016-05-16 23:49:49 +00:00
scrolledClip . SetMaskLayerIndex (
SetupMaskLayerForScrolledClip ( ownLayer . get ( ) , layerClip ) ) ;
}
ownLayer - > SetScrolledClip ( Some ( scrolledClip ) ) ;
2016-08-03 17:48:10 +00:00
} else {
ownLayer - > SetClipRect ( Some ( layerClipRect ) ) ;
// rounded rectangle clipping using mask layers
// (must be done after visible rect is set on layer)
if ( layerClip . GetRoundedRectCount ( ) > 0 ) {
SetupMaskLayer ( ownLayer , layerClip ) ;
}
2016-05-06 23:02:26 +00:00
}
2012-02-07 22:27:44 +00:00
}
2010-07-15 21:07:51 +00:00
ContainerLayer * oldContainer = ownLayer - > GetParent ( ) ;
if ( oldContainer & & oldContainer ! = mContainerLayer ) {
oldContainer - > RemoveChild ( ownLayer ) ;
}
2014-06-23 04:24:00 +00:00
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , ownLayer ) < 0 ,
2010-07-15 21:07:51 +00:00
" Layer already in list??? " ) ;
2010-07-15 21:08:05 +00:00
2014-06-23 04:24:00 +00:00
NewLayerEntry * newLayerEntry = mNewChildLayers . AppendElement ( ) ;
newLayerEntry - > mLayer = ownLayer ;
newLayerEntry - > mAnimatedGeometryRoot = animatedGeometryRoot ;
2015-12-22 15:54:19 +00:00
newLayerEntry - > mScrollClip = agrScrollClip ;
2016-01-13 23:42:27 +00:00
newLayerEntry - > mLayerState = layerState ;
2014-07-22 22:53:37 +00:00
// Don't attempt to flatten compnent alpha layers that are within
// a forced active layer, or an active transform;
if ( itemType = = nsDisplayItem : : TYPE_TRANSFORM | |
layerState = = LAYER_ACTIVE_FORCE ) {
newLayerEntry - > mPropagateComponentAlphaFlattening = false ;
}
2014-07-11 01:17:47 +00:00
// nsDisplayTransform::BuildLayer must set layerContentsVisibleRect.
// We rely on this to ensure 3D transforms compute a reasonable
// layer visible region.
NS_ASSERTION ( itemType ! = nsDisplayItem : : TYPE_TRANSFORM | |
layerContentsVisibleRect . width > = 0 ,
" Transform items must set layerContentsVisibleRect! " ) ;
2014-06-23 04:24:00 +00:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
newLayerEntry - > mLayerContentsVisibleRect = layerContentsVisibleRect ;
2015-11-26 09:32:36 +00:00
if ( itemType = = nsDisplayItem : : TYPE_PERSPECTIVE | |
( itemType = = nsDisplayItem : : TYPE_TRANSFORM & &
( item - > Frame ( ) - > Extend3DContext ( ) | |
item - > Frame ( ) - > Combines3DTransformWithAncestors ( ) | |
item - > Frame ( ) - > HasPerspective ( ) ) ) ) {
2015-09-17 01:31:00 +00:00
// Give untransformed visible region as outer visible region
// to avoid failure caused by singular transforms.
newLayerEntry - > mUntransformedVisibleRegion = true ;
newLayerEntry - > mVisibleRegion =
item - > GetVisibleRectForChildren ( ) . ToOutsidePixels ( mAppUnitsPerDevPixel ) ;
} else {
newLayerEntry - > mVisibleRegion = itemVisibleRect ;
}
2014-06-23 04:24:00 +00:00
newLayerEntry - > mOpaqueRegion = ComputeOpaqueRect ( item ,
2016-01-26 00:36:48 +00:00
animatedGeometryRoot , layerClip , aList ,
2014-08-31 03:29:24 +00:00
& newLayerEntry - > mHideAllLayersBelow ,
& newLayerEntry - > mOpaqueForAnimatedGeometryRootParent ) ;
2014-06-23 04:24:00 +00:00
} else {
2015-09-17 01:31:00 +00:00
bool useChildrenVisible =
itemType = = nsDisplayItem : : TYPE_TRANSFORM & &
2016-04-28 05:05:46 +00:00
( item - > Frame ( ) - > IsPreserve3DLeaf ( ) | |
item - > Frame ( ) - > HasPerspective ( ) ) ;
2015-09-17 01:31:00 +00:00
const nsIntRegion & visible = useChildrenVisible ?
item - > GetVisibleRectForChildren ( ) . ToOutsidePixels ( mAppUnitsPerDevPixel ) :
itemVisibleRect ;
SetOuterVisibleRegionForLayer ( ownLayer , visible ,
layerContentsVisibleRect . width > = 0 ? & layerContentsVisibleRect : nullptr ,
useChildrenVisible ) ;
2014-06-23 04:24:00 +00:00
}
2015-04-21 03:48:10 +00:00
if ( itemType = = nsDisplayItem : : TYPE_SCROLL_INFO_LAYER ) {
nsDisplayScrollInfoLayer * scrollItem = static_cast < nsDisplayScrollInfoLayer * > ( item ) ;
newLayerEntry - > mOpaqueForAnimatedGeometryRootParent = false ;
2016-03-28 23:14:52 +00:00
newLayerEntry - > mBaseScrollMetadata =
scrollItem - > ComputeScrollMetadata ( ownLayer , mParameters ) ;
2014-12-17 23:37:28 +00:00
} else if ( ( itemType = = nsDisplayItem : : TYPE_SUBDOCUMENT | |
itemType = = nsDisplayItem : : TYPE_ZOOM | |
itemType = = nsDisplayItem : : TYPE_RESOLUTION ) & &
gfxPrefs : : LayoutUseContainersForRootFrames ( ) )
{
2016-03-28 23:14:52 +00:00
newLayerEntry - > mBaseScrollMetadata =
static_cast < nsDisplaySubDocument * > ( item ) - > ComputeScrollMetadata ( ownLayer , mParameters ) ;
2014-06-23 04:24:00 +00:00
}
2012-10-17 08:00:00 +00:00
/**
* No need to allocate geometry for items that aren ' t
2014-09-26 17:06:08 +00:00
* part of a PaintedLayer .
2012-10-17 08:00:00 +00:00
*/
2015-12-16 05:24:06 +00:00
mLayerBuilder - > AddLayerDisplayItem ( ownLayer , item , layerState , nullptr ) ;
2010-05-21 03:20:48 +00:00
} else {
2014-09-26 17:06:08 +00:00
PaintedLayerData * paintedLayerData =
2015-12-22 15:54:19 +00:00
mPaintedLayerDataTree . FindPaintedLayerFor ( animatedGeometryRoot , agrScrollClip ,
2016-06-02 20:44:32 +00:00
itemVisibleRect ,
2016-02-08 22:34:13 +00:00
item - > Frame ( ) - > In3DContextAndBackfaceIsHidden ( ) ,
2015-09-17 01:31:00 +00:00
[ & ] ( ) {
2015-12-16 05:24:06 +00:00
return NewPaintedLayerData ( item , animatedGeometryRoot , agrScrollClip ,
2016-08-03 17:48:10 +00:00
topLeft , shouldFixToViewport ) ;
2015-04-02 18:22:40 +00:00
} ) ;
2013-12-16 12:16:24 +00:00
if ( itemType = = nsDisplayItem : : TYPE_LAYER_EVENT_REGIONS ) {
nsDisplayLayerEventRegions * eventRegions =
static_cast < nsDisplayLayerEventRegions * > ( item ) ;
2015-08-31 23:53:34 +00:00
paintedLayerData - > AccumulateEventRegions ( this , eventRegions ) ;
2013-12-16 12:16:24 +00:00
} else {
// check to see if the new item has rounded rect clips in common with
// other items in the layer
2015-03-03 22:00:55 +00:00
if ( mManager - > IsWidgetLayerManager ( ) ) {
paintedLayerData - > UpdateCommonClipCount ( itemClip ) ;
}
2014-06-23 04:24:00 +00:00
nsIntRegion opaquePixels = ComputeOpaqueRect ( item ,
2016-01-26 00:36:48 +00:00
animatedGeometryRoot , itemClip , aList ,
2014-09-26 17:06:08 +00:00
& paintedLayerData - > mHideAllLayersBelow ,
& paintedLayerData - > mOpaqueForAnimatedGeometryRootParent ) ;
2015-02-18 18:01:40 +00:00
MOZ_ASSERT ( nsIntRegion ( itemDrawRect ) . Contains ( opaquePixels ) ) ;
opaquePixels . AndWith ( itemVisibleRect ) ;
2014-09-26 17:06:08 +00:00
paintedLayerData - > Accumulate ( this , item , opaquePixels ,
2015-03-04 05:21:55 +00:00
itemVisibleRect , itemClip , layerState ) ;
2015-03-04 05:18:47 +00:00
2015-09-12 00:00:22 +00:00
// If we removed the clip from the display item above because it's
// fixed to the viewport, save it on the PaintedLayerData so we can
// set it on the layer later.
2016-08-03 17:48:10 +00:00
if ( fixedToViewportClip . HasClip ( ) ) {
paintedLayerData - > mItemClip = fixedToViewportClip ;
2015-09-12 00:00:22 +00:00
}
2015-03-04 05:18:47 +00:00
if ( ! paintedLayerData - > mLayer ) {
// Try to recycle the old layer of this display item.
2015-10-18 05:24:48 +00:00
RefPtr < PaintedLayer > layer =
2015-03-04 05:18:47 +00:00
AttemptToRecyclePaintedLayer ( animatedGeometryRoot , item , topLeft ) ;
if ( layer ) {
paintedLayerData - > mLayer = layer ;
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , layer ) < 0 ,
" Layer already in list??? " ) ;
mNewChildLayers [ paintedLayerData - > mNewChildLayersIndex ] . mLayer = layer . forget ( ) ;
}
}
2014-07-17 15:24:47 +00:00
}
2014-06-09 04:48:00 +00:00
}
2014-06-09 04:48:00 +00:00
if ( itemSameCoordinateSystemChildren & &
itemSameCoordinateSystemChildren - > NeedsTransparentSurface ( ) ) {
aList - > SetNeedsTransparentSurface ( ) ;
}
2010-05-21 03:20:48 +00:00
}
2014-06-09 04:48:00 +00:00
aList - > AppendToTop ( & savedItems ) ;
2010-05-21 03:20:48 +00:00
}
2010-07-15 21:08:05 +00:00
void
2014-09-26 17:06:08 +00:00
ContainerState : : InvalidateForLayerChange ( nsDisplayItem * aItem , PaintedLayer * aNewLayer )
2010-07-15 21:08:05 +00:00
{
2012-10-10 05:00:05 +00:00
NS_ASSERTION ( aItem - > GetPerFrameKey ( ) ,
" Display items that render using Thebes must have a key " ) ;
2014-07-23 06:03:24 +00:00
nsDisplayItemGeometry * oldGeometry = nullptr ;
2013-10-08 18:47:21 +00:00
DisplayItemClip * oldClip = nullptr ;
2014-07-23 06:03:24 +00:00
Layer * oldLayer = mLayerBuilder - > GetOldLayerFor ( aItem , & oldGeometry , & oldClip ) ;
2012-08-29 05:47:15 +00:00
if ( aNewLayer ! = oldLayer & & oldLayer ) {
2010-07-15 21:08:05 +00:00
// The item has changed layers.
2012-09-28 11:19:39 +00:00
// Invalidate the old bounds in the old layer and new bounds in the new layer.
2014-09-26 17:06:08 +00:00
PaintedLayer * t = oldLayer - > AsPaintedLayer ( ) ;
2014-07-23 06:03:24 +00:00
if ( t & & oldGeometry ) {
2011-06-22 12:11:27 +00: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-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-23 22:44:18 +00:00
printf_stderr ( " Display item type %s(%p) changed layers %p to %p! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , t , aNewLayer ) ;
2013-05-13 23:47:02 +00:00
}
2012-08-29 05:47:15 +00:00
# endif
2011-06-22 12:11:27 +00:00
InvalidatePostTransformRegion ( t ,
2012-10-16 01:10:43 +00:00
oldGeometry - > ComputeInvalidationRegion ( ) ,
* oldClip ,
2012-07-17 17:03:51 +00:00
mLayerBuilder - > GetLastPaintOffset ( t ) ) ;
2010-07-15 21:08:05 +00:00
}
2014-07-23 06:03:24 +00:00
// Clear the old geometry so that invalidation thinks the item has been
// added this paint.
mLayerBuilder - > ClearCachedGeometry ( aItem ) ;
2012-12-10 05:34:31 +00:00
aItem - > NotifyRenderingChanged ( ) ;
2012-08-29 05:47:15 +00:00
}
2014-07-23 06:03:24 +00:00
}
2010-07-15 21:08:05 +00:00
2014-07-23 06:03:24 +00:00
void
FrameLayerBuilder : : ComputeGeometryChangeForItem ( DisplayItemData * aData )
{
nsDisplayItem * item = aData - > mItem ;
2014-09-26 17:06:08 +00:00
PaintedLayer * paintedLayer = aData - > mLayer - > AsPaintedLayer ( ) ;
if ( ! item | | ! paintedLayer ) {
2014-07-23 06:03:24 +00:00
aData - > EndUpdate ( ) ;
2012-08-29 05:47:15 +00:00
return ;
}
2014-09-26 17:06:08 +00:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . GetEntry ( paintedLayer ) ;
2014-07-23 06:03:52 +00:00
2015-11-06 03:57:47 +00:00
nsAutoPtr < nsDisplayItemGeometry > geometry ;
2014-07-23 06:03:24 +00:00
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * layerData =
static_cast < PaintedDisplayItemLayerUserData * > ( aData - > mLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2014-07-23 06:03:24 +00:00
nsPoint shift = layerData - > mAnimatedGeometryRootOrigin - layerData - > mLastAnimatedGeometryRootOrigin ;
const DisplayItemClip & clip = item - > GetClip ( ) ;
2015-11-06 03:57:47 +00:00
// If the frame is marked as invalidated, and didn't specify a rect to invalidate then we want to
2012-08-29 05:48:45 +00: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 05:47:15 +00:00
nsRegion combined ;
2014-04-24 02:56:15 +00:00
bool notifyRenderingChanged = true ;
2014-07-23 06:03:24 +00:00
if ( ! aData - > mGeometry ) {
2012-08-29 05:48:43 +00:00
// This item is being added for the first time, invalidate its entire area.
2015-11-06 03:57:47 +00:00
geometry = item - > AllocateGeometry ( mDisplayListBuilder ) ;
2014-07-23 06:03:24 +00:00
combined = clip . ApplyNonRoundedIntersection ( geometry - > ComputeInvalidationRegion ( ) ) ;
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2014-07-23 06:03:24 +00:00
printf_stderr ( " Display item type %s(%p) added to layer %p! \n " , item - > Name ( ) , item - > Frame ( ) , aData - > mLayer . get ( ) ) ;
2013-05-13 23:47:02 +00:00
}
2012-08-29 05:47:15 +00:00
# endif
2014-07-23 06:03:24 +00:00
} else if ( aData - > mIsInvalid | | ( item - > IsInvalid ( invalid ) & & invalid . IsEmpty ( ) ) ) {
2015-11-06 03:57:47 +00: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 06:03:24 +00:00
combined = aData - > mClip . ApplyNonRoundedIntersection ( aData - > mGeometry - > ComputeInvalidationRegion ( ) ) ;
2012-10-16 01:10:43 +00:00
combined . MoveBy ( shift ) ;
2014-07-23 06:03:24 +00:00
combined . Or ( combined , clip . ApplyNonRoundedIntersection ( geometry - > ComputeInvalidationRegion ( ) ) ) ;
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2014-07-23 06:03:24 +00: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-13 23:47:02 +00:00
}
2012-08-29 05:47:15 +00:00
# endif
} else {
2012-08-29 05:48:44 +00:00
// Let the display item check for geometry changes and decide what needs to be
2012-08-29 05:48:43 +00:00
// repainted.
2014-04-24 02:56:15 +00:00
2014-07-23 06:03:24 +00:00
const nsTArray < nsIFrame * > & changedFrames = aData - > GetFrameListChanges ( ) ;
2015-11-06 03:57:47 +00:00
aData - > mGeometry - > MoveBy ( shift ) ;
item - > ComputeInvalidationRegion ( mDisplayListBuilder , aData - > mGeometry , & combined ) ;
2014-07-23 06:03:24 +00:00
2015-11-06 03:57:47 +00:00
// We have an optimization to cache the drawing of background-attachment: fixed canvas
2014-04-24 02:56:15 +00: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 03:05:20 +00: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 03:57:47 +00:00
geometry = item - > AllocateGeometry ( mDisplayListBuilder ) ;
} else if ( aData - > mClip = = clip & & invalid . IsEmpty ( ) & & changedFrames . Length ( ) = = 0 ) {
2014-04-24 02:56:15 +00:00
notifyRenderingChanged = false ;
}
2014-07-23 06:03:52 +00:00
aData - > mClip . AddOffsetAndComputeDifference ( entry - > mCommonClipCount ,
shift , aData - > mGeometry - > ComputeInvalidationRegion ( ) ,
2015-11-06 03:57:47 +00:00
clip , entry - > mLastCommonClipCount ,
geometry ? geometry - > ComputeInvalidationRegion ( ) :
aData - > mGeometry - > ComputeInvalidationRegion ( ) ,
2014-07-23 06:03:24 +00:00
& combined ) ;
2012-08-29 05:48:45 +00:00
// Add in any rect that the frame specified
2012-10-16 01:10:43 +00:00
combined . Or ( combined , invalid ) ;
2014-03-20 06:49:27 +00:00
2012-10-16 01:23:07 +00:00
for ( uint32_t i = 0 ; i < changedFrames . Length ( ) ; i + + ) {
combined . Or ( combined , changedFrames [ i ] - > GetVisualOverflowRect ( ) ) ;
2014-03-20 06:49:27 +00:00
}
2012-10-16 01:10:43 +00:00
// Restrict invalidation to the clipped region
2014-07-23 06:03:24 +00:00
nsRegion clipRegion ;
if ( clip . ComputeRegionInClips ( & aData - > mClip , shift , & clipRegion ) ) {
combined . And ( combined , clipRegion ) ;
2012-10-16 01:10:43 +00:00
}
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
if ( ! combined . IsEmpty ( ) ) {
2014-07-23 06:03:24 +00:00
printf_stderr ( " Display item type %s(%p) (in layer %p) changed geometry! \n " , item - > Name ( ) , item - > Frame ( ) , aData - > mLayer . get ( ) ) ;
2013-05-13 23:47:02 +00:00
}
2012-08-29 05:47:15 +00:00
}
# endif
}
if ( ! combined . IsEmpty ( ) ) {
2014-04-24 02:56:15 +00:00
if ( notifyRenderingChanged ) {
2014-07-23 06:03:24 +00:00
item - > NotifyRenderingChanged ( ) ;
2014-04-24 02:56:15 +00:00
}
2014-09-26 17:06:08 +00:00
InvalidatePostTransformRegion ( paintedLayer ,
2014-07-23 06:03:24 +00:00
combined . ScaleToOutsidePixels ( layerData - > mXScale , layerData - > mYScale , layerData - > mAppUnitsPerDevPixel ) ,
2016-03-28 22:37:07 +00:00
layerData - > mTranslation ) ;
2010-07-15 21:08:05 +00:00
}
2014-07-23 06:03:24 +00:00
aData - > EndUpdate ( geometry ) ;
2010-07-15 21:08:05 +00:00
}
2010-07-15 21:07:51 +00:00
void
2014-09-26 17:07:06 +00:00
FrameLayerBuilder : : AddPaintedDisplayItem ( PaintedLayerData * aLayerData ,
2010-07-15 21:07:51 +00:00
nsDisplayItem * aItem ,
2013-03-04 09:55:59 +00:00
const DisplayItemClip & aClip ,
2015-01-20 14:49:30 +00:00
ContainerState & aContainerState ,
2012-08-29 05:47:15 +00:00
LayerState aLayerState ,
2014-07-23 06:03:24 +00:00
const nsPoint & aTopLeft )
2010-07-15 21:07:51 +00:00
{
2014-09-26 17:06:08 +00:00
PaintedLayer * layer = aLayerData - > mLayer ;
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * paintedData =
static_cast < PaintedDisplayItemLayerUserData * >
( layer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2015-10-18 05:24:48 +00:00
RefPtr < BasicLayerManager > tempManager ;
2012-10-16 01:10:43 +00:00
nsIntRect intClip ;
bool hasClip = false ;
2012-08-29 05:47:15 +00:00
if ( aLayerState ! = LAYER_NONE ) {
2013-12-16 12:16:24 +00:00
DisplayItemData * data = GetDisplayItemDataForManager ( aItem , layer - > Manager ( ) ) ;
2012-08-29 05:47:15 +00:00
if ( data ) {
tempManager = data - > mInactiveManager ;
}
if ( ! tempManager ) {
2014-06-19 18:22:17 +00:00
tempManager = new BasicLayerManager ( BasicLayerManager : : BLM_INACTIVE ) ;
2012-08-29 05:47:15 +00:00
}
2012-10-23 11:05:14 +00:00
2012-10-16 01:10:43 +00:00
// We need to grab these before calling AddLayerDisplayItem because it will overwrite them.
nsRegion clip ;
2013-03-04 09:55:59 +00:00
DisplayItemClip * oldClip = nullptr ;
2012-10-16 01:10:43 +00:00
GetOldLayerFor ( aItem , nullptr , & oldClip ) ;
2013-03-04 09:56:00 +00:00
hasClip = aClip . ComputeRegionInClips ( oldClip ,
2014-09-26 17:07:06 +00:00
aTopLeft - paintedData - > mLastAnimatedGeometryRootOrigin ,
2013-03-04 09:56:00 +00:00
& clip ) ;
2012-10-16 01:10:43 +00:00
if ( hasClip ) {
2014-09-26 17:07:06 +00:00
intClip = clip . GetBounds ( ) . ScaleToOutsidePixels ( paintedData - > mXScale ,
paintedData - > mYScale ,
paintedData - > mAppUnitsPerDevPixel ) ;
2012-10-16 01:10:43 +00:00
}
2012-08-29 05:47:15 +00:00
}
2015-12-16 05:24:06 +00:00
AddLayerDisplayItem ( layer , aItem , aLayerState , tempManager ) ;
2010-07-15 21:07:51 +00:00
2014-09-26 17:06:08 +00:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . PutEntry ( layer ) ;
2010-07-15 21:07:51 +00:00
if ( entry ) {
2014-06-23 04:24:00 +00:00
entry - > mContainerLayerFrame = aContainerState . GetContainerFrame ( ) ;
2012-09-11 21:17:26 +00:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2012-08-29 05:47:15 +00:00
if ( tempManager ) {
2015-01-20 14:49:30 +00:00
FLB_LOG_PAINTED_LAYER_DECISION ( aLayerData , " Creating nested FLB for item %p \n " , aItem ) ;
2012-08-29 05:47:15 +00:00
FrameLayerBuilder * layerBuilder = new FrameLayerBuilder ( ) ;
2015-04-30 18:54:48 +00:00
layerBuilder - > Init ( mDisplayListBuilder , tempManager , aLayerData ) ;
2012-08-29 05:47:15 +00:00
tempManager - > BeginTransaction ( ) ;
if ( mRetainingManager ) {
layerBuilder - > DidBeginRetainedLayerTransaction ( tempManager ) ;
}
2014-03-20 06:49:27 +00:00
2015-11-03 06:29:06 +00:00
UniquePtr < LayerProperties > props ( LayerProperties : : CloneFrom ( tempManager - > GetRoot ( ) ) ) ;
2015-10-18 05:24:48 +00:00
RefPtr < Layer > tmpLayer =
2013-09-27 06:01:16 +00:00
aItem - > BuildLayer ( mDisplayListBuilder , tempManager , ContainerLayerParameters ( ) ) ;
2012-08-29 05:47:15 +00: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 12:16:24 +00:00
if ( ! tmpLayer ) {
2012-08-29 05:47:15 +00:00
tempManager - > EndTransaction ( nullptr , nullptr ) ;
tempManager - > SetUserData ( & gLayerManagerLayerBuilder , nullptr ) ;
return ;
}
2014-06-23 04:24:00 +00:00
bool snap ;
nsRect visibleRect =
aItem - > GetVisibleRect ( ) . Intersect ( aItem - > GetBounds ( mDisplayListBuilder , & snap ) ) ;
2014-09-26 17:07:06 +00:00
nsIntRegion rgn = visibleRect . ToOutsidePixels ( paintedData - > mAppUnitsPerDevPixel ) ;
2014-06-23 04:24:00 +00:00
SetOuterVisibleRegion ( tmpLayer , & rgn ) ;
2012-08-29 05:47:15 +00:00
// If BuildLayer didn't call BuildContainerLayerFor, then our new layer won't have been
// stored in layerBuilder. Manually add it now.
2012-10-11 23:38:24 +00:00
if ( mRetainingManager ) {
2012-10-12 02:39:46 +00:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-11 23:38:24 +00:00
LayerManagerData * parentLmd = static_cast < LayerManagerData * >
2013-12-16 12:16:24 +00:00
( layer - > Manager ( ) - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-10-11 23:38:24 +00:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( tempManager - > GetUserData ( & gLayerManagerUserData ) ) ;
lmd - > mParent = parentLmd ;
2012-10-12 02:39:46 +00:00
# endif
2013-12-16 12:16:24 +00:00
layerBuilder - > StoreDataForFrame ( aItem , tmpLayer , LAYER_ACTIVE ) ;
2012-10-11 23:38:24 +00:00
}
2012-08-29 05:47:15 +00:00
2013-12-16 12:16:24 +00:00
tempManager - > SetRoot ( tmpLayer ) ;
2012-08-29 05:47:15 +00:00
layerBuilder - > WillEndTransaction ( ) ;
2013-11-06 19:10:49 +00:00
tempManager - > AbortTransaction ( ) ;
2012-08-29 05:47:15 +00:00
2015-09-25 22:37:30 +00:00
# ifdef MOZ_DUMP_PAINTING
2015-10-28 13:31:00 +00:00
if ( gfxUtils : : DumpDisplayList ( ) | | gfxEnv : : DumpPaint ( ) ) {
2015-09-25 22:37:30 +00: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 13:31:00 +00:00
tempManager - > Dump ( stream , " " , gfxEnv : : DumpPaintToFile ( ) ) ;
2015-09-25 22:37:30 +00:00
fprint_stderr ( gfxUtils : : sDumpPaintFile , stream ) ; // not a typo, fprint_stderr declared in LayersLogging.h
}
# endif
2015-11-03 06:29:06 +00:00
nsIntPoint offset = GetLastPaintOffset ( layer ) - GetTranslationForPaintedLayer ( layer ) ;
props - > MoveBy ( - offset ) ;
2015-11-02 17:28:00 +00:00
// Effective transforms are needed by ComputeDifferences().
tmpLayer - > ComputeEffectiveTransforms ( Matrix4x4 ( ) ) ;
2015-11-03 06:29:06 +00:00
nsIntRegion invalid = props - > ComputeDifferences ( tmpLayer , nullptr ) ;
if ( aLayerState = = LAYER_SVG_EFFECTS ) {
invalid = nsSVGIntegrationUtils : : AdjustInvalidAreaForSVGEffects ( aItem - > Frame ( ) ,
aItem - > ToReferenceFrame ( ) ,
invalid ) ;
}
if ( ! invalid . IsEmpty ( ) ) {
2015-11-03 03:48:42 +00:00
# ifdef MOZ_DUMP_PAINTING
2015-11-03 06:29:06 +00: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 05:47:18 +00:00
# endif
2015-11-03 06:29:06 +00:00
invalid . ScaleRoundOut ( paintedData - > mXScale , paintedData - > mYScale ) ;
2012-10-16 01:10:43 +00:00
2015-11-03 06:29:06 +00:00
if ( hasClip ) {
invalid . And ( invalid , intClip ) ;
2015-11-03 03:48:42 +00:00
}
2015-11-03 06:29:06 +00:00
InvalidatePostTransformRegion ( layer , invalid ,
2016-03-28 22:37:07 +00:00
GetTranslationForPaintedLayer ( layer ) ) ;
2012-08-29 05:47:18 +00:00
}
2012-08-29 05:47:15 +00:00
}
2010-07-15 21:08:05 +00:00
ClippedDisplayItem * cdi =
2013-03-04 09:56:02 +00:00
entry - > mItems . AppendElement ( ClippedDisplayItem ( aItem ,
2012-07-23 03:00:36 +00:00
mContainerLayerGeneration ) ) ;
2012-10-23 11:05:14 +00:00
cdi - > mInactiveLayerManager = tempManager ;
2010-07-15 21:07:51 +00:00
}
}
2012-10-12 02:39:46 +00:00
FrameLayerBuilder : : DisplayItemData *
FrameLayerBuilder : : StoreDataForFrame ( nsDisplayItem * aItem , Layer * aLayer , LayerState aState )
2012-08-29 10:53:27 +00:00
{
2012-10-12 02:39:46 +00:00
DisplayItemData * oldData = GetDisplayItemDataForManager ( aItem , mRetainingManager ) ;
if ( oldData ) {
if ( ! oldData - > mUsed ) {
2014-07-23 06:03:24 +00:00
oldData - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration , aItem ) ;
2012-10-12 02:39:46 +00:00
}
return oldData ;
2012-10-11 23:38:24 +00:00
}
2014-03-20 06:49:27 +00:00
2012-10-12 02:39:46 +00:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2014-03-20 06:49:27 +00:00
2015-10-18 05:24:48 +00:00
RefPtr < DisplayItemData > data =
2015-04-10 21:11:04 +00:00
new DisplayItemData ( lmd , aItem - > GetPerFrameKey ( ) , aLayer ) ;
2012-10-12 02:39:46 +00:00
2014-07-23 06:03:24 +00:00
data - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration , aItem ) ;
2012-10-12 02:39:46 +00: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 06:03:24 +00:00
oldData - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration ) ;
2012-10-12 02:39:46 +00:00
return ;
}
2014-03-20 06:49:27 +00:00
2012-10-12 02:39:46 +00:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2015-10-18 05:24:48 +00:00
RefPtr < DisplayItemData > data =
2015-04-10 21:11:04 +00:00
new DisplayItemData ( lmd , aDisplayItemKey , aLayer , aFrame ) ;
2012-10-12 02:39:46 +00:00
2014-07-23 06:03:24 +00:00
data - > BeginUpdate ( aLayer , aState , mContainerLayerGeneration ) ;
2012-10-12 02:39:46 +00:00
lmd - > mDisplayItems . PutEntry ( data ) ;
2012-08-29 05:47:15 +00:00
}
2015-10-22 21:00:16 +00:00
FrameLayerBuilder : : ClippedDisplayItem : : ClippedDisplayItem ( nsDisplayItem * aItem ,
uint32_t aGeneration )
: mItem ( aItem )
, mContainerLayerGeneration ( aGeneration )
{
}
2012-08-29 05:47:15 +00:00
FrameLayerBuilder : : ClippedDisplayItem : : ~ ClippedDisplayItem ( )
{
2012-10-23 11:05:14 +00:00
if ( mInactiveLayerManager ) {
2015-03-16 18:19:32 +00:00
mInactiveLayerManager - > SetUserData ( & gLayerManagerLayerBuilder , nullptr ) ;
2012-08-29 10:53:27 +00:00
}
}
2015-10-22 21:00:16 +00: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-13 22:50:57 +00:00
void
2010-07-15 21:07:51 +00:00
FrameLayerBuilder : : AddLayerDisplayItem ( Layer * aLayer ,
2011-05-18 22:54:31 +00:00
nsDisplayItem * aItem ,
2012-08-29 05:47:15 +00:00
LayerState aLayerState ,
2014-07-23 06:03:24 +00:00
BasicLayerManager * aManager )
2010-07-15 21:07:51 +00:00
{
if ( aLayer - > Manager ( ) ! = mRetainingManager )
2012-12-13 22:50:57 +00:00
return ;
2012-10-11 23:38:24 +00:00
2012-10-12 02:39:46 +00:00
DisplayItemData * data = StoreDataForFrame ( aItem , aLayer , aLayerState ) ;
2012-08-29 05:47:15 +00:00
data - > mInactiveManager = aManager ;
2010-07-15 21:07:51 +00:00
}
2011-05-18 05:48:43 +00:00
nsIntPoint
2014-09-26 17:06:08 +00:00
FrameLayerBuilder : : GetLastPaintOffset ( PaintedLayer * aLayer )
2011-05-16 23:05:56 +00:00
{
2014-09-26 17:06:08 +00:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . PutEntry ( aLayer ) ;
2012-07-23 03:00:36 +00:00
if ( entry ) {
2012-09-11 21:17:26 +00:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2012-07-23 03:00:36 +00:00
if ( entry - > mHasExplicitLastPaintOffset )
return entry - > mLastPaintOffset ;
}
2014-09-26 17:06:08 +00:00
return GetTranslationForPaintedLayer ( aLayer ) ;
2011-05-16 23:05:56 +00:00
}
void
2014-09-26 17:06:08 +00:00
FrameLayerBuilder : : SavePreviousDataForLayer ( PaintedLayer * aLayer , uint32_t aClipCount )
2011-05-16 23:05:56 +00:00
{
2014-09-26 17:06:08 +00:00
PaintedLayerItemsEntry * entry = mPaintedLayerItems . PutEntry ( aLayer ) ;
2011-05-16 23:05:56 +00:00
if ( entry ) {
2012-09-11 21:17:26 +00:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2014-09-26 17:06:08 +00:00
entry - > mLastPaintOffset = GetTranslationForPaintedLayer ( aLayer ) ;
2011-10-17 14:59:28 +00:00
entry - > mHasExplicitLastPaintOffset = true ;
2014-07-23 06:03:52 +00:00
entry - > mLastCommonClipCount = aClipCount ;
2011-05-16 23:05:56 +00:00
}
}
2014-01-30 05:41:17 +00:00
bool
FrameLayerBuilder : : CheckInLayerTreeCompressionMode ( )
{
if ( mInLayerTreeCompressionMode ) {
2014-03-20 06:49:27 +00:00
return true ;
2014-01-30 05:41:17 +00:00
}
// If we wanted to be in layer tree compression mode, but weren't, then scheduled
// a delayed repaint where we will be.
mRootPresContext - > PresShell ( ) - > GetRootFrame ( ) - > SchedulePaint ( nsIFrame : : PAINT_DELAYED_COMPRESS ) ;
return false ;
}
2010-07-15 21:07:51 +00:00
void
2010-07-15 21:08:03 +00:00
ContainerState : : CollectOldLayers ( )
2010-07-15 21:07:51 +00:00
{
for ( Layer * layer = mContainerLayer - > GetFirstChild ( ) ; layer ;
layer = layer - > GetNextSibling ( ) ) {
2012-02-07 22:26:40 +00:00
NS_ASSERTION ( ! layer - > HasUserData ( & gMaskLayerUserData ) ,
2016-08-05 02:00:04 +00:00
" Mask layers should not be part of the layer tree. " ) ;
2014-09-26 17:07:06 +00:00
if ( layer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
2014-09-26 17:06:08 +00:00
NS_ASSERTION ( layer - > AsPaintedLayer ( ) , " Wrong layer type " ) ;
2015-03-04 05:21:00 +00:00
mPaintedLayersAvailableForRecycling . PutEntry ( static_cast < PaintedLayer * > ( layer ) ) ;
2010-07-15 21:07:51 +00:00
}
2012-02-07 22:26:40 +00:00
if ( Layer * maskLayer = layer - > GetMaskLayer ( ) ) {
NS_ASSERTION ( maskLayer - > GetType ( ) = = Layer : : TYPE_IMAGE ,
" Could not recycle mask layer, unsupported layer type. " ) ;
2015-06-21 16:28:10 +00: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-07 22:26:40 +00:00
}
2010-07-15 21:07:51 +00:00
}
}
2014-06-23 04:24:00 +00:00
struct OpaqueRegionEntry {
2015-11-24 22:53:51 +00:00
AnimatedGeometryRoot * mAnimatedGeometryRoot ;
2014-06-23 04:24:00 +00:00
nsIntRegion mOpaqueRegion ;
} ;
static OpaqueRegionEntry *
FindOpaqueRegionEntry ( nsTArray < OpaqueRegionEntry > & aEntries ,
2016-01-26 00:36:48 +00:00
AnimatedGeometryRoot * aAnimatedGeometryRoot )
2014-06-23 04:24:00 +00:00
{
for ( uint32_t i = 0 ; i < aEntries . Length ( ) ; + + i ) {
OpaqueRegionEntry * d = & aEntries [ i ] ;
2016-01-26 00:36:48 +00:00
if ( d - > mAnimatedGeometryRoot = = aAnimatedGeometryRoot ) {
2014-06-23 04:24:00 +00:00
return d ;
}
}
return nullptr ;
}
void
2014-08-31 03:29:24 +00:00
ContainerState : : SetupScrollingMetadata ( NewLayerEntry * aEntry )
{
2014-09-06 04:16:33 +00: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 08:03:47 +00:00
if ( ! mBuilder - > IsPaintingToWindow ( ) ) {
// async scrolling not possible, and async scrolling info not computed
// for this paint.
return ;
}
2016-03-28 23:14:52 +00:00
AutoTArray < ScrollMetadata , 2 > metricsArray ;
if ( aEntry - > mBaseScrollMetadata ) {
metricsArray . AppendElement ( * aEntry - > mBaseScrollMetadata ) ;
2015-06-21 16:27:31 +00:00
// The base FrameMetrics was not computed by the nsIScrollableframe, so it
// should not have a mask layer.
2016-04-29 20:14:21 +00:00
MOZ_ASSERT ( ! aEntry - > mBaseScrollMetadata - > HasMaskLayer ( ) ) ;
2014-08-31 03:29:24 +00:00
}
2016-05-06 23:34:16 +00: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 16:27:31 +00:00
2015-12-22 15:54:19 +00:00
for ( const DisplayItemScrollClip * scrollClip = aEntry - > mScrollClip ;
scrollClip & & scrollClip ! = mContainerScrollClip ;
scrollClip = scrollClip - > mParent ) {
if ( ! scrollClip - > mIsAsyncScrollable ) {
// This scroll clip was created for a scroll frame that didn't know
// whether it needs to be async scrollable for scroll handoff. It was
// not activated, so we don't need to create a frame metrics for it.
2015-12-16 10:52:37 +00:00
continue ;
}
2015-12-12 15:58:37 +00:00
2015-12-22 15:54:19 +00:00
nsIScrollableFrame * scrollFrame = scrollClip - > mScrollableFrame ;
const DisplayItemClip * clip = scrollClip - > mClip ;
2016-03-28 23:14:52 +00:00
Maybe < ScrollMetadata > metadata =
scrollFrame - > ComputeScrollMetadata ( aEntry - > mLayer , mContainerReferenceFrame , mParameters , clip ) ;
if ( ! metadata ) {
2015-06-21 16:27:31 +00: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 05:24:48 +00:00
RefPtr < Layer > maskLayer =
2016-01-06 00:08:17 +00:00
CreateMaskLayer ( aEntry - > mLayer , * clip , nextIndex , clip - > GetRoundedRectCount ( ) ) ;
2015-06-21 16:27:31 +00:00
if ( maskLayer ) {
2016-04-29 20:14:21 +00:00
MOZ_ASSERT ( metadata - > HasScrollClip ( ) ) ;
metadata - > ScrollClip ( ) . SetMaskLayerIndex ( nextIndex ) ;
2015-06-21 16:27:31 +00:00
maskLayers . AppendElement ( maskLayer ) ;
}
}
2016-03-28 23:14:52 +00:00
metricsArray . AppendElement ( * metadata ) ;
2014-08-31 03:29:24 +00:00
}
2015-06-21 16:27:31 +00:00
2014-08-31 03:29:24 +00:00
// Watch out for FrameMetrics copies in profiles
2016-03-28 23:14:52 +00:00
aEntry - > mLayer - > SetScrollMetadata ( metricsArray ) ;
2015-06-21 16:27:31 +00:00
aEntry - > mLayer - > SetAncestorMaskLayers ( maskLayers ) ;
2014-08-31 03:29:24 +00:00
}
2016-04-29 20:14:21 +00:00
static inline Maybe < ParentLayerIntRect >
2015-06-02 23:34:28 +00:00
GetStationaryClipInContainer ( Layer * aLayer )
{
2016-03-28 23:14:52 +00:00
if ( size_t metricsCount = aLayer - > GetScrollMetadataCount ( ) ) {
return aLayer - > GetScrollMetadata ( metricsCount - 1 ) . GetClipRect ( ) ;
2015-06-02 23:34:28 +00:00
}
return aLayer - > GetClipRect ( ) ;
}
2014-08-31 03:29:24 +00:00
void
ContainerState : : PostprocessRetainedLayers ( nsIntRegion * aOpaqueRegionForContainer )
2014-06-23 04:24:00 +00:00
{
2016-02-02 15:36:30 +00:00
AutoTArray < OpaqueRegionEntry , 4 > opaqueRegions ;
2014-06-23 04:24:00 +00: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 ;
}
2016-08-25 02:25:57 +00:00
OpaqueRegionEntry * data = FindOpaqueRegionEntry ( opaqueRegions , e - > mAnimatedGeometryRoot ) ;
2014-06-23 04:24:00 +00:00
2014-09-06 04:16:33 +00:00
SetupScrollingMetadata ( e ) ;
2014-06-23 04:24:00 +00:00
if ( hideAll ) {
e - > mVisibleRegion . SetEmpty ( ) ;
2015-01-14 07:55:17 +00:00
} else if ( ! e - > mLayer - > IsScrollbarContainer ( ) ) {
2016-04-29 20:14:21 +00:00
Maybe < ParentLayerIntRect > clipRect = GetStationaryClipInContainer ( e - > mLayer ) ;
2014-09-06 04:16:33 +00:00
if ( clipRect & & opaqueRegionForContainer > = 0 & &
2015-11-07 03:13:40 +00:00
opaqueRegions [ opaqueRegionForContainer ] . mOpaqueRegion . Contains ( clipRect - > ToUnknownRect ( ) ) ) {
2014-09-06 04:16:33 +00:00
e - > mVisibleRegion . SetEmpty ( ) ;
} else if ( data ) {
e - > mVisibleRegion . Sub ( e - > mVisibleRegion , data - > mOpaqueRegion ) ;
}
2014-06-23 04:24:00 +00:00
}
2015-09-17 01:31:00 +00:00
SetOuterVisibleRegionForLayer ( e - > mLayer ,
e - > mVisibleRegion ,
e - > mLayerContentsVisibleRect . width > = 0 ? & e - > mLayerContentsVisibleRect : nullptr ,
e - > mUntransformedVisibleRegion ) ;
2014-08-31 03:29:24 +00:00
2014-06-23 04:24:00 +00:00
if ( ! e - > mOpaqueRegion . IsEmpty ( ) ) {
2016-08-25 02:25:57 +00:00
AnimatedGeometryRoot * animatedGeometryRootToCover = e - > mAnimatedGeometryRoot ;
2014-06-23 04:24:00 +00:00
if ( e - > mOpaqueForAnimatedGeometryRootParent & &
2015-11-24 22:53:51 +00:00
e - > mAnimatedGeometryRoot - > mParentAGR = = mContainerAnimatedGeometryRoot ) {
2014-06-23 04:24:00 +00:00
animatedGeometryRootToCover = mContainerAnimatedGeometryRoot ;
2016-01-26 00:36:48 +00:00
data = FindOpaqueRegionEntry ( opaqueRegions , animatedGeometryRootToCover ) ;
2014-06-23 04:24:00 +00:00
}
if ( ! data ) {
2016-01-26 00:36:48 +00:00
if ( animatedGeometryRootToCover = = mContainerAnimatedGeometryRoot ) {
2014-06-23 04:24:00 +00:00
NS_ASSERTION ( opaqueRegionForContainer = = - 1 , " Already found it? " ) ;
opaqueRegionForContainer = opaqueRegions . Length ( ) ;
}
data = opaqueRegions . AppendElement ( ) ;
data - > mAnimatedGeometryRoot = animatedGeometryRootToCover ;
}
2014-10-22 01:33:12 +00:00
nsIntRegion clippedOpaque = e - > mOpaqueRegion ;
2015-06-02 23:34:28 +00:00
Maybe < ParentLayerIntRect > clipRect = e - > mLayer - > GetCombinedClipRect ( ) ;
2014-10-22 01:33:12 +00:00
if ( clipRect ) {
2015-11-07 03:13:40 +00:00
clippedOpaque . AndWith ( clipRect - > ToUnknownRect ( ) ) ;
2014-10-22 01:33:12 +00:00
}
2016-05-05 00:07:42 +00:00
if ( e - > mLayer - > GetIsFixedPosition ( ) & & e - > mLayer - > GetScrolledClip ( ) ) {
2015-09-25 13:47:41 +00:00
// The clip can move asynchronously, so we can't rely on opaque parts
// staying in the same place.
clippedOpaque . SetEmpty ( ) ;
2016-08-05 02:40:56 +00:00
} else if ( e - > mHideAllLayersBelow ) {
2014-06-23 04:24:00 +00:00
hideAll = true ;
}
2016-08-05 02:40:56 +00:00
data - > mOpaqueRegion . Or ( data - > mOpaqueRegion , clippedOpaque ) ;
2014-06-23 04:24:00 +00: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 04:24:00 +00:00
void
2015-12-16 05:24:06 +00:00
ContainerState : : Finish ( uint32_t * aTextContentFlags ,
2014-06-23 04:24:00 +00:00
const nsIntRect & aContainerPixelBounds ,
2016-01-13 23:42:27 +00:00
nsDisplayList * aChildItems , bool * aHasComponentAlphaChildren )
2010-07-15 21:07:51 +00:00
{
2015-04-02 18:22:40 +00:00
mPaintedLayerDataTree . Finish ( ) ;
2014-03-20 06:49:27 +00:00
2016-08-10 03:15:28 +00:00
if ( ! mParameters . mForEventsAndPluginsOnly ) {
2015-12-22 15:54:19 +00:00
NS_ASSERTION ( mContainerBounds . IsEqualInterior ( mAccumulatedChildBounds ) ,
" Bounds computation mismatch " ) ;
}
2014-06-09 04:48:00 +00:00
2014-06-23 04:24:00 +00:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
nsIntRegion containerOpaqueRegion ;
2014-08-31 03:29:24 +00:00
PostprocessRetainedLayers ( & containerOpaqueRegion ) ;
2014-06-23 04:24:00 +00:00
if ( containerOpaqueRegion . Contains ( aContainerPixelBounds ) ) {
aChildItems - > SetIsOpaque ( ) ;
}
}
2012-08-22 15:56:38 +00:00
uint32_t textContentFlags = 0 ;
2010-12-20 01:26:14 +00:00
2012-08-29 10:53:06 +00:00
// Make sure that current/existing layers are added to the parent and are
// in the correct order.
Layer * layer = nullptr ;
2014-06-23 04:24:00 +00: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 06:49:27 +00:00
2012-08-29 10:53:06 +00:00
if ( ! layer - > GetVisibleRegion ( ) . IsEmpty ( ) ) {
2014-07-18 06:48:23 +00:00
textContentFlags | =
layer - > GetContentFlags ( ) & ( Layer : : CONTENT_COMPONENT_ALPHA |
2015-06-26 22:13:50 +00:00
Layer : : CONTENT_COMPONENT_ALPHA_DESCENDANT |
Layer : : CONTENT_DISABLE_FLATTENING ) ;
2014-07-18 06:48:23 +00:00
// Notify the parent of component alpha children unless it's coming from
2014-07-22 22:53:37 +00:00
// within a child that has asked not to contribute to layer flattening.
2016-01-13 23:42:27 +00:00
if ( aHasComponentAlphaChildren & &
mNewChildLayers [ i ] . mPropagateComponentAlphaFlattening & &
2014-07-22 22:53:37 +00:00
( layer - > GetContentFlags ( ) & Layer : : CONTENT_COMPONENT_ALPHA ) ) {
2016-01-13 23:42:27 +00: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 06:48:23 +00:00
}
2010-07-15 21:07:51 +00:00
}
2012-08-29 10:53:06 +00:00
if ( ! layer - > GetParent ( ) ) {
// This is not currently a child of the container, so just add it
// now.
mContainerLayer - > InsertAfter ( layer , prevChild ) ;
2015-03-16 22:37:04 +00: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-15 21:07:51 +00:00
}
2012-08-29 10:53:06 +00: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-15 21:07:51 +00:00
}
2010-12-20 01:26:14 +00:00
* aTextContentFlags = textContentFlags ;
2010-07-15 21:07:51 +00:00
}
2010-05-21 03:20:48 +00:00
2013-05-12 23:12:19 +00:00
static inline gfxSize RoundToFloatPrecision ( const gfxSize & aSize )
{
return gfxSize ( float ( aSize . width ) , float ( aSize . height ) ) ;
}
2014-07-09 02:01:54 +00: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 ;
}
}
2013-03-21 02:33:00 +00:00
static bool
2011-06-22 12:11:27 +00:00
ChooseScaleAndSetTransform ( FrameLayerBuilder * aLayerBuilder ,
2012-09-16 22:25:33 +00:00
nsDisplayListBuilder * aDisplayListBuilder ,
2011-06-22 12:11:27 +00:00
nsIFrame * aContainerFrame ,
2015-06-29 23:46:16 +00:00
nsDisplayItem * aContainerItem ,
2014-07-09 02:01:54 +00:00
const nsRect & aVisibleRect ,
2014-08-01 12:31:49 +00:00
const Matrix4x4 * aTransform ,
2013-09-27 06:01:16 +00:00
const ContainerLayerParameters & aIncomingScale ,
2012-09-16 22:25:33 +00:00
ContainerLayer * aLayer ,
2013-03-21 02:33:00 +00:00
LayerState aState ,
2013-09-27 06:01:16 +00:00
ContainerLayerParameters & aOutgoingScale )
2011-06-22 12:11:27 +00:00
{
2012-09-16 22:25:33 +00:00
nsIntPoint offset ;
2014-08-01 12:31:49 +00:00
Matrix4x4 transform =
2014-10-08 03:43:00 +00:00
Matrix4x4 : : Scaling ( aIncomingScale . mXScale , aIncomingScale . mYScale , 1.0 ) ;
2011-06-22 12:11:27 +00:00
if ( aTransform ) {
// aTransform is applied first, then the scale is applied to the result
transform = ( * aTransform ) * transform ;
2016-03-21 20:16:52 +00: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 06:04:20 +00:00
}
2014-08-01 12:31:49 +00:00
Matrix transform2d ;
2012-12-04 06:04:20 +00:00
if ( aContainerFrame & &
2013-09-06 09:28:02 +00:00
( aState = = LAYER_INACTIVE | | aState = = LAYER_SVG_EFFECTS ) & &
2012-12-04 06:04:20 +00:00
( ! aTransform | | ( aTransform - > Is2D ( & transform2d ) & &
! transform2d . HasNonTranslation ( ) ) ) ) {
2012-09-16 22:25:33 +00: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 06:04:20 +00: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-16 22:25:33 +00:00
nsPoint appUnitOffset = aDisplayListBuilder - > ToReferenceFrame ( aContainerFrame ) ;
nscoord appUnitsPerDevPixel = aContainerFrame - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
offset = nsIntPoint (
2013-09-06 09:28:34 +00:00
NS_lround ( NSAppUnitsToDoublePixels ( appUnitOffset . x , appUnitsPerDevPixel ) * aIncomingScale . mXScale ) ,
NS_lround ( NSAppUnitsToDoublePixels ( appUnitOffset . y , appUnitsPerDevPixel ) * aIncomingScale . mYScale ) ) ;
2012-09-16 22:25:33 +00:00
}
2014-10-08 03:43:00 +00:00
transform . PostTranslate ( offset . x + aIncomingScale . mOffset . x ,
offset . y + aIncomingScale . mOffset . y ,
0 ) ;
2012-12-04 06:04:20 +00:00
2013-03-21 02:33:00 +00:00
if ( transform . IsSingular ( ) ) {
return false ;
}
2011-06-22 12:11:27 +00:00
2012-02-23 18:03:27 +00:00
bool canDraw2D = transform . CanDraw2D ( & transform2d ) ;
2011-06-22 12:11:27 +00:00
gfxSize scale ;
2012-01-11 11:26:33 +00:00
// XXX Should we do something for 3D transforms?
2015-11-26 09:32:36 +00:00
if ( canDraw2D & &
! aContainerFrame - > Combines3DTransformWithAncestors ( ) & &
! aContainerFrame - > HasPerspective ( ) ) {
2014-02-18 14:58:01 +00:00
// If the container's transform is animated off main thread, fix a suitable scale size
// for animation
2015-07-01 15:55:51 +00:00
if ( aContainerItem & &
2015-06-29 23:46:16 +00:00
aContainerItem - > GetType ( ) = = nsDisplayItem : : TYPE_TRANSFORM & &
2015-12-09 21:28:10 +00:00
EffectCompositor : : HasAnimationsForCompositor (
2015-07-01 15:55:51 +00:00
aContainerFrame , eCSSProperty_transform ) ) {
2015-06-29 23:46:17 +00:00
// 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 ( ) ;
nsSize displaySize ;
if ( widget ) {
2015-11-13 09:37:02 +00:00
LayoutDeviceIntSize widgetSize = widget - > GetClientSize ( ) ;
2015-06-29 23:46:17 +00:00
int32_t p2a = presContext - > AppUnitsPerDevPixel ( ) ;
displaySize . width = NSIntPixelsToAppUnits ( widgetSize . width , p2a ) ;
displaySize . height = NSIntPixelsToAppUnits ( widgetSize . height , p2a ) ;
} else {
displaySize = presContext - > GetVisibleArea ( ) . Size ( ) ;
}
2015-06-29 23:46:16 +00:00
// compute scale using the animation on the container (ignoring
// its ancestors)
2015-05-06 06:52:20 +00:00
scale = nsLayoutUtils : : ComputeSuitableScaleForAnimation (
2015-07-01 15:55:51 +00:00
aContainerFrame , aVisibleRect . Size ( ) ,
2015-06-29 23:46:17 +00:00
displaySize ) ;
2016-03-23 20:18:00 +00: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-21 21:58:17 +00:00
} else {
2013-09-04 11:30:57 +00:00
// Scale factors are normalized to a power of 2 to reduce the number of resolution changes
2014-08-01 12:31:49 +00:00
scale = RoundToFloatPrecision ( ThebesMatrix ( transform2d ) . ScaleFactors ( true ) ) ;
2012-12-21 21:58:17 +00:00
// For frames with a changing transform that's not just a translation,
// 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
// 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 12:31:49 +00:00
Matrix frameTransform ;
2014-10-22 01:54:32 +00:00
if ( ActiveLayerTracker : : IsStyleAnimated ( aDisplayListBuilder , aContainerFrame , eCSSProperty_transform ) & &
2012-12-21 21:58:17 +00:00
aTransform & &
( ! aTransform - > Is2D ( & frameTransform ) | | frameTransform . HasNonTranslationOrFlip ( ) ) ) {
// Don't clamp the scale factor when the new desired scale factor matches the old one
// or it was previously unscaled.
bool clamp = true ;
2014-01-27 15:29:06 +00:00
Matrix oldFrameTransform2d ;
2012-12-21 21:58:17 +00:00
if ( aLayer - > GetBaseTransform ( ) . Is2D ( & oldFrameTransform2d ) ) {
2014-01-27 15:29:06 +00:00
gfxSize oldScale = RoundToFloatPrecision ( ThebesMatrix ( oldFrameTransform2d ) . ScaleFactors ( true ) ) ;
2012-12-21 21:58:17 +00:00
if ( oldScale = = scale | | oldScale = = gfxSize ( 1.0 , 1.0 ) ) {
clamp = false ;
}
2012-12-06 23:58:12 +00:00
}
2012-12-21 21:58:17 +00:00
if ( clamp ) {
scale . width = gfxUtils : : ClampToScaleFactor ( scale . width ) ;
scale . height = gfxUtils : : ClampToScaleFactor ( scale . height ) ;
}
} else {
2016-03-21 20:16:52 +00:00
// XXX Do we need to move nearly-integer values to integers here?
2011-12-07 23:12:41 +00:00
}
2011-06-22 12:11:27 +00:00
}
// If the scale factors are too small, just use 1.0. The content is being
// scaled out of sight anyway.
2011-06-22 12:11:28 +00:00
if ( fabs ( scale . width ) < 1e-8 | | fabs ( scale . height ) < 1e-8 ) {
2012-04-29 21:41:13 +00:00
scale = gfxSize ( 1.0 , 1.0 ) ;
2011-06-22 12:11:27 +00:00
}
2014-07-09 02:01:54 +00:00
// If this is a transform container layer, then pre-rendering might
2015-09-21 09:56:52 +00: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 02:01:54 +00:00
RestrictScaleToMaxLayerSize ( scale , aVisibleRect , aContainerFrame , aLayer ) ;
}
2011-06-22 12:11:27 +00:00
} else {
scale = gfxSize ( 1.0 , 1.0 ) ;
}
2012-08-03 21:29:22 +00:00
// Store the inverse of our resolution-scale on the layer
2014-08-01 12:31:49 +00:00
aLayer - > SetBaseTransform ( transform ) ;
2012-08-03 21:29:22 +00:00
aLayer - > SetPreScale ( 1.0f / float ( scale . width ) ,
1.0f / float ( scale . height ) ) ;
2013-01-08 09:39:12 +00:00
aLayer - > SetInheritedScale ( aIncomingScale . mXScale ,
aIncomingScale . mYScale ) ;
2011-06-22 12:11:28 +00:00
2013-09-27 06:01:16 +00:00
aOutgoingScale =
ContainerLayerParameters ( scale . width , scale . height , - offset , aIncomingScale ) ;
2011-06-22 12:11:28 +00:00
if ( aTransform ) {
2013-03-21 02:33:00 +00:00
aOutgoingScale . mInTransformedSubtree = true ;
2014-10-22 01:54:32 +00:00
if ( ActiveLayerTracker : : IsStyleAnimated ( aDisplayListBuilder , aContainerFrame ,
eCSSProperty_transform ) ) {
2013-03-21 02:33:00 +00:00
aOutgoingScale . mInActiveTransformedSubtree = true ;
2011-06-22 12:11:28 +00:00
}
}
2015-09-17 01:31:00 +00:00
if ( ( aLayerBuilder - > IsBuildingRetainedLayers ( ) & &
( ! canDraw2D | | transform2d . HasNonIntegerTranslation ( ) ) ) | |
aContainerFrame - > Extend3DContext ( ) | |
aContainerFrame - > Combines3DTransformWithAncestors ( ) ) {
2013-03-21 02:33:00 +00:00
aOutgoingScale . mDisableSubpixelAntialiasingInDescendants = true ;
2012-01-11 11:26:33 +00:00
}
2013-03-21 02:33:00 +00:00
return true ;
2011-06-22 12:11:27 +00:00
}
2010-09-03 20:10:45 +00:00
already_AddRefed < ContainerLayer >
2010-07-15 21:07:51 +00:00
FrameLayerBuilder : : BuildContainerLayerFor ( nsDisplayListBuilder * aBuilder ,
LayerManager * aManager ,
nsIFrame * aContainerFrame ,
nsDisplayItem * aContainerItem ,
2014-06-09 04:48:00 +00:00
nsDisplayList * aChildren ,
2013-09-27 06:01:16 +00:00
const ContainerLayerParameters & aParameters ,
2014-08-01 12:31:49 +00:00
const Matrix4x4 * aTransform ,
2013-03-22 02:17:29 +00:00
uint32_t aFlags )
2010-07-15 21:07:51 +00:00
{
2012-08-22 15:56:38 +00:00
uint32_t containerDisplayItemKey =
2012-11-19 10:54:50 +00:00
aContainerItem ? aContainerItem - > GetPerFrameKey ( ) : nsDisplayItem : : TYPE_ZERO ;
2010-07-15 21:07:51 +00:00
NS_ASSERTION ( aContainerFrame , " Container display items here should have a frame " ) ;
NS_ASSERTION ( ! aContainerItem | |
2013-04-19 12:02:13 +00:00
aContainerItem - > Frame ( ) = = aContainerFrame ,
2010-07-15 21:07:51 +00:00
" Container display item must match given frame " ) ;
2013-03-05 20:04:40 +00:00
if ( ! aParameters . mXScale | | ! aParameters . mYScale ) {
return nullptr ;
}
2015-10-18 05:24:48 +00:00
RefPtr < ContainerLayer > containerLayer ;
2012-07-04 00:24:55 +00:00
if ( aManager = = mRetainingManager ) {
2012-08-29 10:53:27 +00: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 05:47:15 +00:00
Layer * oldLayer = nullptr ;
if ( aContainerItem ) {
oldLayer = GetOldLayerFor ( aContainerItem ) ;
} else {
DisplayItemData * data = GetOldLayerForFrame ( aContainerFrame , containerDisplayItemKey ) ;
if ( data ) {
oldLayer = data - > mLayer ;
}
}
2012-08-29 10:53:20 +00:00
2012-07-04 00:24:55 +00:00
if ( oldLayer ) {
NS_ASSERTION ( oldLayer - > Manager ( ) = = aManager , " Wrong manager " ) ;
2014-09-26 17:07:06 +00:00
if ( oldLayer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
2014-09-26 17:06:08 +00:00
// The old layer for this item is actually our PaintedLayer
// because we rendered its layer into that PaintedLayer. So we
2012-07-04 00:24:55 +00: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 20:30:47 +00:00
ResetLayerStateForRecycling ( containerLayer ) ;
2012-07-04 00:24:55 +00:00
}
2010-07-15 21:07:51 +00:00
}
}
if ( ! containerLayer ) {
// No suitable existing layer was found.
containerLayer = aManager - > CreateContainerLayer ( ) ;
if ( ! containerLayer )
2012-07-30 14:20:58 +00:00
return nullptr ;
2010-07-15 21:07:51 +00:00
}
2010-05-21 03:20:48 +00:00
2012-09-16 22:25:33 +00:00
LayerState state = aContainerItem ? aContainerItem - > GetLayerState ( aBuilder , aManager , aParameters ) : LAYER_ACTIVE ;
2012-11-22 23:29:05 +00:00
if ( state = = LAYER_INACTIVE & &
nsDisplayItem : : ForceActiveLayers ( ) ) {
state = LAYER_ACTIVE ;
}
2012-09-16 22:25:33 +00:00
if ( aContainerItem & & state = = LAYER_ACTIVE_EMPTY ) {
2011-05-18 22:54:31 +00: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 17:06:08 +00:00
// determine which painted layer gets invalidated. Since an empty layer
2011-05-18 22:54:31 +00:00
// should never have anything to paint, it should never be invalidated.
2014-06-09 04:48:00 +00:00
NS_ASSERTION ( aChildren - > IsEmpty ( ) , " Should have no children " ) ;
2011-05-18 22:54:31 +00:00
return containerLayer . forget ( ) ;
}
2015-12-22 15:54:19 +00:00
const DisplayItemScrollClip * containerScrollClip = aParameters . mScrollClip ;
2013-09-27 06:01:16 +00:00
ContainerLayerParameters scaleParameters ;
2015-12-24 11:16:46 +00:00
nsRect bounds = aChildren - > GetScrollClippedBoundsUpTo ( aBuilder , containerScrollClip ) ;
2014-07-15 11:49:38 +00:00
nsRect childrenVisible =
aContainerItem ? aContainerItem - > GetVisibleRectForChildren ( ) :
aContainerFrame - > GetVisualOverflowRectRelativeToSelf ( ) ;
if ( ! ChooseScaleAndSetTransform ( this , aBuilder , aContainerFrame ,
2015-06-29 23:46:16 +00:00
aContainerItem ,
2014-07-15 11:49:38 +00:00
bounds . Intersect ( childrenVisible ) ,
aTransform , aParameters ,
containerLayer , state , scaleParameters ) ) {
2013-03-21 02:33:00 +00:00
return nullptr ;
}
2010-05-21 03:20:48 +00:00
2012-08-22 15:56:38 +00:00
uint32_t oldGeneration = mContainerLayerGeneration ;
2012-07-23 03:00:36 +00:00
mContainerLayerGeneration = + + mMaxContainerLayerGeneration ;
2012-08-29 05:47:15 +00:00
if ( mRetainingManager ) {
2012-10-11 23:38:24 +00:00
if ( aContainerItem ) {
2012-10-12 02:39:46 +00:00
StoreDataForFrame ( aContainerItem , containerLayer , LAYER_ACTIVE ) ;
} else {
StoreDataForFrame ( aContainerFrame , containerDisplayItemKey , containerLayer , LAYER_ACTIVE ) ;
2012-10-11 23:38:24 +00:00
}
2012-07-23 03:00:36 +00:00
}
2014-03-20 06:49:27 +00:00
2012-10-12 02:39:46 +00:00
LayerManagerData * data = static_cast < LayerManagerData * >
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-07-23 03:00:36 +00:00
nsIntRect pixBounds ;
2014-06-23 04:24:00 +00:00
nscoord appUnitsPerDevPixel ;
2014-09-06 04:16:33 +00:00
bool flattenToSingleLayer = false ;
2012-11-22 05:34:32 +00:00
if ( ( aContainerFrame - > GetStateBits ( ) & NS_FRAME_NO_COMPONENT_ALPHA ) & &
2015-02-11 04:54:18 +00:00
mRetainingManager & &
mRetainingManager - > ShouldAvoidComponentAlphaLayers ( ) & &
2015-06-04 20:51:10 +00:00
! nsLayoutUtils : : AsyncPanZoomEnabled ( aContainerFrame ) )
2015-02-11 04:54:18 +00:00
{
2014-09-06 04:16:33 +00:00
flattenToSingleLayer = true ;
2012-11-22 05:34:32 +00:00
}
2015-02-25 16:47:22 +00:00
nscolor backgroundColor = NS_RGBA ( 0 , 0 , 0 , 0 ) ;
if ( aFlags & CONTAINER_ALLOW_PULL_BACKGROUND_COLOR ) {
backgroundColor = aParameters . mBackgroundColor ;
}
2012-08-22 15:56:38 +00:00
uint32_t flags ;
2012-07-23 03:00:36 +00:00
while ( true ) {
2012-08-21 04:06:46 +00:00
ContainerState state ( aBuilder , aManager , aManager - > GetLayerBuilder ( ) ,
2014-06-09 04:48:00 +00:00
aContainerFrame , aContainerItem , bounds ,
2015-02-25 16:47:22 +00:00
containerLayer , scaleParameters , flattenToSingleLayer ,
2015-12-22 15:54:19 +00:00
backgroundColor , containerScrollClip ) ;
2014-03-20 06:49:27 +00:00
2014-09-06 04:16:33 +00:00
state . ProcessDisplayItems ( aChildren ) ;
2012-08-03 21:29:22 +00:00
2012-07-23 03:00:36 +00: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 06:48:23 +00:00
bool hasComponentAlphaChildren = false ;
2016-01-13 23:42:27 +00:00
bool mayFlatten =
mRetainingManager & &
mRetainingManager - > ShouldAvoidComponentAlphaLayers ( ) & &
! flattenToSingleLayer & &
! nsLayoutUtils : : AsyncPanZoomEnabled ( aContainerFrame ) ;
2012-07-23 03:00:36 +00:00
pixBounds = state . ScaleToOutsidePixels ( bounds , false ) ;
appUnitsPerDevPixel = state . GetAppUnitsPerDevPixel ( ) ;
2016-01-13 23:42:27 +00:00
state . Finish ( & flags , pixBounds , aChildren , mayFlatten ? & hasComponentAlphaChildren : nullptr ) ;
2012-07-23 03:00:36 +00:00
2014-07-18 06:48:23 +00:00
if ( hasComponentAlphaChildren & &
2015-06-26 22:13:50 +00:00
! ( flags & Layer : : CONTENT_DISABLE_FLATTENING ) & &
2016-01-13 23:42:27 +00:00
containerLayer - > HasMultipleChildren ( ) )
2015-02-11 04:54:18 +00:00
{
2012-07-23 03:00:36 +00: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 04:16:33 +00:00
flattenToSingleLayer = true ;
2015-07-15 09:05:06 +00: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 03:00:36 +00:00
aContainerFrame - > AddStateBits ( NS_FRAME_NO_COMPONENT_ALPHA ) ;
continue ;
}
break ;
}
2010-12-20 01:26:14 +00:00
2014-07-18 06:48:23 +00: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 05:38:09 +00:00
// Make sure that rounding the visible region out didn't add any area
// we won't paint
2014-06-09 04:48:00 +00:00
if ( aChildren - > IsOpaque ( ) & & ! aChildren - > NeedsTransparentSurface ( ) ) {
2011-06-22 12:11:27 +00:00
bounds . ScaleRoundIn ( scaleParameters . mXScale , scaleParameters . mYScale ) ;
2015-04-21 15:04:57 +00:00
if ( bounds . Contains ( ToAppUnits ( pixBounds , appUnitsPerDevPixel ) ) ) {
2014-07-18 06:48:23 +00:00
// Clear CONTENT_COMPONENT_ALPHA and add CONTENT_OPAQUE instead.
flags & = ~ Layer : : CONTENT_COMPONENT_ALPHA ;
flags | = Layer : : CONTENT_OPAQUE ;
2011-06-22 12:11:27 +00:00
}
2010-12-20 01:26:14 +00:00
}
2010-09-02 09:18:40 +00:00
containerLayer - > SetContentFlags ( flags ) ;
2014-06-23 04:24:00 +00: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 07:07:55 +00:00
containerLayer - > SetVisibleRegion ( LayerIntRegion : : FromUnknownRegion ( pixBounds ) ) ;
2014-06-23 04:24:00 +00:00
}
if ( aParameters . mLayerContentsVisibleRect ) {
* aParameters . mLayerContentsVisibleRect = pixBounds + scaleParameters . mOffset ;
}
2010-12-20 01:26:14 +00:00
2012-07-23 03:00:36 +00:00
mContainerLayerGeneration = oldGeneration ;
2013-08-14 11:33:03 +00:00
nsPresContext : : ClearNotifySubDocInvalidationData ( containerLayer ) ;
2012-08-29 05:47:18 +00:00
2010-08-05 22:11:23 +00:00
return containerLayer . forget ( ) ;
2010-05-21 03:20:48 +00:00
}
2010-07-15 21:07:46 +00:00
Layer *
FrameLayerBuilder : : GetLeafLayerFor ( nsDisplayListBuilder * aBuilder ,
nsDisplayItem * aItem )
{
2012-08-29 05:47:15 +00:00
Layer * layer = GetOldLayerFor ( aItem ) ;
2010-07-15 21:07:51 +00:00
if ( ! layer )
2012-07-30 14:20:58 +00:00
return nullptr ;
2014-09-26 17:07:06 +00:00
if ( layer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
2010-07-15 21:07:51 +00: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 14:20:58 +00:00
return nullptr ;
2010-07-15 21:07:51 +00:00
}
2016-07-08 21:24:48 +00:00
ResetLayerStateForRecycling ( layer ) ;
2010-07-15 21:07:51 +00:00
return layer ;
2010-07-15 21:07:46 +00:00
}
2012-09-27 15:34:46 +00:00
/* static */ void
FrameLayerBuilder : : InvalidateAllLayers ( LayerManager * aManager )
{
LayerManagerData * data = static_cast < LayerManagerData * >
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-08-29 05:48:45 +00:00
if ( data ) {
data - > mInvalidateAllLayers = true ;
}
}
2012-08-29 05:48:45 +00:00
/* static */ void
FrameLayerBuilder : : InvalidateAllLayersForFrame ( nsIFrame * aFrame )
{
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-10-11 23:38:24 +00:00
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
AssertDisplayItemData ( array - > ElementAt ( i ) ) - > mParent - > mInvalidateAllLayers = true ;
2012-10-11 23:38:24 +00:00
}
2012-08-29 05:48:45 +00:00
}
}
2010-07-15 21:07:53 +00:00
/* static */
2011-03-27 23:59:47 +00:00
Layer *
2012-08-22 15:56:38 +00:00
FrameLayerBuilder : : GetDedicatedLayer ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2010-07-15 21:07:53 +00:00
{
2012-08-29 05:48:41 +00: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
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-10-11 23:38:24 +00:00
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
DisplayItemData * element = AssertDisplayItemData ( array - > ElementAt ( i ) ) ;
2012-10-12 02:39:46 +00:00
if ( ! element - > mParent - > mLayerManager - > IsWidgetLayerManager ( ) ) {
continue ;
}
if ( element - > mDisplayItemKey = = aDisplayItemKey ) {
if ( element - > mOptLayer ) {
return element - > mOptLayer ;
2012-10-11 23:38:24 +00:00
}
2012-09-24 20:31:30 +00:00
2012-10-12 02:39:46 +00:00
Layer * layer = element - > mLayer ;
2012-10-11 23:38:24 +00:00
if ( ! layer - > HasUserData ( & gColorLayerUserData ) & &
! layer - > HasUserData ( & gImageLayerUserData ) & &
2014-09-26 17:07:06 +00:00
! layer - > HasUserData ( & gPaintedDisplayItemLayerUserData ) ) {
2012-10-11 23:38:24 +00:00
return layer ;
}
}
}
2010-07-15 21:07:53 +00:00
}
2012-07-30 14:20:58 +00:00
return nullptr ;
2010-07-15 21:07:53 +00:00
}
2012-08-04 12:26:38 +00:00
static gfxSize
PredictScaleForContent ( nsIFrame * aFrame , nsIFrame * aAncestorWithScale ,
const gfxSize & aScale )
2012-05-10 05:24:18 +00:00
{
2014-10-08 03:43:00 +00:00
Matrix4x4 transform = Matrix4x4 : : Scaling ( aScale . width , aScale . height , 1.0 ) ;
2012-11-11 08:17:16 +00:00
if ( aFrame ! = aAncestorWithScale ) {
// aTransform is applied first, then the scale is applied to the result
transform = nsLayoutUtils : : GetTransformToAncestor ( aFrame , aAncestorWithScale ) * transform ;
}
2014-08-22 13:40:02 +00:00
Matrix transform2d ;
2012-08-04 12:26:38 +00:00
if ( transform . CanDraw2D ( & transform2d ) ) {
2014-08-22 13:40:02 +00:00
return ThebesMatrix ( transform2d ) . ScaleFactors ( true ) ;
2012-08-04 12:26:38 +00:00
}
return gfxSize ( 1.0 , 1.0 ) ;
}
gfxSize
2014-09-26 17:06:08 +00:00
FrameLayerBuilder : : GetPaintedLayerScaleForFrame ( nsIFrame * aFrame )
2012-08-04 12:26:38 +00:00
{
2014-06-24 17:52:18 +00:00
MOZ_ASSERT ( aFrame , " need a frame " ) ;
nsIFrame * last = nullptr ;
2012-08-04 12:26:38 +00:00
for ( nsIFrame * f = aFrame ; f ; f = nsLayoutUtils : : GetCrossDocParentFrame ( f ) ) {
last = f ;
2012-11-11 08:17:16 +00:00
if ( nsLayoutUtils : : IsPopup ( f ) ) {
// Don't examine ancestors of a popup. It won't make sense to check
// the transform from some content inside the popup to some content
// which is an ancestor of the popup.
break ;
}
2014-03-20 06:49:27 +00:00
2015-04-10 21:42:42 +00:00
const nsTArray < DisplayItemData * > * array =
2016-06-21 20:17:11 +00:00
f - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ;
2012-10-11 23:38:24 +00:00
if ( ! array ) {
2012-08-29 05:48:41 +00:00
continue ;
2012-10-11 23:38:24 +00:00
}
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
Layer * layer = AssertDisplayItemData ( array - > ElementAt ( i ) ) - > mLayer ;
2012-08-29 05:47:15 +00:00
ContainerLayer * container = layer - > AsContainerLayer ( ) ;
2012-10-11 23:38:24 +00:00
if ( ! container | |
! layer - > Manager ( ) - > IsWidgetLayerManager ( ) ) {
2012-08-29 05:47:15 +00:00
continue ;
}
for ( Layer * l = container - > GetFirstChild ( ) ; l ; l = l - > GetNextSibling ( ) ) {
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * data =
static_cast < PaintedDisplayItemLayerUserData * >
( l - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2012-08-29 05:47:15 +00:00
if ( data ) {
return PredictScaleForContent ( aFrame , f , gfxSize ( data - > mXScale , data - > mYScale ) ) ;
2012-08-04 12:26:38 +00:00
}
2012-08-05 13:35:08 +00:00
}
}
}
2015-03-06 23:07:59 +00:00
float presShellResolution = last - > PresContext ( ) - > PresShell ( ) - > GetResolution ( ) ;
2012-08-04 12:26:38 +00:00
return PredictScaleForContent ( aFrame , last ,
2015-03-06 23:07:59 +00:00
gfxSize ( presShellResolution , presShellResolution ) ) ;
2012-05-10 05:24:18 +00:00
}
2012-03-05 18:09:05 +00:00
# ifdef MOZ_DUMP_PAINTING
2014-10-29 17:07:11 +00:00
static void DebugPaintItem ( DrawTarget & aDrawTarget ,
2014-06-20 06:42:30 +00:00
nsPresContext * aPresContext ,
nsDisplayItem * aItem ,
nsDisplayListBuilder * aBuilder )
2012-03-05 18:09:05 +00:00
{
2012-04-10 11:24:18 +00:00
bool snap ;
2014-10-29 17:07:11 +00:00
Rect bounds = NSRectToRect ( aItem - > GetBounds ( aBuilder , & snap ) ,
aPresContext - > AppUnitsPerDevPixel ( ) ) ;
2012-03-05 18:09:05 +00:00
2015-10-18 05:24:48 +00:00
RefPtr < DrawTarget > tempDT =
2016-07-26 14:48:30 +00:00
aDrawTarget . CreateSimilarDrawTarget ( IntSize : : Truncate ( bounds . width , bounds . height ) ,
2014-10-29 17:07:11 +00:00
SurfaceFormat : : B8G8R8A8 ) ;
2016-06-06 23:39:56 +00:00
RefPtr < gfxContext > context = gfxContext : : CreateOrNull ( tempDT ) ;
2016-04-12 19:18:11 +00: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 17:07:11 +00:00
context - > SetMatrix ( gfxMatrix : : Translation ( - bounds . x , - bounds . y ) ) ;
2014-10-31 20:08:49 +00:00
nsRenderingContext ctx ( context ) ;
2012-03-05 18:09:05 +00:00
2014-10-31 20:08:49 +00:00
aItem - > Paint ( aBuilder , & ctx ) ;
2015-10-18 05:24:48 +00:00
RefPtr < SourceSurface > surface = tempDT - > Snapshot ( ) ;
2014-06-27 11:19:40 +00:00
DumpPaintedImage ( aItem , surface ) ;
2012-07-31 17:28:21 +00:00
2014-10-29 17:07:11 +00:00
aDrawTarget . DrawSurface ( surface , bounds , Rect ( Point ( 0 , 0 ) , bounds . Size ( ) ) ) ;
2014-06-27 11:19:40 +00:00
aItem - > SetPainted ( ) ;
2012-03-05 18:09:05 +00:00
}
# endif
2010-05-21 03:20:48 +00:00
/* static */ void
2013-11-06 19:10:49 +00:00
FrameLayerBuilder : : RecomputeVisibilityForItems ( nsTArray < ClippedDisplayItem > & aItems ,
nsDisplayListBuilder * aBuilder ,
const nsIntRegion & aRegionToDraw ,
const nsIntPoint & aOffset ,
int32_t aAppUnitsPerDevPixel ,
float aXScale ,
float aYScale )
2010-05-21 03:20:48 +00:00
{
2012-08-22 15:56:38 +00:00
uint32_t i ;
2014-06-09 04:48:01 +00:00
// Update visible regions. We perform visibility analysis to take account
// of occlusion culling.
2013-11-06 19:10:49 +00:00
nsRegion visible = aRegionToDraw . ToAppUnits ( aAppUnitsPerDevPixel ) ;
visible . MoveBy ( NSIntPixelsToAppUnits ( aOffset . x , aAppUnitsPerDevPixel ) ,
NSIntPixelsToAppUnits ( aOffset . y , aAppUnitsPerDevPixel ) ) ;
visible . ScaleInverseRoundOut ( aXScale , aYScale ) ;
2010-07-15 21:07:51 +00:00
2013-11-06 19:10:49 +00:00
for ( i = aItems . Length ( ) ; i > 0 ; - - i ) {
ClippedDisplayItem * cdi = & aItems [ i - 1 ] ;
2013-03-04 09:56:02 +00:00
const DisplayItemClip & clip = cdi - > mItem - > GetClip ( ) ;
2010-07-15 21:07:51 +00:00
2013-11-06 19:10:49 +00:00
NS_ASSERTION ( AppUnitsPerDevPixel ( cdi - > mItem ) = = aAppUnitsPerDevPixel ,
2014-09-26 17:06:08 +00:00
" a painted layer should contain items only at the same zoom " ) ;
2010-07-15 21:07:51 +00:00
2015-02-09 22:34:50 +00:00
MOZ_ASSERT ( clip . HasClip ( ) | | clip . GetRoundedRectCount ( ) = = 0 ,
" If we have rounded rects, we must have a clip rect " ) ;
2010-09-09 15:21:46 +00:00
2013-03-04 09:56:02 +00:00
if ( ! clip . IsRectAffectedByClip ( visible . GetBounds ( ) ) ) {
2013-11-06 19:10:49 +00:00
cdi - > mItem - > RecomputeVisibility ( aBuilder , & visible ) ;
2012-12-13 22:50:57 +00:00
continue ;
}
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped ;
2013-03-04 09:56:02 +00:00
clipped . And ( visible , clip . NonRoundedIntersection ( ) ) ;
2012-12-13 22:50:57 +00:00
nsRegion finalClipped = clipped ;
2013-11-06 19:10:49 +00:00
cdi - > mItem - > RecomputeVisibility ( aBuilder , & finalClipped ) ;
2012-12-13 22:50:57 +00: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 09:56:02 +00:00
if ( clip . GetRoundedRectCount ( ) = = 0 ) {
2012-12-13 22:50:57 +00: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 15:21:46 +00:00
}
2011-01-26 18:36:11 +00:00
}
2010-07-15 21:07:51 +00:00
}
2013-11-06 19:10:49 +00:00
}
2010-07-15 21:07:51 +00:00
2013-11-06 19:10:49 +00:00
void
FrameLayerBuilder : : PaintItems ( nsTArray < ClippedDisplayItem > & aItems ,
2013-11-06 19:10:50 +00:00
const nsIntRect & aRect ,
2013-11-06 19:10:49 +00:00
gfxContext * aContext ,
nsRenderingContext * aRC ,
nsDisplayListBuilder * aBuilder ,
nsPresContext * aPresContext ,
2013-11-06 19:10:50 +00:00
const nsIntPoint & aOffset ,
float aXScale , float aYScale ,
2013-11-06 19:10:49 +00:00
int32_t aCommonClipCount )
{
2014-10-29 17:07:11 +00:00
DrawTarget & aDrawTarget = * aRC - > GetDrawTarget ( ) ;
2015-02-25 04:59:43 +00:00
2013-11-06 19:10:50 +00:00
int32_t appUnitsPerDevPixel = aPresContext - > AppUnitsPerDevPixel ( ) ;
2015-04-21 15:04:57 +00:00
nsRect boundRect = ToAppUnits ( aRect , appUnitsPerDevPixel ) ;
2013-11-06 19:10:50 +00:00
boundRect . MoveBy ( NSIntPixelsToAppUnits ( aOffset . x , appUnitsPerDevPixel ) ,
NSIntPixelsToAppUnits ( aOffset . y , appUnitsPerDevPixel ) ) ;
boundRect . ScaleInverseRoundOut ( aXScale , aYScale ) ;
2013-03-04 09:55:59 +00:00
DisplayItemClip currentClip ;
2013-03-04 09:56:00 +00:00
bool currentClipIsSetInContext = false ;
2013-03-04 09:56:02 +00:00
DisplayItemClip tmpClip ;
2010-08-08 18:49:07 +00:00
2013-11-06 19:10:49 +00:00
for ( uint32_t i = 0 ; i < aItems . Length ( ) ; + + i ) {
ClippedDisplayItem * cdi = & aItems [ i ] ;
2010-07-15 21:07:51 +00:00
2013-11-06 19:10:50 +00:00
nsRect paintRect = cdi - > mItem - > GetVisibleRect ( ) . Intersect ( boundRect ) ;
if ( paintRect . IsEmpty ( ) )
2010-07-15 21:07:51 +00:00
continue ;
2014-07-09 19:11:51 +00:00
# ifdef MOZ_DUMP_PAINTING
2015-03-07 23:40:03 +00:00
PROFILER_LABEL_PRINTF ( " DisplayList " , " Draw " ,
js : : ProfileEntry : : Category : : GRAPHICS , " %s " , cdi - > mItem - > Name ( ) ) ;
2014-07-09 19:11:51 +00:00
# else
2015-03-07 23:40:03 +00:00
PROFILER_LABEL ( " DisplayList " , " Draw " ,
js : : ProfileEntry : : Category : : GRAPHICS ) ;
2014-07-09 19:11:51 +00:00
# endif
2010-05-21 03:20:48 +00:00
// If the new desired clip state is different from the current state,
// update the clip.
2013-03-04 09:56:02 +00: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 09:56:00 +00:00
if ( currentClipIsSetInContext ) {
2010-05-21 03:20:48 +00:00
aContext - > Restore ( ) ;
}
2013-03-04 09:56:02 +00:00
currentClipIsSetInContext = clip - > HasClip ( ) ;
2013-03-04 09:56:00 +00:00
if ( currentClipIsSetInContext ) {
2013-03-04 09:56:02 +00:00
currentClip = * clip ;
2010-05-21 03:20:48 +00:00
aContext - > Save ( ) ;
2013-11-06 19:10:49 +00:00
NS_ASSERTION ( aCommonClipCount < 100 ,
2012-02-07 22:27:44 +00:00
" Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong. " ) ;
2013-11-06 19:10:49 +00:00
currentClip . ApplyTo ( aContext , aPresContext , aCommonClipCount ) ;
2013-09-19 05:23:30 +00:00
aContext - > NewPath ( ) ;
2010-05-21 03:20:48 +00:00
}
}
2010-07-15 21:07:51 +00:00
2012-10-23 11:05:14 +00:00
if ( cdi - > mInactiveLayerManager ) {
2015-02-25 04:59:43 +00:00
bool saved = aDrawTarget . GetPermitSubpixelAA ( ) ;
2013-11-06 19:10:49 +00:00
PaintInactiveLayer ( aBuilder , cdi - > mInactiveLayerManager , cdi - > mItem , aContext , aRC ) ;
2015-02-25 04:59:43 +00:00
aDrawTarget . SetPermitSubpixelAA ( saved ) ;
2010-07-15 21:08:05 +00:00
} else {
2013-04-19 12:02:13 +00:00
nsIFrame * frame = cdi - > mItem - > Frame ( ) ;
2016-05-06 14:31:11 +00:00
if ( aBuilder - > IsPaintingToWindow ( ) ) {
frame - > AddStateBits ( NS_FRAME_PAINTED_THEBES ) ;
}
2012-03-05 18:09:05 +00:00
# ifdef MOZ_DUMP_PAINTING
2015-10-28 13:31:00 +00:00
if ( gfxEnv : : DumpPaintItems ( ) ) {
2014-10-29 17:07:11 +00:00
DebugPaintItem ( aDrawTarget , aPresContext , cdi - > mItem , aBuilder ) ;
2012-03-05 18:09:05 +00:00
} else {
# else
{
# endif
2013-11-06 19:10:49 +00:00
cdi - > mItem - > Paint ( aBuilder , aRC ) ;
2012-03-05 18:09:05 +00:00
}
2010-05-21 03:20:48 +00:00
}
2010-09-17 19:09:08 +00:00
2013-11-06 19:10:49 +00:00
if ( CheckDOMModified ( ) )
2010-09-17 19:09:08 +00:00
break ;
2010-05-21 03:20:48 +00:00
}
2010-07-15 21:07:51 +00:00
2013-03-04 09:56:00 +00:00
if ( currentClipIsSetInContext ) {
2010-05-21 03:20:48 +00:00
aContext - > Restore ( ) ;
}
2013-11-06 19:10:49 +00:00
}
2013-11-06 19:10:50 +00: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 03:36:09 +00:00
static bool
ShouldDrawRectsSeparately ( DrawTarget * aDrawTarget , DrawRegionClip aClip )
2013-11-06 19:10:50 +00:00
{
2014-05-08 02:56:48 +00:00
if ( ! gfxPrefs : : LayoutPaintRectsSeparately ( ) | |
2014-10-01 05:25:25 +00:00
aClip = = DrawRegionClip : : NONE ) {
2013-11-06 19:10:50 +00:00
return false ;
}
2013-11-14 00:46:19 +00:00
2015-12-18 03:36:09 +00:00
return ! aDrawTarget - > SupportsRegionClipping ( ) ;
2013-11-06 19:10:50 +00:00
}
2014-11-24 00:04:33 +00:00
static void DrawForcedBackgroundColor ( DrawTarget & aDrawTarget ,
2016-05-06 17:53:56 +00:00
const IntRect & aBounds ,
nscolor aBackgroundColor )
2013-11-06 19:10:50 +00:00
{
if ( NS_GET_A ( aBackgroundColor ) > 0 ) {
2014-11-24 00:04:33 +00:00
ColorPattern color ( ToDeviceColor ( aBackgroundColor ) ) ;
2016-05-06 17:53:56 +00:00
aDrawTarget . FillRect ( Rect ( aBounds ) , color ) ;
2013-11-06 19:10:50 +00:00
}
}
2013-11-06 19:10:49 +00:00
/*
* A note on residual transforms :
*
2014-09-26 17:06:08 +00:00
* In a transformed subtree we sometimes apply the PaintedLayer ' s
* " residual transform " when drawing content into the PaintedLayer .
2013-11-06 19:10:49 +00: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 17:06:08 +00:00
* of the content of the PaintedLayer exactly matches what it would be if
2013-11-06 19:10:49 +00:00
* we used cairo / Thebes to draw directly to the screen without going through
* retained layer buffers .
*
2014-09-26 17:06:08 +00:00
* The visible and valid regions of the PaintedLayer are computed without
2013-11-06 19:10:49 +00: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 17:06:08 +00:00
FrameLayerBuilder : : DrawPaintedLayer ( PaintedLayer * aLayer ,
2013-11-06 19:10:49 +00:00
gfxContext * aContext ,
const nsIntRegion & aRegionToDraw ,
2015-09-15 13:41:42 +00:00
const nsIntRegion & aDirtyRegion ,
2013-11-06 19:10:50 +00:00
DrawRegionClip aClip ,
2013-11-06 19:10:49 +00:00
const nsIntRegion & aRegionToInvalidate ,
void * aCallbackData )
{
2014-11-24 00:04:33 +00:00
DrawTarget & aDrawTarget = * aContext - > GetDrawTarget ( ) ;
2014-09-26 17:06:08 +00:00
PROFILER_LABEL ( " FrameLayerBuilder " , " DrawPaintedLayer " ,
2014-05-23 21:12:29 +00:00
js : : ProfileEntry : : Category : : GRAPHICS ) ;
2013-11-06 19:10:49 +00: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 17:06:08 +00:00
PaintedLayerItemsEntry * entry = layerBuilder - > mPaintedLayerItems . GetEntry ( aLayer ) ;
2013-11-06 19:10:49 +00:00
NS_ASSERTION ( entry , " We shouldn't be drawing into a layer with no items! " ) ;
if ( ! entry - > mContainerLayerFrame ) {
return ;
}
2013-11-06 19:10:50 +00:00
2014-09-26 17:07:06 +00:00
PaintedDisplayItemLayerUserData * userData =
static_cast < PaintedDisplayItemLayerUserData * >
( aLayer - > GetUserData ( & gPaintedDisplayItemLayerUserData ) ) ;
2013-11-06 19:10:49 +00:00
NS_ASSERTION ( userData , " where did our user data go? " ) ;
2013-11-06 19:10:50 +00:00
2015-12-18 03:36:09 +00:00
bool shouldDrawRectsSeparately =
ShouldDrawRectsSeparately ( & aDrawTarget , aClip ) ;
2013-11-06 19:10:50 +00:00
if ( ! shouldDrawRectsSeparately ) {
2014-10-01 05:25:25 +00:00
if ( aClip = = DrawRegionClip : : DRAW ) {
2013-11-06 19:10:50 +00:00
gfxUtils : : ClipToRegion ( aContext , aRegionToDraw ) ;
}
2016-05-06 17:53:56 +00:00
DrawForcedBackgroundColor ( aDrawTarget , aRegionToDraw . GetBounds ( ) ,
2014-11-24 00:04:33 +00:00
userData - > mForcedBackgroundColor ) ;
2013-11-06 19:10:49 +00:00
}
2014-10-24 16:32:23 +00:00
if ( NS_GET_A ( userData - > mFontSmoothingBackgroundColor ) > 0 ) {
aContext - > SetFontSmoothingBackgroundColor (
Color : : FromABGR ( userData - > mFontSmoothingBackgroundColor ) ) ;
}
2013-11-06 19:10:49 +00:00
// make the origin of the context coincide with the origin of the
2014-09-26 17:06:08 +00:00
// PaintedLayer
2013-11-06 19:10:49 +00:00
gfxContextMatrixAutoSaveRestore saveMatrix ( aContext ) ;
2014-09-26 17:06:08 +00:00
nsIntPoint offset = GetTranslationForPaintedLayer ( aLayer ) ;
2013-11-06 19:10:49 +00:00
nsPresContext * presContext = entry - > mContainerLayerFrame - > PresContext ( ) ;
2015-09-15 13:41:42 +00:00
if ( ! userData - > mVisibilityComputedRegion . Contains ( aDirtyRegion ) & &
2015-07-21 08:19:25 +00:00
! layerBuilder - > GetContainingPaintedLayerData ( ) ) {
2015-09-15 13:41:42 +00: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 04:24:14 +00:00
int32_t appUnitsPerDevPixel = presContext - > AppUnitsPerDevPixel ( ) ;
2015-09-15 13:41:42 +00:00
RecomputeVisibilityForItems ( entry - > mItems , builder , aDirtyRegion ,
2014-06-23 04:24:14 +00:00
offset , appUnitsPerDevPixel ,
userData - > mXScale , userData - > mYScale ) ;
2015-09-15 13:41:42 +00:00
userData - > mVisibilityComputedRegion = aDirtyRegion ;
2014-06-23 04:24:14 +00:00
}
2013-11-06 19:10:49 +00:00
2014-10-31 20:08:49 +00:00
nsRenderingContext rc ( aContext ) ;
2013-11-06 19:10:49 +00:00
2013-11-06 19:10:50 +00:00
if ( shouldDrawRectsSeparately ) {
2016-01-19 01:20:59 +00:00
for ( auto iter = aRegionToDraw . RectIter ( ) ; ! iter . Done ( ) ; iter . Next ( ) ) {
const nsIntRect & iterRect = iter . Get ( ) ;
2013-11-06 19:10:50 +00:00
gfxContextAutoSaveRestore save ( aContext ) ;
aContext - > NewPath ( ) ;
2016-01-19 01:20:59 +00:00
aContext - > Rectangle ( ThebesRect ( iterRect ) ) ;
2013-11-06 19:10:50 +00:00
aContext - > Clip ( ) ;
2016-05-06 17:53:56 +00:00
DrawForcedBackgroundColor ( aDrawTarget , iterRect ,
2014-11-24 00:04:33 +00:00
userData - > mForcedBackgroundColor ) ;
2013-11-06 19:10:50 +00: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 06:57:38 +00:00
aContext - > SetMatrix (
aContext - > CurrentMatrix ( ) . Translate ( aLayer - > GetResidualTranslation ( ) - gfxPoint ( offset . x , offset . y ) ) .
Scale ( userData - > mXScale , userData - > mYScale ) ) ;
2013-11-06 19:10:50 +00:00
2016-01-19 01:20:59 +00:00
layerBuilder - > PaintItems ( entry - > mItems , iterRect , aContext , & rc ,
2013-11-06 19:10:50 +00:00
builder , presContext ,
2013-11-06 19:10:50 +00:00
offset , userData - > mXScale , userData - > mYScale ,
2013-11-06 19:10:50 +00:00
entry - > mCommonClipCount ) ;
2016-04-19 21:07:57 +00:00
if ( gfxPrefs : : GfxLoggingPaintedPixelCountEnabled ( ) ) {
aLayer - > Manager ( ) - > AddPaintedPixelCount ( iterRect . Area ( ) ) ;
}
2013-11-06 19:10:50 +00: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 06:57:38 +00:00
aContext - > SetMatrix (
aContext - > CurrentMatrix ( ) . Translate ( aLayer - > GetResidualTranslation ( ) - gfxPoint ( offset . x , offset . y ) ) .
Scale ( userData - > mXScale , userData - > mYScale ) ) ;
2013-11-06 19:10:50 +00:00
2014-10-31 20:08:49 +00:00
layerBuilder - > PaintItems ( entry - > mItems , aRegionToDraw . GetBounds ( ) , aContext , & rc ,
2013-11-06 19:10:50 +00:00
builder , presContext ,
2013-11-06 19:10:50 +00:00
offset , userData - > mXScale , userData - > mYScale ,
2013-11-06 19:10:50 +00:00
entry - > mCommonClipCount ) ;
2016-04-19 21:07:57 +00:00
if ( gfxPrefs : : GfxLoggingPaintedPixelCountEnabled ( ) ) {
aLayer - > Manager ( ) - > AddPaintedPixelCount (
aRegionToDraw . GetBounds ( ) . Area ( ) ) ;
}
2013-11-06 19:10:50 +00:00
}
2011-11-15 04:59:03 +00:00
2014-10-24 16:32:23 +00:00
aContext - > SetFontSmoothingBackgroundColor ( Color ( ) ) ;
2014-09-09 18:54:08 +00:00
bool isActiveLayerManager = ! aLayer - > Manager ( ) - > IsInactiveLayerManager ( ) ;
if ( presContext - > GetPaintFlashing ( ) & & isActiveLayerManager ) {
2014-05-22 02:36:26 +00:00
gfxContextAutoSaveRestore save ( aContext ) ;
if ( shouldDrawRectsSeparately ) {
2014-10-01 05:25:25 +00:00
if ( aClip = = DrawRegionClip : : DRAW ) {
2014-05-22 02:36:26 +00:00
gfxUtils : : ClipToRegion ( aContext , aRegionToDraw ) ;
}
}
2013-03-12 18:01:00 +00:00
FlashPaint ( aContext ) ;
}
2015-12-16 23:18:00 +00:00
if ( presContext - > GetDocShell ( ) & & isActiveLayerManager ) {
2014-09-09 18:54:08 +00:00
nsDocShell * docShell = static_cast < nsDocShell * > ( presContext - > GetDocShell ( ) ) ;
2015-10-21 21:10:05 +00:00
RefPtr < TimelineConsumers > timelines = TimelineConsumers : : Get ( ) ;
if ( timelines & & timelines - > HasConsumer ( docShell ) ) {
timelines - > AddMarkerForDocShell ( docShell , Move (
MakeUnique < LayerTimelineMarker > ( aRegionToDraw ) ) ) ;
2014-12-11 15:40:00 +00:00
}
2014-09-09 18:54:08 +00:00
}
2012-08-29 05:47:18 +00:00
if ( ! aRegionToInvalidate . IsEmpty ( ) ) {
aLayer - > AddInvalidRect ( aRegionToInvalidate . GetBounds ( ) ) ;
}
2010-05-21 03:20:48 +00:00
}
2011-09-29 06:19:26 +00:00
bool
2010-09-17 19:09:08 +00:00
FrameLayerBuilder : : CheckDOMModified ( )
{
2010-09-18 18:43:17 +00:00
if ( ! mRootPresContext | |
2010-09-17 19:09:08 +00:00
mInitialDOMGeneration = = mRootPresContext - > GetDOMGeneration ( ) )
2011-10-17 14:59:28 +00:00
return false ;
2010-09-17 19:09:08 +00:00
if ( mDetectedDOMModification ) {
// Don't spam the console with extra warnings
2011-10-17 14:59:28 +00:00
return true ;
2010-09-17 19:09:08 +00:00
}
2011-10-17 14:59:28 +00:00
mDetectedDOMModification = true ;
2010-09-17 19:09:08 +00: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 14:59:28 +00:00
return true ;
2010-09-17 19:09:08 +00:00
}
2012-07-17 17:03:51 +00:00
/* static */ void
2014-06-19 22:36:25 +00:00
FrameLayerBuilder : : DumpRetainedLayerTree ( LayerManager * aManager , std : : stringstream & aStream , bool aDumpHtml )
2010-07-15 21:07:51 +00:00
{
2014-06-19 22:36:25 +00:00
aManager - > Dump ( aStream , " " , aDumpHtml ) ;
2010-07-15 21:07:51 +00:00
}
2015-02-04 21:50:56 +00:00
nsDisplayItemGeometry *
FrameLayerBuilder : : GetMostRecentGeometry ( nsDisplayItem * aItem )
{
typedef nsTArray < DisplayItemData * > DataArray ;
// Retrieve the array of DisplayItemData associated with our frame.
FrameProperties properties = aItem - > Frame ( ) - > Properties ( ) ;
2015-04-10 21:42:42 +00:00
const DataArray * dataArray =
2016-06-21 20:17:11 +00:00
properties . Get ( LayerManagerDataProperty ( ) ) ;
2015-02-04 21:50:56 +00:00
if ( ! dataArray ) {
return nullptr ;
}
// Find our display item data, if it exists, and return its geometry.
uint32_t itemPerFrameKey = aItem - > GetPerFrameKey ( ) ;
for ( uint32_t i = 0 ; i < dataArray - > Length ( ) ; i + + ) {
2015-04-21 18:13:54 +00:00
DisplayItemData * data = AssertDisplayItemData ( dataArray - > ElementAt ( i ) ) ;
2015-02-04 21:50:56 +00:00
if ( data - > GetDisplayItemKey ( ) = = itemPerFrameKey ) {
return data - > GetGeometry ( ) ;
}
}
return nullptr ;
}
2013-12-29 23:35:53 +00:00
gfx : : Rect
2013-03-04 09:55:59 +00:00
CalculateBounds ( const nsTArray < DisplayItemClip : : RoundedRect > & aRects , int32_t A2D )
2012-02-07 22:27:44 +00:00
{
2012-06-26 02:43:30 +00:00
nsRect bounds = aRects [ 0 ] . mRect ;
2012-08-22 15:56:38 +00:00
for ( uint32_t i = 1 ; i < aRects . Length ( ) ; + + i ) {
2012-06-26 02:43:30 +00:00
bounds . UnionRect ( bounds , aRects [ i ] . mRect ) ;
}
2013-12-29 23:35:53 +00:00
return gfx : : ToRect ( nsLayoutUtils : : RectToGfxRect ( bounds , A2D ) ) ;
2012-02-07 22:27:44 +00:00
}
2012-09-04 01:02:56 +00:00
static void
2014-09-26 17:07:06 +00:00
SetClipCount ( PaintedDisplayItemLayerUserData * apaintedData ,
2012-09-04 01:02:56 +00:00
uint32_t aClipCount )
{
2014-09-26 17:07:06 +00:00
if ( apaintedData ) {
apaintedData - > mMaskClipCount = aClipCount ;
2012-09-04 01:02:56 +00:00
}
}
2012-02-07 22:27:44 +00:00
void
2014-06-23 04:24:00 +00:00
ContainerState : : SetupMaskLayer ( Layer * aLayer ,
const DisplayItemClip & aClip ,
2012-08-22 15:56:38 +00:00
uint32_t aRoundedRectClipCount )
2012-02-07 22:27:44 +00:00
{
2012-09-04 01:02:56 +00: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 17:07:06 +00:00
PaintedDisplayItemLayerUserData * paintedData = GetPaintedDisplayItemLayerUserData ( aLayer ) ;
if ( paintedData & &
aRoundedRectClipCount < paintedData - > mMaskClipCount ) {
PaintedLayer * painted = aLayer - > AsPaintedLayer ( ) ;
painted - > InvalidateRegion ( painted - > GetValidRegion ( ) . GetBounds ( ) ) ;
2012-09-04 01:02:56 +00:00
}
2012-02-07 22:27:44 +00:00
// don't build an unnecessary mask
2013-03-04 09:56:00 +00:00
if ( aClip . GetRoundedRectCount ( ) = = 0 | |
2016-07-25 02:41:25 +00:00
aRoundedRectClipCount = = 0 ) {
2014-09-26 17:07:06 +00:00
SetClipCount ( paintedData , 0 ) ;
2012-02-07 22:27:44 +00:00
return ;
}
2015-10-18 05:24:48 +00:00
RefPtr < Layer > maskLayer =
2016-01-06 00:08:17 +00:00
CreateMaskLayer ( aLayer , aClip , Nothing ( ) , aRoundedRectClipCount ) ;
2015-06-20 23:47:57 +00:00
if ( ! maskLayer ) {
SetClipCount ( paintedData , 0 ) ;
return ;
}
aLayer - > SetMaskLayer ( maskLayer ) ;
SetClipCount ( paintedData , aRoundedRectClipCount ) ;
}
already_AddRefed < Layer >
ContainerState : : CreateMaskLayer ( Layer * aLayer ,
const DisplayItemClip & aClip ,
const Maybe < size_t > & aForAncestorMaskLayer ,
uint32_t aRoundedRectClipCount )
{
2012-02-07 22:27:44 +00:00
// check if we can re-use the mask layer
2015-06-21 16:28:10 +00:00
MaskLayerKey recycleKey ( aLayer , aForAncestorMaskLayer ) ;
2015-10-18 05:24:48 +00:00
RefPtr < ImageLayer > maskLayer = CreateOrRecycleMaskImageLayerFor ( recycleKey ) ;
2012-02-07 22:27:44 +00:00
MaskLayerUserData * userData = GetMaskLayerUserData ( maskLayer ) ;
2012-06-26 02:43:30 +00:00
MaskLayerUserData newData ;
2013-03-04 09:56:00 +00:00
aClip . AppendRoundedRects ( & newData . mRoundedClipRects , aRoundedRectClipCount ) ;
2012-06-26 02:43:30 +00:00
newData . mScaleX = mParameters . mXScale ;
newData . mScaleY = mParameters . mYScale ;
2013-04-04 02:59:24 +00:00
newData . mOffset = mParameters . mOffset ;
2013-08-09 09:42:05 +00:00
newData . mAppUnitsPerDevPixel = mContainerFrame - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2012-06-25 21:44:41 +00:00
2012-06-26 02:43:30 +00:00
if ( * userData = = newData ) {
2015-06-20 23:47:57 +00:00
return maskLayer . forget ( ) ;
2012-06-25 22:54:05 +00:00
}
2012-07-31 17:28:21 +00:00
2012-06-26 02:43:30 +00:00
// calculate a more precise bounding rect
2013-12-29 23:35:53 +00:00
gfx : : Rect boundingRect = CalculateBounds ( newData . mRoundedClipRects ,
newData . mAppUnitsPerDevPixel ) ;
2012-06-26 02:43:30 +00:00
boundingRect . Scale ( mParameters . mXScale , mParameters . mYScale ) ;
2012-08-22 15:56:38 +00:00
uint32_t maxSize = mManager - > GetMaxTextureSize ( ) ;
2012-05-16 22:30:10 +00:00
NS_ASSERTION ( maxSize > 0 , " Invalid max texture size " ) ;
2016-08-18 09:19:55 +00:00
# ifdef MOZ_GFX_OPTIMIZE_MOBILE
// Make mask image width aligned to 4. See Bug 1245552.
2016-08-25 17:57:39 +00:00
gfx : : Size surfaceSize ( std : : min < gfx : : Float > ( GetAlignedStride < 4 > ( NSToIntCeil ( boundingRect . Width ( ) ) , 1 ) , maxSize ) ,
2016-08-18 09:19:55 +00:00
std : : min < gfx : : Float > ( boundingRect . Height ( ) , maxSize ) ) ;
# else
2016-08-15 15:54:43 +00:00
gfx : : Size surfaceSize ( std : : min < gfx : : Float > ( boundingRect . Width ( ) , maxSize ) ,
2013-12-29 23:35:53 +00:00
std : : min < gfx : : Float > ( boundingRect . Height ( ) , maxSize ) ) ;
2016-08-18 09:19:55 +00:00
# endif
2012-05-16 22:30:10 +00:00
2012-06-26 02:43:30 +00: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 13:26:12 +00:00
gfx : : Matrix maskTransform =
Matrix : : Scaling ( surfaceSize . width / boundingRect . Width ( ) ,
surfaceSize . height / boundingRect . Height ( ) ) ;
2013-12-29 23:35:53 +00:00
gfx : : Point p = boundingRect . TopLeft ( ) ;
2014-09-10 17:29:35 +00:00
maskTransform . PreTranslate ( - p . x , - p . y ) ;
2012-06-26 02:43:30 +00:00
// imageTransform is only used when the clip is painted to the mask
2013-12-29 23:35:53 +00:00
gfx : : Matrix imageTransform = maskTransform ;
2014-09-10 17:29:35 +00:00
imageTransform . PreScale ( mParameters . mXScale , mParameters . mYScale ) ;
2012-06-26 02:43:30 +00:00
2012-09-04 01:02:56 +00:00
nsAutoPtr < MaskLayerImageCache : : MaskLayerImageKey > newKey (
2012-12-11 21:57:52 +00:00
new MaskLayerImageCache : : MaskLayerImageKey ( ) ) ;
2012-09-04 01:02:56 +00:00
2012-06-26 02:43:30 +00:00
// copy and transform the rounded rects
2012-08-22 15:56:38 +00:00
for ( uint32_t i = 0 ; i < newData . mRoundedClipRects . Length ( ) ; + + i ) {
2012-09-04 01:02:56 +00:00
newKey - > mRoundedClipRects . AppendElement (
2012-06-26 02:43:30 +00:00
MaskLayerImageCache : : PixelRoundedRect ( newData . mRoundedClipRects [ i ] ,
mContainerFrame - > PresContext ( ) ) ) ;
2012-09-04 01:02:56 +00:00
newKey - > mRoundedClipRects [ i ] . ScaleAndTranslate ( imageTransform ) ;
2012-02-07 22:27:44 +00:00
}
2016-05-10 10:18:11 +00:00
newKey - > mForwarder = mManager - > AsShadowForwarder ( ) ;
2013-12-29 23:35:53 +00:00
2012-09-04 01:02:56 +00:00
const MaskLayerImageCache : : MaskLayerImageKey * lookupKey = newKey ;
2012-09-03 10:47:51 +00:00
2012-09-04 01:02:56 +00:00
// check to see if we can reuse a mask image
2015-10-18 05:24:48 +00:00
RefPtr < ImageContainer > container =
2012-06-26 02:43:30 +00:00
GetMaskLayerImageCache ( ) - > FindImageFor ( & lookupKey ) ;
2012-09-04 01:02:56 +00:00
if ( ! container ) {
2016-08-18 09:19:55 +00:00
IntSize surfaceSizeInt ( NSToIntCeil ( surfaceSize . width ) ,
2013-12-31 09:06:12 +00:00
NSToIntCeil ( surfaceSize . height ) ) ;
2012-06-26 02:43:30 +00:00
// no existing mask image, so build a new one
2016-05-10 10:18:11 +00:00
MaskImageData imageData ( surfaceSizeInt , mManager ) ;
RefPtr < DrawTarget > dt = imageData . CreateDrawTarget ( ) ;
2012-06-26 02:43:30 +00:00
// fail if we can't get the right surface
2016-04-12 19:18:11 +00:00
if ( ! dt | | ! dt - > IsValid ( ) ) {
2014-04-10 08:49:49 +00:00
NS_WARNING ( " Could not create DrawTarget for mask layer. " ) ;
2015-06-20 23:47:57 +00:00
return nullptr ;
2012-06-26 02:43:30 +00:00
}
2012-02-07 22:27:44 +00:00
2016-06-06 23:39:56 +00:00
RefPtr < gfxContext > context = gfxContext : : CreateOrNull ( dt ) ;
2016-04-12 19:18:11 +00:00
MOZ_ASSERT ( context ) ; // already checked the draw target above
2013-12-29 23:35:53 +00:00
context - > Multiply ( ThebesMatrix ( imageTransform ) ) ;
2012-02-07 22:27:44 +00:00
2012-06-26 02:43:30 +00:00
// paint the clipping rects with alpha to create the mask
2014-11-24 00:04:33 +00:00
aClip . FillIntersectionOfRoundedRectClips ( context ,
Color ( 1.f , 1.f , 1.f , 1.f ) ,
newData . mAppUnitsPerDevPixel ,
0 ,
aRoundedRectClipCount ) ;
2012-02-07 22:27:44 +00:00
2012-06-26 02:43:30 +00:00
// build the image and container
container = aLayer - > Manager ( ) - > CreateImageContainer ( ) ;
NS_ASSERTION ( container , " Could not create image container for mask layer. " ) ;
2014-04-10 08:49:49 +00:00
2016-05-10 10:18:11 +00:00
RefPtr < Image > image = imageData . CreateImage ( ) ;
if ( ! image ) {
return nullptr ;
}
2012-07-26 18:11:22 +00:00
container - > SetCurrentImageInTransaction ( image ) ;
2012-06-25 22:54:05 +00:00
2012-09-04 01:02:56 +00:00
GetMaskLayerImageCache ( ) - > PutImage ( newKey . forget ( ) , container ) ;
2012-06-26 02:43:30 +00:00
}
2012-06-25 21:44:41 +00:00
2012-06-25 22:54:05 +00:00
maskLayer - > SetContainer ( container ) ;
2013-12-29 23:35:53 +00:00
maskTransform . Invert ( ) ;
2014-01-27 15:28:33 +00:00
Matrix4x4 matrix = Matrix4x4 : : From2D ( maskTransform ) ;
2014-10-16 09:51:12 +00:00
matrix . PreTranslate ( mParameters . mOffset . x , mParameters . mOffset . y , 0 ) ;
2012-09-16 22:25:33 +00:00
maskLayer - > SetBaseTransform ( matrix ) ;
2012-06-26 02:43:30 +00:00
2012-02-07 22:27:44 +00:00
// save the details of the clip in user data
2012-06-26 02:43:30 +00:00
userData - > mScaleX = newData . mScaleX ;
userData - > mScaleY = newData . mScaleY ;
2014-03-10 22:12:48 +00:00
userData - > mOffset = newData . mOffset ;
userData - > mAppUnitsPerDevPixel = newData . mAppUnitsPerDevPixel ;
2012-06-26 02:43:30 +00:00
userData - > mRoundedClipRects . SwapElements ( newData . mRoundedClipRects ) ;
2015-07-13 04:09:57 +00:00
userData - > mImageKey . Reset ( lookupKey ) ;
2012-02-07 22:27:44 +00:00
2015-06-20 23:47:57 +00:00
return maskLayer . forget ( ) ;
2012-02-07 22:27:44 +00:00
}
2010-05-21 03:20:48 +00:00
} // namespace mozilla