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"
2014-06-27 11:19:40 +00:00
# include "mozilla/gfx/Matrix.h"
2010-05-21 03:20:48 +00:00
# include "nsDisplayList.h"
# include "nsPresContext.h"
# include "nsLayoutUtils.h"
2010-07-15 21:07:51 +00:00
# include "Layers.h"
2010-07-15 21:08:05 +00:00
# include "BasicLayers.h"
2010-11-24 09:35:21 +00:00
# include "gfxUtils.h"
2011-04-08 01:04:40 +00:00
# include "nsRenderingContext.h"
2012-06-26 02:43:30 +00:00
# include "MaskLayerImageCache.h"
2012-08-16 23:40:10 +00:00
# include "nsIScrollableFrame.h"
2012-08-29 05:47:15 +00:00
# include "nsPrintfCString.h"
2012-08-29 05:47:18 +00:00
# include "LayerTreeInvalidation.h"
# include "nsSVGIntegrationUtils.h"
2013-10-02 00:57:50 +00:00
# include "ImageContainer.h"
2013-09-04 11:30:57 +00:00
# include "ActiveLayerTracker.h"
2013-12-29 23:35:53 +00:00
# include "gfx2DGlue.h"
2014-06-09 04:48:00 +00:00
# include "mozilla/LookAndFeel.h"
2010-07-15 21:07:51 +00:00
2013-03-18 14:25:50 +00:00
# include "GeckoProfiler.h"
2012-10-02 04:00:09 +00:00
# include "mozilla/gfx/Tools.h"
2013-11-06 19:10:50 +00:00
# include "mozilla/gfx/2D.h"
2014-05-08 02:56:48 +00:00
# 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 {
2014-03-20 06:49:27 +00:00
FrameLayerBuilder : : DisplayItemData : : DisplayItemData ( LayerManagerData * aParent , uint32_t aKey ,
2012-10-11 23:38:24 +00:00
Layer * aLayer , LayerState aLayerState , uint32_t aGeneration )
: mParent ( aParent )
, mLayer ( aLayer )
2012-08-21 04:06:46 +00:00
, mDisplayItemKey ( aKey )
, mContainerLayerGeneration ( aGeneration )
, mLayerState ( aLayerState )
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
{
}
2012-08-21 04:06:46 +00:00
2012-08-29 05:47:15 +00:00
FrameLayerBuilder : : DisplayItemData : : DisplayItemData ( DisplayItemData & toCopy )
{
// This isn't actually a copy-constructor; notice that it steals toCopy's
// mGeometry pointer. Be careful.
2012-10-11 23:38:24 +00:00
mParent = toCopy . mParent ;
2012-08-29 05:47:15 +00:00
mLayer = toCopy . mLayer ;
mInactiveManager = toCopy . mInactiveManager ;
mFrameList = toCopy . mFrameList ;
mGeometry = toCopy . mGeometry ;
mDisplayItemKey = toCopy . mDisplayItemKey ;
2012-10-11 23:38:24 +00:00
mClip = toCopy . mClip ;
2012-08-29 05:47:15 +00:00
mContainerLayerGeneration = toCopy . mContainerLayerGeneration ;
mLayerState = toCopy . mLayerState ;
mUsed = toCopy . mUsed ;
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
{
2012-10-12 02:39:46 +00:00
mFrameList . AppendElement ( aFrame ) ;
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-12 02:39:46 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( FrameLayerBuilder : : LayerManagerDataProperty ( ) ) ) ;
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 )
{
DebugOnly < bool > result = mFrameList . RemoveElement ( aFrame ) ;
NS_ASSERTION ( result , " Can't remove a frame that wasn't added! " ) ;
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-16 01:23:07 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( FrameLayerBuilder : : LayerManagerDataProperty ( ) ) ) ;
NS_ASSERTION ( array , " Must be already stored on the frame! " ) ;
array - > RemoveElement ( this ) ;
}
void
2014-03-20 06:49:27 +00:00
FrameLayerBuilder : : DisplayItemData : : UpdateContents ( Layer * aLayer , LayerState aState ,
2012-10-16 01:23:07 +00:00
uint32_t aContainerLayerGeneration ,
nsDisplayItem * aItem /* = nullptr */ )
2012-10-11 23:38:24 +00:00
{
2012-10-12 02:39:46 +00:00
mLayer = aLayer ;
mOptLayer = nullptr ;
mInactiveManager = nullptr ;
mLayerState = aState ;
mContainerLayerGeneration = aContainerLayerGeneration ;
mGeometry = nullptr ;
2013-03-04 09:56:00 +00:00
mClip = DisplayItemClip ( ) ;
2012-10-12 02:39:46 +00:00
mUsed = true ;
2012-10-16 01:23:07 +00:00
if ( ! aItem ) {
return ;
}
2012-12-19 01:16:06 +00:00
nsAutoTArray < nsIFrame * , 4 > copy ( mFrameList ) ;
2013-04-19 12:02:13 +00:00
if ( ! copy . RemoveElement ( aItem - > Frame ( ) ) ) {
AddFrame ( aItem - > Frame ( ) ) ;
2012-10-16 01:23:07 +00:00
}
nsAutoTArray < nsIFrame * , 4 > mergedFrames ;
aItem - > GetMergedFrames ( & mergedFrames ) ;
for ( uint32_t i = 0 ; i < mergedFrames . Length ( ) ; + + i ) {
if ( ! copy . RemoveElement ( mergedFrames [ i ] ) ) {
AddFrame ( mergedFrames [ i ] ) ;
}
}
for ( uint32_t i = 0 ; i < copy . Length ( ) ; i + + ) {
2014-03-20 06:49:27 +00:00
RemoveFrame ( copy [ i ] ) ;
2012-10-16 01:23:07 +00:00
}
2012-10-11 23:38:24 +00:00
}
2013-10-08 18:47:21 +00:00
static nsIFrame * sDestroyedFrame = nullptr ;
2012-08-21 04:06:46 +00:00
FrameLayerBuilder : : DisplayItemData : : ~ DisplayItemData ( )
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
}
}
2012-08-21 04:06:46 +00:00
2012-10-16 01:23:07 +00:00
void
2014-03-20 06:49:27 +00:00
FrameLayerBuilder : : DisplayItemData : : GetFrameListChanges ( nsDisplayItem * aOther ,
2012-10-16 01:23:07 +00:00
nsTArray < nsIFrame * > & aOut )
2012-08-29 05:47:15 +00:00
{
2012-10-16 01:23:07 +00:00
aOut = mFrameList ;
nsAutoTArray < nsIFrame * , 4 > added ;
2013-04-19 12:02:13 +00:00
if ( ! aOut . RemoveElement ( aOther - > Frame ( ) ) ) {
added . AppendElement ( aOther - > Frame ( ) ) ;
2012-08-29 05:47:15 +00:00
}
2012-10-11 23:38:24 +00:00
2012-08-29 05:47:15 +00:00
nsAutoTArray < nsIFrame * , 4 > mergedFrames ;
aOther - > GetMergedFrames ( & mergedFrames ) ;
for ( uint32_t i = 0 ; i < mergedFrames . Length ( ) ; + + i ) {
2012-10-16 01:23:07 +00:00
if ( ! aOut . RemoveElement ( mergedFrames [ i ] ) ) {
added . AppendElement ( mergedFrames [ i ] ) ;
2012-08-29 05:47:15 +00:00
}
}
2014-03-20 06:49:27 +00:00
aOut . AppendElements ( added ) ;
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 :
2012-10-11 23:38:24 +00:00
LayerManagerData ( LayerManager * aManager )
: 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 ) ;
2012-10-11 23:38:25 +00:00
nsAutoCString prefix ;
prefix + = aPrefix ;
prefix + = " " ;
mDisplayItems . EnumerateEntries (
FrameLayerBuilder : : DumpDisplayItemDataForFrame , ( void * ) prefix . get ( ) ) ;
}
# 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 ( ) ) ;
}
2012-06-26 02:43:30 +00:00
// a global cache of image containers used for mask layers
2012-07-30 14:20:58 +00:00
static MaskLayerImageCache * gMaskLayerImageCache = nullptr ;
2012-06-26 02:43:30 +00:00
static inline MaskLayerImageCache * GetMaskLayerImageCache ( )
{
if ( ! gMaskLayerImageCache ) {
gMaskLayerImageCache = new MaskLayerImageCache ( ) ;
}
return gMaskLayerImageCache ;
}
2013-12-16 12:11:01 +00:00
/**
* We keep a stack of these to represent the ThebesLayers that are
* currently available to have display items added to .
* We use a stack here because as much as possible we want to
* assign display items to existing ThebesLayers , and to the lowest
* ThebesLayer in z - order . This reduces the number of layers and
* makes it more likely a display item will be rendered to an opaque
* layer , giving us the best chance of getting subpixel AA .
*/
class ThebesLayerData {
public :
ThebesLayerData ( ) :
2014-02-26 04:17:18 +00:00
mAnimatedGeometryRoot ( nullptr ) ,
mFixedPosFrameForLayerData ( nullptr ) ,
mReferenceFrame ( nullptr ) ,
2013-12-16 12:11:01 +00:00
mLayer ( nullptr ) ,
mIsSolidColorInVisibleRegion ( false ) ,
2014-02-21 01:11:17 +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 ) ,
2013-12-16 12:11:01 +00:00
mImage ( nullptr ) ,
mCommonClipCount ( - 1 ) ,
2014-06-23 04:24:00 +00:00
mNewChildLayersIndex ( - 1 ) ,
2014-02-21 01:11:17 +00:00
mAllDrawingAbove ( false )
{ }
2013-12-16 12:11:01 +00:00
/**
* Record that an item has been added to the ThebesLayer , so we
* need to update our regions .
* @ param aVisibleRect the area of the item that ' s visible
* @ param aDrawRect the area of the item that would be drawn if it
* was completely visible
* @ param aOpaqueRect if non - null , the area of the item that ' s opaque .
* We pass in a separate opaque rect because the opaque rect can be
* bigger than the visible rect , and we want to have the biggest
* opaque rect that we can .
* @ 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 ,
const nsIntRect & aDrawRect ,
const DisplayItemClip & aClip ) ;
const nsIFrame * GetAnimatedGeometryRoot ( ) { return mAnimatedGeometryRoot ; }
2013-12-16 12:16:24 +00:00
/**
2014-06-20 03:56:36 +00:00
* Add aHitRegion , aMaybeHitRegion , and aDispatchToContentHitRegion to the
* hit regions for this ThebesLayer .
2013-12-16 12:16:24 +00:00
*/
2014-06-20 03:56:36 +00:00
void AccumulateEventRegions ( const nsRegion & aHitRegion ,
const nsRegion & aMaybeHitRegion ,
const nsRegion & aDispatchToContentHitRegion )
2013-12-16 12:16:24 +00:00
{
mHitRegion . Or ( mHitRegion , aHitRegion ) ;
mMaybeHitRegion . Or ( mMaybeHitRegion , aMaybeHitRegion ) ;
mDispatchToContentHitRegion . Or ( mDispatchToContentHitRegion , aDispatchToContentHitRegion ) ;
}
2013-12-16 12:11:01 +00:00
/**
* If this represents only a nsDisplayImage , and the image type
* supports being optimized to an ImageLayer ( TYPE_RASTER only ) returns
* an ImageContainer for the image .
*/
already_AddRefed < ImageContainer > CanOptimizeImageLayer ( nsDisplayListBuilder * aBuilder ) ;
void AddDrawAboveRegion ( const nsIntRegion & aAbove )
{
if ( ! mAllDrawingAbove ) {
mDrawAboveRegion . Or ( mDrawAboveRegion , aAbove ) ;
2014-07-17 03:41:06 +00:00
mDrawAboveRegion . SimplifyOutward ( 8 ) ;
2013-12-16 12:11:01 +00:00
}
}
void AddVisibleAboveRegion ( const nsIntRegion & aAbove )
{
if ( ! mAllDrawingAbove ) {
mVisibleAboveRegion . Or ( mVisibleAboveRegion , aAbove ) ;
2014-07-17 03:41:06 +00:00
mVisibleAboveRegion . SimplifyOutward ( 8 ) ;
2013-12-16 12:11:01 +00:00
}
}
void CopyAboveRegion ( ThebesLayerData * aOther )
{
if ( aOther - > mAllDrawingAbove | | mAllDrawingAbove ) {
SetAllDrawingAbove ( ) ;
} else {
mVisibleAboveRegion . Or ( mVisibleAboveRegion , aOther - > mVisibleAboveRegion ) ;
mVisibleAboveRegion . Or ( mVisibleAboveRegion , aOther - > mVisibleRegion ) ;
2014-07-17 03:41:06 +00:00
mVisibleAboveRegion . SimplifyOutward ( 8 ) ;
2013-12-16 12:11:01 +00:00
mDrawAboveRegion . Or ( mDrawAboveRegion , aOther - > mDrawAboveRegion ) ;
mDrawAboveRegion . Or ( mDrawAboveRegion , aOther - > mDrawRegion ) ;
2014-07-17 03:41:06 +00:00
mDrawAboveRegion . SimplifyOutward ( 8 ) ;
}
2013-12-16 12:11:01 +00:00
}
void SetAllDrawingAbove ( )
{
mAllDrawingAbove = true ;
mDrawAboveRegion . SetEmpty ( ) ;
mVisibleAboveRegion . SetEmpty ( ) ;
}
2014-02-26 04:17:18 +00:00
bool DrawAboveRegionIntersects ( const nsIntRect & aRect )
2013-12-16 12:11:01 +00:00
{
return mAllDrawingAbove | | mDrawAboveRegion . Intersects ( aRect ) ;
}
2014-02-26 04:17:18 +00:00
bool DrawRegionIntersects ( const nsIntRect & aRect )
{
return IsSubjectToAsyncTransforms ( ) | | mDrawRegion . Intersects ( aRect ) ;
}
2013-12-16 12:11:01 +00:00
bool IntersectsVisibleAboveRegion ( const nsIntRegion & aVisibleRegion )
{
if ( mAllDrawingAbove ) {
return true ;
}
nsIntRegion visibleAboveIntersection ;
visibleAboveIntersection . And ( mVisibleAboveRegion , aVisibleRegion ) ;
if ( visibleAboveIntersection . IsEmpty ( ) ) {
return false ;
}
return true ;
}
2014-02-26 04:17:18 +00:00
bool IsSubjectToAsyncTransforms ( )
{
return mFixedPosFrameForLayerData ! = nullptr ;
}
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 ) .
*/
nsIntRegion mVisibleRegion ;
/**
* The region containing the bounds of all display items in the layer ,
* regardless of visbility .
* Same coordinate system as mVisibleRegion .
* This is a conservative approximation : it contains the true region .
*/
nsIntRegion mDrawRegion ;
/**
* 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
/**
* The definitely - hit region for this ThebesLayer .
*/
2014-06-20 03:56:36 +00:00
nsRegion mHitRegion ;
2013-12-16 12:16:24 +00:00
/**
* The maybe - hit region for this ThebesLayer .
*/
2014-06-20 03:56:36 +00:00
nsRegion mMaybeHitRegion ;
2013-12-16 12:16:24 +00:00
/**
* The dispatch - to - content hit region for this ThebesLayer .
*/
2014-06-20 03:56:36 +00:00
nsRegion mDispatchToContentHitRegion ;
2013-12-16 12:11:01 +00:00
/**
* The " active scrolled root " for all content in the layer . Must
* be non - null ; all content in a ThebesLayer must have the same
* active scrolled root .
*/
const nsIFrame * mAnimatedGeometryRoot ;
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 .
*/
const nsIFrame * mFixedPosFrameForLayerData ;
2013-12-16 12:11:01 +00:00
const nsIFrame * mReferenceFrame ;
ThebesLayer * mLayer ;
/**
* 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-02-21 01:11:17 +00:00
/**
* True if the layer contains exactly one item that returned true for
* ShouldFixToViewport .
*/
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
/**
* Set if all layers below this ThebesLayer should be hidden .
*/
bool mHideAllLayersBelow ;
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
* by ThebesDisplayItemLayerUserData : : GetCommonClipCount ( ) - which may even be
* 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 ) ;
private :
/**
* The region of visible content above the layer and below the
* next ThebesLayerData currently in the stack , if any . Note that not
* all ThebesLayers for the container are in the ThebesLayerData stack .
* Same coordinate system as mVisibleRegion .
* This is a conservative approximation : it contains the true region .
*/
nsIntRegion mVisibleAboveRegion ;
/**
* The region containing the bounds of all display items ( regardless
* of visibility ) in the layer and below the next ThebesLayerData
* currently in the stack , if any .
* Note that not all ThebesLayers for the container are in the
* ThebesLayerData stack .
* Same coordinate system as mVisibleRegion .
*/
nsIntRegion mDrawAboveRegion ;
/**
* True if mDrawAboveRegion and mVisibleAboveRegion should be treated
* as infinite , and all display items should be considered ' above ' this layer .
*/
bool mAllDrawingAbove ;
} ;
2014-06-23 04:24:00 +00:00
struct NewLayerEntry {
NewLayerEntry ( )
: mAnimatedGeometryRoot ( nullptr )
, mFixedPosFrameForLayerData ( nullptr )
, mLayerContentsVisibleRect ( 0 , 0 , - 1 , - 1 )
, mHideAllLayersBelow ( false )
, mOpaqueForAnimatedGeometryRootParent ( false )
{ }
// mLayer is null if the previous entry is for a ThebesLayer that hasn't
// been optimized to some other form (yet).
nsRefPtr < Layer > mLayer ;
const nsIFrame * mAnimatedGeometryRoot ;
const nsIFrame * mFixedPosFrameForLayerData ;
// 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 ;
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 ;
} ;
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 ,
2013-09-27 06:01:16 +00:00
const ContainerLayerParameters & aParameters ) :
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 ) ,
2011-06-22 12:11:27 +00:00
mParameters ( aParameters ) ,
2012-08-29 05:47:15 +00:00
mNextFreeRecycledThebesLayer ( 0 )
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 ) ) ;
2014-04-24 08:18:11 +00:00
mContainerAnimatedGeometryRoot = aContainerItem
? nsLayoutUtils : : GetAnimatedGeometryRootFor ( aContainerItem , aBuilder )
: mContainerReferenceFrame ;
2014-06-23 04:24:00 +00:00
NS_ASSERTION ( ! aContainerItem | | ! aContainerItem - > ShouldFixToViewport ( aBuilder ) ,
" Container items never return true for ShouldFixToViewport " ) ;
mContainerFixedPosFrame =
FindFixedPosFrameForLayerData ( mContainerAnimatedGeometryRoot , false ) ;
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
2012-07-23 03:00:36 +00:00
enum ProcessDisplayItemsFlags {
NO_COMPONENT_ALPHA = 0x01 ,
} ;
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-06-09 04:48:00 +00:00
void ProcessDisplayItems ( nsDisplayList * aList , uint32_t aFlags ) ;
2010-07-15 21:07:51 +00:00
/**
* This finalizes all the open ThebesLayers by popping every element off
* mThebesLayerDataStack , then sets the children of the container layer
* 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
*/
2014-06-23 04:24:00 +00:00
void Finish ( uint32_t * aTextContentFlags , LayerManagerData * aData ,
const nsIntRect & aContainerPixelBounds ,
nsDisplayList * aChildItems , bool & aHasComponentAlphaChildren ) ;
2014-07-17 15:24:47 +00:00
2012-04-10 11:24:18 +00:00
nscoord GetAppUnitsPerDevPixel ( ) { return mAppUnitsPerDevPixel ; }
nsIntRect ScaleToNearestPixels ( const nsRect & aRect )
{
return aRect . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2012-07-23 03:00:36 +00:00
nsIntRegion ScaleRegionToNearestPixels ( const nsRegion & aRegion )
{
return aRegion . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2013-12-16 12:11:59 +00:00
nsIntRect ScaleToOutsidePixels ( const nsRect & aRect , bool aSnap = false )
2012-04-10 11:24:18 +00:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2013-12-16 12:11:59 +00:00
nsIntRect ScaleToInsidePixels ( const nsRect & aRect , bool aSnap = false )
2012-04-10 11:24:18 +00:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToInsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2013-12-16 12:11:59 +00:00
nsIntRegion ScaleRegionToInsidePixels ( const nsRegion & aRegion , bool aSnap = false )
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 ) ;
}
nsIntRegion ScaleRegionToOutsidePixels ( const nsRegion & aRegion , bool aSnap = false )
{
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 ; }
/**
* Sets aOuterVisibleRegion as aLayer ' s visible region . aOuterVisibleRegion
* is in the coordinate space of the container reference frame .
* aLayerContentsVisibleRect , if non - null , is in the layer ' s own
* coordinate system .
*/
void SetOuterVisibleRegionForLayer ( Layer * aLayer ,
const nsIntRegion & aOuterVisibleRegion ,
const nsIntRect * aLayerContentsVisibleRect = nullptr ) const ;
2010-07-15 21:07:51 +00:00
protected :
2011-06-22 12:11:27 +00:00
friend class ThebesLayerData ;
2010-05-21 03:20:48 +00:00
2010-07-15 21:07:51 +00:00
/**
* Grab the next recyclable ThebesLayer , or create one if there are no
* more recyclable ThebesLayers . Does any necessary invalidation of
* a recycled ThebesLayer , and sets up the transform on the ThebesLayer
2010-07-15 21:08:03 +00:00
* to account for scrolling .
2010-07-15 21:07:51 +00:00
*/
2014-03-20 06:49:27 +00:00
already_AddRefed < ThebesLayer > CreateOrRecycleThebesLayer ( const nsIFrame * aAnimatedGeometryRoot ,
const nsIFrame * aReferenceFrame ,
2012-09-28 11:19:39 +00:00
const nsPoint & aTopLeft ) ;
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 .
*/
2012-08-20 10:00:49 +00:00
already_AddRefed < ColorLayer > CreateOrRecycleColorLayer ( ThebesLayer * aThebes ) ;
2011-01-17 21:47:18 +00:00
/**
* Grab the next recyclable ImageLayer , or create one if there are no
* more recyclable ImageLayers .
*/
2012-08-20 10:00:49 +00:00
already_AddRefed < ImageLayer > CreateOrRecycleImageLayer ( ThebesLayer * aThebes ) ;
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 .
*/
already_AddRefed < ImageLayer > CreateOrRecycleMaskImageLayerFor ( Layer * aLayer ) ;
2010-07-15 21:08:03 +00:00
/**
* Grabs all ThebesLayers 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
/**
* If aItem used to belong to a ThebesLayer , invalidates the area of
* aItem in that layer . If aNewLayer is a ThebesLayer , invalidates the area of
* aItem in that layer .
*/
2014-03-20 06:49:27 +00:00
void InvalidateForLayerChange ( nsDisplayItem * aItem ,
2012-08-29 05:48:43 +00:00
Layer * aNewLayer ,
2013-03-04 09:55:59 +00:00
const DisplayItemClip & aClip ,
2012-10-11 23:38:24 +00:00
const nsPoint & aTopLeft ,
nsDisplayItemGeometry * aGeometry ) ;
2010-09-02 09:18:39 +00:00
/**
* Try to determine whether the ThebesLayer at aThebesLayerIndex
2011-01-04 10:35:57 +00:00
* has a single opaque color behind it , over the entire bounds of its visible
* region .
2010-09-02 09:18:39 +00:00
* If successful , return that color , otherwise return NS_RGBA ( 0 , 0 , 0 , 0 ) .
*/
2012-08-22 15:56:38 +00:00
nscolor FindOpaqueBackgroundColorFor ( int32_t aThebesLayerIndex ) ;
2013-09-27 06:01:16 +00:00
/**
* Find the fixed - pos frame , if any , containing ( or equal to )
* aAnimatedGeometryRoot . Only return a fixed - pos frame if its viewport
* has a displayport . Updates * aVisibleRegion to be the intersection of
* aDrawRegion and the displayport , and updates * aIsSolidColorInVisibleRegion
* ( if non - null ) to false if the visible region grows .
2014-02-21 01:11:17 +00:00
* aDisplayItemFixedToViewport is true if the layer contains a single display
* item which returned true for ShouldFixToViewport .
2013-12-17 11:30:21 +00:00
* This can return the actual viewport frame for layers whose display items
* are directly on the viewport ( e . g . background - attachment : fixed backgrounds ) .
2013-09-27 06:01:16 +00:00
*/
const nsIFrame * FindFixedPosFrameForLayerData ( const nsIFrame * aAnimatedGeometryRoot ,
2014-02-26 04:17:18 +00:00
bool aDisplayItemFixedToViewport ) ;
void AdjustLayerDataForFixedPositioning ( const nsIFrame * aFixedPosFrame ,
const nsIntRegion & aDrawRegion ,
nsIntRegion * aVisibleRegion ,
bool * aIsSolidColorInVisibleRegion = nullptr ) ;
2013-09-27 06:01:16 +00:00
/**
* Set fixed - pos layer metadata on aLayer according to the data for aFixedPosFrame .
*/
void SetFixedPositionLayerData ( Layer * aLayer ,
const nsIFrame * aFixedPosFrame ) ;
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 ) ;
/**
* 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 .
*/
void ApplyOcclusionCulling ( nsIntRegion * aOpaqueRegionForContainer ) ;
/**
* 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 ,
const nsIFrame * aAnimatedGeometryRoot ,
const nsIFrame * aFixedPosFrame ,
const DisplayItemClip & aClip ,
nsDisplayList * aList ,
bool * aHideAllLayersBelow ) ;
2010-07-15 21:07:51 +00:00
/**
* Indicate that we are done adding items to the ThebesLayer at the top of
* mThebesLayerDataStack . Set the final visible region and opaque - content
* flag , and pop it off the stack .
*/
void PopThebesLayerData ( ) ;
/**
* Find the ThebesLayer to which we should assign the next display item .
2010-08-02 03:06:58 +00:00
* We scan the ThebesLayerData stack to find the topmost ThebesLayer
* that is compatible with the display item ( i . e . , has the same
* active scrolled root ) , and that has no content from other layers above
* it and intersecting the aVisibleRect .
2010-07-15 21:07:51 +00:00
* Returns the layer , and also updates the ThebesLayerData . Will
2010-08-02 03:06:58 +00:00
* push a new ThebesLayerData onto the stack if no suitable existing
* layer is found . If we choose a ThebesLayer that ' s already on the
* ThebesLayerData stack , later elements on the stack will be popped off .
2010-07-15 21:07:51 +00:00
* @ param aVisibleRect the area of the next display item that ' s visible
2013-09-25 21:07:26 +00:00
* @ param aAnimatedGeometryRoot the active scrolled root for the next
2010-07-15 21:07:51 +00:00
* display item
2010-07-15 21:08:11 +00:00
* @ param aOpaqueRect if non - null , a region of the display item that is opaque
2010-07-15 21:08:03 +00:00
* @ param aSolidColor if non - null , indicates that every pixel in aVisibleRect
* will be painted with aSolidColor by the item
2014-02-21 01:11:17 +00:00
* @ 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
*/
2012-02-07 22:27:44 +00:00
ThebesLayerData * FindThebesLayerFor ( nsDisplayItem * aItem ,
2013-12-16 12:11:01 +00:00
const nsIntRect & aVisibleRect ,
const nsIFrame * aAnimatedGeometryRoot ,
2014-02-21 01:11:17 +00:00
const nsPoint & aTopLeft ,
bool aShouldFixToViewport ) ;
2010-07-15 21:07:51 +00:00
ThebesLayerData * GetTopThebesLayerData ( )
2010-05-21 03:20:48 +00:00
{
2012-07-30 14:20:58 +00:00
return mThebesLayerDataStack . IsEmpty ( ) ? nullptr
2010-07-15 21:07:51 +00:00
: mThebesLayerDataStack [ mThebesLayerDataStack . Length ( ) - 1 ] . get ( ) ;
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
* aLayerVisibleRegion is the region that will be set as aLayer ' s visible region ,
* relative to the container reference frame
2012-02-07 22:27:44 +00:00
* aRoundedRectClipCount is used when building mask layers for ThebesLayers ,
* 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 ,
2014-06-23 04:24:00 +00:00
const nsIntRegion & aLayerVisibleRegion ,
2012-09-28 06:57:33 +00:00
uint32_t aRoundedRectClipCount = UINT32_MAX ) ;
2012-02-07 22:27:44 +00:00
2013-09-25 21:07:26 +00:00
bool ChooseAnimatedGeometryRoot ( const nsDisplayList & aList ,
const nsIFrame * * 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 ;
2014-04-24 08:18:11 +00:00
const nsIFrame * mContainerAnimatedGeometryRoot ;
2014-06-23 04:24:00 +00:00
const nsIFrame * mContainerFixedPosFrame ;
2010-07-15 21:07:51 +00:00
ContainerLayer * mContainerLayer ;
2014-06-09 04:48:00 +00:00
nsRect mContainerBounds ;
DebugOnly < nsRect > mAccumulatedChildBounds ;
2013-09-27 06:01:16 +00:00
ContainerLayerParameters mParameters ;
2010-07-15 21:07:51 +00:00
/**
* The region of ThebesLayers that should be invalidated every time
* we recycle one .
*/
nsIntRegion mInvalidThebesContent ;
nsAutoTArray < nsAutoPtr < ThebesLayerData > , 1 > mThebesLayerDataStack ;
/**
* 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-06-23 04:24:00 +00:00
* ThebesLayers have two entries in this array : the second one is used only if
* the ThebesLayer is optimized away to a ColorLayer or ImageLayer .
* It ' s essential that this array is only appended to , since ThebesLayerData
* records the index of its ThebesLayer in this array .
2010-07-15 21:07:51 +00:00
*/
2014-06-23 04:24:00 +00:00
typedef nsAutoTArray < NewLayerEntry , 1 > AutoLayersArray ;
2010-11-09 02:48:59 +00:00
AutoLayersArray mNewChildLayers ;
2010-07-15 21:07:51 +00:00
nsTArray < nsRefPtr < ThebesLayer > > mRecycledThebesLayers ;
2012-02-07 22:26:40 +00:00
nsDataHashtable < nsPtrHashKey < Layer > , nsRefPtr < ImageLayer > >
mRecycledMaskImageLayers ;
2012-08-22 15:56:38 +00:00
uint32_t mNextFreeRecycledThebesLayer ;
2012-04-10 11:24:18 +00:00
nscoord mAppUnitsPerDevPixel ;
bool mSnappingEnabled ;
2010-05-21 03:20:48 +00:00
} ;
2010-09-02 09:18:39 +00:00
class ThebesDisplayItemLayerUserData : public LayerUserData
{
public :
ThebesDisplayItemLayerUserData ( ) :
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 ) ) ,
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 ) ,
2013-09-25 21:07:26 +00:00
mAnimatedGeometryRootPosition ( 0 , 0 ) { }
2010-09-02 09:18:39 +00:00
2012-09-04 01:02:56 +00:00
/**
* Record the number of clips in the Thebes layer ' s mask layer .
* 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
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
/**
* The offset from the ThebesLayer ' s 0 , 0 to the
* reference frame . This isn ' t necessarily the same as the transform
* set on the ThebesLayer since we might also be applying an extra
* offset specified by the parent ContainerLayer /
*/
nsIntPoint mTranslation ;
2011-06-22 12:11:28 +00:00
/**
* We try to make 0 , 0 of the ThebesLayer be the top - left of the
* border - box of the " active scrolled root " frame ( i . e . the nearest ancestor
* frame for the display items that is being actively scrolled ) . But
* we force the ThebesLayer transform to be an integer translation , and we may
* have a resolution scale , so we have to snap the ThebesLayer transform , so
* 0 , 0 may not be exactly the top - left of the active scrolled root . Here we
* store the coordinates in ThebesLayer space of the top - left of the
* 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
2012-08-20 10:00:49 +00:00
nsRefPtr < ColorLayer > mColorLayer ;
nsRefPtr < ImageLayer > mImageLayer ;
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
}
nsRefPtr < const MaskLayerImageCache : : MaskLayerImageKey > 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
} ;
2010-05-21 03:20:48 +00:00
/**
2010-07-15 21:07:51 +00:00
* The address of gThebesDisplayItemLayerUserData is used as the user
2010-09-02 09:18:39 +00:00
* data key for ThebesLayers created by FrameLayerBuilder .
2010-07-15 21:07:51 +00:00
* It identifies ThebesLayers used to draw non - layer content , which are
* therefore eligible for recycling . We want display items to be able to
* create their own dedicated ThebesLayers in BuildLayer , if necessary ,
* and we wouldn ' t want to accidentally recycle those .
2010-09-02 09:18:39 +00:00
* The user data is a ThebesDisplayItemLayerUserData .
2010-05-21 03:20:48 +00:00
*/
2012-08-22 15:56:38 +00:00
uint8_t gThebesDisplayItemLayerUserData ;
2010-07-15 21:08:03 +00:00
/**
* The address of gColorLayerUserData is used as the user
2010-09-02 09:18:39 +00:00
* data key for ColorLayers created by FrameLayerBuilder .
* The user data is null .
2010-07-15 21:08:03 +00:00
*/
2012-08-22 15:56:38 +00:00
uint8_t gColorLayerUserData ;
2011-01-17 21:47:18 +00:00
/**
* The address of gImageLayerUserData is used as the user
* data key for ImageLayers created by FrameLayerBuilder .
* The user data is null .
*/
2012-08-22 15:56:38 +00:00
uint8_t gImageLayerUserData ;
2010-09-02 09:18:39 +00:00
/**
* The address of gLayerManagerUserData is used as the user
* data key for retained LayerManagers managed by FrameLayerBuilder .
* The user data is a LayerManagerData .
*/
2012-08-22 15:56:38 +00:00
uint8_t gLayerManagerUserData ;
2012-02-07 22:26:33 +00:00
/**
* The address of gMaskLayerUserData is used as the user
* data key for mask layers managed by FrameLayerBuilder .
* The user data is a MaskLayerUserData .
*/
2012-08-22 15:56:38 +00:00
uint8_t gMaskLayerUserData ;
2010-07-15 21:07:51 +00:00
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 ) ) ;
}
ThebesDisplayItemLayerUserData * GetThebesDisplayItemLayerUserData ( Layer * aLayer )
{
return static_cast < ThebesDisplayItemLayerUserData * > (
aLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
}
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 ,
ThebesLayerData * 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 ( ) ;
}
2013-12-16 12:16:24 +00:00
mContainingThebesLayer = 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 ;
aContext - > SetColor ( gfxRGBA ( r , g , b , 0.4 ) ) ;
aContext - > Paint ( ) ;
2011-11-15 04:59:03 +00:00
}
2012-10-11 23:38:24 +00:00
FrameLayerBuilder : : DisplayItemData *
FrameLayerBuilder : : GetDisplayItemData ( nsIFrame * aFrame , uint32_t aKey )
{
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-11 23:38:24 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
DisplayItemData * item = array - > ElementAt ( i ) ;
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 ;
nsIntRegionRectIterator it ( r ) ;
s + = " < " ;
while ( const nsIntRect * sr = it . Next ( ) ) {
AppendToString ( s , * sr ) + = " ; " ;
}
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 .
*/
static void
InvalidatePostTransformRegion ( ThebesLayer * aLayer , const nsIntRegion & aRegion ,
const nsIntPoint & aTranslation )
{
// Convert the region from the coordinates of the container layer
// (relative to the snapped top-left of the display list reference frame)
// to the ThebesLayer's own coordinates
nsIntRegion rgn = aRegion ;
rgn . MoveBy ( - aTranslation ) ;
aLayer - > InvalidateRegion ( rgn ) ;
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
nsAutoCString str ;
AppendToString ( str , rgn ) ;
2013-11-23 22:44:18 +00:00
printf_stderr ( " Invalidating layer %p: %s \n " , aLayer , str . get ( ) ) ;
2013-05-13 23:47:02 +00:00
}
2012-08-29 05:47:15 +00:00
# endif
}
2012-10-16 01:10:43 +00:00
static void
2014-03-20 06:49:27 +00:00
InvalidatePostTransformRegion ( ThebesLayer * 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 )
{
ThebesDisplayItemLayerUserData * data =
static_cast < ThebesDisplayItemLayerUserData * > ( aLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
nsRect rect = aClip . ApplyNonRoundedIntersection ( aRect ) ;
nsIntRect pixelRect = rect . ScaleToOutsidePixels ( data - > mXScale , data - > mYScale , data - > mAppUnitsPerDevPixel ) ;
InvalidatePostTransformRegion ( aLayer , pixelRect , aTranslation ) ;
}
2012-08-29 05:47:15 +00:00
static nsIntPoint
GetTranslationForThebesLayer ( ThebesLayer * aLayer )
{
2014-03-20 06:49:27 +00:00
ThebesDisplayItemLayerUserData * data =
2012-08-29 05:47:15 +00:00
static_cast < ThebesDisplayItemLayerUserData * >
( aLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
NS_ASSERTION ( data , " Must be a tracked thebes layer! " ) ;
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
2011-10-06 21:35:08 +00:00
FrameLayerBuilder : : RemoveFrameFromLayerManager ( nsIFrame * aFrame ,
void * aPropertyValue )
2010-07-15 21:07:51 +00:00
{
2012-10-11 23:38:24 +00:00
sDestroyedFrame = aFrame ;
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-11 23:38:24 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aPropertyValue ) ;
// Hold a reference to all the items so that they don't get
// deleted from under us.
nsTArray < nsRefPtr < DisplayItemData > > arrayCopy ;
for ( uint32_t i = 0 ; i < array - > Length ( ) ; + + i ) {
arrayCopy . AppendElement ( array - > ElementAt ( i ) ) ;
}
2012-08-29 05:47:15 +00:00
2012-10-11 23:38:25 +00:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
if ( array - > Length ( ) ) {
LayerManagerData * rootData = array - > ElementAt ( 0 ) - > mParent ;
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
2012-10-11 23:38:24 +00:00
for ( uint32_t i = 0 ; i < array - > Length ( ) ; + + i ) {
DisplayItemData * data = array - > ElementAt ( i ) ;
ThebesLayer * t = data - > mLayer - > AsThebesLayer ( ) ;
2012-08-29 05:47:15 +00:00
if ( t ) {
2012-10-11 23:38:24 +00:00
ThebesDisplayItemLayerUserData * thebesData =
2012-08-29 05:47:15 +00:00
static_cast < ThebesDisplayItemLayerUserData * > ( t - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
2012-10-11 23:38:24 +00:00
if ( thebesData ) {
nsRegion old = data - > mGeometry - > ComputeInvalidationRegion ( ) ;
nsIntRegion rgn = old . ScaleToOutsidePixels ( thebesData - > mXScale , thebesData - > mYScale , thebesData - > mAppUnitsPerDevPixel ) ;
2012-08-29 05:47:15 +00:00
rgn . MoveBy ( - GetTranslationForThebesLayer ( t ) ) ;
2012-10-11 23:38:24 +00:00
thebesData - > mRegionToInvalidate . Or ( thebesData - > mRegionToInvalidate , rgn ) ;
2013-03-02 17:21:00 +00:00
thebesData - > 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 ( ) ;
delete array ;
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! " ) ;
// Update all the frames that used to have layers.
2012-12-12 20:47:05 +00:00
data - > mDisplayItems . EnumerateEntries ( ProcessRemovedDisplayItems , this ) ;
2011-10-17 14:59:28 +00:00
data - > mInvalidateAllLayers = false ;
2012-09-27 15:34:46 +00:00
}
2012-08-29 05:47:15 +00:00
/* static */ PLDHashOperator
2012-10-11 23:38:24 +00:00
FrameLayerBuilder : : ProcessRemovedDisplayItems ( nsRefPtrHashKey < DisplayItemData > * aEntry ,
2012-08-29 05:47:15 +00:00
void * aUserArg )
2010-05-21 03:20:48 +00:00
{
2012-10-11 23:38:24 +00:00
DisplayItemData * data = aEntry - > GetKey ( ) ;
2012-10-12 02:39:46 +00:00
if ( ! data - > mUsed ) {
2012-10-11 23:38:24 +00:00
// This item was visible, but isn't anymore.
2012-12-12 20:47:05 +00:00
FrameLayerBuilder * layerBuilder = static_cast < FrameLayerBuilder * > ( aUserArg ) ;
ThebesLayer * t = data - > mLayer - > AsThebesLayer ( ) ;
if ( t ) {
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 ( " Invalidating unused display item (%i) belonging to frame %p from layer %p \n " , data - > mDisplayItemKey , data - > mFrameList [ 0 ] , t ) ;
2013-05-13 23:47:02 +00:00
}
2012-12-12 20:47:05 +00:00
# endif
InvalidatePostTransformRegion ( t ,
data - > mGeometry - > ComputeInvalidationRegion ( ) ,
data - > mClip ,
layerBuilder - > GetLastPaintOffset ( t ) ) ;
}
2010-07-15 21:07:51 +00:00
return PL_DHASH_REMOVE ;
}
2012-10-12 02:39:46 +00:00
data - > mUsed = false ;
2012-11-06 22:04:53 +00:00
data - > mIsInvalid = false ;
2010-07-15 21:07:51 +00:00
return PL_DHASH_NEXT ;
}
2014-03-20 06:49:27 +00:00
/* static */ PLDHashOperator
2012-10-11 23:38:25 +00:00
FrameLayerBuilder : : DumpDisplayItemDataForFrame ( nsRefPtrHashKey < DisplayItemData > * aEntry ,
void * aClosure )
{
# ifdef DEBUG_DISPLAY_ITEM_DATA
DisplayItemData * data = aEntry - > GetKey ( ) ;
nsAutoCString prefix ;
prefix + = static_cast < const char * > ( aClosure ) ;
2014-03-20 06:49:27 +00:00
2012-10-11 23:38:25 +00:00
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 " ;
2013-11-23 22:44:18 +00:00
printf_stderr ( " %s " , str . get ( ) ) ;
2014-03-20 06:49:27 +00:00
2012-10-11 23:38:25 +00:00
if ( data - > mInactiveManager ) {
prefix + = " " ;
2013-11-23 22:44:18 +00:00
printf_stderr ( " %sDumping inactive layer info: \n " , prefix . get ( ) ) ;
2012-10-11 23:38:25 +00:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( data - > mInactiveManager - > GetUserData ( & gLayerManagerUserData ) ) ;
lmd - > Dump ( prefix . get ( ) ) ;
}
# endif
return PL_DHASH_NEXT ;
}
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
{
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2013-04-19 12:02:13 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aItem - > Frame ( ) - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
2012-10-11 23:38:24 +00:00
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
DisplayItemData * item = array - > ElementAt ( i ) ;
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
{
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-11 23:38:24 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2012-12-13 22:51:00 +00:00
if ( 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
{
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-11-06 22:04:53 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
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 + + ) {
2012-11-19 10:54:50 +00:00
DisplayItemData * data = 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 ,
2013-03-04 09:55:59 +00:00
DisplayItemClip * * aOldClip ,
2012-11-06 22:04:53 +00:00
nsTArray < nsIFrame * > * aChangedFrames ,
bool * aIsInvalid )
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 ;
}
if ( aChangedFrames ) {
oldData - > GetFrameListChanges ( aItem , * aChangedFrames ) ;
}
if ( aIsInvalid ) {
* aIsInvalid = oldData - > mIsInvalid ;
}
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
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
{
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-11 23:38:24 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( 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 + + ) {
DisplayItemData * data = 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
}
2010-07-15 21:08:03 +00:00
already_AddRefed < ColorLayer >
2012-08-20 10:00:49 +00:00
ContainerState : : CreateOrRecycleColorLayer ( ThebesLayer * aThebes )
2010-07-15 21:08:03 +00:00
{
2014-03-20 06:49:27 +00:00
ThebesDisplayItemLayerUserData * data =
2012-08-20 10:00:49 +00:00
static_cast < ThebesDisplayItemLayerUserData * > ( aThebes - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
nsRefPtr < ColorLayer > layer = data - > mColorLayer ;
if ( layer ) {
2012-07-30 14:20:58 +00:00
layer - > SetMaskLayer ( nullptr ) ;
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 ;
2010-07-15 21:08:03 +00:00
// Mark this layer as being used for Thebes-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
2012-08-20 10:00:49 +00:00
// Remove other layer types we might have stored for this ThebesLayer
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 >
2012-08-20 10:00:49 +00:00
ContainerState : : CreateOrRecycleImageLayer ( ThebesLayer * aThebes )
2011-01-17 21:47:18 +00:00
{
2014-03-20 06:49:27 +00:00
ThebesDisplayItemLayerUserData * data =
2012-08-20 10:00:49 +00:00
static_cast < ThebesDisplayItemLayerUserData * > ( aThebes - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
nsRefPtr < ImageLayer > layer = data - > mImageLayer ;
if ( layer ) {
2012-07-30 14:20:58 +00:00
layer - > SetMaskLayer ( nullptr ) ;
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 ;
2011-01-17 21:47:18 +00:00
// Mark this layer as being used for Thebes-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
// Remove other layer types we might have stored for this ThebesLayer
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 >
ContainerState : : CreateOrRecycleMaskImageLayerFor ( Layer * aLayer )
{
nsRefPtr < ImageLayer > result = mRecycledMaskImageLayers . Get ( aLayer ) ;
if ( result ) {
mRecycledMaskImageLayers . Remove ( aLayer ) ;
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 ( ) ) ;
2013-08-01 23:02:06 +00:00
result - > SetDisallowBigImage ( true ) ;
2012-02-07 22:26:40 +00:00
}
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
2013-09-25 21:07:26 +00:00
ResetScrollPositionForLayerPixelAlignment ( const nsIFrame * aAnimatedGeometryRoot )
2012-08-16 23:40:10 +00:00
{
2013-09-25 21:07:26 +00:00
nsIScrollableFrame * sf = nsLayoutUtils : : GetScrollableFrameFor ( aAnimatedGeometryRoot ) ;
2012-08-16 23:40:10 +00:00
if ( sf ) {
sf - > ResetScrollPositionForLayerPixelAlignment ( ) ;
}
}
static void
2013-09-25 21:07:26 +00:00
InvalidateEntireThebesLayer ( ThebesLayer * aLayer , const nsIFrame * aAnimatedGeometryRoot )
2012-08-16 23:40:10 +00:00
{
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 ( " Invalidating entire layer %p \n " , aLayer ) ;
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
}
2010-07-15 21:07:51 +00:00
already_AddRefed < ThebesLayer >
2013-09-25 21:07:26 +00:00
ContainerState : : CreateOrRecycleThebesLayer ( const nsIFrame * aAnimatedGeometryRoot ,
2012-09-28 11:19:39 +00:00
const nsIFrame * aReferenceFrame ,
const nsPoint & aTopLeft )
2010-07-15 21:07:51 +00:00
{
// We need a new thebes layer
nsRefPtr < ThebesLayer > layer ;
2011-06-22 12:11:27 +00:00
ThebesDisplayItemLayerUserData * data ;
2014-06-13 16:11:08 +00:00
bool layerRecycled = false ;
2014-06-30 10:31:07 +00:00
# ifndef MOZ_ANDROID_OMTC
2012-08-16 23:40:10 +00:00
bool didResetScrollPositionForLayerPixelAlignment = false ;
2014-06-30 10:31:07 +00:00
# endif
2014-06-13 16:11:08 +00:00
// Check whether the layer will be scrollable. This is used as a hint to
// influence whether tiled layers are used or not.
LayerManager : : ThebesLayerCreationHint creationHint = LayerManager : : NONE ;
nsIFrame * animatedGeometryRootParent = aAnimatedGeometryRoot - > GetParent ( ) ;
if ( animatedGeometryRootParent & &
animatedGeometryRootParent - > GetType ( ) = = nsGkAtoms : : scrollFrame ) {
creationHint = LayerManager : : SCROLLABLE ;
}
2010-07-15 21:08:03 +00:00
if ( mNextFreeRecycledThebesLayer < mRecycledThebesLayers . Length ( ) ) {
2014-06-13 16:11:08 +00:00
// Try to recycle a layer
2010-07-15 21:07:51 +00:00
layer = mRecycledThebesLayers [ mNextFreeRecycledThebesLayer ] ;
+ + mNextFreeRecycledThebesLayer ;
2014-06-13 16:11:08 +00:00
// Check if the layer hint has changed and whether or not the layer should
// be recreated because of it.
if ( mManager - > IsOptimizedFor ( layer - > AsThebesLayer ( ) , creationHint ) ) {
layerRecycled = true ;
// Clear clip rect and mask layer so we don't accidentally stay clipped.
// We will reapply any necessary clipping.
layer - > SetMaskLayer ( nullptr ) ;
data = static_cast < ThebesDisplayItemLayerUserData * >
( layer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
NS_ASSERTION ( data , " Recycled ThebesLayers must have user data " ) ;
// This gets called on recycled ThebesLayers 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 ThebesLayer 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 ThebesLayer to its new
// transform. See nsGfxScrollFrame::InvalidateInternal, where
// we ensure that mInvalidThebesContent 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 ) {
2014-05-12 19:37:21 +00:00
# ifdef MOZ_DUMP_PAINTING
2014-06-13 16:11:08 +00:00
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
printf_stderr ( " Recycled layer %p changed scale \n " , layer . get ( ) ) ;
}
2014-05-12 19:37:21 +00:00
# endif
2014-06-13 16:11:08 +00:00
InvalidateEntireThebesLayer ( layer , aAnimatedGeometryRoot ) ;
2014-06-30 10:31:07 +00:00
# ifndef MOZ_ANDROID_OMTC
2014-06-13 16:11:08 +00:00
didResetScrollPositionForLayerPixelAlignment = true ;
2014-06-30 10:31:07 +00:00
# endif
2013-05-13 23:47:02 +00:00
}
2014-06-13 16:11:08 +00:00
if ( ! data - > mRegionToInvalidate . IsEmpty ( ) ) {
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
printf_stderr ( " Invalidating deleted frame content from layer %p \n " , layer . get ( ) ) ;
}
2012-08-29 05:47:15 +00:00
# endif
2014-06-13 16:11:08 +00:00
layer - > InvalidateRegion ( data - > mRegionToInvalidate ) ;
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
2014-06-13 16:11:08 +00:00
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
nsAutoCString str ;
AppendToString ( str , data - > mRegionToInvalidate ) ;
printf_stderr ( " Invalidating layer %p: %s \n " , layer . get ( ) , str . get ( ) ) ;
}
2012-08-29 05:47:15 +00:00
# endif
2014-06-13 16:11:08 +00:00
data - > mRegionToInvalidate . SetEmpty ( ) ;
}
2012-08-29 05:47:15 +00:00
2014-06-13 16:11:08 +00:00
// We do not need to Invalidate these areas in the widget because we
// assume the caller of InvalidateThebesLayerContents has ensured
// the area is invalidated in the widget.
2013-09-17 17:55:09 +00:00
}
2014-06-13 16:11:08 +00:00
}
if ( ! layerRecycled ) {
2010-07-15 21:07:51 +00:00
// Create a new thebes layer
2014-06-13 16:11:08 +00:00
layer = mManager - > CreateThebesLayerWithHint ( creationHint ) ;
2010-07-15 21:07:51 +00:00
if ( ! layer )
2012-07-30 14:20:58 +00:00
return nullptr ;
2010-07-15 21:07:51 +00:00
// Mark this layer as being used for Thebes-painting display items
2011-06-22 12:11:27 +00:00
data = new ThebesDisplayItemLayerUserData ( ) ;
layer - > SetUserData ( & gThebesDisplayItemLayerUserData , data ) ;
2013-09-25 21:07:26 +00:00
ResetScrollPositionForLayerPixelAlignment ( aAnimatedGeometryRoot ) ;
2014-06-30 10:31:07 +00:00
# ifndef MOZ_ANDROID_OMTC
2012-08-16 23:40:10 +00:00
didResetScrollPositionForLayerPixelAlignment = true ;
2014-06-30 10:31:07 +00:00
# endif
2010-07-15 21:07:51 +00:00
}
2011-06-22 12:11:27 +00:00
data - > mXScale = mParameters . mXScale ;
data - > mYScale = mParameters . mYScale ;
2013-09-25 21:07:26 +00:00
data - > mLastAnimatedGeometryRootOrigin = data - > mAnimatedGeometryRootOrigin ;
data - > mAnimatedGeometryRootOrigin = aTopLeft ;
2012-08-29 05:47:15 +00:00
data - > mAppUnitsPerDevPixel = mAppUnitsPerDevPixel ;
2012-04-10 11:24:18 +00:00
layer - > SetAllowResidualTranslation ( mParameters . AllowResidualTranslation ( ) ) ;
2010-07-15 21:07:51 +00:00
2012-07-17 17:03:51 +00:00
mLayerBuilder - > SaveLastPaintOffset ( layer ) ;
2011-05-16 23:05:56 +00:00
2010-07-15 21:07:51 +00:00
// Set up transform so that 0,0 in the Thebes layer corresponds to the
2013-09-25 21:07:26 +00:00
// (pixel-snapped) top-left of the aAnimatedGeometryRoot.
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
2013-09-25 21:07:26 +00:00
// is close to data->mAnimatedGeometryRootPosition if possible.
nsIntPoint pixOffset ( RoundToMatchResidual ( scaledOffset . x , data - > mAnimatedGeometryRootPosition . x ) ,
RoundToMatchResidual ( scaledOffset . y , data - > mAnimatedGeometryRootPosition . y ) ) ;
2012-09-16 22:25:33 +00:00
data - > mTranslation = pixOffset ;
pixOffset + = mParameters . mOffset ;
2014-01-27 15:28:33 +00:00
Matrix matrix ;
matrix . Translate ( pixOffset . x , pixOffset . y ) ;
layer - > SetBaseTransform ( Matrix4x4 : : From2D ( matrix ) ) ;
2010-07-15 21:07:51 +00:00
2014-06-30 10:31:07 +00:00
// FIXME: Temporary workaround for bug 681192 and bug 724786.
# ifndef MOZ_ANDROID_OMTC
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.
2013-09-25 21:07:26 +00:00
if ( ! animatedGeometryRootTopLeft . WithinEpsilonOf ( data - > mAnimatedGeometryRootPosition , SUBPIXEL_OFFSET_EPSILON ) ) {
data - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
InvalidateEntireThebesLayer ( layer , aAnimatedGeometryRoot ) ;
2012-08-16 23:40:10 +00:00
} else if ( didResetScrollPositionForLayerPixelAlignment ) {
2013-09-25 21:07:26 +00:00
data - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
2011-06-22 12:11:28 +00:00
}
2014-06-30 10:31:07 +00:00
# endif
2011-06-22 12:11:28 +00:00
2010-07-15 21:07:51 +00:00
return layer . forget ( ) ;
}
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 ,
const nsIntRect * aLayerContentsVisibleRect = nullptr )
2010-07-15 21:07:51 +00:00
{
2014-01-27 15:28:47 +00:00
gfx3DMatrix transform ;
To3DMatrix ( aLayer - > GetTransform ( ) , transform ) ;
2014-06-23 04:24:00 +00:00
gfxMatrix transform2D ;
if ( transform . Is2D ( & transform2D ) & & ! transform2D . HasNonIntegerTranslation ( ) ) {
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
gfxRect outerVisible ( outerRect . x , outerRect . y , outerRect . width , outerRect . height ) ;
gfxRect layerVisible = transform . Inverse ( ) . ProjectRectBounds ( outerVisible ) ;
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)
gfxRect layerContentsVisible (
aLayerContentsVisibleRect - > x , aLayerContentsVisibleRect - > y ,
aLayerContentsVisibleRect - > width , aLayerContentsVisibleRect - > height ) ;
layerVisible . IntersectRect ( layerVisible , 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
aLayer - > SetVisibleRegion ( * aOuterVisibleRegion ) ;
}
void
ContainerState : : SetOuterVisibleRegionForLayer ( Layer * aLayer ,
const nsIntRegion & aOuterVisibleRegion ,
const nsIntRect * aLayerContentsVisibleRect ) const
{
nsIntRegion visRegion = aOuterVisibleRegion ;
visRegion . MoveBy ( mParameters . mOffset ) ;
SetOuterVisibleRegion ( aLayer , & visRegion , aLayerContentsVisibleRect ) ;
2010-07-15 21:07:51 +00:00
}
2010-09-02 09:18:39 +00:00
nscolor
2012-08-22 15:56:38 +00:00
ContainerState : : FindOpaqueBackgroundColorFor ( int32_t aThebesLayerIndex )
2010-09-02 09:18:39 +00:00
{
ThebesLayerData * target = mThebesLayerDataStack [ aThebesLayerIndex ] ;
2012-08-22 15:56:38 +00:00
for ( int32_t i = aThebesLayerIndex - 1 ; i > = 0 ; - - i ) {
2010-09-02 09:18:39 +00:00
ThebesLayerData * candidate = mThebesLayerDataStack [ i ] ;
2013-11-08 06:04:12 +00:00
if ( candidate - > IntersectsVisibleAboveRegion ( target - > mVisibleRegion ) ) {
2010-09-02 09:18:39 +00:00
// Some non-Thebes content between target and candidate; this is
// hopeless
break ;
}
nsIntRegion intersection ;
intersection . And ( candidate - > mVisibleRegion , target - > mVisibleRegion ) ;
if ( intersection . IsEmpty ( ) ) {
// The layer doesn't intersect our target, ignore it and move on
continue ;
}
2011-06-22 12:11:27 +00:00
2010-09-02 09:18:39 +00:00
// The candidate intersects our target. If any layer has a solid-color
// area behind our target, this must be it. Scan its display items.
2012-12-05 02:53:17 +00:00
nsIntRect deviceRect = target - > mVisibleRegion . GetBounds ( ) ;
nsRect appUnitRect = deviceRect . ToAppUnits ( mAppUnitsPerDevPixel ) ;
appUnitRect . ScaleInverseRoundOut ( mParameters . mXScale , mParameters . mYScale ) ;
FrameLayerBuilder : : ThebesLayerItemsEntry * entry =
mLayerBuilder - > GetThebesLayerItemsEntry ( candidate - > mLayer ) ;
NS_ASSERTION ( entry , " Must know about this layer! " ) ;
for ( int32_t j = entry - > mItems . Length ( ) - 1 ; j > = 0 ; - - j ) {
nsDisplayItem * item = entry - > mItems [ j ] . mItem ;
bool snap ;
nsRect bounds = item - > GetBounds ( mBuilder , & snap ) ;
if ( snap & & mSnappingEnabled ) {
nsIntRect snappedBounds = ScaleToNearestPixels ( bounds ) ;
if ( ! snappedBounds . Intersects ( deviceRect ) )
continue ;
if ( ! snappedBounds . Contains ( deviceRect ) )
break ;
} 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 ;
if ( ! bounds . Contains ( appUnitRect ) )
break ;
}
2014-06-03 12:50:42 +00:00
if ( item - > IsInvisibleInRect ( appUnitRect ) ) {
continue ;
}
2012-12-05 02:53:17 +00:00
nscolor color ;
if ( item - > IsUniform ( mBuilder , & color ) & & NS_GET_A ( color ) = = 255 )
return color ;
break ;
}
break ;
2010-09-02 09:18:39 +00:00
}
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2012-02-07 22:27:44 +00:00
void
2013-12-16 12:11:01 +00:00
ThebesLayerData : : 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
}
2012-01-30 05:16:54 +00:00
already_AddRefed < ImageContainer >
2013-12-16 12:11:01 +00:00
ThebesLayerData : : CanOptimizeImageLayer ( 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
}
2013-09-27 06:01:16 +00:00
const nsIFrame *
ContainerState : : FindFixedPosFrameForLayerData ( const nsIFrame * aAnimatedGeometryRoot ,
2014-02-26 04:17:18 +00:00
bool aDisplayItemFixedToViewport )
2013-09-27 06:01:16 +00:00
{
2014-02-17 01:51:49 +00:00
if ( ! mManager - > IsWidgetLayerManager ( ) ) {
// Never attach any fixed-pos metadata to inactive layers, it's pointless!
return nullptr ;
}
2013-12-17 11:30:21 +00:00
nsPresContext * presContext = mContainerFrame - > PresContext ( ) ;
nsIFrame * viewport = presContext - > PresShell ( ) - > GetRootFrame ( ) ;
2014-02-21 01:11:17 +00:00
if ( viewport = = aAnimatedGeometryRoot & & aDisplayItemFixedToViewport & &
2014-03-03 06:04:59 +00:00
nsLayoutUtils : : ViewportHasDisplayPort ( presContext ) ) {
2013-12-17 11:30:21 +00:00
// Probably a background-attachment:fixed item
2014-03-03 06:04:59 +00:00
return viewport ;
}
// Viewports with no fixed-pos frames are not relevant.
if ( ! viewport - > GetFirstChild ( nsIFrame : : kFixedList ) ) {
return nullptr ;
}
for ( const nsIFrame * f = aAnimatedGeometryRoot ; f ; f = f - > GetParent ( ) ) {
if ( nsLayoutUtils : : IsFixedPosFrameInDisplayPort ( f ) ) {
return f ;
2013-12-17 11:30:21 +00:00
}
2014-03-03 06:04:59 +00:00
if ( f = = mContainerReferenceFrame ) {
// The metadata will go on an ancestor layer if necessary.
2013-12-17 11:30:21 +00:00
return nullptr ;
2013-09-27 06:01:16 +00:00
}
}
2014-03-03 06:04:59 +00:00
return nullptr ;
2014-02-26 04:17:18 +00:00
}
2013-12-17 11:30:21 +00:00
2014-02-26 04:17:18 +00:00
void
ContainerState : : AdjustLayerDataForFixedPositioning ( const nsIFrame * aFixedPosFrame ,
const nsIntRegion & aDrawRegion ,
nsIntRegion * aVisibleRegion ,
bool * aIsSolidColorInVisibleRegion )
{
if ( ! aFixedPosFrame ) {
return ;
}
2014-03-03 01:49:39 +00:00
nsRect fixedVisibleRect ;
2014-02-26 04:17:18 +00:00
nsPresContext * presContext = aFixedPosFrame - > PresContext ( ) ;
2014-03-03 01:49:39 +00:00
nsIPresShell * presShell = presContext - > PresShell ( ) ;
2014-02-26 04:17:18 +00:00
DebugOnly < bool > hasDisplayPort =
2014-03-03 01:49:39 +00:00
nsLayoutUtils : : ViewportHasDisplayPort ( presContext , & fixedVisibleRect ) ;
2014-02-26 04:17:18 +00:00
NS_ASSERTION ( hasDisplayPort , " No fixed-pos layer data if there's no displayport " ) ;
2013-12-17 11:30:21 +00:00
// Display ports are relative to the viewport, convert it to be relative
// to our reference frame.
2014-03-03 01:49:39 +00:00
nsIFrame * viewport = presShell - > GetRootFrame ( ) ;
if ( aFixedPosFrame ! = viewport ) {
// position: fixed items are reflowed into and only drawn inside the
// viewport, or the scroll position clamping scrollport size, if one is
// set. We differentiate background-attachment: fixed items from
// position: fixed items by the fact that background-attachment: fixed
// items use the viewport as their aFixedPosFrame.
NS_ASSERTION ( aFixedPosFrame - > StyleDisplay ( ) - > mPosition = = NS_STYLE_POSITION_FIXED ,
" should be position fixed items only " ) ;
fixedVisibleRect . MoveTo ( 0 , 0 ) ;
if ( presShell - > IsScrollPositionClampingScrollPortSizeSet ( ) ) {
fixedVisibleRect . SizeTo ( presShell - > GetScrollPositionClampingScrollPortSize ( ) ) ;
} else {
fixedVisibleRect . SizeTo ( viewport - > GetSize ( ) ) ;
}
}
fixedVisibleRect + = viewport - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2013-12-17 11:30:21 +00:00
nsIntRegion newVisibleRegion ;
2014-03-03 01:49:39 +00:00
newVisibleRegion . And ( ScaleToOutsidePixels ( fixedVisibleRect , false ) ,
2013-12-17 11:30:21 +00:00
aDrawRegion ) ;
if ( ! aVisibleRegion - > Contains ( newVisibleRegion ) ) {
if ( aIsSolidColorInVisibleRegion ) {
* aIsSolidColorInVisibleRegion = false ;
}
* aVisibleRegion = newVisibleRegion ;
}
2013-09-27 06:01:16 +00:00
}
void
ContainerState : : SetFixedPositionLayerData ( Layer * aLayer ,
const nsIFrame * aFixedPosFrame )
{
aLayer - > SetIsFixedPosition ( aFixedPosFrame ! = nullptr ) ;
if ( ! aFixedPosFrame ) {
return ;
}
nsPresContext * presContext = aFixedPosFrame - > PresContext ( ) ;
2013-12-17 11:30:21 +00:00
const nsIFrame * viewportFrame = aFixedPosFrame - > GetParent ( ) ;
// anchorRect will be in the container's coordinate system (aLayer's parent layer).
// This is the same as the display items' reference frame.
nsRect anchorRect ;
if ( viewportFrame ) {
// Fixed position frames are reflowed into the scroll-port size if one has
// been set.
if ( presContext - > PresShell ( ) - > IsScrollPositionClampingScrollPortSizeSet ( ) ) {
anchorRect . SizeTo ( presContext - > PresShell ( ) - > GetScrollPositionClampingScrollPortSize ( ) ) ;
} else {
anchorRect . SizeTo ( viewportFrame - > GetSize ( ) ) ;
}
} else {
// A display item directly attached to the viewport.
// For background-attachment:fixed items, the anchor point is always the
// top-left of the viewport currently.
viewportFrame = aFixedPosFrame ;
2013-09-27 06:01:16 +00:00
}
2013-12-17 11:30:21 +00:00
// The anchorRect top-left is always the viewport top-left.
anchorRect . MoveTo ( viewportFrame - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ) ;
2013-09-27 06:01:16 +00:00
2013-09-27 06:02:03 +00:00
nsLayoutUtils : : SetFixedPositionLayerData ( aLayer ,
2013-12-17 11:30:21 +00:00
viewportFrame , anchorRect , aFixedPosFrame , presContext , mParameters ) ;
2013-09-27 06:01:16 +00:00
}
2014-04-22 14:27:44 +00:00
static bool
CanOptimizeAwayThebesLayer ( ThebesLayerData * aData ,
FrameLayerBuilder * aLayerBuilder )
{
2014-06-23 04:24:00 +00:00
if ( ! aLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
2014-04-22 14:27:44 +00:00
return false ;
}
// If there's no thebes layer with valid content in it that we can reuse,
// always create a color or image layer (and potentially throw away an
// existing completely invalid thebes layer).
if ( aData - > mLayer - > GetValidRegion ( ) . IsEmpty ( ) ) {
return true ;
}
// There is an existing thebes layer we can reuse. Throwing it away can make
// compositing cheaper (see bug 946952), but it might cause us to re-allocate
// the thebes layer frequently due to an animation. So we only discard it if
// 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
2010-07-15 21:07:51 +00:00
void
ContainerState : : PopThebesLayerData ( )
{
NS_ASSERTION ( ! mThebesLayerDataStack . IsEmpty ( ) , " Can't pop " ) ;
2012-08-22 15:56:38 +00:00
int32_t lastIndex = mThebesLayerDataStack . Length ( ) - 1 ;
2010-07-15 21:07:51 +00:00
ThebesLayerData * data = mThebesLayerDataStack [ lastIndex ] ;
2014-02-26 04:17:18 +00:00
AdjustLayerDataForFixedPositioning ( data - > mFixedPosFrameForLayerData ,
data - > mDrawRegion ,
& data - > mVisibleRegion ,
& data - > mIsSolidColorInVisibleRegion ) ;
2014-06-23 04:24:00 +00:00
NewLayerEntry * newLayerEntry = & mNewChildLayers [ data - > mNewChildLayersIndex ] ;
2011-01-17 21:47:18 +00:00
nsRefPtr < Layer > layer ;
2012-11-19 03:28:18 +00:00
nsRefPtr < ImageContainer > imageContainer = data - > CanOptimizeImageLayer ( mBuilder ) ;
2014-04-22 14:27:44 +00:00
if ( ( data - > mIsSolidColorInVisibleRegion | | imageContainer ) & &
CanOptimizeAwayThebesLayer ( data , mLayerBuilder ) ) {
2011-01-17 21:47:18 +00:00
NS_ASSERTION ( ! ( data - > mIsSolidColorInVisibleRegion & & imageContainer ) ,
" Can't be a solid color as well as an image! " ) ;
if ( imageContainer ) {
2013-04-19 15:17:21 +00:00
nsRefPtr < ImageLayer > imageLayer = CreateOrRecycleImageLayer ( data - > mLayer ) ;
2011-01-17 21:47:18 +00:00
imageLayer - > SetContainer ( imageContainer ) ;
2012-09-16 22:25:33 +00:00
data - > mImage - > ConfigureLayer ( imageLayer , mParameters . mOffset ) ;
2012-08-03 21:29:22 +00:00
imageLayer - > SetPostScale ( mParameters . mXScale ,
mParameters . mYScale ) ;
2013-03-04 09:56:00 +00:00
if ( data - > mItemClip . HasClip ( ) ) {
nsIntRect clip = ScaleToNearestPixels ( data - > mItemClip . GetClipRect ( ) ) ;
2012-09-24 02:56:39 +00:00
clip . MoveBy ( mParameters . mOffset ) ;
2013-03-22 02:17:29 +00:00
imageLayer - > SetClipRect ( & clip ) ;
} else {
imageLayer - > SetClipRect ( nullptr ) ;
2011-03-31 21:33:46 +00:00
}
2011-01-17 21:47:18 +00:00
layer = imageLayer ;
2012-10-12 02:39:46 +00:00
mLayerBuilder - > StoreOptimizedLayerForFrame ( data - > mImage ,
2012-09-24 20:31:30 +00:00
imageLayer ) ;
2011-01-17 21:47:18 +00:00
} else {
2013-04-19 15:17:21 +00:00
nsRefPtr < ColorLayer > colorLayer = CreateOrRecycleColorLayer ( data - > mLayer ) ;
2011-01-17 21:47:18 +00:00
colorLayer - > SetColor ( data - > mSolidColor ) ;
2012-07-30 18:36:12 +00:00
// Copy transform
2014-01-27 15:29:06 +00:00
colorLayer - > SetBaseTransform ( data - > mLayer - > GetBaseTransform ( ) ) ;
2013-04-19 15:17:21 +00:00
colorLayer - > SetPostScale ( data - > mLayer - > GetPostXScale ( ) , data - > mLayer - > GetPostYScale ( ) ) ;
2012-08-03 21:29:22 +00:00
2011-01-17 21:47:18 +00:00
nsIntRect visibleRect = data - > mVisibleRegion . GetBounds ( ) ;
2013-07-09 14:11:00 +00:00
visibleRect . MoveBy ( - GetTranslationForThebesLayer ( data - > mLayer ) ) ;
colorLayer - > SetBounds ( visibleRect ) ;
2011-01-17 21:47:18 +00:00
layer = colorLayer ;
}
2010-07-15 21:08:03 +00:00
2014-06-23 04:24:00 +00:00
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , layer ) < 0 ,
" Layer already in list??? " ) ;
NS_ASSERTION ( newLayerEntry - > mLayer = = data - > mLayer ,
" Thebes 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 ;
newLayerEntry - > mFixedPosFrameForLayerData = data - > mFixedPosFrameForLayerData ;
2010-07-15 21:08:03 +00:00
// Hide the ThebesLayer. We leave it in the layer tree so that we
// can find and recycle it later.
2013-03-22 02:17:29 +00:00
nsIntRect emptyRect ;
2013-04-19 15:17:21 +00:00
data - > mLayer - > SetClipRect ( & emptyRect ) ;
data - > mLayer - > SetVisibleRegion ( nsIntRegion ( ) ) ;
2013-12-16 12:16:24 +00:00
data - > mLayer - > SetEventRegions ( EventRegions ( ) ) ;
2010-07-15 21:08:03 +00:00
} else {
2013-04-19 15:17:21 +00:00
layer = data - > mLayer ;
2012-07-30 14:20:58 +00:00
imageContainer = nullptr ;
2013-04-19 15:17:21 +00:00
layer - > SetClipRect ( nullptr ) ;
2010-07-15 21:08:03 +00:00
}
2014-06-23 04:24:00 +00:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
newLayerEntry - > mVisibleRegion = data - > mVisibleRegion ;
newLayerEntry - > mOpaqueRegion = data - > mOpaqueRegion ;
newLayerEntry - > mHideAllLayersBelow = data - > mHideAllLayersBelow ;
if ( nsLayoutUtils : : GetScrollableFrameFor ( newLayerEntry - > mAnimatedGeometryRoot ) & &
! nsDisplayScrollLayer : : IsConstructingScrollLayerForScrolledFrame ( newLayerEntry - > mAnimatedGeometryRoot ) ) {
// Async scrolling not currently active so we can propagate our opaque region
// up to the parent animated geometry root.
newLayerEntry - > mOpaqueForAnimatedGeometryRootParent = true ;
}
} else {
SetOuterVisibleRegionForLayer ( layer , data - > mVisibleRegion ) ;
2010-07-15 21:07:51 +00:00
}
nsIntRegion transparentRegion ;
transparentRegion . Sub ( data - > mVisibleRegion , data - > mOpaqueRegion ) ;
2011-09-29 06:19:26 +00:00
bool isOpaque = transparentRegion . IsEmpty ( ) ;
2010-09-02 09:18:39 +00:00
// For translucent ThebesLayers, try to find an opaque background
// 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 ) {
backgroundColor = FindOpaqueBackgroundColorFor ( lastIndex ) ;
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
ThebesDisplayItemLayerUserData * userData =
2012-02-07 22:27:44 +00:00
GetThebesDisplayItemLayerUserData ( data - > mLayer ) ;
2010-09-02 09:18:39 +00:00
NS_ASSERTION ( userData , " where did our user data go? " ) ;
if ( userData - > mForcedBackgroundColor ! = backgroundColor ) {
// Invalidate the entire target ThebesLayer since we're changing
// 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
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).
int32_t commonClipCount = std : : max ( 0 , data - > mCommonClipCount ) ;
2014-06-23 04:24:00 +00:00
SetupMaskLayer ( layer , data - > mItemClip , data - > mVisibleRegion , commonClipCount ) ;
2012-02-07 22:27:44 +00:00
// copy commonClipCount to the entry
2012-07-17 17:03:51 +00:00
FrameLayerBuilder : : ThebesLayerItemsEntry * entry = mLayerBuilder - >
2012-02-07 22:27:44 +00:00
GetThebesLayerItemsEntry ( static_cast < ThebesLayer * > ( layer . get ( ) ) ) ;
entry - > mCommonClipCount = commonClipCount ;
} else {
// mask layer for image and color layers
2014-06-23 04:24:00 +00:00
SetupMaskLayer ( layer , data - > mItemClip , data - > mVisibleRegion ) ;
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
}
2010-09-02 09:18:40 +00:00
layer - > SetContentFlags ( flags ) ;
2010-09-02 09:18:39 +00:00
2014-02-26 04:17:18 +00:00
SetFixedPositionLayerData ( layer , data - > mFixedPosFrameForLayerData ) ;
2013-09-27 06:01:16 +00:00
2013-12-16 12:16:24 +00:00
ThebesLayerData * containingThebesLayerData =
mLayerBuilder - > GetContainingThebesLayerData ( ) ;
if ( containingThebesLayerData ) {
2014-07-03 18:40:13 +00:00
if ( ! data - > mDispatchToContentHitRegion . GetBounds ( ) . IsEmpty ( ) ) {
nsRect rect = nsLayoutUtils : : TransformFrameRectToAncestor (
mContainerReferenceFrame ,
data - > mDispatchToContentHitRegion . GetBounds ( ) ,
containingThebesLayerData - > mReferenceFrame ) ;
containingThebesLayerData - > mDispatchToContentHitRegion . Or (
containingThebesLayerData - > mDispatchToContentHitRegion , rect ) ;
}
if ( ! data - > mMaybeHitRegion . GetBounds ( ) . IsEmpty ( ) ) {
nsRect rect = nsLayoutUtils : : TransformFrameRectToAncestor (
mContainerReferenceFrame ,
data - > mMaybeHitRegion . GetBounds ( ) ,
containingThebesLayerData - > mReferenceFrame ) ;
containingThebesLayerData - > mMaybeHitRegion . Or (
containingThebesLayerData - > mMaybeHitRegion , rect ) ;
}
if ( ! data - > mHitRegion . GetBounds ( ) . IsEmpty ( ) ) {
// Our definitely-hit region must go to the maybe-hit-region since
// this function is an approximation.
gfx3DMatrix matrix = nsLayoutUtils : : GetTransformToAncestor (
mContainerReferenceFrame , containingThebesLayerData - > mReferenceFrame ) ;
gfxMatrix matrix2D ;
bool isPrecise = matrix . Is2D ( & matrix2D ) & & ! matrix2D . HasNonAxisAlignedTransform ( ) ;
nsRect rect = nsLayoutUtils : : TransformFrameRectToAncestor (
mContainerReferenceFrame ,
data - > mHitRegion . GetBounds ( ) ,
containingThebesLayerData - > mReferenceFrame ) ;
nsRegion * dest = isPrecise ? & containingThebesLayerData - > mHitRegion
: & containingThebesLayerData - > mMaybeHitRegion ;
dest - > Or ( * dest , rect ) ;
}
2013-12-16 12:16:24 +00:00
} else {
EventRegions regions ;
2014-06-20 03:56:36 +00:00
regions . mHitRegion = ScaleRegionToOutsidePixels ( data - > mHitRegion ) ;
2013-12-16 12:16:24 +00:00
// Points whose hit-region status we're not sure about need to be dispatched
// to the content thread.
2014-06-20 03:56:36 +00:00
nsIntRegion maybeHitRegion = ScaleRegionToOutsidePixels ( data - > mMaybeHitRegion ) ;
regions . mDispatchToContentHitRegion . Sub ( maybeHitRegion , regions . mHitRegion ) ;
2013-12-16 12:16:24 +00:00
regions . mDispatchToContentHitRegion . Or ( regions . mDispatchToContentHitRegion ,
2014-06-20 03:56:36 +00:00
ScaleRegionToOutsidePixels ( data - > mDispatchToContentHitRegion ) ) ;
nsIntPoint translation = - GetTranslationForThebesLayer ( data - > mLayer ) ;
regions . mHitRegion . MoveBy ( translation ) ;
regions . mDispatchToContentHitRegion . MoveBy ( translation ) ;
2013-12-16 12:16:24 +00:00
layer - > SetEventRegions ( regions ) ;
}
2010-09-02 09:18:39 +00:00
if ( lastIndex > 0 ) {
// Since we're going to pop off the last ThebesLayerData, the
// mVisibleAboveRegion of the second-to-last item will need to include
// the regions of the last item.
ThebesLayerData * nextData = mThebesLayerDataStack [ lastIndex - 1 ] ;
2013-11-08 06:04:12 +00:00
nextData - > CopyAboveRegion ( data ) ;
2010-09-02 09:18:39 +00:00
}
2010-07-15 21:07:51 +00:00
mThebesLayerDataStack . RemoveElementAt ( lastIndex ) ;
}
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
2013-12-16 12:11:01 +00:00
ThebesLayerData : : 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 ,
const nsIntRect & aDrawRect ,
const DisplayItemClip & aClip )
2010-07-15 21:07:51 +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.
// Note that the transform (if any) on the ThebesLayer is always an integer translation so
// we don't have to factor that in here.
aItem - > DisableComponentAlpha ( ) ;
}
2012-05-03 04:29:05 +00:00
2011-10-26 03:24:58 +00:00
/* Mark as available for conversion to image layer if this is a nsDisplayImage and
* we are the first visible item in the ThebesLayerData object .
*/
2012-09-24 20:29:14 +00:00
if ( mVisibleRegion . IsEmpty ( ) & &
2012-11-19 03:28:18 +00:00
aItem - > SupportsOptimizingToImage ( ) ) {
2012-09-24 20:29:14 +00:00
mImage = static_cast < nsDisplayImageContainer * > ( aItem ) ;
2011-10-26 03:24:58 +00:00
} else {
2012-07-30 14:20:58 +00:00
mImage = nullptr ;
2011-10-26 03:24:58 +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
2012-05-03 04:29:05 +00:00
if ( ! mIsSolidColorInVisibleRegion & & mOpaqueRegion . Contains ( aDrawRect ) & &
mVisibleRegion . Contains ( aVisibleRect ) ) {
// A very common case! Most pages have a ThebesLayer with the page
// background (opaque) visible and most or all of the page content over the
// top of that background.
// The rest of this method won't do anything. mVisibleRegion, mOpaqueRegion
// and mDrawRegion don't need updating. mVisibleRegion contains aVisibleRect
// already, mOpaqueRegion contains aDrawRect and therefore whatever
// the opaque region of the item is. mDrawRegion must contain mOpaqueRegion
// and therefore aDrawRect.
NS_ASSERTION ( mDrawRegion . Contains ( aDrawRect ) , " Draw region not covered " ) ;
return ;
}
nscolor uniformColor ;
bool isUniform = aItem - > IsUniform ( aState - > mBuilder , & uniformColor ) ;
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.
if ( ! isUniform | | 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).
if ( isUniform ) {
bool snap ;
nsRect bounds = aItem - > GetBounds ( aState - > mBuilder , & snap ) ;
if ( ! aState - > ScaleToInsidePixels ( bounds , snap ) . Contains ( aVisibleRect ) ) {
isUniform = false ;
}
}
2014-02-28 19:52:03 +00:00
if ( isUniform ) {
2011-01-16 10:38:45 +00:00
if ( mVisibleRegion . IsEmpty ( ) ) {
// This color is all we have
mSolidColor = uniformColor ;
2011-10-17 14:59:28 +00:00
mIsSolidColorInVisibleRegion = true ;
2011-01-16 10:38:45 +00:00
} else if ( mIsSolidColorInVisibleRegion & &
2014-02-28 19:52:03 +00:00
mVisibleRegion . IsEqual ( nsIntRegion ( aVisibleRect ) ) & &
clipMatches ) {
2011-01-16 10:38:45 +00:00
// we can just blend the colors together
mSolidColor = NS_ComposeColors ( mSolidColor , uniformColor ) ;
} else {
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 {
2011-10-17 14:59:28 +00:00
mIsSolidColorInVisibleRegion = false ;
2010-07-15 21:08:03 +00:00
}
2011-01-16 10:38:45 +00:00
mVisibleRegion . Or ( mVisibleRegion , aVisibleRect ) ;
mVisibleRegion . SimplifyOutward ( 4 ) ;
mDrawRegion . Or ( mDrawRegion , aDrawRect ) ;
mDrawRegion . SimplifyOutward ( 4 ) ;
}
2014-02-21 01:11:17 +00:00
2014-06-09 04:48:00 +00:00
if ( ! aClippedOpaqueRegion . IsEmpty ( ) ) {
nsIntRegionRectIterator iter ( aClippedOpaqueRegion ) ;
for ( const nsIntRect * r = iter . Next ( ) ; r ; r = 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 ;
2012-07-23 03:00:36 +00:00
tmp . Or ( mOpaqueRegion , * r ) ;
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 ( ) ) {
2011-01-03 01:48:09 +00:00
mOpaqueRegion = tmp ;
}
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
}
}
2013-12-16 12:11:01 +00:00
ThebesLayerData *
2010-09-02 09:18:39 +00:00
ContainerState : : FindThebesLayerFor ( nsDisplayItem * aItem ,
const nsIntRect & aVisibleRect ,
2014-02-26 04:17:18 +00:00
const nsIFrame * aAnimatedGeometryRoot ,
2014-02-21 01:11:17 +00:00
const nsPoint & aTopLeft ,
bool aShouldFixToViewport )
2010-07-15 21:07:51 +00:00
{
2012-08-22 15:56:38 +00:00
int32_t i ;
int32_t lowestUsableLayerWithScrolledRoot = - 1 ;
int32_t topmostLayerWithScrolledRoot = - 1 ;
2010-07-15 21:07:51 +00:00
for ( i = mThebesLayerDataStack . Length ( ) - 1 ; i > = 0 ; - - i ) {
2014-02-26 04:17:18 +00:00
// Don't let should-fix-to-viewport items share a layer with any other items.
if ( aShouldFixToViewport ) {
+ + i ;
break ;
}
2010-07-15 21:07:51 +00:00
ThebesLayerData * data = mThebesLayerDataStack [ i ] ;
2014-02-26 04:17:18 +00:00
// Give up if there is content drawn above (in z-order) this layer that
// intersects aItem's visible region; aItem must be placed in a
2014-06-04 12:44:28 +00:00
// layer above this layer.
2014-02-26 04:17:18 +00:00
if ( data - > DrawAboveRegionIntersects ( aVisibleRect ) ) {
2010-07-15 21:07:51 +00:00
+ + i ;
break ;
}
2014-02-26 04:17:18 +00:00
// If the animated scrolled roots are the same and we can share this layer
// with the item, note this as a usable layer.
if ( data - > mAnimatedGeometryRoot = = aAnimatedGeometryRoot & &
! data - > mSingleItemFixedToViewport ) {
2010-07-15 21:07:51 +00:00
lowestUsableLayerWithScrolledRoot = i ;
if ( topmostLayerWithScrolledRoot < 0 ) {
topmostLayerWithScrolledRoot = i ;
2010-05-21 03:20:48 +00:00
}
}
2014-02-26 04:17:18 +00:00
// If the layer's drawn region intersects the item, stop now since no
// lower layer will be usable. Do the same if the layer is subject to
// async transforms, since we don't know where it will really be drawn.
if ( data - > DrawRegionIntersects ( aVisibleRect ) )
2010-07-15 21:07:51 +00:00
break ;
}
if ( topmostLayerWithScrolledRoot < 0 ) {
- - i ;
for ( ; i > = 0 ; - - i ) {
ThebesLayerData * data = mThebesLayerDataStack [ i ] ;
2014-02-26 04:17:18 +00:00
if ( data - > mAnimatedGeometryRoot = = aAnimatedGeometryRoot ) {
2010-07-15 21:07:51 +00:00
topmostLayerWithScrolledRoot = i ;
break ;
}
}
}
2010-05-21 03:20:48 +00:00
2010-07-15 21:07:51 +00:00
if ( topmostLayerWithScrolledRoot > = 0 ) {
2012-08-22 15:56:38 +00:00
while ( uint32_t ( topmostLayerWithScrolledRoot + 1 ) < mThebesLayerDataStack . Length ( ) ) {
2010-07-15 21:07:51 +00:00
PopThebesLayerData ( ) ;
2010-05-21 03:20:48 +00:00
}
}
2012-07-30 14:20:58 +00:00
ThebesLayerData * thebesLayerData = nullptr ;
2010-07-15 21:07:51 +00:00
if ( lowestUsableLayerWithScrolledRoot < 0 ) {
2013-12-16 12:16:24 +00:00
nsRefPtr < ThebesLayer > layer =
2014-02-26 04:17:18 +00:00
CreateOrRecycleThebesLayer ( aAnimatedGeometryRoot , aItem - > ReferenceFrame ( ) , aTopLeft ) ;
2010-07-15 21:08:03 +00:00
2010-07-15 21:07:51 +00:00
thebesLayerData = new ThebesLayerData ( ) ;
mThebesLayerDataStack . AppendElement ( thebesLayerData ) ;
thebesLayerData - > mLayer = layer ;
2014-02-26 04:17:18 +00:00
thebesLayerData - > mAnimatedGeometryRoot = aAnimatedGeometryRoot ;
thebesLayerData - > mFixedPosFrameForLayerData =
FindFixedPosFrameForLayerData ( aAnimatedGeometryRoot , aShouldFixToViewport ) ;
2013-09-27 06:01:15 +00:00
thebesLayerData - > mReferenceFrame = aItem - > ReferenceFrame ( ) ;
2014-02-21 01:11:17 +00:00
thebesLayerData - > mSingleItemFixedToViewport = aShouldFixToViewport ;
2013-12-16 12:16:24 +00:00
2014-06-23 04:24:00 +00:00
NS_ASSERTION ( FindIndexOfLayerIn ( mNewChildLayers , layer ) < 0 ,
" Layer already in list??? " ) ;
thebesLayerData - > mNewChildLayersIndex = mNewChildLayers . Length ( ) ;
NewLayerEntry * newLayerEntry = mNewChildLayers . AppendElement ( ) ;
newLayerEntry - > mLayer = layer . forget ( ) ;
newLayerEntry - > mAnimatedGeometryRoot = aAnimatedGeometryRoot ;
newLayerEntry - > mFixedPosFrameForLayerData = thebesLayerData - > mFixedPosFrameForLayerData ;
// newLayerEntry->mOpaqueRegion is filled in later from
// thebesLayerData->mOpaqueRegion, if necessary.
// Allocate another entry for this layer's optimization to ColorLayer/ImageLayer
mNewChildLayers . AppendElement ( ) ;
2010-07-15 21:07:51 +00:00
} else {
thebesLayerData = mThebesLayerDataStack [ lowestUsableLayerWithScrolledRoot ] ;
}
2012-02-07 22:27:44 +00:00
return thebesLayerData ;
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 ) ;
2013-11-23 22:44:18 +00:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " array[ \" %s \" ]= \" " , string . BeginReading ( ) ) ;
2014-06-27 11:19:40 +00:00
gfxUtils : : DumpAsDataURI ( aSurface , gfxUtils : : sDumpPaintFile ) ;
2013-11-23 22:44:18 +00:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " \" ; " ) ;
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
{
2011-02-10 08:58:11 +00:00
// This item has an inactive layer. Render it to a ThebesLayer
// using a temporary BasicLayerManager.
2012-08-29 05:47:15 +00:00
BasicLayerManager * basic = static_cast < BasicLayerManager * > ( aManager ) ;
nsRefPtr < gfxContext > context = aContext ;
# 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 ) ;
2014-06-27 11:19:40 +00:00
RefPtr < DrawTarget > tempDT ;
2012-03-05 18:09:05 +00:00
if ( gfxUtils : : sDumpPainting ) {
2014-06-27 11:19:40 +00:00
tempDT = gfxPlatform : : GetPlatform ( ) - > CreateOffscreenContentDrawTarget (
itemVisibleRect . Size ( ) . ToIntSize ( ) ,
SurfaceFormat : : B8G8R8A8 ) ;
context = new gfxContext ( tempDT ) ;
context - > SetMatrix ( gfxMatrix ( ) . Translate ( - gfxPoint ( 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
2012-07-17 17:03:51 +00:00
if ( aItem - > GetType ( ) = = nsDisplayItem : : TYPE_SVG_EFFECTS ) {
2012-08-29 05:47:15 +00:00
static_cast < nsDisplaySVGEffects * > ( aItem ) - > PaintAsLayer ( aBuilder , aCtx , basic ) ;
if ( basic - > InTransaction ( ) ) {
basic - > AbortTransaction ( ) ;
2012-07-20 04:53:55 +00:00
}
2012-07-17 17:03:51 +00:00
} else {
2012-08-29 05:47:15 +00:00
basic - > EndTransaction ( FrameLayerBuilder : : DrawThebesLayer , aBuilder ) ;
}
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
if ( gfxUtils : : sDumpPainting ) {
2014-06-27 11:19:40 +00:00
RefPtr < SourceSurface > surface = tempDT - > Snapshot ( ) ;
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 ,
2013-09-27 06:01:16 +00:00
const nsIFrame * * 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 ) ;
// Don't use an item that won't be part of any ThebesLayers to pick the
// 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.
2013-09-27 06:01:16 +00:00
* aAnimatedGeometryRoot =
nsLayoutUtils : : GetAnimatedGeometryRootFor ( item , mBuilder ) ;
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-09 04:48:00 +00:00
/* Checks if aPotentialScrollItem is a scroll layer item and aPotentialScrollbarItem
* is an overlay scrollbar item for the same scroll frame .
*/
static bool
IsScrollLayerItemAndOverlayScrollbarForScrollFrame (
nsDisplayItem * aPotentialScrollItem , nsDisplayItem * aPotentialScrollbarItem )
{
if ( aPotentialScrollItem - > GetType ( ) = = nsDisplayItem : : TYPE_SCROLL_LAYER & &
aPotentialScrollbarItem & &
aPotentialScrollbarItem - > GetType ( ) = = nsDisplayItem : : TYPE_OWN_LAYER & &
LookAndFeel : : GetInt ( LookAndFeel : : eIntID_UseOverlayScrollbars ) ) {
nsDisplayScrollLayer * scrollItem =
static_cast < nsDisplayScrollLayer * > ( aPotentialScrollItem ) ;
nsDisplayOwnLayer * layerItem =
static_cast < nsDisplayOwnLayer * > ( aPotentialScrollbarItem ) ;
if ( ( layerItem - > GetFlags ( ) &
( nsDisplayOwnLayer : : VERTICAL_SCROLLBAR |
nsDisplayOwnLayer : : HORIZONTAL_SCROLLBAR ) ) & &
layerItem - > Frame ( ) - > GetParent ( ) = = scrollItem - > GetScrollFrame ( ) ) {
return true ;
}
}
return false ;
}
2014-06-23 04:24:00 +00:00
bool
ContainerState : : ItemCoversScrollableArea ( nsDisplayItem * aItem , const nsRegion & aOpaque )
{
nsIPresShell * presShell = aItem - > Frame ( ) - > PresContext ( ) - > PresShell ( ) ;
nsIFrame * rootFrame = presShell - > GetRootFrame ( ) ;
if ( mContainerFrame ! = rootFrame ) {
return false ;
}
nsRect scrollableArea ;
if ( presShell - > IsScrollPositionClampingScrollPortSizeSet ( ) ) {
scrollableArea = nsRect ( nsPoint ( 0 , 0 ) ,
presShell - > GetScrollPositionClampingScrollPortSize ( ) ) ;
} else {
scrollableArea = rootFrame - > GetRectRelativeToSelf ( ) ;
}
return aOpaque . Contains ( scrollableArea ) ;
}
nsIntRegion
ContainerState : : ComputeOpaqueRect ( nsDisplayItem * aItem ,
const nsIFrame * aAnimatedGeometryRoot ,
const nsIFrame * aFixedPosFrame ,
const DisplayItemClip & aClip ,
nsDisplayList * aList ,
bool * aHideAllLayersBelow )
{
bool snapOpaque ;
nsRegion opaque = aItem - > GetOpaqueRegion ( mBuilder , & snapOpaque ) ;
nsIntRegion opaquePixels ;
if ( ! opaque . IsEmpty ( ) ) {
nsRegion opaqueClipped ;
nsRegionRectIterator iter ( opaque ) ;
for ( const nsRect * r = iter . Next ( ) ; r ; r = iter . Next ( ) ) {
opaqueClipped . Or ( opaqueClipped , aClip . ApproximateIntersectInward ( * r ) ) ;
}
if ( aAnimatedGeometryRoot = = mContainerAnimatedGeometryRoot & &
aFixedPosFrame = = mContainerFixedPosFrame & &
! aList - > IsOpaque ( ) & &
opaqueClipped . Contains ( mContainerBounds ) ) {
aList - > SetIsOpaque ( ) ;
}
2014-07-14 00:46:13 +00:00
// Add opaque areas to the "exclude glass" region. Only do this for
// ThebesLayers which are direct children of the root layer; this means
// they can't have transforms or opacity wrapping them.
2014-07-15 04:23:37 +00:00
if ( ! mContainerLayer - > GetParent ( ) ) {
mBuilder - > AddWindowOpaqueRegion ( opaqueClipped ) ;
2014-07-14 00:46:13 +00:00
}
2014-06-23 04:24:00 +00:00
opaquePixels = ScaleRegionToInsidePixels ( opaqueClipped , snapOpaque ) ;
if ( aFixedPosFrame & & ItemCoversScrollableArea ( aItem , opaque ) ) {
* aHideAllLayersBelow = true ;
}
}
return opaquePixels ;
}
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
* to a layer . We invalidate the areas in ThebesLayers where an item
* has moved from one ThebesLayer to another . Also ,
* aState - > mInvalidThebesContent is invalidated in every ThebesLayer .
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 .
2010-07-15 21:07:51 +00:00
* ( ThebesLayers don ' t need a clip rect on the layer , we clip the items
* individually when we draw them . )
* We set the visible rect for all layers , although the actual setting
* of visible rects for some ThebesLayers is deferred until the calling
* of ContainerState : : Finish .
*/
void
2014-06-09 04:48:00 +00:00
ContainerState : : ProcessDisplayItems ( nsDisplayList * aList ,
2013-03-04 09:56:02 +00:00
uint32_t aFlags )
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
2014-02-18 04:00:35 +00:00
const nsIFrame * lastAnimatedGeometryRoot = mContainerReferenceFrame ;
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.
if ( aFlags & NO_COMPONENT_ALPHA ) {
2014-06-09 04:48:00 +00:00
if ( ChooseAnimatedGeometryRoot ( * aList , & lastAnimatedGeometryRoot ) ) {
2014-02-18 04:00:35 +00:00
topLeft = lastAnimatedGeometryRoot - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2012-12-04 06:05:22 +00:00
}
}
2013-07-16 20:17:18 +00:00
int32_t maxLayers = nsDisplayItem : : MaxActiveLayers ( ) ;
int layerCount = 0 ;
2014-06-09 04:48:00 +00:00
nsDisplayList savedItems ;
nsDisplayItem * item ;
while ( ( item = aList - > RemoveBottom ( ) ) ! = nullptr ) {
// Peek ahead to the next item and try merging with it or swapping with it
// if necessary.
nsDisplayItem * aboveItem ;
while ( ( aboveItem = aList - > GetBottom ( ) ) ! = nullptr ) {
if ( aboveItem - > TryMerge ( mBuilder , item ) ) {
aList - > RemoveBottom ( ) ;
item - > ~ nsDisplayItem ( ) ;
item = aboveItem ;
} else if ( IsScrollLayerItemAndOverlayScrollbarForScrollFrame ( aboveItem , item ) ) {
// If an overlay scrollbar item is between a scroll layer item and the
// other scroll layer items that we need to merge with just move the
// scrollbar item up, that way it will be on top of the scrolled content
// and we can try to merge all the scroll layer items.
aList - > RemoveBottom ( ) ;
aList - > AppendToBottom ( item ) ;
item = aboveItem ;
} else {
break ;
}
}
nsDisplayList * itemSameCoordinateSystemChildren
= item - > GetSameCoordinateSystemChildren ( ) ;
if ( itemSameCoordinateSystemChildren ) {
if ( item - > ShouldFlattenAway ( mBuilder ) ) {
aList - > AppendToBottom ( itemSameCoordinateSystemChildren ) ;
item - > ~ nsDisplayItem ( ) ;
continue ;
}
}
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 " ) ;
2011-10-26 02:55:51 +00:00
nsIntRect itemVisibleRect =
2012-04-10 11:24:18 +00:00
ScaleToOutsidePixels ( item - > GetVisibleRect ( ) , false ) ;
bool snap ;
nsRect itemContent = item - > GetBounds ( mBuilder , & snap ) ;
2012-04-13 11:44:05 +00:00
nsIntRect itemDrawRect = ScaleToOutsidePixels ( itemContent , snap ) ;
2013-12-16 12:16:24 +00:00
nsDisplayItem : : Type itemType = item - > GetType ( ) ;
2013-03-22 02:17:29 +00:00
nsIntRect clipRect ;
2013-03-04 09:56:02 +00:00
const DisplayItemClip & itemClip = item - > GetClip ( ) ;
if ( itemClip . HasClip ( ) ) {
itemContent . IntersectRect ( itemContent , itemClip . GetClipRect ( ) ) ;
clipRect = ScaleToNearestPixels ( itemClip . GetClipRect ( ) ) ;
2012-04-13 11:44:05 +00:00
itemDrawRect . IntersectRect ( itemDrawRect , clipRect ) ;
2013-03-22 02:17:29 +00:00
clipRect . MoveBy ( mParameters . mOffset ) ;
2010-08-02 03:06:58 +00:00
}
2014-06-09 04:48:00 +00:00
# ifdef DEBUG
( ( nsRect & ) mAccumulatedChildBounds ) . UnionRect ( mAccumulatedChildBounds , itemContent ) ;
# endif
2012-04-10 11:24:18 +00:00
itemVisibleRect . IntersectRect ( itemVisibleRect , itemDrawRect ) ;
2012-05-03 14:05:55 +00:00
LayerState layerState = item - > GetLayerState ( mBuilder , mManager , mParameters ) ;
2012-11-22 23:29:05 +00:00
if ( layerState = = LAYER_INACTIVE & &
nsDisplayItem : : ForceActiveLayers ( ) ) {
layerState = LAYER_ACTIVE ;
}
2010-07-15 21:08:05 +00:00
2012-09-13 10:34:34 +00:00
bool forceInactive ;
2013-09-27 06:01:16 +00:00
const nsIFrame * animatedGeometryRoot ;
2012-07-23 03:00:36 +00:00
if ( aFlags & NO_COMPONENT_ALPHA ) {
forceInactive = true ;
2013-09-27 06:01:16 +00:00
animatedGeometryRoot = lastAnimatedGeometryRoot ;
2012-07-23 03:00:36 +00:00
} else {
2012-09-13 10:34:34 +00:00
forceInactive = false ;
2014-02-18 04:00:35 +00:00
if ( mManager - > IsWidgetLayerManager ( ) ) {
animatedGeometryRoot = nsLayoutUtils : : GetAnimatedGeometryRootFor ( item , mBuilder ) ;
} else {
// For inactive layer subtrees, splitting content into ThebesLayers
// based on animated geometry roots is pointless. It's more efficient
// to build the minimum number of layers.
2014-04-24 08:18:11 +00:00
animatedGeometryRoot = mContainerAnimatedGeometryRoot ;
2014-02-18 04:00:35 +00:00
}
2013-09-27 06:01:16 +00:00
if ( animatedGeometryRoot ! = lastAnimatedGeometryRoot ) {
lastAnimatedGeometryRoot = animatedGeometryRoot ;
topLeft = animatedGeometryRoot - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2012-10-11 23:38:25 +00:00
}
2012-07-23 03:00:36 +00:00
}
2014-02-21 01:11:17 +00:00
bool shouldFixToViewport = ! animatedGeometryRoot - > GetParent ( ) & &
item - > ShouldFixToViewport ( mBuilder ) ;
2011-04-06 05:00:25 +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-03-20 06:49:27 +00:00
// As long as the new layer isn't going to be a ThebesLayer,
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.
2013-03-04 09:56:02 +00:00
InvalidateForLayerChange ( item , nullptr , itemClip , topLeft , 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
// way, since their ThebesLayer may decide it wants to draw them
// 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 ;
}
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 ) ;
mParameters . mLayerContentsVisibleRect = & layerContentsVisibleRect ;
2011-06-22 12:11:27 +00:00
nsRefPtr < Layer > ownLayer = item - > BuildLayer ( mBuilder , mManager , mParameters ) ;
2010-07-15 21:08:05 +00:00
if ( ! ownLayer ) {
continue ;
}
2013-09-27 06:01:16 +00:00
NS_ASSERTION ( ! ownLayer - > AsThebesLayer ( ) ,
2012-10-12 02:39:46 +00:00
" Should never have created a dedicated Thebes layer! " ) ;
2014-02-21 01:11:17 +00:00
const nsIFrame * fixedPosFrame =
2014-02-26 04:17:18 +00:00
FindFixedPosFrameForLayerData ( animatedGeometryRoot , shouldFixToViewport ) ;
2013-09-27 06:01:16 +00:00
if ( fixedPosFrame ) {
2014-02-26 04:17:18 +00:00
nsIntRegion visibleRegion ( itemVisibleRect ) ;
AdjustLayerDataForFixedPositioning ( fixedPosFrame ,
nsIntRegion ( itemDrawRect ) , & visibleRegion ) ;
2013-09-27 06:01:16 +00:00
itemVisibleRect = visibleRegion . GetBounds ( ) ;
}
SetFixedPositionLayerData ( ownLayer , fixedPosFrame ) ;
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! " ) ;
2013-03-04 09:56:02 +00:00
NS_ASSERTION ( itemClip . HasClip ( ) | |
itemClip . GetRoundedRectCount ( ) = = 0 ,
2012-01-19 20:21:41 +00:00
" If we have rounded rects, we must have a clip rect " ) ;
2010-07-15 21:07:51 +00:00
// It has its own layer. Update that layer's clip and visible rects.
2013-03-04 09:56:02 +00:00
if ( itemClip . HasClip ( ) ) {
2013-03-22 02:17:29 +00:00
ownLayer - > SetClipRect ( & clipRect ) ;
2013-03-22 02:17:29 +00:00
} else {
ownLayer - > SetClipRect ( nullptr ) ;
2010-05-21 03:20:48 +00:00
}
2010-07-15 21:07:51 +00:00
ThebesLayerData * data = GetTopThebesLayerData ( ) ;
if ( data ) {
2013-11-08 06:04:12 +00:00
// Prerendered transform items can be updated without layer building
2014-06-25 08:36:13 +00:00
// (async animations or an empty transaction), so we need to put items
// that the transform item can potentially move under into a layer
// above this item.
2014-07-11 01:18:10 +00:00
if ( itemType = = nsDisplayItem : : TYPE_TRANSFORM & &
2013-11-08 06:04:12 +00:00
nsDisplayTransform : : ShouldPrerenderTransformedContent ( mBuilder ,
item - > Frame ( ) ,
false ) ) {
2014-06-25 08:36:13 +00:00
if ( ! itemClip . HasClip ( ) ) {
// The transform item can move anywhere, treat all other content
// as being above this item.
data - > SetAllDrawingAbove ( ) ;
} else {
// The transform can't escape from the clip rect, and the clip
// rect can't change without new layer building. Treat all content
// that intersects the clip rect as being above this item.
data - > AddVisibleAboveRegion ( clipRect ) ;
data - > AddDrawAboveRegion ( clipRect ) ;
}
2013-11-08 06:04:12 +00:00
} else {
data - > AddVisibleAboveRegion ( itemVisibleRect ) ;
// Add the entire bounds rect to the mDrawAboveRegion.
// The visible region may be excluding opaque content above the
// item, and we need to ensure that that content is not placed
// in a ThebesLayer below the item!
data - > AddDrawAboveRegion ( itemDrawRect ) ;
}
2010-07-15 21:07:51 +00:00
}
2012-02-07 22:27:44 +00:00
// rounded rectangle clipping using mask layers
// (must be done after visible rect is set on layer)
2013-03-04 09:56:02 +00:00
if ( itemClip . IsRectClippedByRoundedCorner ( itemContent ) ) {
2014-06-23 04:24:00 +00:00
SetupMaskLayer ( ownLayer , itemClip , itemVisibleRect ) ;
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 ;
newLayerEntry - > mFixedPosFrameForLayerData = fixedPosFrame ;
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 ;
newLayerEntry - > mVisibleRegion = itemVisibleRect ;
newLayerEntry - > mOpaqueRegion = ComputeOpaqueRect ( item ,
animatedGeometryRoot , fixedPosFrame , itemClip , aList ,
& newLayerEntry - > mHideAllLayersBelow ) ;
} else {
SetOuterVisibleRegionForLayer ( ownLayer , itemVisibleRect ,
2014-07-11 01:17:47 +00:00
layerContentsVisibleRect . width > = 0 ? & layerContentsVisibleRect : nullptr ) ;
2014-06-23 04:24:00 +00:00
}
if ( itemType = = nsDisplayItem : : TYPE_SCROLL_LAYER ) {
nsDisplayScrollLayer * scrollItem = static_cast < nsDisplayScrollLayer * > ( item ) ;
newLayerEntry - > mOpaqueForAnimatedGeometryRootParent =
scrollItem - > IsDisplayPortOpaque ( ) ;
}
2012-10-17 08:00:00 +00:00
/**
* No need to allocate geometry for items that aren ' t
* part of a ThebesLayer .
*/
nsAutoPtr < nsDisplayItemGeometry > dummy ;
2014-03-20 06:49:27 +00:00
mLayerBuilder - > AddLayerDisplayItem ( ownLayer , item ,
2013-03-04 09:56:02 +00:00
itemClip , layerState ,
2012-10-11 23:38:24 +00:00
topLeft , nullptr ,
2012-10-17 08:00:00 +00:00
dummy ) ;
2010-05-21 03:20:48 +00:00
} else {
2014-06-09 04:48:00 +00:00
ThebesLayerData * thebesLayerData =
2014-02-21 01:11:17 +00:00
FindThebesLayerFor ( item , itemVisibleRect , animatedGeometryRoot , topLeft ,
shouldFixToViewport ) ;
2013-12-16 12:16:24 +00:00
if ( itemType = = nsDisplayItem : : TYPE_LAYER_EVENT_REGIONS ) {
nsDisplayLayerEventRegions * eventRegions =
static_cast < nsDisplayLayerEventRegions * > ( item ) ;
2014-06-09 04:48:00 +00:00
thebesLayerData - > AccumulateEventRegions ( eventRegions - > HitRegion ( ) ,
eventRegions - > MaybeHitRegion ( ) ,
eventRegions - > DispatchToContentHitRegion ( ) ) ;
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
2014-06-09 04:48:00 +00:00
thebesLayerData - > UpdateCommonClipCount ( itemClip ) ;
2013-12-16 12:16:24 +00:00
nsAutoPtr < nsDisplayItemGeometry > geometry ( item - > AllocateGeometry ( mBuilder ) ) ;
2014-06-09 04:48:00 +00:00
InvalidateForLayerChange ( item , thebesLayerData - > mLayer , itemClip , topLeft , geometry ) ;
2014-06-09 04:48:00 +00:00
2014-06-23 04:24:00 +00:00
mLayerBuilder - > AddThebesDisplayItem ( thebesLayerData , item , itemClip , itemVisibleRect ,
* this , layerState , topLeft , geometry ) ;
nsIntRegion opaquePixels = ComputeOpaqueRect ( item ,
animatedGeometryRoot , thebesLayerData - > mFixedPosFrameForLayerData ,
itemClip , aList ,
& thebesLayerData - > mHideAllLayersBelow ) ;
thebesLayerData - > Accumulate ( this , item , opaquePixels ,
itemVisibleRect , itemDrawRect , itemClip ) ;
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-03-20 06:49:27 +00:00
ContainerState : : InvalidateForLayerChange ( nsDisplayItem * aItem ,
2012-08-29 05:48:43 +00:00
Layer * aNewLayer ,
2013-03-04 09:55:59 +00:00
const DisplayItemClip & aClip ,
2012-10-11 23:38:24 +00:00
const nsPoint & aTopLeft ,
nsDisplayItemGeometry * aGeometry )
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 " ) ;
2013-10-08 18:47:21 +00:00
nsDisplayItemGeometry * oldGeometry = nullptr ;
DisplayItemClip * oldClip = nullptr ;
2012-10-16 01:23:07 +00:00
nsAutoTArray < nsIFrame * , 4 > changedFrames ;
2012-11-06 22:04:53 +00:00
bool isInvalid = false ;
Layer * oldLayer = mLayerBuilder - > GetOldLayerFor ( aItem , & oldGeometry , & oldClip , & changedFrames , & isInvalid ) ;
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.
2010-07-15 21:08:05 +00:00
ThebesLayer * t = oldLayer - > AsThebesLayer ( ) ;
if ( t ) {
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
}
if ( aNewLayer ) {
2012-08-29 05:47:15 +00:00
ThebesLayer * newThebesLayer = aNewLayer - > AsThebesLayer ( ) ;
if ( newThebesLayer ) {
InvalidatePostTransformRegion ( newThebesLayer ,
2012-10-16 01:10:43 +00:00
aGeometry - > ComputeInvalidationRegion ( ) ,
aClip ,
2012-08-29 05:47:15 +00:00
GetTranslationForThebesLayer ( newThebesLayer ) ) ;
2010-07-15 21:08:05 +00:00
}
}
2012-12-10 05:34:31 +00:00
aItem - > NotifyRenderingChanged ( ) ;
2012-08-29 05:47:15 +00:00
return ;
2014-03-20 06:49:27 +00:00
}
2012-08-29 05:47:15 +00:00
if ( ! aNewLayer ) {
return ;
}
2010-07-15 21:08:05 +00:00
2012-08-29 05:47:15 +00:00
ThebesLayer * newThebesLayer = aNewLayer - > AsThebesLayer ( ) ;
2012-08-29 05:47:18 +00:00
if ( ! newThebesLayer ) {
2012-08-29 05:47:15 +00:00
return ;
}
ThebesDisplayItemLayerUserData * data =
static_cast < ThebesDisplayItemLayerUserData * > ( newThebesLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
2014-03-20 06:49:27 +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 ;
2013-09-25 21:07:26 +00:00
nsPoint shift = aTopLeft - data - > mLastAnimatedGeometryRootOrigin ;
2014-04-24 02:56:15 +00:00
bool notifyRenderingChanged = true ;
2012-08-29 05:47:15 +00:00
if ( ! oldLayer ) {
2012-08-29 05:48:43 +00:00
// This item is being added for the first time, invalidate its entire area.
2012-08-29 05:47:15 +00:00
//TODO: We call GetGeometry again in AddThebesDisplayItem, we should reuse this.
2012-10-16 01:10:43 +00:00
combined = aClip . ApplyNonRoundedIntersection ( aGeometry - > ComputeInvalidationRegion ( ) ) ;
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) added to layer %p! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , aNewLayer ) ;
2013-05-13 23:47:02 +00:00
}
2012-08-29 05:47:15 +00:00
# endif
2012-11-06 22:04:53 +00:00
} else if ( isInvalid | | ( aItem - > IsInvalid ( invalid ) & & invalid . IsEmpty ( ) ) ) {
2012-08-29 05:48:44 +00:00
// Either layout marked item as needing repainting, invalidate the entire old and new areas.
2012-10-16 01:10:43 +00:00
combined = oldClip - > ApplyNonRoundedIntersection ( oldGeometry - > ComputeInvalidationRegion ( ) ) ;
combined . MoveBy ( shift ) ;
combined . Or ( combined , aClip . ApplyNonRoundedIntersection ( aGeometry - > ComputeInvalidationRegion ( ) ) ) ;
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) (in layer %p) belongs to an invalidated frame! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , aNewLayer ) ;
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
// We have an optimization to cache the drawing background-attachment: fixed canvas
// 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).
if ( oldGeometry - > ComputeInvalidationRegion ( ) = = aGeometry - > ComputeInvalidationRegion ( ) & &
* oldClip = = aClip & & invalid . IsEmpty ( ) & & changedFrames . Length ( ) = = 0 ) {
notifyRenderingChanged = false ;
}
2012-08-29 05:47:15 +00:00
oldGeometry - > MoveBy ( shift ) ;
aItem - > ComputeInvalidationRegion ( mBuilder , oldGeometry , & combined ) ;
2012-08-29 05:48:44 +00:00
oldClip - > AddOffsetAndComputeDifference ( shift , oldGeometry - > ComputeInvalidationRegion ( ) ,
2012-10-11 23:38:24 +00:00
aClip , aGeometry - > ComputeInvalidationRegion ( ) ,
2012-08-29 05:48:44 +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
nsRegion clip ;
2013-03-04 09:56:00 +00:00
if ( aClip . ComputeRegionInClips ( oldClip , shift , & clip ) ) {
2012-10-16 01:10:43 +00:00
combined . And ( combined , clip ) ;
}
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
if ( ! combined . IsEmpty ( ) ) {
2013-11-23 22:44:18 +00:00
printf_stderr ( " Display item type %s(%p) (in layer %p) changed geometry! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , aNewLayer ) ;
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 ) {
aItem - > NotifyRenderingChanged ( ) ;
}
2012-08-29 05:47:15 +00:00
InvalidatePostTransformRegion ( newThebesLayer ,
combined . ScaleToOutsidePixels ( data - > mXScale , data - > mYScale , mAppUnitsPerDevPixel ) ,
GetTranslationForThebesLayer ( newThebesLayer ) ) ;
2010-07-15 21:08:05 +00:00
}
}
2010-07-15 21:07:51 +00:00
void
2013-12-16 12:16:24 +00:00
FrameLayerBuilder : : AddThebesDisplayItem ( ThebesLayerData * aLayerData ,
2010-07-15 21:07:51 +00:00
nsDisplayItem * aItem ,
2013-03-04 09:55:59 +00:00
const DisplayItemClip & aClip ,
2014-06-23 04:24:00 +00:00
const nsIntRect & aItemVisibleRect ,
const ContainerState & aContainerState ,
2012-08-29 05:47:15 +00:00
LayerState aLayerState ,
2012-10-11 23:38:24 +00:00
const nsPoint & aTopLeft ,
nsAutoPtr < nsDisplayItemGeometry > aGeometry )
2010-07-15 21:07:51 +00:00
{
2013-12-16 12:16:24 +00:00
ThebesLayer * layer = aLayerData - > mLayer ;
2012-10-16 01:10:43 +00:00
ThebesDisplayItemLayerUserData * thebesData =
2013-12-16 12:16:24 +00:00
static_cast < ThebesDisplayItemLayerUserData * >
( layer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
2013-11-06 19:10:49 +00:00
nsRefPtr < 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 ,
2013-09-25 21:07:26 +00:00
aTopLeft - thebesData - > mLastAnimatedGeometryRootOrigin ,
2013-03-04 09:56:00 +00:00
& clip ) ;
2012-10-16 01:10:43 +00:00
if ( hasClip ) {
2014-03-20 06:49:27 +00:00
intClip = clip . GetBounds ( ) . ScaleToOutsidePixels ( thebesData - > mXScale ,
thebesData - > mYScale ,
2012-10-16 01:10:43 +00:00
thebesData - > mAppUnitsPerDevPixel ) ;
}
2012-08-29 05:47:15 +00:00
}
2013-12-16 12:16:24 +00:00
AddLayerDisplayItem ( layer , aItem , aClip , aLayerState , aTopLeft , tempManager , aGeometry ) ;
2010-07-15 21:07:51 +00:00
2013-12-16 12:16:24 +00:00
ThebesLayerItemsEntry * entry = mThebesLayerItems . 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 ) {
FrameLayerBuilder * layerBuilder = new FrameLayerBuilder ( ) ;
2013-12-16 12:16:24 +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
2012-08-29 05:47:18 +00:00
nsAutoPtr < LayerProperties > props ( LayerProperties : : CloneFrom ( tempManager - > GetRoot ( ) ) ) ;
2013-12-16 12:16:24 +00:00
nsRefPtr < 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 ) ) ;
nsIntRegion rgn = visibleRect . ToOutsidePixels ( thebesData - > mAppUnitsPerDevPixel ) ;
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
2013-12-16 12:16:24 +00:00
nsIntPoint offset = GetLastPaintOffset ( layer ) - GetTranslationForThebesLayer ( layer ) ;
2012-09-16 22:57:22 +00:00
props - > MoveBy ( - offset ) ;
2013-12-16 12:16:24 +00:00
nsIntRegion invalid = props - > ComputeDifferences ( tmpLayer , nullptr ) ;
2012-08-29 05:47:18 +00:00
if ( aLayerState = = LAYER_SVG_EFFECTS ) {
2013-04-19 12:02:13 +00:00
invalid = nsSVGIntegrationUtils : : AdjustInvalidAreaForSVGEffects ( aItem - > Frame ( ) ,
2012-11-28 04:06:07 +00:00
aItem - > ToReferenceFrame ( ) ,
2014-04-24 08:25:17 +00:00
invalid ) ;
2012-08-29 05:47:18 +00:00
}
if ( ! invalid . IsEmpty ( ) ) {
2013-05-13 23:47:02 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-12-16 12:16:24 +00:00
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 ) ;
2013-05-13 23:47:02 +00:00
}
2012-08-29 05:47:18 +00:00
# endif
2012-10-16 01:10:43 +00:00
if ( hasClip ) {
2012-11-12 18:31:15 +00:00
invalid . And ( invalid , intClip ) ;
2012-10-16 01:10:43 +00:00
}
invalid . ScaleRoundOut ( thebesData - > mXScale , thebesData - > mYScale ) ;
2013-12-16 12:16:24 +00:00
InvalidatePostTransformRegion ( layer , invalid ,
GetTranslationForThebesLayer ( 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 ) {
2012-10-19 04:36:00 +00:00
oldData - > UpdateContents ( 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
nsRefPtr < DisplayItemData > data =
2012-10-12 02:39:46 +00:00
new DisplayItemData ( lmd , aItem - > GetPerFrameKey ( ) ,
aLayer , aState , mContainerLayerGeneration ) ;
2013-04-19 12:02:13 +00:00
data - > AddFrame ( aItem - > Frame ( ) ) ;
2012-10-12 02:39:46 +00:00
2012-10-11 23:38:24 +00:00
nsAutoTArray < nsIFrame * , 4 > mergedFrames ;
aItem - > GetMergedFrames ( & mergedFrames ) ;
for ( uint32_t i = 0 ; i < mergedFrames . Length ( ) ; + + i ) {
2012-10-12 02:39:46 +00:00
data - > AddFrame ( mergedFrames [ i ] ) ;
2012-08-29 05:47:15 +00:00
}
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 ) {
oldData - > UpdateContents ( aLayer , aState , mContainerLayerGeneration ) ;
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 ) ) ;
nsRefPtr < DisplayItemData > data =
new DisplayItemData ( lmd , aDisplayItemKey , aLayer ,
aState , mContainerLayerGeneration ) ;
data - > AddFrame ( aFrame ) ;
lmd - > mDisplayItems . PutEntry ( data ) ;
2012-08-29 05:47:15 +00:00
}
FrameLayerBuilder : : ClippedDisplayItem : : ~ ClippedDisplayItem ( )
{
2012-10-23 11:05:14 +00:00
if ( mInactiveLayerManager ) {
BasicLayerManager * basic = static_cast < BasicLayerManager * > ( mInactiveLayerManager . get ( ) ) ;
2012-08-29 05:47:15 +00:00
basic - > SetUserData ( & gLayerManagerLayerBuilder , nullptr ) ;
2012-08-29 10:53:27 +00:00
}
}
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 ,
2013-03-04 09:55:59 +00:00
const DisplayItemClip & aClip ,
2012-08-29 05:47:15 +00:00
LayerState aLayerState ,
const nsPoint & aTopLeft ,
2013-11-06 19:10:49 +00:00
BasicLayerManager * aManager ,
2012-10-11 23:38:24 +00:00
nsAutoPtr < nsDisplayItemGeometry > aGeometry )
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
ThebesLayer * t = aLayer - > AsThebesLayer ( ) ;
if ( t ) {
2012-10-11 23:38:24 +00:00
data - > mGeometry = aGeometry ;
2012-08-29 05:48:43 +00:00
data - > mClip = aClip ;
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
FrameLayerBuilder : : GetLastPaintOffset ( ThebesLayer * aLayer )
2011-05-16 23:05:56 +00:00
{
ThebesLayerItemsEntry * entry = mThebesLayerItems . 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 ;
}
2011-05-18 05:48:43 +00:00
return GetTranslationForThebesLayer ( aLayer ) ;
2011-05-16 23:05:56 +00:00
}
void
2011-05-18 05:48:43 +00:00
FrameLayerBuilder : : SaveLastPaintOffset ( ThebesLayer * aLayer )
2011-05-16 23:05:56 +00:00
{
ThebesLayerItemsEntry * entry = mThebesLayerItems . PutEntry ( aLayer ) ;
if ( entry ) {
2012-09-11 21:17:26 +00:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2011-05-18 05:48:43 +00:00
entry - > mLastPaintOffset = GetTranslationForThebesLayer ( aLayer ) ;
2011-10-17 14:59:28 +00:00
entry - > mHasExplicitLastPaintOffset = true ;
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 ) ,
" Mask layer in layer tree; could not be recycled. " ) ;
2012-08-20 10:00:49 +00:00
if ( layer - > HasUserData ( & gThebesDisplayItemLayerUserData ) ) {
2010-07-15 21:08:03 +00:00
NS_ASSERTION ( layer - > AsThebesLayer ( ) , " Wrong layer type " ) ;
mRecycledThebesLayers . AppendElement ( static_cast < ThebesLayer * > ( 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. " ) ;
mRecycledMaskImageLayers . Put ( layer , static_cast < ImageLayer * > ( maskLayer ) ) ;
}
2010-07-15 21:07:51 +00:00
}
}
2014-06-23 04:24:00 +00:00
struct OpaqueRegionEntry {
const nsIFrame * mAnimatedGeometryRoot ;
const nsIFrame * mFixedPosFrameForLayerData ;
nsIntRegion mOpaqueRegion ;
} ;
static OpaqueRegionEntry *
FindOpaqueRegionEntry ( nsTArray < OpaqueRegionEntry > & aEntries ,
const nsIFrame * aAnimatedGeometryRoot ,
const nsIFrame * aFixedPosFrameForLayerData )
{
for ( uint32_t i = 0 ; i < aEntries . Length ( ) ; + + i ) {
OpaqueRegionEntry * d = & aEntries [ i ] ;
if ( d - > mAnimatedGeometryRoot = = aAnimatedGeometryRoot & &
d - > mFixedPosFrameForLayerData = = aFixedPosFrameForLayerData ) {
return d ;
}
}
return nullptr ;
}
void
ContainerState : : ApplyOcclusionCulling ( nsIntRegion * aOpaqueRegionForContainer )
{
nsAutoTArray < OpaqueRegionEntry , 4 > opaqueRegions ;
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 ;
}
OpaqueRegionEntry * data = FindOpaqueRegionEntry ( opaqueRegions ,
e - > mAnimatedGeometryRoot , e - > mFixedPosFrameForLayerData ) ;
if ( hideAll ) {
e - > mVisibleRegion . SetEmpty ( ) ;
} else if ( data ) {
e - > mVisibleRegion . Sub ( e - > mVisibleRegion , data - > mOpaqueRegion ) ;
}
if ( ! e - > mOpaqueRegion . IsEmpty ( ) ) {
const nsIFrame * animatedGeometryRootToCover = e - > mAnimatedGeometryRoot ;
if ( e - > mOpaqueForAnimatedGeometryRootParent & &
nsLayoutUtils : : GetAnimatedGeometryRootForFrame ( e - > mAnimatedGeometryRoot - > GetParent ( ) ,
mContainerAnimatedGeometryRoot )
= = mContainerAnimatedGeometryRoot ) {
animatedGeometryRootToCover = mContainerAnimatedGeometryRoot ;
data = FindOpaqueRegionEntry ( opaqueRegions ,
animatedGeometryRootToCover , e - > mFixedPosFrameForLayerData ) ;
}
if ( ! data ) {
if ( animatedGeometryRootToCover = = mContainerAnimatedGeometryRoot & &
! e - > mFixedPosFrameForLayerData ) {
NS_ASSERTION ( opaqueRegionForContainer = = - 1 , " Already found it? " ) ;
opaqueRegionForContainer = opaqueRegions . Length ( ) ;
}
data = opaqueRegions . AppendElement ( ) ;
data - > mAnimatedGeometryRoot = animatedGeometryRootToCover ;
data - > mFixedPosFrameForLayerData = e - > mFixedPosFrameForLayerData ;
}
data - > mOpaqueRegion . Or ( data - > mOpaqueRegion , e - > mOpaqueRegion ) ;
if ( e - > mHideAllLayersBelow ) {
hideAll = true ;
}
}
SetOuterVisibleRegionForLayer ( e - > mLayer , e - > mVisibleRegion ,
e - > mLayerContentsVisibleRect . width > = 0 ? & e - > mLayerContentsVisibleRect : nullptr ) ;
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
2014-06-23 04:24:00 +00:00
ContainerState : : Finish ( uint32_t * aTextContentFlags , LayerManagerData * aData ,
const nsIntRect & aContainerPixelBounds ,
nsDisplayList * aChildItems , bool & aHasComponentAlphaChildren )
2010-07-15 21:07:51 +00:00
{
while ( ! mThebesLayerDataStack . IsEmpty ( ) ) {
PopThebesLayerData ( ) ;
}
2014-03-20 06:49:27 +00:00
2014-06-09 04:48:00 +00:00
NS_ASSERTION ( mContainerBounds . IsEqualInterior ( mAccumulatedChildBounds ) ,
" Bounds computation mismatch " ) ;
2014-06-23 04:24:00 +00:00
if ( mLayerBuilder - > IsBuildingRetainedLayers ( ) ) {
nsIntRegion containerOpaqueRegion ;
ApplyOcclusionCulling ( & containerOpaqueRegion ) ;
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 |
Layer : : CONTENT_COMPONENT_ALPHA_DESCENDANT ) ;
2014-07-18 06:48:23 +00:00
// Notify the parent of component alpha children unless it's coming from
// within a transformed child since we don't want flattening of component
// alpha layers to happen across transforms. Re-rendering the text during
// transform animations looks worse than losing subpixel-AA.
if ( ( layer - > GetContentFlags ( ) & Layer : : CONTENT_COMPONENT_ALPHA ) & &
( layer - > GetType ( ) ! = Layer : : TYPE_CONTAINER | |
layer - > GetBaseTransform ( ) . IsIdentity ( ) ) ) {
aHasComponentAlphaChildren = true ;
}
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 ) ;
continue ;
2010-07-15 21:07:51 +00:00
}
2012-08-29 10:53:06 +00:00
NS_ASSERTION ( layer - > GetParent ( ) = = mContainerLayer ,
" Layer shouldn't be the child of some other container " ) ;
2013-03-22 02:17:29 +00:00
if ( layer - > GetPrevSibling ( ) ! = prevChild ) {
mContainerLayer - > RepositionChild ( layer , prevChild ) ;
}
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 ,
2014-07-09 02:01:54 +00:00
const nsRect & aVisibleRect ,
2011-06-22 12:11:27 +00:00
const gfx3DMatrix * 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 ;
2011-06-22 12:11:27 +00:00
gfx3DMatrix transform =
2011-08-27 00:06:03 +00:00
gfx3DMatrix : : ScalingMatrix ( 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 ;
2012-08-25 04:41:46 +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.
2014-05-12 19:37:21 +00:00
// 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
}
gfxMatrix transform2d ;
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
}
2012-12-18 05:58:44 +00:00
transform = transform * gfx3DMatrix : : Translation ( 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?
2013-12-16 05:37:47 +00:00
if ( canDraw2D ) {
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
2012-12-21 21:58:17 +00:00
if ( aContainerFrame - > GetContent ( ) & &
nsLayoutUtils : : HasAnimationsForCompositor (
aContainerFrame - > GetContent ( ) , eCSSProperty_transform ) ) {
2014-02-18 14:58:01 +00:00
scale = nsLayoutUtils : : ComputeSuitableScaleForAnimation ( aContainerFrame - > GetContent ( ) ) ;
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
2013-05-12 23:12:19 +00:00
scale = RoundToFloatPrecision ( 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.
gfxMatrix frameTransform ;
2013-09-04 11:30:57 +00:00
if ( ActiveLayerTracker : : IsStyleAnimated ( 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 {
// 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
// mean we try render a layer bigger than the max texture size. Apply
// clmaping to prevent this.
if ( aTransform ) {
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-01-27 15:28:33 +00:00
Matrix4x4 baseTransform ;
ToMatrix4x4 ( transform , baseTransform ) ;
aLayer - > SetBaseTransform ( baseTransform ) ;
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 ;
2013-09-04 11:30:57 +00:00
if ( ActiveLayerTracker : : IsStyleAnimated ( aContainerFrame , eCSSProperty_transform ) ) {
2013-03-21 02:33:00 +00:00
aOutgoingScale . mInActiveTransformedSubtree = true ;
2011-06-22 12:11:28 +00:00
}
}
2014-06-23 04:24:00 +00:00
if ( aLayerBuilder - > IsBuildingRetainedLayers ( ) & &
( ! canDraw2D | | transform2d . HasNonIntegerTranslation ( ) ) ) {
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
}
2012-07-23 03:00:36 +00:00
/* static */ PLDHashOperator
2012-10-12 02:39:46 +00:00
FrameLayerBuilder : : RestoreDisplayItemData ( nsRefPtrHashKey < DisplayItemData > * aEntry , void * aUserArg )
2012-07-23 03:00:36 +00:00
{
2012-10-12 02:39:46 +00:00
DisplayItemData * data = aEntry - > GetKey ( ) ;
2012-08-22 15:56:38 +00:00
uint32_t * generation = static_cast < uint32_t * > ( aUserArg ) ;
2012-07-23 03:00:36 +00:00
2012-10-12 02:39:46 +00:00
if ( data - > mUsed & & data - > mContainerLayerGeneration > = * generation ) {
2012-07-23 03:00:36 +00:00
return PL_DHASH_REMOVE ;
}
return PL_DHASH_NEXT ;
}
/* static */ PLDHashOperator
FrameLayerBuilder : : RestoreThebesLayerItemEntries ( ThebesLayerItemsEntry * aEntry , void * aUserArg )
{
2012-08-22 15:56:38 +00:00
uint32_t * generation = static_cast < uint32_t * > ( aUserArg ) ;
2012-07-23 03:00:36 +00:00
if ( aEntry - > mContainerLayerGeneration > = * generation ) {
2012-10-12 02:39:46 +00:00
// 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.
2012-07-23 03:00:36 +00:00
return PL_DHASH_REMOVE ;
}
2012-08-22 15:56:38 +00:00
for ( uint32_t i = 0 ; i < aEntry - > mItems . Length ( ) ; i + + ) {
2012-07-23 03:00:36 +00:00
if ( aEntry - > mItems [ i ] . mContainerLayerGeneration > = * generation ) {
aEntry - > mItems . TruncateLength ( i ) ;
return PL_DHASH_NEXT ;
}
}
return PL_DHASH_NEXT ;
}
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 ,
2013-03-22 02:17:29 +00:00
const gfx3DMatrix * aTransform ,
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 ;
}
2010-07-15 21:07:51 +00:00
nsRefPtr < 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 " ) ;
if ( oldLayer - > HasUserData ( & gThebesDisplayItemLayerUserData ) ) {
// The old layer for this item is actually our ThebesLayer
// because we rendered its layer into that ThebesLayer. So we
// don't actually have a retained container layer.
} else {
NS_ASSERTION ( oldLayer - > GetType ( ) = = Layer : : TYPE_CONTAINER ,
" Wrong layer type " ) ;
containerLayer = static_cast < ContainerLayer * > ( oldLayer ) ;
2012-07-30 14:20:58 +00:00
containerLayer - > SetMaskLayer ( nullptr ) ;
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
// determine which thebes layer gets invalidated. Since an empty layer
// 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 ( ) ;
}
2013-09-27 06:01:16 +00:00
ContainerLayerParameters scaleParameters ;
2014-07-15 11:49:38 +00:00
nsRect bounds = aChildren - > GetBounds ( aBuilder ) ;
nsRect childrenVisible =
aContainerItem ? aContainerItem - > GetVisibleRectForChildren ( ) :
aContainerFrame - > GetVisualOverflowRectRelativeToSelf ( ) ;
if ( ! ChooseScaleAndSetTransform ( this , aBuilder , aContainerFrame ,
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-07-30 14:20:58 +00:00
nsRefPtr < RefCountedRegion > thebesLayerInvalidRegion = nullptr ;
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 ;
2012-11-22 05:34:32 +00:00
uint32_t stateFlags = 0 ;
if ( ( aContainerFrame - > GetStateBits ( ) & NS_FRAME_NO_COMPONENT_ALPHA ) & &
2014-07-18 06:48:23 +00:00
mRetainingManager & & mRetainingManager - > ShouldAvoidComponentAlphaLayers ( ) ) {
2012-11-22 05:34:32 +00:00
stateFlags = ContainerState : : NO_COMPONENT_ALPHA ;
}
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 ,
2012-09-28 11:19:39 +00:00
containerLayer , scaleParameters ) ;
2014-03-20 06:49:27 +00:00
2013-03-04 09:56:02 +00:00
state . ProcessDisplayItems ( aChildren , stateFlags ) ;
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 ;
2012-07-23 03:00:36 +00:00
pixBounds = state . ScaleToOutsidePixels ( bounds , false ) ;
appUnitsPerDevPixel = state . GetAppUnitsPerDevPixel ( ) ;
2014-06-23 04:24:00 +00:00
state . Finish ( & flags , data , pixBounds , aChildren , hasComponentAlphaChildren ) ;
2012-07-23 03:00:36 +00:00
2014-07-18 06:48:23 +00:00
if ( hasComponentAlphaChildren & &
2012-07-23 03:00:36 +00:00
mRetainingManager & &
2014-07-18 06:48:23 +00:00
mRetainingManager - > ShouldAvoidComponentAlphaLayers ( ) & &
2014-07-18 06:48:22 +00:00
containerLayer - > HasMultipleChildren ( ) & &
2012-07-23 03:00:36 +00:00
! stateFlags ) {
// 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.
stateFlags = ContainerState : : NO_COMPONENT_ALPHA ;
2012-10-12 02:39:46 +00:00
data - > mDisplayItems . EnumerateEntries ( RestoreDisplayItemData ,
2012-07-23 03:00:36 +00:00
& mContainerLayerGeneration ) ;
mThebesLayerItems . EnumerateEntries ( RestoreThebesLayerItemEntries ,
& mContainerLayerGeneration ) ;
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 ) ;
2012-07-23 03:00:36 +00:00
if ( bounds . Contains ( pixBounds . ToAppUnits ( 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 ) {
containerLayer - > SetVisibleRegion ( pixBounds ) ;
}
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 ;
2010-09-02 09:18:39 +00:00
if ( layer - > HasUserData ( & gThebesDisplayItemLayerUserData ) ) {
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
}
2012-07-30 14:20:58 +00:00
layer - > SetMaskLayer ( nullptr ) ;
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 )
{
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-11 23:38:24 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
array - > ElementAt ( i ) - > mParent - > mInvalidateAllLayers = true ;
}
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
2014-03-20 06:49:27 +00:00
nsTArray < DisplayItemData * > * array =
2012-10-11 23:38:24 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2012-10-12 02:39:46 +00:00
DisplayItemData * element = array - > ElementAt ( i ) ;
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 ) & &
! layer - > HasUserData ( & gThebesDisplayItemLayerUserData ) ) {
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
{
2012-08-04 12:26:38 +00:00
gfx3DMatrix transform =
gfx3DMatrix : : ScalingMatrix ( 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 ;
}
2012-08-04 12:26:38 +00:00
gfxMatrix transform2d ;
if ( transform . CanDraw2D ( & transform2d ) ) {
return transform2d . ScaleFactors ( true ) ;
}
return gfxSize ( 1.0 , 1.0 ) ;
}
gfxSize
FrameLayerBuilder : : GetThebesLayerScaleForFrame ( nsIFrame * aFrame )
{
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
nsTArray < DisplayItemData * > * array =
2014-06-26 03:55:20 +00:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( 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 + + ) {
2012-08-29 05:47:15 +00:00
Layer * layer = array - > ElementAt ( i ) - > mLayer ;
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 ( ) ) {
ThebesDisplayItemLayerUserData * data =
static_cast < ThebesDisplayItemLayerUserData * >
( l - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
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
}
}
}
2012-08-04 12:26:38 +00:00
return PredictScaleForContent ( aFrame , last ,
last - > PresContext ( ) - > PresShell ( ) - > GetResolution ( ) ) ;
2012-05-10 05:24:18 +00:00
}
2012-03-05 18:09:05 +00:00
# ifdef MOZ_DUMP_PAINTING
2014-06-20 06:42:30 +00:00
static void DebugPaintItem ( nsRenderingContext * aDest ,
nsPresContext * aPresContext ,
nsDisplayItem * aItem ,
nsDisplayListBuilder * aBuilder )
2012-03-05 18:09:05 +00:00
{
2012-04-10 11:24:18 +00:00
bool snap ;
nsRect appUnitBounds = aItem - > GetBounds ( aBuilder , & snap ) ;
2012-03-05 18:09:05 +00:00
gfxRect bounds ( appUnitBounds . x , appUnitBounds . y , appUnitBounds . width , appUnitBounds . height ) ;
2014-06-20 06:42:30 +00:00
bounds . ScaleInverse ( aPresContext - > AppUnitsPerDevPixel ( ) ) ;
2012-03-05 18:09:05 +00:00
2014-06-27 11:19:40 +00:00
RefPtr < DrawTarget > tempDT =
gfxPlatform : : GetPlatform ( ) - > CreateOffscreenContentDrawTarget (
IntSize ( bounds . width , bounds . height ) ,
SurfaceFormat : : B8G8R8A8 ) ;
nsRefPtr < gfxContext > context = new gfxContext ( tempDT ) ;
context - > SetMatrix ( gfxMatrix ( ) . Translate ( - gfxPoint ( bounds . x , bounds . y ) ) ) ;
2012-03-05 18:09:05 +00:00
nsRefPtr < nsRenderingContext > ctx = new nsRenderingContext ( ) ;
ctx - > Init ( aDest - > DeviceContext ( ) , context ) ;
aItem - > Paint ( aBuilder , ctx ) ;
2014-06-27 11:19:40 +00:00
RefPtr < SourceSurface > surface = tempDT - > Snapshot ( ) ;
DumpPaintedImage ( aItem , surface ) ;
2012-07-31 17:28:21 +00:00
2014-06-27 11:19:40 +00:00
DrawTarget * drawTarget = aDest - > ThebesContext ( ) - > GetDrawTarget ( ) ;
Rect rect = ToRect ( bounds ) ;
drawTarget - > DrawSurface ( surface , rect , Rect ( Point ( 0 , 0 ) , rect . Size ( ) ) ) ;
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 ,
2010-08-08 18:49:07 +00:00
" a thebes layer should contain items only at the same zoom " ) ;
2010-07-15 21:07:51 +00:00
2013-03-04 09:56:02 +00:00
NS_ABORT_IF_FALSE ( clip . HasClip ( ) | |
clip . GetRoundedRectCount ( ) = = 0 ,
2010-09-09 15:21:46 +00:00
" If we have rounded rects, we must have a clip rect " ) ;
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 )
{
2013-11-06 19:10:50 +00:00
int32_t appUnitsPerDevPixel = aPresContext - > AppUnitsPerDevPixel ( ) ;
nsRect boundRect = aRect . ToAppUnits ( appUnitsPerDevPixel ) ;
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
PROFILER_LABEL_PRINTF ( " DisplayList " , " Draw " , js : : ProfileEntry : : Category : : GRAPHICS , " %s %p " , cdi - > mItem - > Name ( ) , cdi - > mItem ) ;
# else
PROFILER_LABEL_PRINTF ( " DisplayList " , " Draw " , js : : ProfileEntry : : Category : : GRAPHICS , " %p " , cdi - > mItem ) ;
# 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 ) {
2013-11-06 19:10:49 +00:00
PaintInactiveLayer ( aBuilder , cdi - > mInactiveLayerManager , cdi - > mItem , aContext , aRC ) ;
2010-07-15 21:08:05 +00:00
} else {
2013-04-19 12:02:13 +00:00
nsIFrame * frame = cdi - > mItem - > Frame ( ) ;
2013-04-19 12:01:41 +00:00
frame - > AddStateBits ( NS_FRAME_PAINTED_THEBES ) ;
2012-03-05 18:09:05 +00:00
# ifdef MOZ_DUMP_PAINTING
if ( gfxUtils : : sDumpPainting ) {
2014-06-20 06:42:30 +00:00
DebugPaintItem ( aRC , 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 .
*/
static bool ShouldDrawRectsSeparately ( gfxContext * aContext , DrawRegionClip aClip )
{
2014-05-08 02:56:48 +00:00
if ( ! gfxPrefs : : LayoutPaintRectsSeparately ( ) | |
2014-01-23 18:26:41 +00:00
aClip = = DrawRegionClip : : CLIP_NONE ) {
2013-11-06 19:10:50 +00:00
return false ;
}
2013-11-14 00:46:19 +00:00
2013-11-06 19:10:50 +00:00
DrawTarget * dt = aContext - > GetDrawTarget ( ) ;
2014-06-19 20:35:33 +00:00
return dt - > GetBackendType ( ) = = BackendType : : DIRECT2D ;
2013-11-06 19:10:50 +00:00
}
static void DrawForcedBackgroundColor ( gfxContext * aContext , Layer * aLayer , nscolor aBackgroundColor )
{
if ( NS_GET_A ( aBackgroundColor ) > 0 ) {
nsIntRect r = aLayer - > GetVisibleRegion ( ) . GetBounds ( ) ;
aContext - > NewPath ( ) ;
aContext - > Rectangle ( gfxRect ( r . x , r . y , r . width , r . height ) ) ;
aContext - > SetColor ( gfxRGBA ( aBackgroundColor ) ) ;
aContext - > Fill ( ) ;
}
}
2013-11-06 19:10:49 +00:00
/*
* A note on residual transforms :
*
* In a transformed subtree we sometimes apply the ThebesLayer ' s
* " residual transform " when drawing content into the ThebesLayer .
* 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
* of the content of the ThebesLayer exactly matches what it would be if
* we used cairo / Thebes to draw directly to the screen without going through
* retained layer buffers .
*
* The visible and valid regions of the ThebesLayer are computed without
* 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
FrameLayerBuilder : : DrawThebesLayer ( ThebesLayer * aLayer ,
gfxContext * aContext ,
const nsIntRegion & aRegionToDraw ,
2013-11-06 19:10:50 +00:00
DrawRegionClip aClip ,
2013-11-06 19:10:49 +00:00
const nsIntRegion & aRegionToInvalidate ,
void * aCallbackData )
{
2014-05-23 21:12:29 +00:00
PROFILER_LABEL ( " FrameLayerBuilder " , " DrawThebesLayer " ,
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 ;
ThebesLayerItemsEntry * entry = layerBuilder - > mThebesLayerItems . GetEntry ( aLayer ) ;
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
2013-11-06 19:10:49 +00:00
ThebesDisplayItemLayerUserData * userData =
static_cast < ThebesDisplayItemLayerUserData * >
( aLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
NS_ASSERTION ( userData , " where did our user data go? " ) ;
2013-11-06 19:10:50 +00:00
bool shouldDrawRectsSeparately = ShouldDrawRectsSeparately ( aContext , aClip ) ;
if ( ! shouldDrawRectsSeparately ) {
2014-01-23 18:26:41 +00:00
if ( aClip = = DrawRegionClip : : DRAW_SNAPPED ) {
2013-11-06 19:10:50 +00:00
gfxUtils : : ClipToRegionSnapped ( aContext , aRegionToDraw ) ;
2014-01-23 18:26:41 +00:00
} else if ( aClip = = DrawRegionClip : : DRAW ) {
2013-11-06 19:10:50 +00:00
gfxUtils : : ClipToRegion ( aContext , aRegionToDraw ) ;
}
DrawForcedBackgroundColor ( aContext , aLayer , userData - > mForcedBackgroundColor ) ;
2013-11-06 19:10:49 +00:00
}
// make the origin of the context coincide with the origin of the
// ThebesLayer
gfxContextMatrixAutoSaveRestore saveMatrix ( aContext ) ;
nsIntPoint offset = GetTranslationForThebesLayer ( aLayer ) ;
nsPresContext * presContext = entry - > mContainerLayerFrame - > PresContext ( ) ;
2014-06-23 04:24:14 +00:00
if ( ! layerBuilder - > GetContainingThebesLayerData ( ) ) {
// Recompute visibility of items in our ThebesLayer. 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 ThebesLayers.
int32_t appUnitsPerDevPixel = presContext - > AppUnitsPerDevPixel ( ) ;
RecomputeVisibilityForItems ( entry - > mItems , builder , aRegionToDraw ,
offset , appUnitsPerDevPixel ,
userData - > mXScale , userData - > mYScale ) ;
}
2013-11-06 19:10:49 +00:00
nsRefPtr < nsRenderingContext > rc = new nsRenderingContext ( ) ;
rc - > Init ( presContext - > DeviceContext ( ) , aContext ) ;
2013-11-06 19:10:50 +00:00
if ( shouldDrawRectsSeparately ) {
nsIntRegionRectIterator it ( aRegionToDraw ) ;
while ( const nsIntRect * iterRect = it . Next ( ) ) {
gfxContextAutoSaveRestore save ( aContext ) ;
aContext - > NewPath ( ) ;
2014-01-23 18:26:41 +00:00
aContext - > Rectangle ( * iterRect , aClip = = DrawRegionClip : : DRAW_SNAPPED ) ;
2013-11-06 19:10:50 +00:00
aContext - > Clip ( ) ;
DrawForcedBackgroundColor ( aContext , aLayer , userData - > mForcedBackgroundColor ) ;
// 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.
aContext - > Translate ( aLayer - > GetResidualTranslation ( ) - gfxPoint ( offset . x , offset . y ) ) ;
aContext - > Scale ( userData - > mXScale , userData - > mYScale ) ;
2013-11-06 19:10:50 +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 ) ;
}
} 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.
aContext - > Translate ( aLayer - > GetResidualTranslation ( ) - gfxPoint ( offset . x , offset . y ) ) ;
aContext - > Scale ( userData - > mXScale , userData - > mYScale ) ;
2013-11-06 19:10:50 +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 ) ;
}
2011-11-15 04:59:03 +00:00
2014-06-19 18:22:17 +00:00
if ( presContext - > GetPaintFlashing ( ) & &
! aLayer - > Manager ( ) - > IsInactiveLayerManager ( ) ) {
2014-05-22 02:36:26 +00:00
gfxContextAutoSaveRestore save ( aContext ) ;
if ( shouldDrawRectsSeparately ) {
if ( aClip = = DrawRegionClip : : DRAW_SNAPPED ) {
gfxUtils : : ClipToRegionSnapped ( aContext , aRegionToDraw ) ;
} else if ( aClip = = DrawRegionClip : : DRAW ) {
gfxUtils : : ClipToRegion ( aContext , aRegionToDraw ) ;
}
}
2013-03-12 18:01:00 +00:00
FlashPaint ( aContext ) ;
}
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
}
2011-11-17 03:44:16 +00:00
# ifdef MOZ_DUMP_PAINTING
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
}
# endif
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
SetClipCount ( ThebesDisplayItemLayerUserData * aThebesData ,
uint32_t aClipCount )
{
if ( aThebesData ) {
aThebesData - > mMaskClipCount = aClipCount ;
}
}
2012-02-07 22:27:44 +00:00
void
2014-06-23 04:24:00 +00:00
ContainerState : : SetupMaskLayer ( Layer * aLayer ,
const DisplayItemClip & aClip ,
const nsIntRegion & aLayerVisibleRegion ,
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.
ThebesDisplayItemLayerUserData * thebesData = GetThebesDisplayItemLayerUserData ( aLayer ) ;
if ( thebesData & &
aRoundedRectClipCount < thebesData - > mMaskClipCount ) {
ThebesLayer * thebes = aLayer - > AsThebesLayer ( ) ;
thebes - > InvalidateRegion ( thebes - > GetValidRegion ( ) . GetBounds ( ) ) ;
}
2012-02-07 22:27:44 +00:00
// don't build an unnecessary mask
2014-06-23 04:24:00 +00:00
nsIntRect layerBounds = aLayerVisibleRegion . GetBounds ( ) ;
2013-03-04 09:56:00 +00:00
if ( aClip . GetRoundedRectCount ( ) = = 0 | |
2012-09-04 01:02:56 +00:00
aRoundedRectClipCount = = 0 | |
2012-06-26 02:43:30 +00:00
layerBounds . IsEmpty ( ) ) {
2012-09-04 01:02:56 +00:00
SetClipCount ( thebesData , 0 ) ;
2012-02-07 22:27:44 +00:00
return ;
}
// check if we can re-use the mask layer
nsRefPtr < ImageLayer > maskLayer = CreateOrRecycleMaskImageLayerFor ( aLayer ) ;
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 ) {
aLayer - > SetMaskLayer ( maskLayer ) ;
2012-09-04 01:02:56 +00:00
SetClipCount ( thebesData , aRoundedRectClipCount ) ;
2012-06-25 22:54:05 +00:00
return ;
}
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 " ) ;
2013-12-29 23:35:53 +00:00
gfx : : Size surfaceSize ( std : : min < gfx : : Float > ( boundingRect . Width ( ) , maxSize ) ,
std : : min < gfx : : Float > ( boundingRect . Height ( ) , maxSize ) ) ;
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
2013-12-29 23:35:53 +00:00
gfx : : Matrix maskTransform ;
2013-04-05 03:16:38 +00:00
maskTransform . Scale ( surfaceSize . width / boundingRect . Width ( ) ,
surfaceSize . height / boundingRect . Height ( ) ) ;
2013-12-29 23:35:53 +00:00
gfx : : Point p = boundingRect . TopLeft ( ) ;
maskTransform . Translate ( - 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 ;
2012-06-26 02:43:30 +00:00
imageTransform . Scale ( mParameters . mXScale , mParameters . mYScale ) ;
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
}
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
2012-06-26 02:43:30 +00:00
nsRefPtr < ImageContainer > container =
GetMaskLayerImageCache ( ) - > FindImageFor ( & lookupKey ) ;
2012-09-04 01:02:56 +00:00
if ( ! container ) {
2013-12-31 09:06:12 +00:00
IntSize surfaceSizeInt ( NSToIntCeil ( surfaceSize . width ) ,
NSToIntCeil ( surfaceSize . height ) ) ;
2012-06-26 02:43:30 +00:00
// no existing mask image, so build a new one
2014-04-10 08:49:49 +00:00
RefPtr < DrawTarget > dt =
aLayer - > Manager ( ) - > CreateOptimalMaskDrawTarget ( surfaceSizeInt ) ;
2012-06-26 02:43:30 +00:00
// fail if we can't get the right surface
2014-04-10 08:49:49 +00:00
if ( ! dt ) {
NS_WARNING ( " Could not create DrawTarget for mask layer. " ) ;
2012-09-04 01:02:56 +00:00
SetClipCount ( thebesData , 0 ) ;
2012-06-26 02:43:30 +00:00
return ;
}
2012-02-07 22:27:44 +00:00
2014-04-10 08:49:49 +00:00
nsRefPtr < gfxContext > context = new gfxContext ( dt ) ;
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
2012-06-26 02:43:31 +00:00
context - > SetColor ( gfxRGBA ( 1 , 1 , 1 , 1 ) ) ;
2013-08-09 09:42:05 +00:00
aClip . DrawRoundedRectsTo ( context ,
newData . mAppUnitsPerDevPixel ,
0 ,
aRoundedRectClipCount ) ;
2012-02-07 22:27:44 +00:00
2014-04-10 08:49:49 +00:00
RefPtr < SourceSurface > surface = dt - > Snapshot ( ) ;
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-01-30 22:58:51 +00:00
nsRefPtr < Image > image = container - > CreateImage ( ImageFormat : : CAIRO_SURFACE ) ;
2012-06-26 02:43:30 +00:00
NS_ASSERTION ( image , " Could not create image container for mask layer. " ) ;
CairoImage : : Data data ;
2013-04-05 03:16:38 +00:00
data . mSize = surfaceSizeInt ;
2014-04-10 08:49:49 +00:00
data . mSourceSurface = surface ;
2012-06-26 02:43:30 +00:00
static_cast < CairoImage * > ( image . get ( ) ) - > SetData ( data ) ;
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 ) ;
matrix . Translate ( 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 ) ;
2012-09-04 01:02:56 +00:00
userData - > mImageKey = lookupKey ;
2012-02-07 22:27:44 +00:00
aLayer - > SetMaskLayer ( maskLayer ) ;
2012-09-04 01:02:56 +00:00
SetClipCount ( thebesData , aRoundedRectClipCount ) ;
2012-02-07 22:27:44 +00:00
return ;
}
2010-05-21 03:20:48 +00:00
} // namespace mozilla