2010-05-21 07:20:48 +04:00
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2012-05-21 15:12:37 +04:00
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
2010-05-21 07:20:48 +04:00
2012-12-15 03:58:45 +04:00
# include "mozilla/DebugOnly.h"
2010-05-21 07:20:48 +04:00
# include "FrameLayerBuilder.h"
# include "nsDisplayList.h"
# include "nsPresContext.h"
# include "nsLayoutUtils.h"
2010-07-16 01:07:51 +04:00
# include "Layers.h"
2010-07-16 01:08:05 +04:00
# include "BasicLayers.h"
2010-11-24 12:35:21 +03:00
# include "gfxUtils.h"
2011-04-08 05:04:40 +04:00
# include "nsRenderingContext.h"
2012-06-26 06:43:30 +04:00
# include "MaskLayerImageCache.h"
2012-08-17 03:40:10 +04:00
# include "nsIScrollableFrame.h"
2012-08-29 09:47:15 +04:00
# include "nsPrintfCString.h"
2012-08-29 09:47:18 +04:00
# include "LayerTreeInvalidation.h"
# include "nsSVGIntegrationUtils.h"
2013-10-02 04:57:50 +04:00
# include "ImageContainer.h"
2013-09-04 15:30:57 +04:00
# include "ActiveLayerTracker.h"
2013-12-30 03:35:53 +04:00
# include "gfx2DGlue.h"
2010-07-16 01:07:51 +04:00
2013-03-18 18:25:50 +04:00
# include "GeckoProfiler.h"
2012-10-02 08:00:09 +04:00
# include "mozilla/gfx/Tools.h"
2013-11-06 23:10:50 +04:00
# include "mozilla/gfx/2D.h"
2013-11-17 08:24:53 +04:00
# include "mozilla/Preferences.h"
2011-11-15 08:59:03 +04:00
2013-01-15 16:22:03 +04:00
# include <algorithm>
2012-07-31 21:28:21 +04:00
2010-05-21 07:20:48 +04:00
using namespace mozilla : : layers ;
2012-10-02 08:00:09 +04:00
using namespace mozilla : : gfx ;
2010-05-21 07:20:48 +04:00
namespace mozilla {
2013-12-16 16:11:01 +04:00
class ContainerState ;
2012-10-12 06:39:46 +04:00
FrameLayerBuilder : : DisplayItemData : : DisplayItemData ( LayerManagerData * aParent , uint32_t aKey ,
2012-10-12 03:38:24 +04:00
Layer * aLayer , LayerState aLayerState , uint32_t aGeneration )
: mParent ( aParent )
, mLayer ( aLayer )
2012-08-21 08:06:46 +04:00
, mDisplayItemKey ( aKey )
, mContainerLayerGeneration ( aGeneration )
, mLayerState ( aLayerState )
2012-10-12 06:39:46 +04:00
, mUsed ( true )
2012-11-07 02:04:53 +04:00
, mIsInvalid ( false )
2012-10-12 03:38:24 +04:00
{
}
2012-08-21 08:06:46 +04:00
2012-08-29 09:47:15 +04: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-12 03:38:24 +04:00
mParent = toCopy . mParent ;
2012-08-29 09:47:15 +04:00
mLayer = toCopy . mLayer ;
mInactiveManager = toCopy . mInactiveManager ;
mFrameList = toCopy . mFrameList ;
mGeometry = toCopy . mGeometry ;
mDisplayItemKey = toCopy . mDisplayItemKey ;
2012-10-12 03:38:24 +04:00
mClip = toCopy . mClip ;
2012-08-29 09:47:15 +04:00
mContainerLayerGeneration = toCopy . mContainerLayerGeneration ;
mLayerState = toCopy . mLayerState ;
mUsed = toCopy . mUsed ;
2012-10-12 03:38:24 +04:00
}
void
2012-10-12 06:39:46 +04:00
FrameLayerBuilder : : DisplayItemData : : AddFrame ( nsIFrame * aFrame )
2012-10-12 03:38:24 +04:00
{
2012-10-12 06:39:46 +04:00
mFrameList . AppendElement ( aFrame ) ;
nsTArray < DisplayItemData * > * array =
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( FrameLayerBuilder : : LayerManagerDataProperty ( ) ) ) ;
if ( ! array ) {
array = new nsTArray < DisplayItemData * > ( ) ;
aFrame - > Properties ( ) . Set ( FrameLayerBuilder : : LayerManagerDataProperty ( ) , array ) ;
2012-10-12 03:38:24 +04:00
}
2012-10-12 06:39:46 +04:00
array - > AppendElement ( this ) ;
2012-08-29 09:47:15 +04:00
}
2012-10-12 03:38:24 +04:00
void
2012-10-16 05:23:07 +04:00
FrameLayerBuilder : : DisplayItemData : : RemoveFrame ( nsIFrame * aFrame )
{
DebugOnly < bool > result = mFrameList . RemoveElement ( aFrame ) ;
NS_ASSERTION ( result , " Can't remove a frame that wasn't added! " ) ;
nsTArray < DisplayItemData * > * array =
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( FrameLayerBuilder : : LayerManagerDataProperty ( ) ) ) ;
NS_ASSERTION ( array , " Must be already stored on the frame! " ) ;
array - > RemoveElement ( this ) ;
}
void
FrameLayerBuilder : : DisplayItemData : : UpdateContents ( Layer * aLayer , LayerState aState ,
uint32_t aContainerLayerGeneration ,
nsDisplayItem * aItem /* = nullptr */ )
2012-10-12 03:38:24 +04:00
{
2012-10-12 06:39:46 +04:00
mLayer = aLayer ;
mOptLayer = nullptr ;
mInactiveManager = nullptr ;
mLayerState = aState ;
mContainerLayerGeneration = aContainerLayerGeneration ;
mGeometry = nullptr ;
2013-03-04 13:56:00 +04:00
mClip = DisplayItemClip ( ) ;
2012-10-12 06:39:46 +04:00
mUsed = true ;
2012-10-16 05:23:07 +04:00
if ( ! aItem ) {
return ;
}
2012-12-19 05:16:06 +04:00
nsAutoTArray < nsIFrame * , 4 > copy ( mFrameList ) ;
2013-04-19 16:02:13 +04:00
if ( ! copy . RemoveElement ( aItem - > Frame ( ) ) ) {
AddFrame ( aItem - > Frame ( ) ) ;
2012-10-16 05:23:07 +04: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 + + ) {
RemoveFrame ( copy [ i ] ) ;
}
2012-10-12 03:38:24 +04:00
}
2013-10-08 22:47:21 +04:00
static nsIFrame * sDestroyedFrame = nullptr ;
2012-08-21 08:06:46 +04:00
FrameLayerBuilder : : DisplayItemData : : ~ DisplayItemData ( )
2012-10-12 03:38:24 +04:00
{
for ( uint32_t i = 0 ; i < mFrameList . Length ( ) ; i + + ) {
2012-10-12 06:39:46 +04:00
nsIFrame * frame = mFrameList [ i ] ;
if ( frame = = sDestroyedFrame ) {
2012-10-12 03:38:24 +04:00
continue ;
}
nsTArray < DisplayItemData * > * array =
2012-10-12 06:39:46 +04:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( frame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
array - > RemoveElement ( this ) ;
2012-10-12 03:38:24 +04:00
}
}
2012-08-21 08:06:46 +04:00
2012-10-16 05:23:07 +04:00
void
FrameLayerBuilder : : DisplayItemData : : GetFrameListChanges ( nsDisplayItem * aOther ,
nsTArray < nsIFrame * > & aOut )
2012-08-29 09:47:15 +04:00
{
2012-10-16 05:23:07 +04:00
aOut = mFrameList ;
nsAutoTArray < nsIFrame * , 4 > added ;
2013-04-19 16:02:13 +04:00
if ( ! aOut . RemoveElement ( aOther - > Frame ( ) ) ) {
added . AppendElement ( aOther - > Frame ( ) ) ;
2012-08-29 09:47:15 +04:00
}
2012-10-12 03:38:24 +04:00
2012-08-29 09:47:15 +04:00
nsAutoTArray < nsIFrame * , 4 > mergedFrames ;
aOther - > GetMergedFrames ( & mergedFrames ) ;
for ( uint32_t i = 0 ; i < mergedFrames . Length ( ) ; + + i ) {
2012-10-16 05:23:07 +04:00
if ( ! aOut . RemoveElement ( mergedFrames [ i ] ) ) {
added . AppendElement ( mergedFrames [ i ] ) ;
2012-08-29 09:47:15 +04:00
}
}
2012-10-16 05:23:07 +04:00
aOut . AppendElements ( added ) ;
2012-08-29 09:47:15 +04:00
}
2010-05-21 07:20:48 +04:00
/**
2010-07-16 01:07:51 +04:00
* This is the userdata we associate with a layer manager .
2010-05-21 07:20:48 +04:00
*/
2010-09-02 13:18:39 +04:00
class LayerManagerData : public LayerUserData {
2010-05-21 07:20:48 +04:00
public :
2012-10-12 03:38:24 +04:00
LayerManagerData ( LayerManager * aManager )
: mLayerManager ( aManager )
2012-10-12 06:39:46 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-12 03:38:24 +04:00
, mParent ( nullptr )
2012-10-12 06:39:46 +04:00
# endif
2012-10-12 03:38:24 +04:00
, mInvalidateAllLayers ( false )
2010-05-21 07:20:48 +04:00
{
2010-09-02 13:18:39 +04:00
MOZ_COUNT_CTOR ( LayerManagerData ) ;
2010-05-21 07:20:48 +04:00
}
2010-09-02 13:18:39 +04:00
~ LayerManagerData ( ) {
2012-08-29 09:48:41 +04:00
MOZ_COUNT_DTOR ( LayerManagerData ) ;
2010-09-02 13:18:39 +04:00
}
2012-10-12 03:38:25 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
void Dump ( const char * aPrefix = " " ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " %sLayerManagerData %p \n " , aPrefix , this ) ;
2012-10-12 03:38:25 +04:00
nsAutoCString prefix ;
prefix + = aPrefix ;
prefix + = " " ;
mDisplayItems . EnumerateEntries (
FrameLayerBuilder : : DumpDisplayItemDataForFrame , ( void * ) prefix . get ( ) ) ;
}
# endif
2010-07-16 01:07:51 +04:00
/**
* Tracks which frames have layers associated with them .
*/
2012-10-12 03:38:24 +04:00
LayerManager * mLayerManager ;
2012-10-12 06:39:46 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-12 03:38:24 +04:00
LayerManagerData * mParent ;
2012-10-12 06:39:46 +04:00
# endif
2012-10-12 03:38:24 +04:00
nsTHashtable < nsRefPtrHashKey < FrameLayerBuilder : : DisplayItemData > > mDisplayItems ;
2011-09-29 10:19:26 +04:00
bool mInvalidateAllLayers ;
2010-07-16 01:07:51 +04:00
} ;
2012-08-29 09:48:41 +04:00
/* static */ void
FrameLayerBuilder : : DestroyDisplayItemDataFor ( nsIFrame * aFrame )
{
FrameProperties props = aFrame - > Properties ( ) ;
props . Delete ( LayerManagerDataProperty ( ) ) ;
}
2012-06-26 06:43:30 +04:00
// a global cache of image containers used for mask layers
2012-07-30 18:20:58 +04:00
static MaskLayerImageCache * gMaskLayerImageCache = nullptr ;
2012-06-26 06:43:30 +04:00
static inline MaskLayerImageCache * GetMaskLayerImageCache ( )
{
if ( ! gMaskLayerImageCache ) {
gMaskLayerImageCache = new MaskLayerImageCache ( ) ;
}
return gMaskLayerImageCache ;
}
2013-12-16 16:11:01 +04: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 ( ) :
mAnimatedGeometryRoot ( nullptr ) , mReferenceFrame ( nullptr ) ,
mLayer ( nullptr ) ,
mIsSolidColorInVisibleRegion ( false ) ,
mNeedComponentAlpha ( false ) ,
mForceTransparentSurface ( false ) ,
mImage ( nullptr ) ,
mCommonClipCount ( - 1 ) ,
mAllDrawingAbove ( false ) { }
/**
* 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 ,
const nsIntRect & aVisibleRect ,
const nsIntRect & aDrawRect ,
const DisplayItemClip & aClip ) ;
const nsIFrame * GetAnimatedGeometryRoot ( ) { return mAnimatedGeometryRoot ; }
/**
* 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 ) ;
mDrawAboveRegion . SimplifyOutward ( 4 ) ;
}
}
void AddVisibleAboveRegion ( const nsIntRegion & aAbove )
{
if ( ! mAllDrawingAbove ) {
mVisibleAboveRegion . Or ( mVisibleAboveRegion , aAbove ) ;
mVisibleAboveRegion . SimplifyOutward ( 4 ) ;
}
}
void CopyAboveRegion ( ThebesLayerData * aOther )
{
if ( aOther - > mAllDrawingAbove | | mAllDrawingAbove ) {
SetAllDrawingAbove ( ) ;
} else {
mVisibleAboveRegion . Or ( mVisibleAboveRegion , aOther - > mVisibleAboveRegion ) ;
mVisibleAboveRegion . Or ( mVisibleAboveRegion , aOther - > mVisibleRegion ) ;
mVisibleAboveRegion . SimplifyOutward ( 4 ) ;
mDrawAboveRegion . Or ( mDrawAboveRegion , aOther - > mDrawAboveRegion ) ;
mDrawAboveRegion . Or ( mDrawAboveRegion , aOther - > mDrawRegion ) ;
mDrawAboveRegion . SimplifyOutward ( 4 ) ;
}
}
void SetAllDrawingAbove ( )
{
mAllDrawingAbove = true ;
mDrawAboveRegion . SetEmpty ( ) ;
mVisibleAboveRegion . SetEmpty ( ) ;
}
bool IsBelow ( const nsIntRect & aRect )
{
return mAllDrawingAbove | | mDrawAboveRegion . Intersects ( aRect ) ;
}
bool IntersectsVisibleAboveRegion ( const nsIntRegion & aVisibleRegion )
{
if ( mAllDrawingAbove ) {
return true ;
}
nsIntRegion visibleAboveIntersection ;
visibleAboveIntersection . And ( mVisibleAboveRegion , aVisibleRegion ) ;
if ( visibleAboveIntersection . IsEmpty ( ) ) {
return false ;
}
return true ;
}
/**
* 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 ;
/**
* 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 ;
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 ;
/**
* 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 ;
/**
* 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 ;
/*
* 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 ;
} ;
2010-07-16 01:07:51 +04:00
/**
* This is a helper object used to build up the layer children for
* a ContainerLayer .
*/
class ContainerState {
public :
ContainerState ( nsDisplayListBuilder * aBuilder ,
LayerManager * aManager ,
2012-07-17 21:03:51 +04:00
FrameLayerBuilder * aLayerBuilder ,
2010-07-16 01:07:51 +04:00
nsIFrame * aContainerFrame ,
2012-09-28 15:19:39 +04:00
nsDisplayItem * aContainerItem ,
2011-06-22 16:11:27 +04:00
ContainerLayer * aContainerLayer ,
2013-09-27 10:01:16 +04:00
const ContainerLayerParameters & aParameters ) :
2010-07-16 01:07:51 +04:00
mBuilder ( aBuilder ) , mManager ( aManager ) ,
2012-07-17 21:03:51 +04:00
mLayerBuilder ( aLayerBuilder ) ,
2012-09-28 15:19:39 +04:00
mContainerFrame ( aContainerFrame ) ,
mContainerLayer ( aContainerLayer ) ,
2011-06-22 16:11:27 +04:00
mParameters ( aParameters ) ,
2012-08-29 09:47:15 +04:00
mNextFreeRecycledThebesLayer ( 0 )
2010-05-21 07:20:48 +04:00
{
2012-04-10 15:24:18 +04:00
nsPresContext * presContext = aContainerFrame - > PresContext ( ) ;
mAppUnitsPerDevPixel = presContext - > AppUnitsPerDevPixel ( ) ;
2012-10-16 05:10:48 +04:00
mContainerReferenceFrame = aContainerItem ? aContainerItem - > ReferenceFrameForChildren ( ) :
2012-09-28 15:19:39 +04:00
mBuilder - > FindReferenceFrameFor ( mContainerFrame ) ;
2012-04-10 15:24:18 +04:00
// When AllowResidualTranslation is false, display items will be drawn
// scaled with a translation by integer pixels, so we know how the snapping
// will work.
mSnappingEnabled = aManager - > IsSnappingEffectiveTransforms ( ) & &
! mParameters . AllowResidualTranslation ( ) ;
2010-07-16 01:08:03 +04:00
CollectOldLayers ( ) ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:51 +04:00
2012-07-23 07:00:36 +04:00
enum ProcessDisplayItemsFlags {
NO_COMPONENT_ALPHA = 0x01 ,
} ;
2010-07-16 01:07:51 +04:00
/**
* This is the method that actually walks a display list and builds
2013-03-04 13:56:02 +04:00
* the child layers .
2010-07-16 01:07:51 +04:00
*/
2013-03-04 13:56:02 +04:00
void ProcessDisplayItems ( const nsDisplayList & aList , uint32_t aFlags ) ;
2010-07-16 01:07:51 +04: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 04:26:14 +03:00
* @ param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA ,
* set * aTextContentFlags to CONTENT_COMPONENT_ALPHA
2010-07-16 01:07:51 +04:00
*/
2012-08-29 09:47:15 +04:00
void Finish ( uint32_t * aTextContentFlags , LayerManagerData * aData ) ;
2010-07-16 01:07:51 +04:00
2011-02-23 08:38:09 +03:00
nsRect GetChildrenBounds ( ) { return mBounds ; }
2012-04-10 15:24:18 +04:00
nscoord GetAppUnitsPerDevPixel ( ) { return mAppUnitsPerDevPixel ; }
nsIntRect ScaleToNearestPixels ( const nsRect & aRect )
{
return aRect . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2012-07-23 07:00:36 +04:00
nsIntRegion ScaleRegionToNearestPixels ( const nsRegion & aRegion )
{
return aRegion . ScaleToNearestPixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2013-12-16 16:11:59 +04:00
nsIntRect ScaleToOutsidePixels ( const nsRect & aRect , bool aSnap = false )
2012-04-10 15:24:18 +04:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2013-12-16 16:11:59 +04:00
nsIntRect ScaleToInsidePixels ( const nsRect & aRect , bool aSnap = false )
2012-04-10 15:24:18 +04:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleToNearestPixels ( aRect ) ;
}
return aRect . ScaleToInsidePixels ( mParameters . mXScale , mParameters . mYScale ,
mAppUnitsPerDevPixel ) ;
}
2013-12-16 16:11:59 +04:00
nsIntRegion ScaleRegionToInsidePixels ( const nsRegion & aRegion , bool aSnap = false )
2012-07-23 07:00:36 +04:00
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleRegionToNearestPixels ( aRegion ) ;
}
return aRegion . ScaleToInsidePixels ( mParameters . mXScale , mParameters . mYScale ,
2013-12-16 16:11:59 +04:00
mAppUnitsPerDevPixel ) ;
}
nsIntRegion ScaleRegionToOutsidePixels ( const nsRegion & aRegion , bool aSnap = false )
{
if ( aSnap & & mSnappingEnabled ) {
return ScaleRegionToNearestPixels ( aRegion ) ;
}
return aRegion . ScaleToOutsidePixels ( mParameters . mXScale , mParameters . mYScale ,
2012-07-23 07:00:36 +04:00
mAppUnitsPerDevPixel ) ;
}
2010-07-16 01:07:51 +04:00
protected :
2011-06-22 16:11:27 +04:00
friend class ThebesLayerData ;
2010-05-21 07:20:48 +04:00
2010-07-16 01:07:51 +04: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-16 01:08:03 +04:00
* to account for scrolling .
2010-07-16 01:07:51 +04:00
*/
2013-09-26 01:07:26 +04:00
already_AddRefed < ThebesLayer > CreateOrRecycleThebesLayer ( const nsIFrame * aAnimatedGeometryRoot ,
2012-09-28 15:19:39 +04:00
const nsIFrame * aReferenceFrame ,
const nsPoint & aTopLeft ) ;
2010-07-16 01:07:51 +04:00
/**
2010-07-16 01:08:03 +04:00
* Grab the next recyclable ColorLayer , or create one if there are no
* more recyclable ColorLayers .
*/
2012-08-20 14:00:49 +04:00
already_AddRefed < ColorLayer > CreateOrRecycleColorLayer ( ThebesLayer * aThebes ) ;
2011-01-18 00:47:18 +03:00
/**
* Grab the next recyclable ImageLayer , or create one if there are no
* more recyclable ImageLayers .
*/
2012-08-20 14:00:49 +04:00
already_AddRefed < ImageLayer > CreateOrRecycleImageLayer ( ThebesLayer * aThebes ) ;
2012-02-08 02:26:40 +04:00
/**
* Grab a recyclable ImageLayer for use as a mask layer for aLayer ( that is a
* mask layer which has been used for aLayer before ) , or create one if such
* a layer doesn ' t exist .
*/
already_AddRefed < ImageLayer > CreateOrRecycleMaskImageLayerFor ( Layer * aLayer ) ;
2010-07-16 01:08:03 +04:00
/**
* Grabs all ThebesLayers and ColorLayers from the ContainerLayer and makes them
2010-07-16 01:07:51 +04:00
* available for recycling .
*/
2010-07-16 01:08:03 +04:00
void CollectOldLayers ( ) ;
2010-07-16 01:08:05 +04:00
/**
* 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 .
*/
2012-08-29 09:47:15 +04:00
void InvalidateForLayerChange ( nsDisplayItem * aItem ,
2012-08-29 09:48:43 +04:00
Layer * aNewLayer ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2012-10-12 03:38:24 +04:00
const nsPoint & aTopLeft ,
nsDisplayItemGeometry * aGeometry ) ;
2010-09-02 13:18:39 +04:00
/**
* Try to determine whether the ThebesLayer at aThebesLayerIndex
2011-01-04 13:35:57 +03:00
* has a single opaque color behind it , over the entire bounds of its visible
* region .
2010-09-02 13:18:39 +04:00
* If successful , return that color , otherwise return NS_RGBA ( 0 , 0 , 0 , 0 ) .
*/
2012-08-22 19:56:38 +04:00
nscolor FindOpaqueBackgroundColorFor ( int32_t aThebesLayerIndex ) ;
2013-09-27 10:01:16 +04: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 .
*/
const nsIFrame * FindFixedPosFrameForLayerData ( const nsIFrame * aAnimatedGeometryRoot ,
const nsIntRegion & aDrawRegion ,
nsIntRegion * aVisibleRegion ,
bool * aIsSolidColorInVisibleRegion = nullptr ) ;
/**
* Set fixed - pos layer metadata on aLayer according to the data for aFixedPosFrame .
*/
void SetFixedPositionLayerData ( Layer * aLayer ,
const nsIFrame * aFixedPosFrame ) ;
2010-07-16 01:07:51 +04: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 07:06:58 +04: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-16 01:07:51 +04:00
* Returns the layer , and also updates the ThebesLayerData . Will
2010-08-02 07:06:58 +04: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-16 01:07:51 +04:00
* @ param aVisibleRect the area of the next display item that ' s visible
2013-09-26 01:07:26 +04:00
* @ param aAnimatedGeometryRoot the active scrolled root for the next
2010-07-16 01:07:51 +04:00
* display item
2010-07-16 01:08:11 +04:00
* @ param aOpaqueRect if non - null , a region of the display item that is opaque
2010-07-16 01:08:03 +04:00
* @ param aSolidColor if non - null , indicates that every pixel in aVisibleRect
* will be painted with aSolidColor by the item
2010-07-16 01:07:51 +04:00
*/
2012-02-08 02:27:44 +04:00
ThebesLayerData * FindThebesLayerFor ( nsDisplayItem * aItem ,
2013-12-16 16:11:01 +04:00
const nsIntRect & aVisibleRect ,
const nsIntRect & aDrawRect ,
const DisplayItemClip & aClip ,
const nsIFrame * aAnimatedGeometryRoot ,
const nsPoint & aTopLeft ) ;
2010-07-16 01:07:51 +04:00
ThebesLayerData * GetTopThebesLayerData ( )
2010-05-21 07:20:48 +04:00
{
2012-07-30 18:20:58 +04:00
return mThebesLayerDataStack . IsEmpty ( ) ? nullptr
2010-07-16 01:07:51 +04:00
: mThebesLayerDataStack [ mThebesLayerDataStack . Length ( ) - 1 ] . get ( ) ;
2010-05-21 07:20:48 +04:00
}
2012-02-08 02:27:44 +04:00
/* Build a mask layer to represent the clipping region. Will return null if
* there is no clipping specified or a mask layer cannot be built .
* Builds an ImageLayer for the appropriate backend ; the mask is relative to
* aLayer ' s visible region .
* aLayer is the layer to be clipped .
* 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 13:55:59 +04:00
void SetupMaskLayer ( Layer * aLayer , const DisplayItemClip & aClip ,
2012-09-28 10:57:33 +04:00
uint32_t aRoundedRectClipCount = UINT32_MAX ) ;
2012-02-08 02:27:44 +04:00
2013-09-26 01:07:26 +04:00
bool ChooseAnimatedGeometryRoot ( const nsDisplayList & aList ,
const nsIFrame * * aAnimatedGeometryRoot ) ;
2012-12-12 00:36:22 +04:00
2010-07-16 01:07:51 +04:00
nsDisplayListBuilder * mBuilder ;
LayerManager * mManager ;
2012-07-17 21:03:51 +04:00
FrameLayerBuilder * mLayerBuilder ;
2010-07-16 01:07:51 +04:00
nsIFrame * mContainerFrame ;
2012-09-28 15:19:39 +04:00
const nsIFrame * mContainerReferenceFrame ;
2010-07-16 01:07:51 +04:00
ContainerLayer * mContainerLayer ;
2013-09-27 10:01:16 +04:00
ContainerLayerParameters mParameters ;
2010-07-16 01:07:51 +04:00
/**
* The region of ThebesLayers that should be invalidated every time
* we recycle one .
*/
nsIntRegion mInvalidThebesContent ;
2011-02-23 08:38:09 +03:00
nsRect mBounds ;
2010-07-16 01:07:51 +04:00
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 .
*/
2010-11-09 05:48:59 +03:00
typedef nsAutoTArray < nsRefPtr < Layer > , 1 > AutoLayersArray ;
AutoLayersArray mNewChildLayers ;
2010-07-16 01:07:51 +04:00
nsTArray < nsRefPtr < ThebesLayer > > mRecycledThebesLayers ;
2012-02-08 02:26:40 +04:00
nsDataHashtable < nsPtrHashKey < Layer > , nsRefPtr < ImageLayer > >
mRecycledMaskImageLayers ;
2012-08-22 19:56:38 +04:00
uint32_t mNextFreeRecycledThebesLayer ;
2012-04-10 15:24:18 +04:00
nscoord mAppUnitsPerDevPixel ;
bool mSnappingEnabled ;
2010-05-21 07:20:48 +04:00
} ;
2010-09-02 13:18:39 +04:00
class ThebesDisplayItemLayerUserData : public LayerUserData
{
public :
ThebesDisplayItemLayerUserData ( ) :
2012-09-06 08:07:53 +04:00
mMaskClipCount ( 0 ) ,
2011-06-22 16:11:28 +04:00
mForcedBackgroundColor ( NS_RGBA ( 0 , 0 , 0 , 0 ) ) ,
mXScale ( 1.f ) , mYScale ( 1.f ) ,
2012-08-29 09:47:15 +04:00
mAppUnitsPerDevPixel ( 0 ) ,
2012-09-17 02:25:33 +04:00
mTranslation ( 0 , 0 ) ,
2013-09-26 01:07:26 +04:00
mAnimatedGeometryRootPosition ( 0 , 0 ) { }
2010-09-02 13:18:39 +04:00
2012-09-04 05:02:56 +04: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 13:35:57 +03:00
/**
* A color that should be painted over the bounds of the layer ' s visible
* region before any other content is painted .
*/
2010-09-02 13:18:39 +04:00
nscolor mForcedBackgroundColor ;
2012-09-04 05:02:56 +04:00
2011-06-22 16:11:27 +04:00
/**
* The resolution scale used .
*/
float mXScale , mYScale ;
2012-02-08 02:27:44 +04:00
2012-08-29 09:47:15 +04:00
/**
* The appunits per dev pixel for the items in this layer .
*/
nscoord mAppUnitsPerDevPixel ;
2012-09-17 02:25:33 +04:00
/**
* 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 16:11:28 +04: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-26 01:07:26 +04:00
gfxPoint mAnimatedGeometryRootPosition ;
2012-08-20 14:00:49 +04:00
2012-08-29 09:47:15 +04:00
nsIntRegion mRegionToInvalidate ;
2012-09-28 15:19:39 +04:00
// The offset between the active scrolled root of this layer
// and the root of the container for the previous and current
// paints respectively.
2013-09-26 01:07:26 +04:00
nsPoint mLastAnimatedGeometryRootOrigin ;
nsPoint mAnimatedGeometryRootOrigin ;
2012-08-29 09:47:15 +04:00
2012-08-20 14:00:49 +04:00
nsRefPtr < ColorLayer > mColorLayer ;
nsRefPtr < ImageLayer > mImageLayer ;
2010-09-02 13:18:39 +04:00
} ;
2012-02-08 02:26:33 +04:00
/*
* User data for layers which will be used as masks .
*/
struct MaskLayerUserData : public LayerUserData
{
2012-07-30 18:20:58 +04:00
MaskLayerUserData ( ) : mImageKey ( nullptr ) { }
2012-06-26 06:43:30 +04:00
bool
operator = = ( const MaskLayerUserData & aOther ) const
{
return mRoundedClipRects = = aOther . mRoundedClipRects & &
mScaleX = = aOther . mScaleX & &
2013-04-04 06:59:24 +04:00
mScaleY = = aOther . mScaleY & &
2013-08-09 13:42:05 +04:00
mOffset = = aOther . mOffset & &
mAppUnitsPerDevPixel = = aOther . mAppUnitsPerDevPixel ;
2012-06-26 06:43:30 +04:00
}
nsRefPtr < const MaskLayerImageCache : : MaskLayerImageKey > mImageKey ;
2012-02-08 02:26:33 +04:00
// properties of the mask layer; the mask layer may be re-used if these
// remain unchanged.
2013-03-04 13:55:59 +04:00
nsTArray < DisplayItemClip : : RoundedRect > mRoundedClipRects ;
2012-06-26 06:43:30 +04:00
// scale from the masked layer which is applied to the mask
float mScaleX , mScaleY ;
2013-09-27 10:01:16 +04:00
// The ContainerLayerParameters offset which is applied to the mask's transform.
2013-04-04 06:59:24 +04:00
nsIntPoint mOffset ;
2013-08-09 13:42:05 +04:00
int32_t mAppUnitsPerDevPixel ;
2012-02-08 02:26:33 +04:00
} ;
2010-05-21 07:20:48 +04:00
/**
2010-07-16 01:07:51 +04:00
* The address of gThebesDisplayItemLayerUserData is used as the user
2010-09-02 13:18:39 +04:00
* data key for ThebesLayers created by FrameLayerBuilder .
2010-07-16 01:07:51 +04: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 13:18:39 +04:00
* The user data is a ThebesDisplayItemLayerUserData .
2010-05-21 07:20:48 +04:00
*/
2012-08-22 19:56:38 +04:00
uint8_t gThebesDisplayItemLayerUserData ;
2010-07-16 01:08:03 +04:00
/**
* The address of gColorLayerUserData is used as the user
2010-09-02 13:18:39 +04:00
* data key for ColorLayers created by FrameLayerBuilder .
* The user data is null .
2010-07-16 01:08:03 +04:00
*/
2012-08-22 19:56:38 +04:00
uint8_t gColorLayerUserData ;
2011-01-18 00:47:18 +03: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 19:56:38 +04:00
uint8_t gImageLayerUserData ;
2010-09-02 13:18:39 +04: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 19:56:38 +04:00
uint8_t gLayerManagerUserData ;
2012-02-08 02:26:33 +04: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 19:56:38 +04:00
uint8_t gMaskLayerUserData ;
2010-07-16 01:07:51 +04:00
2012-02-08 02:27:44 +04:00
/**
* Helper functions for getting user data and casting it to the correct type .
* aLayer is the layer where the user data is stored .
*/
MaskLayerUserData * GetMaskLayerUserData ( Layer * aLayer )
{
return static_cast < MaskLayerUserData * > ( aLayer - > GetUserData ( & gMaskLayerUserData ) ) ;
}
ThebesDisplayItemLayerUserData * GetThebesDisplayItemLayerUserData ( Layer * aLayer )
{
return static_cast < ThebesDisplayItemLayerUserData * > (
aLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
}
2012-06-26 06:43:30 +04:00
/* static */ void
FrameLayerBuilder : : Shutdown ( )
{
if ( gMaskLayerImageCache ) {
delete gMaskLayerImageCache ;
2012-07-30 18:20:58 +04:00
gMaskLayerImageCache = nullptr ;
2012-06-26 06:43:30 +04:00
}
}
2010-09-17 23:09:08 +04:00
void
2012-08-21 08:06:46 +04:00
FrameLayerBuilder : : Init ( nsDisplayListBuilder * aBuilder , LayerManager * aManager )
2010-09-17 23:09:08 +04:00
{
2012-08-29 09:47:15 +04:00
mDisplayListBuilder = aBuilder ;
2012-09-16 14:32:59 +04:00
mRootPresContext = aBuilder - > RootReferenceFrame ( ) - > PresContext ( ) - > GetRootPresContext ( ) ;
2010-09-17 23:09:08 +04:00
if ( mRootPresContext ) {
mInitialDOMGeneration = mRootPresContext - > GetDOMGeneration ( ) ;
}
2012-08-29 09:48:15 +04:00
aManager - > SetUserData ( & gLayerManagerLayerBuilder , this ) ;
2010-09-17 23:09:08 +04:00
}
2011-11-15 08:59:03 +04:00
void
FrameLayerBuilder : : FlashPaint ( gfxContext * aContext )
{
2013-03-12 22:01:00 +04:00
float r = float ( rand ( ) ) / RAND_MAX ;
float g = float ( rand ( ) ) / RAND_MAX ;
float b = float ( rand ( ) ) / RAND_MAX ;
aContext - > SetColor ( gfxRGBA ( r , g , b , 0.4 ) ) ;
aContext - > Paint ( ) ;
2011-11-15 08:59:03 +04:00
}
2012-10-12 03:38:24 +04:00
FrameLayerBuilder : : DisplayItemData *
FrameLayerBuilder : : GetDisplayItemData ( nsIFrame * aFrame , uint32_t aKey )
{
nsTArray < DisplayItemData * > * array =
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 09:47:15 +04:00
}
2012-10-12 03:38:24 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2012-08-29 09:47:15 +04:00
nsACString &
AppendToString ( nsACString & s , const nsIntRect & r ,
const char * pfx = " " , const char * sfx = " " )
{
s + = pfx ;
s + = nsPrintfCString (
" (x=%d, y=%d, w=%d, h=%d) " ,
r . x , r . y , r . width , r . height ) ;
return s + = sfx ;
}
nsACString &
AppendToString ( nsACString & s , const nsIntRegion & r ,
const char * pfx = " " , const char * sfx = " " )
{
s + = pfx ;
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-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
nsAutoCString str ;
AppendToString ( str , rgn ) ;
2013-11-24 02:44:18 +04:00
printf_stderr ( " Invalidating layer %p: %s \n " , aLayer , str . get ( ) ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
}
2012-10-16 05:10:43 +04:00
static void
InvalidatePostTransformRegion ( ThebesLayer * aLayer , const nsRect & aRect ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2012-10-16 05:10:43 +04:00
const nsIntPoint & aTranslation )
{
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 09:47:15 +04:00
static nsIntPoint
GetTranslationForThebesLayer ( ThebesLayer * aLayer )
{
ThebesDisplayItemLayerUserData * data =
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
* the layer manager destroys the LayerManagerData and calls into
2012-10-12 06:39:46 +04:00
* the DisplayItemData destructor . If the inner layer manager had any
2012-08-29 09:47:15 +04:00
* items with the same frame , then we attempt to retrieve properties
* from the deleted frame .
*
* Cache the destroyed frame pointer here so we can avoid crashing in this case .
*/
2010-07-16 01:07:51 +04:00
/* static */ void
2011-10-07 01:35:08 +04:00
FrameLayerBuilder : : RemoveFrameFromLayerManager ( nsIFrame * aFrame ,
void * aPropertyValue )
2010-07-16 01:07:51 +04:00
{
2012-10-12 03:38:24 +04:00
sDestroyedFrame = aFrame ;
nsTArray < DisplayItemData * > * array =
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 09:47:15 +04:00
2012-10-12 03:38:25 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
if ( array - > Length ( ) ) {
LayerManagerData * rootData = array - > ElementAt ( 0 ) - > mParent ;
while ( rootData - > mParent ) {
rootData = rootData - > mParent ;
}
2013-11-24 02:44:18 +04:00
printf_stderr ( " Removing frame %p - dumping display data \n " , aFrame ) ;
2012-10-12 03:38:25 +04:00
rootData - > Dump ( ) ;
}
# endif
2012-10-12 03:38:24 +04:00
for ( uint32_t i = 0 ; i < array - > Length ( ) ; + + i ) {
DisplayItemData * data = array - > ElementAt ( i ) ;
ThebesLayer * t = data - > mLayer - > AsThebesLayer ( ) ;
2012-08-29 09:47:15 +04:00
if ( t ) {
2012-10-12 03:38:24 +04:00
ThebesDisplayItemLayerUserData * thebesData =
2012-08-29 09:47:15 +04:00
static_cast < ThebesDisplayItemLayerUserData * > ( t - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
2012-10-12 03:38:24 +04:00
if ( thebesData ) {
nsRegion old = data - > mGeometry - > ComputeInvalidationRegion ( ) ;
nsIntRegion rgn = old . ScaleToOutsidePixels ( thebesData - > mXScale , thebesData - > mYScale , thebesData - > mAppUnitsPerDevPixel ) ;
2012-08-29 09:47:15 +04:00
rgn . MoveBy ( - GetTranslationForThebesLayer ( t ) ) ;
2012-10-12 03:38:24 +04:00
thebesData - > mRegionToInvalidate . Or ( thebesData - > mRegionToInvalidate , rgn ) ;
2013-03-02 21:21:00 +04:00
thebesData - > mRegionToInvalidate . SimplifyOutward ( 8 ) ;
2012-08-29 09:47:15 +04:00
}
}
2012-10-12 03:38:24 +04:00
data - > mParent - > mDisplayItems . RemoveEntry ( data ) ;
2012-09-27 19:34:46 +04:00
}
2012-09-28 15:19:39 +04:00
2012-10-12 03:38:24 +04:00
arrayCopy . Clear ( ) ;
delete array ;
2013-10-08 22:47:21 +04:00
sDestroyedFrame = nullptr ;
2010-07-16 01:07:51 +04:00
}
void
2011-01-19 11:27:54 +03:00
FrameLayerBuilder : : DidBeginRetainedLayerTransaction ( LayerManager * aManager )
2010-07-16 01:07:51 +04:00
{
mRetainingManager = aManager ;
LayerManagerData * data = static_cast < LayerManagerData * >
2010-09-02 13:18:39 +04:00
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2010-07-16 01:07:51 +04:00
if ( data ) {
mInvalidateAllLayers = data - > mInvalidateAllLayers ;
2012-08-29 09:48:41 +04:00
} else {
2012-10-12 03:38:24 +04:00
data = new LayerManagerData ( aManager ) ;
2012-08-29 09:48:41 +04:00
aManager - > SetUserData ( & gLayerManagerUserData , data ) ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:51 +04:00
}
2010-05-21 07:20:48 +04:00
2012-09-25 00:31:30 +04:00
void
2012-10-12 06:39:46 +04:00
FrameLayerBuilder : : StoreOptimizedLayerForFrame ( nsDisplayItem * aItem , Layer * aLayer )
2012-09-25 00:31:30 +04:00
{
2012-10-12 06:39:46 +04:00
if ( ! mRetainingManager ) {
2012-09-25 00:31:30 +04:00
return ;
2012-10-12 06:39:46 +04:00
}
2012-09-25 00:31:30 +04:00
2012-10-12 06:39:46 +04:00
DisplayItemData * data = GetDisplayItemDataForManager ( aItem , aLayer - > Manager ( ) ) ;
NS_ASSERTION ( data , " Must have already stored data for this item! " ) ;
data - > mOptLayer = aLayer ;
2012-09-25 00:31:30 +04:00
}
2010-07-16 01:07:51 +04:00
void
2012-08-29 09:47:15 +04:00
FrameLayerBuilder : : DidEndTransaction ( )
2010-07-16 01:07:51 +04:00
{
2012-06-26 06:43:30 +04:00
GetMaskLayerImageCache ( ) - > Sweep ( ) ;
2010-07-16 01:08:11 +04:00
}
void
2012-08-29 09:47:15 +04:00
FrameLayerBuilder : : WillEndTransaction ( )
2010-07-16 01:08:11 +04:00
{
2012-08-29 09:47:15 +04:00
if ( ! mRetainingManager ) {
2010-07-16 01:08:11 +04:00
return ;
2012-08-29 09:47:15 +04:00
}
2010-05-21 07:20:48 +04:00
2012-08-29 09:47:15 +04:00
// We need to save the data we'll need to support retaining.
2010-07-16 01:07:51 +04:00
LayerManagerData * data = static_cast < LayerManagerData * >
2010-09-02 13:18:39 +04:00
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-08-29 09:48:41 +04:00
NS_ASSERTION ( data , " Must have data! " ) ;
// Update all the frames that used to have layers.
2012-12-13 00:47:05 +04:00
data - > mDisplayItems . EnumerateEntries ( ProcessRemovedDisplayItems , this ) ;
2011-10-17 18:59:28 +04:00
data - > mInvalidateAllLayers = false ;
2012-09-27 19:34:46 +04:00
}
2012-08-29 09:47:15 +04:00
/* static */ PLDHashOperator
2012-10-12 03:38:24 +04:00
FrameLayerBuilder : : ProcessRemovedDisplayItems ( nsRefPtrHashKey < DisplayItemData > * aEntry ,
2012-08-29 09:47:15 +04:00
void * aUserArg )
2010-05-21 07:20:48 +04:00
{
2012-10-12 03:38:24 +04:00
DisplayItemData * data = aEntry - > GetKey ( ) ;
2012-10-12 06:39:46 +04:00
if ( ! data - > mUsed ) {
2012-10-12 03:38:24 +04:00
// This item was visible, but isn't anymore.
2012-12-13 00:47:05 +04:00
FrameLayerBuilder * layerBuilder = static_cast < FrameLayerBuilder * > ( aUserArg ) ;
ThebesLayer * t = data - > mLayer - > AsThebesLayer ( ) ;
if ( t ) {
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Invalidating unused display item (%i) belonging to frame %p from layer %p \n " , data - > mDisplayItemKey , data - > mFrameList [ 0 ] , t ) ;
2013-05-14 03:47:02 +04:00
}
2012-12-13 00:47:05 +04:00
# endif
InvalidatePostTransformRegion ( t ,
data - > mGeometry - > ComputeInvalidationRegion ( ) ,
data - > mClip ,
layerBuilder - > GetLastPaintOffset ( t ) ) ;
}
2010-07-16 01:07:51 +04:00
return PL_DHASH_REMOVE ;
}
2012-10-12 06:39:46 +04:00
data - > mUsed = false ;
2012-11-07 02:04:53 +04:00
data - > mIsInvalid = false ;
2010-07-16 01:07:51 +04:00
return PL_DHASH_NEXT ;
}
2012-08-29 09:47:15 +04:00
2012-10-12 03:38:25 +04:00
/* static */ PLDHashOperator
FrameLayerBuilder : : DumpDisplayItemDataForFrame ( nsRefPtrHashKey < DisplayItemData > * aEntry ,
void * aClosure )
{
# ifdef DEBUG_DISPLAY_ITEM_DATA
DisplayItemData * data = aEntry - > GetKey ( ) ;
nsAutoCString prefix ;
prefix + = static_cast < const char * > ( aClosure ) ;
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-24 02:44:18 +04:00
printf_stderr ( " %s " , str . get ( ) ) ;
2012-10-12 03:38:25 +04:00
if ( data - > mInactiveManager ) {
prefix + = " " ;
2013-11-24 02:44:18 +04:00
printf_stderr ( " %sDumping inactive layer info: \n " , prefix . get ( ) ) ;
2012-10-12 03:38:25 +04:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( data - > mInactiveManager - > GetUserData ( & gLayerManagerUserData ) ) ;
lmd - > Dump ( prefix . get ( ) ) ;
}
# endif
return PL_DHASH_NEXT ;
}
2012-08-29 09:48:45 +04:00
/* static */ FrameLayerBuilder : : DisplayItemData *
FrameLayerBuilder : : GetDisplayItemDataForManager ( nsDisplayItem * aItem ,
LayerManager * aManager )
2012-08-29 09:47:15 +04:00
{
2012-10-12 03:38:24 +04:00
nsTArray < DisplayItemData * > * array =
2013-04-19 16:02:13 +04:00
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aItem - > Frame ( ) - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
2012-10-12 03:38:24 +04: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 05:23:07 +04:00
item - > mLayer - > Manager ( ) = = aManager ) {
2012-10-12 03:38:24 +04:00
return item ;
}
2012-08-29 09:47:15 +04:00
}
}
return nullptr ;
}
2012-08-29 09:48:45 +04:00
bool
2012-12-14 02:51:00 +04:00
FrameLayerBuilder : : HasRetainedDataFor ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2012-08-29 09:48:45 +04:00
{
2012-10-12 03:38:24 +04:00
nsTArray < DisplayItemData * > * array =
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2012-12-14 02:51:00 +04:00
if ( array - > ElementAt ( i ) - > mDisplayItemKey = = aDisplayItemKey ) {
2012-10-12 03:38:24 +04:00
return true ;
}
}
2012-08-29 09:48:45 +04:00
}
return false ;
}
2012-11-07 02:04:53 +04:00
void
2012-12-14 02:50:57 +04:00
FrameLayerBuilder : : IterateRetainedDataFor ( nsIFrame * aFrame , DisplayItemDataCallback aCallback )
2012-11-07 02:04:53 +04:00
{
nsTArray < DisplayItemData * > * array =
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( ! array ) {
return ;
}
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2012-11-19 14:54:50 +04:00
DisplayItemData * data = array - > ElementAt ( i ) ;
2012-12-14 02:50:57 +04:00
if ( data - > mDisplayItemKey ! = nsDisplayItem : : TYPE_ZERO ) {
2012-11-19 14:54:50 +04:00
aCallback ( aFrame , data ) ;
}
2012-11-07 02:04:53 +04:00
}
}
2012-08-29 09:47:15 +04:00
FrameLayerBuilder : : DisplayItemData *
2012-08-29 14:53:27 +04:00
FrameLayerBuilder : : GetOldLayerForFrame ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2010-07-16 01:07:51 +04:00
{
// If we need to build a new layer tree, then just refuse to recycle
// anything.
if ( ! mRetainingManager | | mInvalidateAllLayers )
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
2012-10-12 03:38:24 +04:00
DisplayItemData * data = GetDisplayItemData ( aFrame , aDisplayItemKey ) ;
2010-07-16 01:07:51 +04:00
2012-10-12 03:38:24 +04:00
if ( data & & data - > mLayer - > Manager ( ) = = mRetainingManager ) {
return data ;
2010-05-21 07:20:48 +04:00
}
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-05-21 07:20:48 +04:00
}
2012-08-29 14:53:27 +04:00
Layer *
2012-10-16 05:23:07 +04:00
FrameLayerBuilder : : GetOldLayerFor ( nsDisplayItem * aItem ,
nsDisplayItemGeometry * * aOldGeometry ,
2013-03-04 13:55:59 +04:00
DisplayItemClip * * aOldClip ,
2012-11-07 02:04:53 +04:00
nsTArray < nsIFrame * > * aChangedFrames ,
bool * aIsInvalid )
2012-08-29 14:53:27 +04:00
{
uint32_t key = aItem - > GetPerFrameKey ( ) ;
2013-04-19 16:02:13 +04:00
nsIFrame * frame = aItem - > Frame ( ) ;
2012-08-29 14:53:27 +04:00
2013-04-19 16:01:41 +04:00
DisplayItemData * oldData = GetOldLayerForFrame ( frame , key ) ;
if ( oldData ) {
if ( aOldGeometry ) {
* aOldGeometry = oldData - > mGeometry . get ( ) ;
2012-08-29 14:53:27 +04:00
}
2013-04-19 16:01:41 +04:00
if ( aOldClip ) {
* aOldClip = & oldData - > mClip ;
}
if ( aChangedFrames ) {
oldData - > GetFrameListChanges ( aItem , * aChangedFrames ) ;
}
if ( aIsInvalid ) {
* aIsInvalid = oldData - > mIsInvalid ;
}
return oldData - > mLayer ;
2012-08-29 14:53:27 +04:00
}
return nullptr ;
2012-08-29 09:47:15 +04:00
}
2012-08-29 14:53:27 +04:00
2012-07-17 21:03:51 +04:00
/* static */ Layer *
2012-08-22 19:56:38 +04:00
FrameLayerBuilder : : GetDebugOldLayerFor ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2012-07-17 21:03:51 +04:00
{
2012-10-12 03:38:24 +04:00
nsTArray < DisplayItemData * > * array =
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
2012-07-17 21:03:51 +04:00
2012-10-12 03:38:24 +04:00
if ( ! array ) {
2012-07-30 18:20:58 +04:00
return nullptr ;
2012-07-17 21:03:51 +04:00
}
2012-10-12 03:38:24 +04:00
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
DisplayItemData * data = array - > ElementAt ( i ) ;
2012-08-29 09:47:15 +04:00
2012-10-12 03:38:24 +04:00
if ( data - > mDisplayItemKey = = aDisplayItemKey ) {
return data - > mLayer ;
2012-08-29 09:47:15 +04:00
}
}
2012-10-12 03:38:24 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2010-07-16 01:08:03 +04:00
already_AddRefed < ColorLayer >
2012-08-20 14:00:49 +04:00
ContainerState : : CreateOrRecycleColorLayer ( ThebesLayer * aThebes )
2010-07-16 01:08:03 +04:00
{
2012-08-20 14:00:49 +04:00
ThebesDisplayItemLayerUserData * data =
static_cast < ThebesDisplayItemLayerUserData * > ( aThebes - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
nsRefPtr < ColorLayer > layer = data - > mColorLayer ;
if ( layer ) {
2012-07-30 18:20:58 +04:00
layer - > SetMaskLayer ( nullptr ) ;
2010-07-16 01:08:03 +04:00
} else {
// Create a new layer
layer = mManager - > CreateColorLayer ( ) ;
if ( ! layer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:08:03 +04:00
// Mark this layer as being used for Thebes-painting display items
2012-08-20 14:00:49 +04:00
data - > mColorLayer = layer ;
2012-07-30 18:20:58 +04:00
layer - > SetUserData ( & gColorLayerUserData , nullptr ) ;
2012-08-20 14:00:49 +04:00
// Remove other layer types we might have stored for this ThebesLayer
data - > mImageLayer = nullptr ;
2010-07-16 01:08:03 +04:00
}
return layer . forget ( ) ;
}
2011-01-18 00:47:18 +03:00
already_AddRefed < ImageLayer >
2012-08-20 14:00:49 +04:00
ContainerState : : CreateOrRecycleImageLayer ( ThebesLayer * aThebes )
2011-01-18 00:47:18 +03:00
{
2012-08-20 14:00:49 +04:00
ThebesDisplayItemLayerUserData * data =
static_cast < ThebesDisplayItemLayerUserData * > ( aThebes - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
nsRefPtr < ImageLayer > layer = data - > mImageLayer ;
if ( layer ) {
2012-07-30 18:20:58 +04:00
layer - > SetMaskLayer ( nullptr ) ;
2011-01-18 00:47:18 +03:00
} else {
// Create a new layer
layer = mManager - > CreateImageLayer ( ) ;
if ( ! layer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2011-01-18 00:47:18 +03:00
// Mark this layer as being used for Thebes-painting display items
2012-08-20 14:00:49 +04:00
data - > mImageLayer = layer ;
2012-07-30 18:20:58 +04:00
layer - > SetUserData ( & gImageLayerUserData , nullptr ) ;
2012-08-20 14:00:49 +04:00
// Remove other layer types we might have stored for this ThebesLayer
data - > mColorLayer = nullptr ;
2011-01-18 00:47:18 +03:00
}
return layer . forget ( ) ;
}
2012-02-08 02:26:40 +04:00
already_AddRefed < ImageLayer >
ContainerState : : CreateOrRecycleMaskImageLayerFor ( Layer * aLayer )
{
nsRefPtr < ImageLayer > result = mRecycledMaskImageLayers . Get ( aLayer ) ;
if ( result ) {
mRecycledMaskImageLayers . Remove ( aLayer ) ;
2012-06-26 06:43:30 +04:00
// XXX if we use clip on mask layers, null it out here
2012-02-08 02:26:40 +04:00
} else {
// Create a new layer
result = mManager - > CreateImageLayer ( ) ;
if ( ! result )
2012-07-30 18:20:58 +04:00
return nullptr ;
2012-02-08 02:26:40 +04:00
result - > SetUserData ( & gMaskLayerUserData , new MaskLayerUserData ( ) ) ;
2013-08-02 03:02:06 +04:00
result - > SetDisallowBigImage ( true ) ;
2012-02-08 02:26:40 +04:00
}
2012-07-30 22:36:12 +04:00
2012-02-08 02:26:40 +04:00
return result . forget ( ) ;
}
2012-05-10 09:24:20 +04:00
static const double SUBPIXEL_OFFSET_EPSILON = 0.02 ;
/**
* This normally computes NSToIntRoundUp ( aValue ) . However , if that would
* give a residual near 0.5 while aOldResidual is near - 0.5 , or
* it would give a residual near - 0.5 while aOldResidual is near 0.5 , then
* instead we return the integer in the other direction so that the residual
* is close to aOldResidual .
*/
2012-08-22 19:56:38 +04:00
static int32_t
2012-05-10 09:24:20 +04:00
RoundToMatchResidual ( double aValue , double aOldResidual )
{
2012-08-22 19:56:38 +04:00
int32_t v = NSToIntRoundUp ( aValue ) ;
2012-05-10 09:24:20 +04:00
double residual = aValue - v ;
if ( aOldResidual < 0 ) {
if ( residual > 0 & & fabs ( residual - 1.0 - aOldResidual ) < SUBPIXEL_OFFSET_EPSILON ) {
// Round up instead
2012-08-22 19:56:38 +04:00
return int32_t ( ceil ( aValue ) ) ;
2012-05-10 09:24:20 +04:00
}
} else if ( aOldResidual > 0 ) {
if ( residual < 0 & & fabs ( residual + 1.0 - aOldResidual ) < SUBPIXEL_OFFSET_EPSILON ) {
// Round down instead
2012-08-22 19:56:38 +04:00
return int32_t ( floor ( aValue ) ) ;
2012-05-10 09:24:20 +04:00
}
}
return v ;
2012-05-10 09:24:18 +04:00
}
2012-08-17 03:40:10 +04:00
static void
2013-09-26 01:07:26 +04:00
ResetScrollPositionForLayerPixelAlignment ( const nsIFrame * aAnimatedGeometryRoot )
2012-08-17 03:40:10 +04:00
{
2013-09-26 01:07:26 +04:00
nsIScrollableFrame * sf = nsLayoutUtils : : GetScrollableFrameFor ( aAnimatedGeometryRoot ) ;
2012-08-17 03:40:10 +04:00
if ( sf ) {
sf - > ResetScrollPositionForLayerPixelAlignment ( ) ;
}
}
static void
2013-09-26 01:07:26 +04:00
InvalidateEntireThebesLayer ( ThebesLayer * aLayer , const nsIFrame * aAnimatedGeometryRoot )
2012-08-17 03:40:10 +04:00
{
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Invalidating entire layer %p \n " , aLayer ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
2012-08-17 03:40:10 +04:00
nsIntRect invalidate = aLayer - > GetValidRegion ( ) . GetBounds ( ) ;
aLayer - > InvalidateRegion ( invalidate ) ;
2013-09-26 01:07:26 +04:00
ResetScrollPositionForLayerPixelAlignment ( aAnimatedGeometryRoot ) ;
2012-08-17 03:40:10 +04:00
}
2010-07-16 01:07:51 +04:00
already_AddRefed < ThebesLayer >
2013-09-26 01:07:26 +04:00
ContainerState : : CreateOrRecycleThebesLayer ( const nsIFrame * aAnimatedGeometryRoot ,
2012-09-28 15:19:39 +04:00
const nsIFrame * aReferenceFrame ,
const nsPoint & aTopLeft )
2010-07-16 01:07:51 +04:00
{
// We need a new thebes layer
nsRefPtr < ThebesLayer > layer ;
2011-06-22 16:11:27 +04:00
ThebesDisplayItemLayerUserData * data ;
2012-11-30 20:06:37 +04:00
# ifndef MOZ_ANDROID_OMTC
2012-08-17 03:40:10 +04:00
bool didResetScrollPositionForLayerPixelAlignment = false ;
2012-11-30 20:06:37 +04:00
# endif
2010-07-16 01:08:03 +04:00
if ( mNextFreeRecycledThebesLayer < mRecycledThebesLayers . Length ( ) ) {
2010-07-16 01:07:51 +04:00
// Recycle a layer
layer = mRecycledThebesLayers [ mNextFreeRecycledThebesLayer ] ;
+ + mNextFreeRecycledThebesLayer ;
2013-04-19 19:17:21 +04:00
// Clear clip rect and mask layer so we don't accidentally stay clipped.
// We will reapply any necessary clipping.
2012-07-30 18:20:58 +04:00
layer - > SetMaskLayer ( nullptr ) ;
2010-07-16 01:07:51 +04:00
2011-06-22 16:11:27 +04:00
data = static_cast < ThebesDisplayItemLayerUserData * >
( layer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
NS_ASSERTION ( data , " Recycled ThebesLayers must have user data " ) ;
2010-07-16 01:07:51 +04:00
// 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.
2013-04-28 14:02:35 +04:00
if ( ! FuzzyEqual ( data - > mXScale , mParameters . mXScale , 0.00001f ) | |
! FuzzyEqual ( data - > mYScale , mParameters . mYScale , 0.00001f ) | |
2012-10-16 05:10:51 +04:00
data - > mAppUnitsPerDevPixel ! = mAppUnitsPerDevPixel ) {
2013-09-26 01:07:26 +04:00
InvalidateEntireThebesLayer ( layer , aAnimatedGeometryRoot ) ;
2012-11-30 20:06:37 +04:00
# ifndef MOZ_ANDROID_OMTC
2012-08-17 03:40:10 +04:00
didResetScrollPositionForLayerPixelAlignment = true ;
2012-11-30 20:06:37 +04:00
# endif
2010-07-16 01:07:51 +04:00
}
2012-08-29 09:47:15 +04:00
if ( ! data - > mRegionToInvalidate . IsEmpty ( ) ) {
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Invalidating deleted frame content from layer %p \n " , layer . get ( ) ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
layer - > InvalidateRegion ( data - > mRegionToInvalidate ) ;
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
nsAutoCString str ;
AppendToString ( str , data - > mRegionToInvalidate ) ;
2013-11-24 02:44:18 +04:00
printf_stderr ( " Invalidating layer %p: %s \n " , layer . get ( ) , str . get ( ) ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
data - > mRegionToInvalidate . SetEmpty ( ) ;
}
2010-07-16 01:07:51 +04:00
// We do not need to Invalidate these areas in the widget because we
2011-02-11 02:21:07 +03:00
// assume the caller of InvalidateThebesLayerContents has ensured
2010-07-16 01:07:51 +04:00
// the area is invalidated in the widget.
} else {
2013-09-17 21:55:09 +04:00
// Check whether the layer will be scrollable. This is used as a hint to
// influence whether tiled layers are used or not.
bool canScroll = false ;
nsIFrame * animatedGeometryRootParent = aAnimatedGeometryRoot - > GetParent ( ) ;
if ( animatedGeometryRootParent & &
animatedGeometryRootParent - > GetType ( ) = = nsGkAtoms : : scrollFrame ) {
canScroll = true ;
}
2010-07-16 01:07:51 +04:00
// Create a new thebes layer
2013-09-17 21:55:09 +04:00
layer = mManager - > CreateThebesLayerWithHint ( canScroll ? LayerManager : : SCROLLABLE :
LayerManager : : NONE ) ;
2010-07-16 01:07:51 +04:00
if ( ! layer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
// Mark this layer as being used for Thebes-painting display items
2011-06-22 16:11:27 +04:00
data = new ThebesDisplayItemLayerUserData ( ) ;
layer - > SetUserData ( & gThebesDisplayItemLayerUserData , data ) ;
2013-09-26 01:07:26 +04:00
ResetScrollPositionForLayerPixelAlignment ( aAnimatedGeometryRoot ) ;
2012-11-30 20:06:37 +04:00
# ifndef MOZ_ANDROID_OMTC
2012-08-17 03:40:10 +04:00
didResetScrollPositionForLayerPixelAlignment = true ;
2012-11-30 20:06:37 +04:00
# endif
2010-07-16 01:07:51 +04:00
}
2011-06-22 16:11:27 +04:00
data - > mXScale = mParameters . mXScale ;
data - > mYScale = mParameters . mYScale ;
2013-09-26 01:07:26 +04:00
data - > mLastAnimatedGeometryRootOrigin = data - > mAnimatedGeometryRootOrigin ;
data - > mAnimatedGeometryRootOrigin = aTopLeft ;
2012-08-29 09:47:15 +04:00
data - > mAppUnitsPerDevPixel = mAppUnitsPerDevPixel ;
2012-04-10 15:24:18 +04:00
layer - > SetAllowResidualTranslation ( mParameters . AllowResidualTranslation ( ) ) ;
2010-07-16 01:07:51 +04:00
2012-07-17 21:03:51 +04:00
mLayerBuilder - > SaveLastPaintOffset ( layer ) ;
2011-05-17 03:05:56 +04:00
2010-07-16 01:07:51 +04:00
// Set up transform so that 0,0 in the Thebes layer corresponds to the
2013-09-26 01:07:26 +04:00
// (pixel-snapped) top-left of the aAnimatedGeometryRoot.
nsPoint offset = aAnimatedGeometryRoot - > GetOffsetToCrossDoc ( aReferenceFrame ) ;
nscoord appUnitsPerDevPixel = aAnimatedGeometryRoot - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2011-06-22 16:11:28 +04:00
gfxPoint scaledOffset (
NSAppUnitsToDoublePixels ( offset . x , appUnitsPerDevPixel ) * mParameters . mXScale ,
NSAppUnitsToDoublePixels ( offset . y , appUnitsPerDevPixel ) * mParameters . mYScale ) ;
2012-05-10 09:24:20 +04:00
// We call RoundToMatchResidual here so that the residual after rounding
2013-09-26 01:07:26 +04:00
// is close to data->mAnimatedGeometryRootPosition if possible.
nsIntPoint pixOffset ( RoundToMatchResidual ( scaledOffset . x , data - > mAnimatedGeometryRootPosition . x ) ,
RoundToMatchResidual ( scaledOffset . y , data - > mAnimatedGeometryRootPosition . y ) ) ;
2012-09-17 02:25:33 +04:00
data - > mTranslation = pixOffset ;
pixOffset + = mParameters . mOffset ;
2010-07-16 01:07:51 +04:00
gfxMatrix matrix ;
matrix . Translate ( gfxPoint ( pixOffset . x , pixOffset . y ) ) ;
2012-07-31 06:20:00 +04:00
layer - > SetBaseTransform ( gfx3DMatrix : : From2D ( matrix ) ) ;
2010-07-16 01:07:51 +04:00
2012-03-13 20:57:31 +04:00
// FIXME: Temporary workaround for bug 681192 and bug 724786.
2012-10-02 00:01:35 +04:00
# ifndef MOZ_ANDROID_OMTC
2011-06-22 16:11:28 +04:00
// Calculate exact position of the top-left of the active scrolled root.
// This might not be 0,0 due to the snapping in ScaleToNearestPixels.
2013-09-26 01:07:26 +04:00
gfxPoint animatedGeometryRootTopLeft = scaledOffset - matrix . GetTranslation ( ) + mParameters . mOffset ;
2011-06-22 16:11:28 +04:00
// If it has changed, then we need to invalidate the entire layer since the
// pixels in the layer buffer have the content at a (subpixel) offset
// from what we need.
2013-09-26 01:07:26 +04:00
if ( ! animatedGeometryRootTopLeft . WithinEpsilonOf ( data - > mAnimatedGeometryRootPosition , SUBPIXEL_OFFSET_EPSILON ) ) {
data - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
InvalidateEntireThebesLayer ( layer , aAnimatedGeometryRoot ) ;
2012-08-17 03:40:10 +04:00
} else if ( didResetScrollPositionForLayerPixelAlignment ) {
2013-09-26 01:07:26 +04:00
data - > mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft ;
2011-06-22 16:11:28 +04:00
}
2012-02-08 10:21:38 +04:00
# endif
2011-06-22 16:11:28 +04:00
2010-07-16 01:07:51 +04:00
return layer . forget ( ) ;
}
2013-11-18 00:33:21 +04:00
# if defined(DEBUG) || defined(MOZ_DUMP_PAINTING)
2010-07-16 01:07:51 +04:00
/**
2013-03-04 13:56:02 +04:00
* Returns the appunits per dev pixel for the item ' s frame
2010-07-16 01:07:51 +04:00
*/
2012-08-22 19:56:38 +04:00
static int32_t
2010-07-16 01:07:51 +04:00
AppUnitsPerDevPixel ( nsDisplayItem * aItem )
{
2010-08-08 22:49:06 +04:00
// The underlying frame for zoom items is the root frame of the subdocument.
// But zoom display items report their bounds etc using the parent document's
// APD because zoom items act as a conversion layer between the two different
// APDs.
if ( aItem - > GetType ( ) = = nsDisplayItem : : TYPE_ZOOM ) {
return static_cast < nsDisplayZoom * > ( aItem ) - > GetParentAppUnitsPerDevPixel ( ) ;
}
2013-04-19 16:02:13 +04:00
return aItem - > Frame ( ) - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2010-07-16 01:07:51 +04:00
}
2012-10-10 09:00:05 +04:00
# endif
2010-07-16 01:07:51 +04:00
/**
2011-02-23 08:38:09 +03:00
* Restrict the visible region of aLayer to the region that is actually visible .
* Because we only reduce the visible region here , we don ' t need to worry
2013-03-22 06:17:29 +04:00
* about whether CONTENT_OPAQUE is set ; if layer was opaque in the old
2011-02-23 08:38:09 +03:00
* visible region , it will still be opaque in the new one .
2013-03-22 06:17:29 +04:00
* @ param aLayerVisibleRegion the visible region of the layer , in the layer ' s
* coordinate space
* @ param aRestrictToRect the rect to restrict the visible region to , in the
* parent ' s coordinate system
2010-07-16 01:07:51 +04:00
*/
static void
2013-03-22 06:17:29 +04:00
SetVisibleRegionForLayer ( Layer * aLayer , const nsIntRegion & aLayerVisibleRegion ,
const nsIntRect & aRestrictToRect )
2010-07-16 01:07:51 +04:00
{
2011-08-03 07:04:21 +04:00
gfx3DMatrix transform = aLayer - > GetTransform ( ) ;
2011-02-23 08:38:09 +03:00
// if 'transform' is not invertible, then nothing will be displayed
// for the layer, so it doesn't really matter what we do here
2013-03-22 06:17:29 +04:00
gfxRect itemVisible ( aRestrictToRect . x , aRestrictToRect . y ,
aRestrictToRect . width , aRestrictToRect . height ) ;
2011-08-03 07:04:21 +04:00
gfxRect layerVisible = transform . Inverse ( ) . ProjectRectBounds ( itemVisible ) ;
2011-02-23 08:38:09 +03:00
layerVisible . RoundOut ( ) ;
nsIntRect visibleRect ;
2013-03-22 06:17:29 +04:00
if ( ! gfxUtils : : GfxRectToIntRect ( layerVisible , & visibleRect ) ) {
aLayer - > SetVisibleRegion ( nsIntRegion ( ) ) ;
} else {
nsIntRegion rgn ;
rgn . And ( aLayerVisibleRegion , visibleRect ) ;
2011-02-23 08:38:09 +03:00
aLayer - > SetVisibleRegion ( rgn ) ;
2010-07-16 01:07:51 +04:00
}
}
2010-09-02 13:18:39 +04:00
nscolor
2012-08-22 19:56:38 +04:00
ContainerState : : FindOpaqueBackgroundColorFor ( int32_t aThebesLayerIndex )
2010-09-02 13:18:39 +04:00
{
ThebesLayerData * target = mThebesLayerDataStack [ aThebesLayerIndex ] ;
2012-08-22 19:56:38 +04:00
for ( int32_t i = aThebesLayerIndex - 1 ; i > = 0 ; - - i ) {
2010-09-02 13:18:39 +04:00
ThebesLayerData * candidate = mThebesLayerDataStack [ i ] ;
2013-11-08 10:04:12 +04:00
if ( candidate - > IntersectsVisibleAboveRegion ( target - > mVisibleRegion ) ) {
2010-09-02 13:18:39 +04: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 16:11:27 +04:00
2010-09-02 13:18:39 +04: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 06:53:17 +04: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 ;
}
nscolor color ;
if ( item - > IsUniform ( mBuilder , & color ) & & NS_GET_A ( color ) = = 255 )
return color ;
break ;
}
break ;
2010-09-02 13:18:39 +04:00
}
return NS_RGBA ( 0 , 0 , 0 , 0 ) ;
}
2012-02-08 02:27:44 +04:00
void
2013-12-16 16:11:01 +04:00
ThebesLayerData : : UpdateCommonClipCount (
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aCurrentClip )
2012-02-08 02:27:44 +04:00
{
if ( mCommonClipCount > = 0 ) {
2013-03-04 13:56:00 +04:00
mCommonClipCount = mItemClip . GetCommonRoundedRectCount ( aCurrentClip , mCommonClipCount ) ;
2012-02-08 02:27:44 +04:00
} else {
// first item in the layer
2013-03-04 13:56:00 +04:00
mCommonClipCount = aCurrentClip . GetRoundedRectCount ( ) ;
2012-07-31 21:28:21 +04:00
}
2012-02-08 02:27:44 +04:00
}
2012-01-30 09:16:54 +04:00
already_AddRefed < ImageContainer >
2013-12-16 16:11:01 +04:00
ThebesLayerData : : CanOptimizeImageLayer ( nsDisplayListBuilder * aBuilder )
2011-01-18 00:47:18 +03:00
{
2012-02-08 02:27:44 +04:00
if ( ! mImage ) {
2012-07-30 18:20:58 +04:00
return nullptr ;
2011-01-18 00:47:18 +03:00
}
2012-11-28 06:34:45 +04:00
return mImage - > GetContainer ( mLayer - > Manager ( ) , aBuilder ) ;
2011-01-18 00:47:18 +03:00
}
2013-09-27 10:01:16 +04:00
const nsIFrame *
ContainerState : : FindFixedPosFrameForLayerData ( const nsIFrame * aAnimatedGeometryRoot ,
const nsIntRegion & aDrawRegion ,
nsIntRegion * aVisibleRegion ,
bool * aIsSolidColorInVisibleRegion )
{
2013-11-29 09:17:53 +04:00
nsIFrame * viewport = mContainerFrame - > PresContext ( ) - > PresShell ( ) - > GetRootFrame ( ) ;
2013-09-27 10:01:16 +04:00
// Viewports with no fixed-pos frames are not relevant.
2013-11-29 09:17:53 +04:00
if ( ! viewport - > GetFirstChild ( nsIFrame : : kFixedList ) ) {
2013-09-27 10:01:16 +04:00
return nullptr ;
}
nsRect displayPort ;
for ( const nsIFrame * f = aAnimatedGeometryRoot ; f ; f = f - > GetParent ( ) ) {
if ( nsLayoutUtils : : IsFixedPosFrameInDisplayPort ( f , & displayPort ) ) {
2013-11-29 09:17:53 +04:00
// Display ports are relative to the viewport, convert it to be relative
// to our reference frame.
displayPort + = viewport - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2013-09-27 10:01:16 +04:00
nsIntRegion newVisibleRegion ;
newVisibleRegion . And ( ScaleToOutsidePixels ( displayPort , false ) ,
aDrawRegion ) ;
if ( ! aVisibleRegion - > Contains ( newVisibleRegion ) ) {
if ( aIsSolidColorInVisibleRegion ) {
* aIsSolidColorInVisibleRegion = false ;
}
* aVisibleRegion = newVisibleRegion ;
}
return f ;
}
}
return nullptr ;
}
void
ContainerState : : SetFixedPositionLayerData ( Layer * aLayer ,
const nsIFrame * aFixedPosFrame )
{
aLayer - > SetIsFixedPosition ( aFixedPosFrame ! = nullptr ) ;
if ( ! aFixedPosFrame ) {
return ;
}
nsIFrame * viewportFrame = aFixedPosFrame - > GetParent ( ) ;
nsPresContext * presContext = aFixedPosFrame - > PresContext ( ) ;
// Fixed position frames are reflowed into the scroll-port size if one has
// been set.
nsSize viewportSize = viewportFrame - > GetSize ( ) ;
if ( presContext - > PresShell ( ) - > IsScrollPositionClampingScrollPortSizeSet ( ) ) {
viewportSize = presContext - > PresShell ( ) - >
GetScrollPositionClampingScrollPortSize ( ) ;
}
2013-09-27 10:02:03 +04:00
nsLayoutUtils : : SetFixedPositionLayerData ( aLayer ,
2013-12-12 16:33:02 +04:00
viewportFrame , viewportSize , aFixedPosFrame , presContext , mParameters ) ;
2013-09-27 10:01:16 +04:00
}
2010-07-16 01:07:51 +04:00
void
ContainerState : : PopThebesLayerData ( )
{
NS_ASSERTION ( ! mThebesLayerDataStack . IsEmpty ( ) , " Can't pop " ) ;
2012-08-22 19:56:38 +04:00
int32_t lastIndex = mThebesLayerDataStack . Length ( ) - 1 ;
2010-07-16 01:07:51 +04:00
ThebesLayerData * data = mThebesLayerDataStack [ lastIndex ] ;
2013-09-27 10:01:16 +04:00
const nsIFrame * fixedPosFrameForLayerData =
FindFixedPosFrameForLayerData ( data - > mAnimatedGeometryRoot ,
data - > mDrawRegion ,
& data - > mVisibleRegion ,
& data - > mIsSolidColorInVisibleRegion ) ;
2011-01-18 00:47:18 +03:00
nsRefPtr < Layer > layer ;
2012-11-19 07:28:18 +04:00
nsRefPtr < ImageContainer > imageContainer = data - > CanOptimizeImageLayer ( mBuilder ) ;
2011-01-18 00:47:18 +03:00
2012-02-16 08:17:20 +04:00
if ( ( data - > mIsSolidColorInVisibleRegion | | imageContainer ) & &
2013-04-19 19:17:21 +04:00
data - > mLayer - > GetValidRegion ( ) . IsEmpty ( ) ) {
2011-01-18 00:47:18 +03:00
NS_ASSERTION ( ! ( data - > mIsSolidColorInVisibleRegion & & imageContainer ) ,
" Can't be a solid color as well as an image! " ) ;
if ( imageContainer ) {
2013-04-19 19:17:21 +04:00
nsRefPtr < ImageLayer > imageLayer = CreateOrRecycleImageLayer ( data - > mLayer ) ;
2011-01-18 00:47:18 +03:00
imageLayer - > SetContainer ( imageContainer ) ;
2012-09-17 02:25:33 +04:00
data - > mImage - > ConfigureLayer ( imageLayer , mParameters . mOffset ) ;
2012-08-04 01:29:22 +04:00
imageLayer - > SetPostScale ( mParameters . mXScale ,
mParameters . mYScale ) ;
2013-03-04 13:56:00 +04:00
if ( data - > mItemClip . HasClip ( ) ) {
nsIntRect clip = ScaleToNearestPixels ( data - > mItemClip . GetClipRect ( ) ) ;
2012-09-24 06:56:39 +04:00
clip . MoveBy ( mParameters . mOffset ) ;
2013-03-22 06:17:29 +04:00
imageLayer - > SetClipRect ( & clip ) ;
} else {
imageLayer - > SetClipRect ( nullptr ) ;
2011-04-01 01:33:46 +04:00
}
2011-01-18 00:47:18 +03:00
layer = imageLayer ;
2012-10-12 06:39:46 +04:00
mLayerBuilder - > StoreOptimizedLayerForFrame ( data - > mImage ,
2012-09-25 00:31:30 +04:00
imageLayer ) ;
2011-01-18 00:47:18 +03:00
} else {
2013-04-19 19:17:21 +04:00
nsRefPtr < ColorLayer > colorLayer = CreateOrRecycleColorLayer ( data - > mLayer ) ;
2011-01-18 00:47:18 +03:00
colorLayer - > SetColor ( data - > mSolidColor ) ;
2012-07-30 22:36:12 +04:00
// Copy transform
2013-04-19 19:17:21 +04:00
colorLayer - > SetBaseTransform ( data - > mLayer - > GetBaseTransform ( ) ) ;
colorLayer - > SetPostScale ( data - > mLayer - > GetPostXScale ( ) , data - > mLayer - > GetPostYScale ( ) ) ;
2012-08-04 01:29:22 +04:00
2011-01-18 00:47:18 +03:00
nsIntRect visibleRect = data - > mVisibleRegion . GetBounds ( ) ;
2013-07-09 18:11:00 +04:00
visibleRect . MoveBy ( - GetTranslationForThebesLayer ( data - > mLayer ) ) ;
colorLayer - > SetBounds ( visibleRect ) ;
2011-01-18 00:47:18 +03:00
layer = colorLayer ;
}
2010-07-16 01:08:03 +04:00
2011-01-18 00:47:18 +03:00
NS_ASSERTION ( ! mNewChildLayers . Contains ( layer ) , " Layer already in list??? " ) ;
2010-11-09 05:48:59 +03:00
AutoLayersArray : : index_type index = mNewChildLayers . IndexOf ( data - > mLayer ) ;
NS_ASSERTION ( index ! = AutoLayersArray : : NoIndex , " Thebes layer not found? " ) ;
2011-01-18 00:47:18 +03:00
mNewChildLayers . InsertElementAt ( index + 1 , layer ) ;
2010-07-16 01:08:03 +04:00
// Hide the ThebesLayer. We leave it in the layer tree so that we
// can find and recycle it later.
2013-03-22 06:17:29 +04:00
nsIntRect emptyRect ;
2013-04-19 19:17:21 +04:00
data - > mLayer - > SetClipRect ( & emptyRect ) ;
data - > mLayer - > SetVisibleRegion ( nsIntRegion ( ) ) ;
2010-07-16 01:08:03 +04:00
} else {
2013-04-19 19:17:21 +04:00
layer = data - > mLayer ;
2012-07-30 18:20:58 +04:00
imageContainer = nullptr ;
2013-04-19 19:17:21 +04:00
layer - > SetClipRect ( nullptr ) ;
2010-07-16 01:08:03 +04:00
}
2010-07-16 01:07:51 +04:00
gfxMatrix transform ;
2011-01-18 00:47:18 +03:00
if ( ! layer - > GetTransform ( ) . Is2D ( & transform ) ) {
NS_ERROR ( " Only 2D transformations currently supported " ) ;
}
2012-07-31 21:28:21 +04:00
2012-03-19 11:26:39 +04:00
// ImageLayers are already configured with a visible region
2011-01-18 00:47:18 +03:00
if ( ! imageContainer ) {
2010-07-16 01:07:51 +04:00
NS_ASSERTION ( ! transform . HasNonIntegerTranslation ( ) ,
" Matrix not just an integer translation? " ) ;
// Convert from relative to the container to relative to the
// ThebesLayer itself.
nsIntRegion rgn = data - > mVisibleRegion ;
2012-09-17 02:25:33 +04:00
rgn . MoveBy ( - GetTranslationForThebesLayer ( data - > mLayer ) ) ;
2010-07-16 01:08:03 +04:00
layer - > SetVisibleRegion ( rgn ) ;
2010-07-16 01:07:51 +04:00
}
nsIntRegion transparentRegion ;
transparentRegion . Sub ( data - > mVisibleRegion , data - > mOpaqueRegion ) ;
2011-09-29 10:19:26 +04:00
bool isOpaque = transparentRegion . IsEmpty ( ) ;
2010-09-02 13:18:39 +04: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 18:59:28 +04:00
isOpaque = true ;
2010-09-02 13:18:39 +04:00
}
}
// Store the background color
ThebesDisplayItemLayerUserData * userData =
2012-02-08 02:27:44 +04:00
GetThebesDisplayItemLayerUserData ( data - > mLayer ) ;
2010-09-02 13:18:39 +04: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
data - > mLayer - > InvalidateRegion ( data - > mLayer - > GetValidRegion ( ) ) ;
}
userData - > mForcedBackgroundColor = backgroundColor ;
2012-02-08 02:27:44 +04:00
// use a mask layer for rounded rect clipping
2012-08-22 19:56:38 +04:00
int32_t commonClipCount = data - > mCommonClipCount ;
2012-02-08 02:27:44 +04:00
NS_ASSERTION ( commonClipCount > = 0 , " Inconsistent clip count. " ) ;
SetupMaskLayer ( layer , data - > mItemClip , commonClipCount ) ;
// copy commonClipCount to the entry
2012-07-17 21:03:51 +04:00
FrameLayerBuilder : : ThebesLayerItemsEntry * entry = mLayerBuilder - >
2012-02-08 02:27:44 +04:00
GetThebesLayerItemsEntry ( static_cast < ThebesLayer * > ( layer . get ( ) ) ) ;
entry - > mCommonClipCount = commonClipCount ;
} else {
// mask layer for image and color layers
SetupMaskLayer ( layer , data - > mItemClip ) ;
2010-09-02 13:18:39 +04:00
}
2013-12-13 22:53:18 +04:00
uint32_t flags = 0 ;
nsIWidget * widget = mContainerReferenceFrame - > PresContext ( ) - > GetRootWidget ( ) ;
// Disable subpixelAA on hidpi
bool hidpi = widget & & widget - > GetDefaultScale ( ) . scale > = 2 ;
if ( hidpi ) {
flags | = Layer : : CONTENT_DISABLE_SUBPIXEL_AA ;
}
2010-12-20 04:26:14 +03:00
if ( isOpaque & & ! data - > mForceTransparentSurface ) {
2013-12-13 22:53:18 +04:00
flags | = Layer : : CONTENT_OPAQUE ;
} else if ( data - > mNeedComponentAlpha & & ! hidpi ) {
flags | = Layer : : CONTENT_COMPONENT_ALPHA ;
2010-12-20 04:26:14 +03:00
}
2010-09-02 13:18:40 +04:00
layer - > SetContentFlags ( flags ) ;
2010-09-02 13:18:39 +04:00
2013-09-27 10:01:16 +04:00
SetFixedPositionLayerData ( layer , fixedPosFrameForLayerData ) ;
2010-09-02 13:18:39 +04: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 10:04:12 +04:00
nextData - > CopyAboveRegion ( data ) ;
2010-09-02 13:18:39 +04:00
}
2010-07-16 01:07:51 +04:00
mThebesLayerDataStack . RemoveElementAt ( lastIndex ) ;
}
2011-09-29 10:19:26 +04:00
static bool
2011-01-03 04:48:09 +03:00
SuppressComponentAlpha ( nsDisplayListBuilder * aBuilder ,
2011-01-03 04:48:09 +03:00
nsDisplayItem * aItem ,
const nsRect & aComponentAlphaBounds )
2011-01-03 04:48:09 +03:00
{
const nsRegion * windowTransparentRegion = aBuilder - > GetFinalTransparentRegion ( ) ;
if ( ! windowTransparentRegion | | windowTransparentRegion - > IsEmpty ( ) )
2011-10-17 18:59:28 +04:00
return false ;
2011-01-03 04:48:09 +03:00
// Suppress component alpha for items in the toplevel window that are over
// the window translucent area
2013-04-19 16:02:13 +04:00
nsIFrame * f = aItem - > Frame ( ) ;
2012-09-16 14:32:59 +04:00
nsIFrame * ref = aBuilder - > RootReferenceFrame ( ) ;
2011-01-03 04:48:09 +03:00
if ( f - > PresContext ( ) ! = ref - > PresContext ( ) )
2011-10-17 18:59:28 +04:00
return false ;
2011-01-03 04:48:09 +03:00
for ( nsIFrame * t = f ; t ; t = t - > GetParent ( ) ) {
if ( t - > IsTransformed ( ) )
2011-10-17 18:59:28 +04:00
return false ;
2011-01-03 04:48:09 +03:00
}
2011-01-03 04:48:09 +03:00
return windowTransparentRegion - > Intersects ( aComponentAlphaBounds ) ;
2011-01-03 04:48:09 +03:00
}
2011-09-29 10:19:26 +04:00
static bool
2011-01-03 04:48:09 +03:00
WindowHasTransparency ( nsDisplayListBuilder * aBuilder )
{
const nsRegion * windowTransparentRegion = aBuilder - > GetFinalTransparentRegion ( ) ;
return windowTransparentRegion & & ! windowTransparentRegion - > IsEmpty ( ) ;
}
2010-07-16 01:07:51 +04:00
void
2013-12-16 16:11:01 +04:00
ThebesLayerData : : Accumulate ( ContainerState * aState ,
nsDisplayItem * aItem ,
const nsIntRect & aVisibleRect ,
const nsIntRect & aDrawRect ,
const DisplayItemClip & aClip )
2010-07-16 01:07:51 +04:00
{
2012-05-03 08:29:05 +04:00
if ( aState - > mBuilder - > NeedToForceTransparentSurfaceForItem ( aItem ) ) {
mForceTransparentSurface = true ;
}
2012-05-03 08:29:05 +04:00
if ( aState - > mParameters . mDisableSubpixelAntialiasingInDescendants ) {
// Disable component alpha.
// 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 08:29:05 +04:00
2011-10-26 07:24:58 +04: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-25 00:29:14 +04:00
if ( mVisibleRegion . IsEmpty ( ) & &
2012-11-19 07:28:18 +04:00
aItem - > SupportsOptimizingToImage ( ) ) {
2012-09-25 00:29:14 +04:00
mImage = static_cast < nsDisplayImageContainer * > ( aItem ) ;
2011-10-26 07:24:58 +04:00
} else {
2012-07-30 18:20:58 +04:00
mImage = nullptr ;
2011-10-26 07:24:58 +04:00
}
2012-02-08 02:27:44 +04:00
mItemClip = aClip ;
2011-10-26 07:24:58 +04:00
2012-05-03 08:29:05 +04: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 13:38:45 +03:00
// Some display items have to exist (so they can set forceTransparentSurface
// below) but don't draw anything. They'll return true for isUniform but
// a color with opacity 0.
if ( ! isUniform | | NS_GET_A ( uniformColor ) > 0 ) {
2012-04-10 15:24:18 +04:00
// Make sure that the visible area is covered by uniform pixels. In
// particular this excludes cases where the edges of the item are not
// pixel-aligned (thus the item will not be truly uniform).
if ( isUniform ) {
bool snap ;
nsRect bounds = aItem - > GetBounds ( aState - > mBuilder , & snap ) ;
if ( ! aState - > ScaleToInsidePixels ( bounds , snap ) . Contains ( aVisibleRect ) ) {
isUniform = false ;
}
}
2013-03-04 13:56:00 +04:00
if ( isUniform & & aClip . GetRoundedRectCount ( ) = = 0 ) {
2011-01-16 13:38:45 +03:00
if ( mVisibleRegion . IsEmpty ( ) ) {
// This color is all we have
mSolidColor = uniformColor ;
2011-10-17 18:59:28 +04:00
mIsSolidColorInVisibleRegion = true ;
2011-01-16 13:38:45 +03:00
} else if ( mIsSolidColorInVisibleRegion & &
mVisibleRegion . IsEqual ( nsIntRegion ( aVisibleRect ) ) ) {
// we can just blend the colors together
mSolidColor = NS_ComposeColors ( mSolidColor , uniformColor ) ;
} else {
2011-10-17 18:59:28 +04:00
mIsSolidColorInVisibleRegion = false ;
2011-01-16 13:38:45 +03:00
}
2010-07-16 01:08:03 +04:00
} else {
2011-10-17 18:59:28 +04:00
mIsSolidColorInVisibleRegion = false ;
2010-07-16 01:08:03 +04:00
}
2011-01-16 13:38:45 +03:00
mVisibleRegion . Or ( mVisibleRegion , aVisibleRect ) ;
mVisibleRegion . SimplifyOutward ( 4 ) ;
mDrawRegion . Or ( mDrawRegion , aDrawRect ) ;
mDrawRegion . SimplifyOutward ( 4 ) ;
}
2011-01-18 00:47:18 +03:00
2012-04-10 15:24:18 +04:00
bool snap ;
2012-05-03 08:29:05 +04:00
nsRegion opaque = aItem - > GetOpaqueRegion ( aState - > mBuilder , & snap ) ;
2011-01-03 04:48:09 +03:00
if ( ! opaque . IsEmpty ( ) ) {
2012-07-23 07:00:36 +04:00
nsRegion opaqueClipped ;
2011-01-03 04:48:09 +03:00
nsRegionRectIterator iter ( opaque ) ;
for ( const nsRect * r = iter . Next ( ) ; r ; r = iter . Next ( ) ) {
2013-03-04 13:56:02 +04:00
opaqueClipped . Or ( opaqueClipped , aClip . ApproximateIntersectInward ( * r ) ) ;
2012-07-23 07:00:36 +04:00
}
nsIntRegion opaquePixels = aState - > ScaleRegionToInsidePixels ( opaqueClipped , snap ) ;
nsIntRegionRectIterator iter2 ( opaquePixels ) ;
for ( const nsIntRect * r = iter2 . Next ( ) ; r ; r = iter2 . Next ( ) ) {
2011-01-03 04:48:09 +03:00
// We don't use SimplifyInward here since it's not defined exactly
// what it will discard. For our purposes the most important case
// is a large opaque background at the bottom of z-order (e.g.,
// a canvas background), so we need to make sure that the first rect
// we see doesn't get discarded.
nsIntRegion tmp ;
2012-07-23 07:00:36 +04:00
tmp . Or ( mOpaqueRegion , * r ) ;
2011-01-03 04:48:09 +03:00
// Opaque display items in chrome documents whose window is partially
// transparent are always added to the opaque region. This helps ensure
// that we get as much subpixel-AA as possible in the chrome.
if ( tmp . GetNumRects ( ) < = 4 | |
2011-06-22 16:11:27 +04:00
( WindowHasTransparency ( aState - > mBuilder ) & &
2013-04-19 16:02:13 +04:00
aItem - > Frame ( ) - > PresContext ( ) - > IsChrome ( ) ) ) {
2011-01-03 04:48:09 +03:00
mOpaqueRegion = tmp ;
}
2010-07-16 01:08:11 +04:00
}
2011-01-03 04:48:09 +03:00
}
2012-05-03 08:29:05 +04:00
if ( ! aState - > mParameters . mDisableSubpixelAntialiasingInDescendants ) {
2012-01-11 15:26:33 +04:00
nsRect componentAlpha = aItem - > GetComponentAlphaBounds ( aState - > mBuilder ) ;
if ( ! componentAlpha . IsEmpty ( ) ) {
2012-04-10 15:24:18 +04:00
nsIntRect componentAlphaRect =
aState - > ScaleToOutsidePixels ( componentAlpha , false ) . Intersect ( aVisibleRect ) ;
if ( ! mOpaqueRegion . Contains ( componentAlphaRect ) ) {
2012-01-11 15:26:33 +04:00
if ( SuppressComponentAlpha ( aState - > mBuilder , aItem , componentAlpha ) ) {
aItem - > DisableComponentAlpha ( ) ;
} else {
mNeedComponentAlpha = true ;
}
2011-01-03 04:48:09 +03:00
}
2010-09-02 13:18:40 +04:00
}
2010-07-16 01:07:51 +04:00
}
}
2013-12-16 16:11:01 +04:00
ThebesLayerData *
2010-09-02 13:18:39 +04:00
ContainerState : : FindThebesLayerFor ( nsDisplayItem * aItem ,
const nsIntRect & aVisibleRect ,
2010-08-02 07:06:58 +04:00
const nsIntRect & aDrawRect ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2012-09-28 15:19:39 +04:00
const nsIFrame * aActiveScrolledRoot ,
const nsPoint & aTopLeft )
2010-07-16 01:07:51 +04:00
{
2012-08-22 19:56:38 +04:00
int32_t i ;
int32_t lowestUsableLayerWithScrolledRoot = - 1 ;
int32_t topmostLayerWithScrolledRoot = - 1 ;
2010-07-16 01:07:51 +04:00
for ( i = mThebesLayerDataStack . Length ( ) - 1 ; i > = 0 ; - - i ) {
ThebesLayerData * data = mThebesLayerDataStack [ i ] ;
2013-11-08 10:04:12 +04:00
if ( data - > IsBelow ( aVisibleRect ) ) {
2010-07-16 01:07:51 +04:00
+ + i ;
break ;
}
2013-09-26 01:07:26 +04:00
if ( data - > mAnimatedGeometryRoot = = aActiveScrolledRoot ) {
2010-07-16 01:07:51 +04:00
lowestUsableLayerWithScrolledRoot = i ;
if ( topmostLayerWithScrolledRoot < 0 ) {
topmostLayerWithScrolledRoot = i ;
2010-05-21 07:20:48 +04:00
}
}
2010-08-02 07:06:58 +04:00
if ( data - > mDrawRegion . Intersects ( aVisibleRect ) )
2010-07-16 01:07:51 +04:00
break ;
}
if ( topmostLayerWithScrolledRoot < 0 ) {
- - i ;
for ( ; i > = 0 ; - - i ) {
ThebesLayerData * data = mThebesLayerDataStack [ i ] ;
2013-09-26 01:07:26 +04:00
if ( data - > mAnimatedGeometryRoot = = aActiveScrolledRoot ) {
2010-07-16 01:07:51 +04:00
topmostLayerWithScrolledRoot = i ;
break ;
}
}
}
2010-05-21 07:20:48 +04:00
2010-07-16 01:07:51 +04:00
if ( topmostLayerWithScrolledRoot > = 0 ) {
2012-08-22 19:56:38 +04:00
while ( uint32_t ( topmostLayerWithScrolledRoot + 1 ) < mThebesLayerDataStack . Length ( ) ) {
2010-07-16 01:07:51 +04:00
PopThebesLayerData ( ) ;
2010-05-21 07:20:48 +04:00
}
}
2010-07-16 01:07:51 +04:00
nsRefPtr < ThebesLayer > layer ;
2012-07-30 18:20:58 +04:00
ThebesLayerData * thebesLayerData = nullptr ;
2010-07-16 01:07:51 +04:00
if ( lowestUsableLayerWithScrolledRoot < 0 ) {
2012-09-28 15:19:39 +04:00
layer = CreateOrRecycleThebesLayer ( aActiveScrolledRoot , aItem - > ReferenceFrame ( ) , aTopLeft ) ;
2010-07-16 01:08:03 +04:00
NS_ASSERTION ( ! mNewChildLayers . Contains ( layer ) , " Layer already in list??? " ) ;
mNewChildLayers . AppendElement ( layer ) ;
2010-07-16 01:07:51 +04:00
thebesLayerData = new ThebesLayerData ( ) ;
mThebesLayerDataStack . AppendElement ( thebesLayerData ) ;
thebesLayerData - > mLayer = layer ;
2013-09-26 01:07:26 +04:00
thebesLayerData - > mAnimatedGeometryRoot = aActiveScrolledRoot ;
2013-09-27 10:01:15 +04:00
thebesLayerData - > mReferenceFrame = aItem - > ReferenceFrame ( ) ;
2010-07-16 01:07:51 +04:00
} else {
thebesLayerData = mThebesLayerDataStack [ lowestUsableLayerWithScrolledRoot ] ;
layer = thebesLayerData - > mLayer ;
}
2012-09-04 05:02:56 +04:00
// check to see if the new item has rounded rect clips in common with
// other items in the layer
thebesLayerData - > UpdateCommonClipCount ( aClip ) ;
2011-06-22 16:11:27 +04:00
thebesLayerData - > Accumulate ( this , aItem , aVisibleRect , aDrawRect , aClip ) ;
2012-02-08 02:27:44 +04:00
return thebesLayerData ;
2010-07-16 01:07:51 +04:00
}
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
static void
DumpPaintedImage ( nsDisplayItem * aItem , gfxASurface * aSurf )
{
nsCString string ( aItem - > Name ( ) ) ;
string . Append ( " - " ) ;
2012-08-22 19:56:38 +04:00
string . AppendInt ( ( uint64_t ) aItem ) ;
2013-11-24 02:44:18 +04:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " array[ \" %s \" ]= \" " , string . BeginReading ( ) ) ;
2012-03-05 22:09:05 +04:00
aSurf - > DumpAsDataURL ( gfxUtils : : sDumpPaintFile ) ;
2013-11-24 02:44:18 +04:00
fprintf_stderr ( gfxUtils : : sDumpPaintFile , " \" ; " ) ;
2012-03-05 22:09:05 +04:00
}
# endif
2011-02-10 11:58:11 +03:00
static void
PaintInactiveLayer ( nsDisplayListBuilder * aBuilder ,
2012-08-29 09:47:15 +04:00
LayerManager * aManager ,
2011-02-10 11:58:11 +03:00
nsDisplayItem * aItem ,
2012-07-17 21:03:51 +04:00
gfxContext * aContext ,
2012-08-29 09:47:15 +04:00
nsRenderingContext * aCtx )
2010-08-03 07:33:24 +04:00
{
2011-02-10 11:58:11 +03:00
// This item has an inactive layer. Render it to a ThebesLayer
// using a temporary BasicLayerManager.
2012-08-29 09:47:15 +04:00
BasicLayerManager * basic = static_cast < BasicLayerManager * > ( aManager ) ;
nsRefPtr < gfxContext > context = aContext ;
# ifdef MOZ_DUMP_PAINTING
2012-08-22 19:56:38 +04:00
int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel ( aItem ) ;
2012-03-05 22:09:05 +04:00
nsIntRect itemVisibleRect =
aItem - > GetVisibleRect ( ) . ToOutsidePixels ( appUnitsPerDevPixel ) ;
2012-07-31 21:28:21 +04:00
nsRefPtr < gfxASurface > surf ;
2012-03-05 22:09:05 +04:00
if ( gfxUtils : : sDumpPainting ) {
2012-07-31 21:28:21 +04:00
surf = gfxPlatform : : GetPlatform ( ) - > CreateOffscreenSurface ( itemVisibleRect . Size ( ) ,
2013-09-25 00:45:13 +04:00
GFX_CONTENT_COLOR_ALPHA ) ;
2012-03-05 22:09:05 +04:00
surf - > SetDeviceOffset ( - itemVisibleRect . TopLeft ( ) ) ;
context = new gfxContext ( surf ) ;
}
# endif
2013-11-06 23:10:49 +04:00
basic - > BeginTransaction ( ) ;
2012-08-29 09:47:15 +04:00
basic - > SetTarget ( context ) ;
2012-03-05 22:09:05 +04:00
2012-07-17 21:03:51 +04:00
if ( aItem - > GetType ( ) = = nsDisplayItem : : TYPE_SVG_EFFECTS ) {
2012-08-29 09:47:15 +04:00
static_cast < nsDisplaySVGEffects * > ( aItem ) - > PaintAsLayer ( aBuilder , aCtx , basic ) ;
if ( basic - > InTransaction ( ) ) {
basic - > AbortTransaction ( ) ;
2012-07-20 08:53:55 +04:00
}
2012-07-17 21:03:51 +04:00
} else {
2012-08-29 09:47:15 +04:00
basic - > EndTransaction ( FrameLayerBuilder : : DrawThebesLayer , aBuilder ) ;
}
FrameLayerBuilder * builder = static_cast < FrameLayerBuilder * > ( basic - > GetUserData ( & gLayerManagerLayerBuilder ) ) ;
if ( builder ) {
builder - > DidEndTransaction ( ) ;
2012-07-17 21:03:51 +04:00
}
2012-10-23 15:05:14 +04:00
2012-11-09 10:01:24 +04:00
basic - > SetTarget ( nullptr ) ;
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( gfxUtils : : sDumpPainting ) {
DumpPaintedImage ( aItem , surf ) ;
2012-07-31 21:28:21 +04:00
2012-03-05 22:09:05 +04:00
surf - > SetDeviceOffset ( gfxPoint ( 0 , 0 ) ) ;
aContext - > SetSource ( surf , itemVisibleRect . TopLeft ( ) ) ;
aContext - > Rectangle ( itemVisibleRect ) ;
aContext - > Fill ( ) ;
aItem - > SetPainted ( ) ;
}
# endif
2010-08-03 07:33:24 +04:00
}
2012-12-04 10:05:22 +04:00
/**
* Chooses a single active scrolled root for the entire display list , used
* when we are flattening layers .
*/
2012-12-12 00:36:22 +04:00
bool
2013-09-26 01:07:26 +04:00
ContainerState : : ChooseAnimatedGeometryRoot ( const nsDisplayList & aList ,
2013-09-27 10:01:16 +04:00
const nsIFrame * * aAnimatedGeometryRoot )
2012-12-04 10:05:22 +04:00
{
for ( nsDisplayItem * item = aList . GetBottom ( ) ; item ; item = item - > GetAbove ( ) ) {
2012-12-12 00:36:22 +04:00
LayerState layerState = item - > GetLayerState ( mBuilder , mManager , mParameters ) ;
// 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 10:01:16 +04:00
* aAnimatedGeometryRoot =
nsLayoutUtils : : GetAnimatedGeometryRootFor ( item , mBuilder ) ;
return true ;
2012-12-04 10:05:22 +04:00
}
2012-12-12 00:36:22 +04:00
return false ;
2012-12-04 10:05:22 +04:00
}
2010-07-16 01:07:51 +04:00
/*
* Iterate through the non - clip items in aList and its descendants .
* For each item we compute the effective clip rect . Each item is assigned
* 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-08 02:27:44 +04:00
* We set the clip rect for items that generated their own layer , and
* create a mask layer to do any rounded rect clipping .
2010-07-16 01:07:51 +04: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
ContainerState : : ProcessDisplayItems ( const nsDisplayList & aList ,
2013-03-04 13:56:02 +04:00
uint32_t aFlags )
2010-07-16 01:07:51 +04:00
{
2013-03-16 08:47:02 +04:00
PROFILER_LABEL ( " ContainerState " , " ProcessDisplayItems " ) ;
2012-10-12 03:38:25 +04:00
2013-09-26 01:07:26 +04:00
const nsIFrame * lastAnimatedGeometryRoot = nullptr ;
2012-10-12 03:38:25 +04:00
nsPoint topLeft ;
2012-12-04 10:05:22 +04:00
// When NO_COMPONENT_ALPHA is set, items will be flattened into a single
// layer, so we need to choose which active scrolled root to use for all
// items.
if ( aFlags & NO_COMPONENT_ALPHA ) {
2013-09-26 01:07:26 +04:00
if ( ! ChooseAnimatedGeometryRoot ( aList , & lastAnimatedGeometryRoot ) ) {
lastAnimatedGeometryRoot = mContainerReferenceFrame ;
2012-12-04 10:05:22 +04:00
}
2013-09-26 01:07:26 +04:00
topLeft = lastAnimatedGeometryRoot - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2012-12-04 10:05:22 +04:00
}
2013-07-17 00:17:18 +04:00
int32_t maxLayers = nsDisplayItem : : MaxActiveLayers ( ) ;
int layerCount = 0 ;
2010-07-16 01:07:51 +04:00
for ( nsDisplayItem * item = aList . GetBottom ( ) ; item ; item = item - > GetAbove ( ) ) {
2012-04-10 15:24:18 +04:00
NS_ASSERTION ( mAppUnitsPerDevPixel = = AppUnitsPerDevPixel ( item ) ,
2010-08-08 22:49:07 +04:00
" items in a container layer should all have the same app units per dev pixel " ) ;
2011-10-26 06:55:51 +04:00
nsIntRect itemVisibleRect =
2012-04-10 15:24:18 +04:00
ScaleToOutsidePixels ( item - > GetVisibleRect ( ) , false ) ;
bool snap ;
nsRect itemContent = item - > GetBounds ( mBuilder , & snap ) ;
2012-04-13 15:44:05 +04:00
nsIntRect itemDrawRect = ScaleToOutsidePixels ( itemContent , snap ) ;
2013-03-22 06:17:29 +04:00
nsIntRect clipRect ;
2013-03-04 13:56:02 +04:00
const DisplayItemClip & itemClip = item - > GetClip ( ) ;
if ( itemClip . HasClip ( ) ) {
itemContent . IntersectRect ( itemContent , itemClip . GetClipRect ( ) ) ;
clipRect = ScaleToNearestPixels ( itemClip . GetClipRect ( ) ) ;
2012-04-13 15:44:05 +04:00
itemDrawRect . IntersectRect ( itemDrawRect , clipRect ) ;
2013-03-22 06:17:29 +04:00
clipRect . MoveBy ( mParameters . mOffset ) ;
2010-08-02 07:06:58 +04:00
}
2011-02-23 08:38:09 +03:00
mBounds . UnionRect ( mBounds , itemContent ) ;
2012-04-10 15:24:18 +04:00
itemVisibleRect . IntersectRect ( itemVisibleRect , itemDrawRect ) ;
2012-05-03 18:05:55 +04:00
LayerState layerState = item - > GetLayerState ( mBuilder , mManager , mParameters ) ;
2012-11-23 03:29:05 +04:00
if ( layerState = = LAYER_INACTIVE & &
nsDisplayItem : : ForceActiveLayers ( ) ) {
layerState = LAYER_ACTIVE ;
}
2010-07-16 01:08:05 +04:00
2012-09-13 14:34:34 +04:00
bool forceInactive ;
2013-09-27 10:01:16 +04:00
const nsIFrame * animatedGeometryRoot ;
2012-07-23 07:00:36 +04:00
if ( aFlags & NO_COMPONENT_ALPHA ) {
forceInactive = true ;
2013-09-27 10:01:16 +04:00
animatedGeometryRoot = lastAnimatedGeometryRoot ;
2012-07-23 07:00:36 +04:00
} else {
2012-09-13 14:34:34 +04:00
forceInactive = false ;
2013-09-27 10:01:16 +04:00
animatedGeometryRoot = nsLayoutUtils : : GetAnimatedGeometryRootFor ( item , mBuilder ) ;
if ( animatedGeometryRoot ! = lastAnimatedGeometryRoot ) {
lastAnimatedGeometryRoot = animatedGeometryRoot ;
topLeft = animatedGeometryRoot - > GetOffsetToCrossDoc ( mContainerReferenceFrame ) ;
2012-10-12 03:38:25 +04:00
}
2012-07-23 07:00:36 +04:00
}
2011-04-06 09:00:25 +04:00
2013-07-17 00:17:18 +04:00
if ( maxLayers ! = - 1 & & layerCount > = maxLayers ) {
forceInactive = true ;
}
2010-07-16 01:07:51 +04:00
// Assign the item to a layer
2011-03-16 02:20:19 +03:00
if ( layerState = = LAYER_ACTIVE_FORCE | |
2012-11-14 02:22:21 +04:00
( layerState = = LAYER_INACTIVE & & ! mManager - > IsWidgetLayerManager ( ) ) | |
2012-07-23 07:00:36 +04:00
( ! forceInactive & &
( layerState = = LAYER_ACTIVE_EMPTY | |
layerState = = LAYER_ACTIVE ) ) ) {
2011-04-14 01:12:22 +04:00
2013-07-17 00:17:18 +04:00
layerCount + + ;
2011-04-14 01:12:22 +04:00
// LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
// We should never see an empty layer with any visible content!
NS_ASSERTION ( layerState ! = LAYER_ACTIVE_EMPTY | |
2011-10-26 06:55:51 +04:00
itemVisibleRect . IsEmpty ( ) ,
2011-04-14 01:12:22 +04:00
" State is LAYER_ACTIVE_EMPTY but visible rect is not. " ) ;
2012-10-12 06:39:46 +04:00
// As long as the new layer isn't going to be a ThebesLayer,
// 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 13:56:02 +04:00
InvalidateForLayerChange ( item , nullptr , itemClip , topLeft , nullptr ) ;
2012-10-12 06:39:46 +04:00
2010-07-16 01:08:09 +04:00
// If the item would have its own layer but is invisible, just hide it.
// Note that items without their own layers can't be skipped this
// way, since their ThebesLayer may decide it wants to draw them
// into its buffer even if they're currently covered.
2013-03-19 17:08:29 +04:00
if ( itemVisibleRect . IsEmpty ( ) & &
! item - > ShouldBuildLayerEvenIfInvisible ( mBuilder ) ) {
2010-07-16 01:08:09 +04:00
continue ;
}
2013-03-04 13:56:02 +04:00
nsDisplayItem : : Type type = item - > GetType ( ) ;
2013-12-18 09:02:56 +04:00
bool setVisibleRegion = ( type ! = nsDisplayItem : : TYPE_TRANSFORM ) & &
( type ! = nsDisplayItem : : TYPE_SCROLL_LAYER ) ;
if ( type = = nsDisplayItem : : TYPE_TRANSFORM ) {
2013-03-04 13:56:02 +04:00
mParameters . mAncestorClipRect = itemClip . HasClip ( ) ? & clipRect : nullptr ;
2013-12-18 09:02:56 +04:00
} else {
mParameters . mAncestorClipRect = nullptr ;
2013-03-22 06:17:29 +04:00
}
2010-07-16 01:08:05 +04:00
// Just use its layer.
2011-06-22 16:11:27 +04:00
nsRefPtr < Layer > ownLayer = item - > BuildLayer ( mBuilder , mManager , mParameters ) ;
2010-07-16 01:08:05 +04:00
if ( ! ownLayer ) {
continue ;
}
2013-09-27 10:01:16 +04:00
NS_ASSERTION ( ! ownLayer - > AsThebesLayer ( ) ,
2012-10-12 06:39:46 +04:00
" Should never have created a dedicated Thebes layer! " ) ;
2013-09-27 10:01:16 +04:00
nsIntRegion visibleRegion ( itemVisibleRect ) ;
const nsIFrame * fixedPosFrame = FindFixedPosFrameForLayerData ( animatedGeometryRoot ,
nsIntRegion ( itemDrawRect ) , & visibleRegion ) ;
if ( fixedPosFrame ) {
itemVisibleRect = visibleRegion . GetBounds ( ) ;
}
SetFixedPositionLayerData ( ownLayer , fixedPosFrame ) ;
2012-08-29 09:48:45 +04:00
nsRect invalid ;
if ( item - > IsInvalid ( invalid ) ) {
2012-08-29 09:47:18 +04:00
ownLayer - > SetInvalidRectToVisibleRegion ( ) ;
}
2011-06-22 16:11:27 +04:00
// If it's not a ContainerLayer, we need to apply the scale transform
// ourselves.
if ( ! ownLayer - > AsContainerLayer ( ) ) {
2012-08-04 01:29:22 +04:00
ownLayer - > SetPostScale ( mParameters . mXScale ,
mParameters . mYScale ) ;
2011-06-22 16:11:27 +04:00
}
2010-07-16 01:08:05 +04:00
// Update that layer's clip and visible rects.
2010-07-16 01:07:51 +04:00
NS_ASSERTION ( ownLayer - > Manager ( ) = = mManager , " Wrong manager " ) ;
2010-09-02 13:18:39 +04:00
NS_ASSERTION ( ! ownLayer - > HasUserData ( & gLayerManagerUserData ) ,
2010-07-16 01:07:51 +04:00
" We shouldn't have a FrameLayerBuilder-managed layer here! " ) ;
2013-03-04 13:56:02 +04:00
NS_ASSERTION ( itemClip . HasClip ( ) | |
itemClip . GetRoundedRectCount ( ) = = 0 ,
2012-01-20 00:21:41 +04:00
" If we have rounded rects, we must have a clip rect " ) ;
2010-07-16 01:07:51 +04:00
// It has its own layer. Update that layer's clip and visible rects.
2013-03-04 13:56:02 +04:00
if ( itemClip . HasClip ( ) ) {
2013-03-22 06:17:29 +04:00
ownLayer - > SetClipRect ( & clipRect ) ;
2013-03-22 06:17:29 +04:00
} else {
ownLayer - > SetClipRect ( nullptr ) ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:51 +04:00
ThebesLayerData * data = GetTopThebesLayerData ( ) ;
if ( data ) {
2013-11-08 10:04:12 +04:00
// Prerendered transform items can be updated without layer building
// (async animations or an empty transaction), so we treat all other
// content as being above this so that the transformed layer can correctly
// move behind other content.
if ( item - > GetType ( ) = = nsDisplayItem : : TYPE_TRANSFORM & &
nsDisplayTransform : : ShouldPrerenderTransformedContent ( mBuilder ,
item - > Frame ( ) ,
false ) ) {
data - > SetAllDrawingAbove ( ) ;
} 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-16 01:07:51 +04:00
}
2012-09-17 02:25:33 +04:00
itemVisibleRect . MoveBy ( mParameters . mOffset ) ;
2013-03-22 06:17:29 +04:00
if ( setVisibleRegion ) {
SetVisibleRegionForLayer ( ownLayer , ownLayer - > GetVisibleRegion ( ) , itemVisibleRect ) ;
2013-03-19 17:08:29 +04:00
}
2012-02-08 02:27:44 +04:00
// rounded rectangle clipping using mask layers
// (must be done after visible rect is set on layer)
2013-03-04 13:56:02 +04:00
if ( itemClip . IsRectClippedByRoundedCorner ( itemContent ) ) {
SetupMaskLayer ( ownLayer , itemClip ) ;
2012-02-08 02:27:44 +04:00
}
2010-07-16 01:07:51 +04:00
ContainerLayer * oldContainer = ownLayer - > GetParent ( ) ;
if ( oldContainer & & oldContainer ! = mContainerLayer ) {
oldContainer - > RemoveChild ( ownLayer ) ;
}
NS_ASSERTION ( ! mNewChildLayers . Contains ( ownLayer ) ,
" Layer already in list??? " ) ;
2010-07-16 01:08:05 +04:00
2010-07-16 01:07:51 +04:00
mNewChildLayers . AppendElement ( ownLayer ) ;
2012-10-17 12:00:00 +04:00
/**
* No need to allocate geometry for items that aren ' t
* part of a ThebesLayer .
*/
nsAutoPtr < nsDisplayItemGeometry > dummy ;
2012-08-29 09:47:15 +04:00
mLayerBuilder - > AddLayerDisplayItem ( ownLayer , item ,
2013-03-04 13:56:02 +04:00
itemClip , layerState ,
2012-10-12 03:38:24 +04:00
topLeft , nullptr ,
2012-10-17 12:00:00 +04:00
dummy ) ;
2010-05-21 07:20:48 +04:00
} else {
2012-02-08 02:27:44 +04:00
ThebesLayerData * data =
2013-03-04 13:56:02 +04:00
FindThebesLayerFor ( item , itemVisibleRect , itemDrawRect , itemClip ,
2013-09-27 10:01:16 +04:00
animatedGeometryRoot , topLeft ) ;
2011-04-06 09:00:25 +04:00
2012-10-17 12:00:00 +04:00
nsAutoPtr < nsDisplayItemGeometry > geometry ( item - > AllocateGeometry ( mBuilder ) ) ;
2013-03-04 13:56:02 +04:00
InvalidateForLayerChange ( item , data - > mLayer , itemClip , topLeft , geometry ) ;
2012-02-08 02:27:44 +04:00
2013-03-04 13:56:02 +04:00
mLayerBuilder - > AddThebesDisplayItem ( data - > mLayer , item , itemClip ,
2012-07-17 21:03:51 +04:00
mContainerFrame ,
2012-10-12 03:38:24 +04:00
layerState , topLeft ,
geometry ) ;
2010-07-16 01:07:51 +04:00
2012-02-08 02:27:44 +04:00
// check to see if the new item has rounded rect clips in common with
// other items in the layer
2013-03-04 13:56:02 +04:00
data - > UpdateCommonClipCount ( itemClip ) ;
2010-05-21 07:20:48 +04:00
}
}
}
2010-07-16 01:08:05 +04:00
void
2012-08-29 09:47:15 +04:00
ContainerState : : InvalidateForLayerChange ( nsDisplayItem * aItem ,
2012-08-29 09:48:43 +04:00
Layer * aNewLayer ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2012-10-12 03:38:24 +04:00
const nsPoint & aTopLeft ,
nsDisplayItemGeometry * aGeometry )
2010-07-16 01:08:05 +04:00
{
2012-10-10 09:00:05 +04:00
NS_ASSERTION ( aItem - > GetPerFrameKey ( ) ,
" Display items that render using Thebes must have a key " ) ;
2013-10-08 22:47:21 +04:00
nsDisplayItemGeometry * oldGeometry = nullptr ;
DisplayItemClip * oldClip = nullptr ;
2012-10-16 05:23:07 +04:00
nsAutoTArray < nsIFrame * , 4 > changedFrames ;
2012-11-07 02:04:53 +04:00
bool isInvalid = false ;
Layer * oldLayer = mLayerBuilder - > GetOldLayerFor ( aItem , & oldGeometry , & oldClip , & changedFrames , & isInvalid ) ;
2012-08-29 09:47:15 +04:00
if ( aNewLayer ! = oldLayer & & oldLayer ) {
2010-07-16 01:08:05 +04:00
// The item has changed layers.
2012-09-28 15:19:39 +04:00
// Invalidate the old bounds in the old layer and new bounds in the new layer.
2010-07-16 01:08:05 +04:00
ThebesLayer * t = oldLayer - > AsThebesLayer ( ) ;
if ( t ) {
2011-06-22 16:11:27 +04:00
// Note that whenever the layer's scale changes, we invalidate the whole thing,
// so it doesn't matter whether we are using the old scale at last paint
// or a new scale here
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Display item type %s(%p) changed layers %p to %p! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , t , aNewLayer ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
2011-06-22 16:11:27 +04:00
InvalidatePostTransformRegion ( t ,
2012-10-16 05:10:43 +04:00
oldGeometry - > ComputeInvalidationRegion ( ) ,
* oldClip ,
2012-07-17 21:03:51 +04:00
mLayerBuilder - > GetLastPaintOffset ( t ) ) ;
2010-07-16 01:08:05 +04:00
}
if ( aNewLayer ) {
2012-08-29 09:47:15 +04:00
ThebesLayer * newThebesLayer = aNewLayer - > AsThebesLayer ( ) ;
if ( newThebesLayer ) {
InvalidatePostTransformRegion ( newThebesLayer ,
2012-10-16 05:10:43 +04:00
aGeometry - > ComputeInvalidationRegion ( ) ,
aClip ,
2012-08-29 09:47:15 +04:00
GetTranslationForThebesLayer ( newThebesLayer ) ) ;
2010-07-16 01:08:05 +04:00
}
}
2012-12-10 09:34:31 +04:00
aItem - > NotifyRenderingChanged ( ) ;
2012-08-29 09:47:15 +04:00
return ;
}
if ( ! aNewLayer ) {
return ;
}
2010-07-16 01:08:05 +04:00
2012-08-29 09:47:15 +04:00
ThebesLayer * newThebesLayer = aNewLayer - > AsThebesLayer ( ) ;
2012-08-29 09:47:18 +04:00
if ( ! newThebesLayer ) {
2012-08-29 09:47:15 +04:00
return ;
}
ThebesDisplayItemLayerUserData * data =
static_cast < ThebesDisplayItemLayerUserData * > ( newThebesLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
2012-08-29 09:48:45 +04:00
// If the frame is marked as invalidated, and didn't specify a rect to invalidate then we want to
// invalidate both the old and new bounds, otherwise we only want to invalidate the changed areas.
// If we do get an invalid rect, then we want to add this on top of the change areas.
nsRect invalid ;
2012-08-29 09:47:15 +04:00
nsRegion combined ;
2013-09-26 01:07:26 +04:00
nsPoint shift = aTopLeft - data - > mLastAnimatedGeometryRootOrigin ;
2012-08-29 09:47:15 +04:00
if ( ! oldLayer ) {
2012-08-29 09:48:43 +04:00
// This item is being added for the first time, invalidate its entire area.
2012-08-29 09:47:15 +04:00
//TODO: We call GetGeometry again in AddThebesDisplayItem, we should reuse this.
2012-10-16 05:10:43 +04:00
combined = aClip . ApplyNonRoundedIntersection ( aGeometry - > ComputeInvalidationRegion ( ) ) ;
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Display item type %s(%p) added to layer %p! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , aNewLayer ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
2012-11-07 02:04:53 +04:00
} else if ( isInvalid | | ( aItem - > IsInvalid ( invalid ) & & invalid . IsEmpty ( ) ) ) {
2012-08-29 09:48:44 +04:00
// Either layout marked item as needing repainting, invalidate the entire old and new areas.
2012-10-16 05:10:43 +04:00
combined = oldClip - > ApplyNonRoundedIntersection ( oldGeometry - > ComputeInvalidationRegion ( ) ) ;
combined . MoveBy ( shift ) ;
combined . Or ( combined , aClip . ApplyNonRoundedIntersection ( aGeometry - > ComputeInvalidationRegion ( ) ) ) ;
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Display item type %s(%p) (in layer %p) belongs to an invalidated frame! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , aNewLayer ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
# endif
} else {
2012-08-29 09:48:44 +04:00
// Let the display item check for geometry changes and decide what needs to be
2012-08-29 09:48:43 +04:00
// repainted.
2012-08-29 09:47:15 +04:00
oldGeometry - > MoveBy ( shift ) ;
aItem - > ComputeInvalidationRegion ( mBuilder , oldGeometry , & combined ) ;
2012-08-29 09:48:44 +04:00
oldClip - > AddOffsetAndComputeDifference ( shift , oldGeometry - > ComputeInvalidationRegion ( ) ,
2012-10-12 03:38:24 +04:00
aClip , aGeometry - > ComputeInvalidationRegion ( ) ,
2012-08-29 09:48:44 +04:00
& combined ) ;
2012-08-29 09:48:45 +04:00
// Add in any rect that the frame specified
2012-10-16 05:10:43 +04:00
combined . Or ( combined , invalid ) ;
2012-10-16 05:23:07 +04:00
for ( uint32_t i = 0 ; i < changedFrames . Length ( ) ; i + + ) {
combined . Or ( combined , changedFrames [ i ] - > GetVisualOverflowRect ( ) ) ;
}
2012-10-16 05:10:43 +04:00
// Restrict invalidation to the clipped region
nsRegion clip ;
2013-03-04 13:56:00 +04:00
if ( aClip . ComputeRegionInClips ( oldClip , shift , & clip ) ) {
2012-10-16 05:10:43 +04:00
combined . And ( combined , clip ) ;
}
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
if ( ! combined . IsEmpty ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Display item type %s(%p) (in layer %p) changed geometry! \n " , aItem - > Name ( ) , aItem - > Frame ( ) , aNewLayer ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:15 +04:00
}
# endif
}
if ( ! combined . IsEmpty ( ) ) {
2012-12-10 09:34:31 +04:00
aItem - > NotifyRenderingChanged ( ) ;
2012-08-29 09:47:15 +04:00
InvalidatePostTransformRegion ( newThebesLayer ,
combined . ScaleToOutsidePixels ( data - > mXScale , data - > mYScale , mAppUnitsPerDevPixel ) ,
GetTranslationForThebesLayer ( newThebesLayer ) ) ;
2010-07-16 01:08:05 +04:00
}
}
2010-07-16 01:07:51 +04:00
void
FrameLayerBuilder : : AddThebesDisplayItem ( ThebesLayer * aLayer ,
nsDisplayItem * aItem ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2010-07-16 01:08:05 +04:00
nsIFrame * aContainerLayerFrame ,
2012-08-29 09:47:15 +04:00
LayerState aLayerState ,
2012-10-12 03:38:24 +04:00
const nsPoint & aTopLeft ,
nsAutoPtr < nsDisplayItemGeometry > aGeometry )
2010-07-16 01:07:51 +04:00
{
2012-10-16 05:10:43 +04:00
ThebesDisplayItemLayerUserData * thebesData =
static_cast < ThebesDisplayItemLayerUserData * > ( aLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
2013-11-06 23:10:49 +04:00
nsRefPtr < BasicLayerManager > tempManager ;
2012-10-16 05:10:43 +04:00
nsIntRect intClip ;
bool hasClip = false ;
2012-08-29 09:47:15 +04:00
if ( aLayerState ! = LAYER_NONE ) {
DisplayItemData * data = GetDisplayItemDataForManager ( aItem , aLayer - > Manager ( ) ) ;
if ( data ) {
tempManager = data - > mInactiveManager ;
}
if ( ! tempManager ) {
tempManager = new BasicLayerManager ( ) ;
}
2012-10-23 15:05:14 +04:00
2012-10-16 05:10:43 +04:00
// We need to grab these before calling AddLayerDisplayItem because it will overwrite them.
nsRegion clip ;
2013-03-04 13:55:59 +04:00
DisplayItemClip * oldClip = nullptr ;
2012-10-16 05:10:43 +04:00
GetOldLayerFor ( aItem , nullptr , & oldClip ) ;
2013-03-04 13:56:00 +04:00
hasClip = aClip . ComputeRegionInClips ( oldClip ,
2013-09-26 01:07:26 +04:00
aTopLeft - thebesData - > mLastAnimatedGeometryRootOrigin ,
2013-03-04 13:56:00 +04:00
& clip ) ;
2012-10-16 05:10:43 +04:00
if ( hasClip ) {
intClip = clip . GetBounds ( ) . ScaleToOutsidePixels ( thebesData - > mXScale ,
thebesData - > mYScale ,
thebesData - > mAppUnitsPerDevPixel ) ;
}
2012-08-29 09:47:15 +04:00
}
2012-12-14 02:50:57 +04:00
AddLayerDisplayItem ( aLayer , aItem , aClip , aLayerState , aTopLeft , tempManager , aGeometry ) ;
2010-07-16 01:07:51 +04:00
ThebesLayerItemsEntry * entry = mThebesLayerItems . PutEntry ( aLayer ) ;
if ( entry ) {
entry - > mContainerLayerFrame = aContainerLayerFrame ;
2012-09-12 01:17:26 +04:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2012-08-29 09:47:15 +04:00
if ( tempManager ) {
FrameLayerBuilder * layerBuilder = new FrameLayerBuilder ( ) ;
layerBuilder - > Init ( mDisplayListBuilder , tempManager ) ;
tempManager - > BeginTransaction ( ) ;
if ( mRetainingManager ) {
layerBuilder - > DidBeginRetainedLayerTransaction ( tempManager ) ;
}
2012-08-29 09:47:18 +04:00
nsAutoPtr < LayerProperties > props ( LayerProperties : : CloneFrom ( tempManager - > GetRoot ( ) ) ) ;
2012-08-29 09:47:15 +04:00
nsRefPtr < Layer > layer =
2013-09-27 10:01:16 +04:00
aItem - > BuildLayer ( mDisplayListBuilder , tempManager , ContainerLayerParameters ( ) ) ;
2012-08-29 09:47:15 +04:00
// We have no easy way of detecting if this transaction will ever actually get finished.
// For now, I've just silenced the warning with nested transactions in BasicLayers.cpp
if ( ! layer ) {
tempManager - > EndTransaction ( nullptr , nullptr ) ;
tempManager - > SetUserData ( & gLayerManagerLayerBuilder , nullptr ) ;
return ;
}
// If BuildLayer didn't call BuildContainerLayerFor, then our new layer won't have been
// stored in layerBuilder. Manually add it now.
2012-10-12 03:38:24 +04:00
if ( mRetainingManager ) {
2012-10-12 06:39:46 +04:00
# ifdef DEBUG_DISPLAY_ITEM_DATA
2012-10-12 03:38:24 +04:00
LayerManagerData * parentLmd = static_cast < LayerManagerData * >
( aLayer - > Manager ( ) - > GetUserData ( & gLayerManagerUserData ) ) ;
LayerManagerData * lmd = static_cast < LayerManagerData * >
( tempManager - > GetUserData ( & gLayerManagerUserData ) ) ;
lmd - > mParent = parentLmd ;
2012-10-12 06:39:46 +04:00
# endif
layerBuilder - > StoreDataForFrame ( aItem , layer , LAYER_ACTIVE ) ;
2012-10-12 03:38:24 +04:00
}
2012-08-29 09:47:15 +04:00
tempManager - > SetRoot ( layer ) ;
layerBuilder - > WillEndTransaction ( ) ;
2013-11-06 23:10:49 +04:00
tempManager - > AbortTransaction ( ) ;
2012-08-29 09:47:15 +04:00
2012-09-17 02:57:22 +04:00
nsIntPoint offset = GetLastPaintOffset ( aLayer ) - GetTranslationForThebesLayer ( aLayer ) ;
props - > MoveBy ( - offset ) ;
2012-11-12 22:31:15 +04:00
nsIntRegion invalid = props - > ComputeDifferences ( layer , nullptr ) ;
2012-08-29 09:47:18 +04:00
if ( aLayerState = = LAYER_SVG_EFFECTS ) {
2013-04-19 16:02:13 +04:00
invalid = nsSVGIntegrationUtils : : AdjustInvalidAreaForSVGEffects ( aItem - > Frame ( ) ,
2012-11-28 08:06:07 +04:00
aItem - > ToReferenceFrame ( ) ,
invalid . GetBounds ( ) ) ;
2012-08-29 09:47:18 +04:00
}
if ( ! invalid . IsEmpty ( ) ) {
2013-05-14 03:47:02 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( nsLayoutUtils : : InvalidationDebuggingIsEnabled ( ) ) {
2013-11-24 02:44:18 +04:00
printf_stderr ( " Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p \n " , tempManager . get ( ) , aItem - > Name ( ) , aItem - > Frame ( ) , aLayer ) ;
2013-05-14 03:47:02 +04:00
}
2012-08-29 09:47:18 +04:00
# endif
2012-10-16 05:10:43 +04:00
if ( hasClip ) {
2012-11-12 22:31:15 +04:00
invalid . And ( invalid , intClip ) ;
2012-10-16 05:10:43 +04:00
}
invalid . ScaleRoundOut ( thebesData - > mXScale , thebesData - > mYScale ) ;
2012-08-29 09:47:18 +04:00
InvalidatePostTransformRegion ( aLayer , invalid ,
GetTranslationForThebesLayer ( aLayer ) ) ;
}
2012-08-29 09:47:15 +04:00
}
2010-07-16 01:08:05 +04:00
ClippedDisplayItem * cdi =
2013-03-04 13:56:02 +04:00
entry - > mItems . AppendElement ( ClippedDisplayItem ( aItem ,
2012-07-23 07:00:36 +04:00
mContainerLayerGeneration ) ) ;
2012-10-23 15:05:14 +04:00
cdi - > mInactiveLayerManager = tempManager ;
2010-07-16 01:07:51 +04:00
}
}
2012-10-12 06:39:46 +04:00
FrameLayerBuilder : : DisplayItemData *
FrameLayerBuilder : : StoreDataForFrame ( nsDisplayItem * aItem , Layer * aLayer , LayerState aState )
2012-08-29 14:53:27 +04:00
{
2012-10-12 06:39:46 +04:00
DisplayItemData * oldData = GetDisplayItemDataForManager ( aItem , mRetainingManager ) ;
if ( oldData ) {
if ( ! oldData - > mUsed ) {
2012-10-19 08:36:00 +04:00
oldData - > UpdateContents ( aLayer , aState , mContainerLayerGeneration , aItem ) ;
2012-10-12 06:39:46 +04:00
}
return oldData ;
2012-10-12 03:38:24 +04:00
}
2012-10-12 06:39:46 +04:00
LayerManagerData * lmd = static_cast < LayerManagerData * >
( mRetainingManager - > GetUserData ( & gLayerManagerUserData ) ) ;
nsRefPtr < DisplayItemData > data =
new DisplayItemData ( lmd , aItem - > GetPerFrameKey ( ) ,
aLayer , aState , mContainerLayerGeneration ) ;
2013-04-19 16:02:13 +04:00
data - > AddFrame ( aItem - > Frame ( ) ) ;
2012-10-12 06:39:46 +04:00
2012-10-12 03:38:24 +04:00
nsAutoTArray < nsIFrame * , 4 > mergedFrames ;
aItem - > GetMergedFrames ( & mergedFrames ) ;
for ( uint32_t i = 0 ; i < mergedFrames . Length ( ) ; + + i ) {
2012-10-12 06:39:46 +04:00
data - > AddFrame ( mergedFrames [ i ] ) ;
2012-08-29 09:47:15 +04:00
}
2012-10-12 06:39:46 +04:00
lmd - > mDisplayItems . PutEntry ( data ) ;
return data ;
}
void
FrameLayerBuilder : : StoreDataForFrame ( nsIFrame * aFrame ,
uint32_t aDisplayItemKey ,
Layer * aLayer ,
LayerState aState )
{
DisplayItemData * oldData = GetDisplayItemData ( aFrame , aDisplayItemKey ) ;
if ( oldData & & oldData - > mFrameList . Length ( ) = = 1 ) {
oldData - > UpdateContents ( aLayer , aState , mContainerLayerGeneration ) ;
return ;
}
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 09:47:15 +04:00
}
FrameLayerBuilder : : ClippedDisplayItem : : ~ ClippedDisplayItem ( )
{
2012-10-23 15:05:14 +04:00
if ( mInactiveLayerManager ) {
BasicLayerManager * basic = static_cast < BasicLayerManager * > ( mInactiveLayerManager . get ( ) ) ;
2012-08-29 09:47:15 +04:00
basic - > SetUserData ( & gLayerManagerLayerBuilder , nullptr ) ;
2012-08-29 14:53:27 +04:00
}
}
2012-12-14 02:50:57 +04:00
void
2010-07-16 01:07:51 +04:00
FrameLayerBuilder : : AddLayerDisplayItem ( Layer * aLayer ,
2011-05-19 02:54:31 +04:00
nsDisplayItem * aItem ,
2013-03-04 13:55:59 +04:00
const DisplayItemClip & aClip ,
2012-08-29 09:47:15 +04:00
LayerState aLayerState ,
const nsPoint & aTopLeft ,
2013-11-06 23:10:49 +04:00
BasicLayerManager * aManager ,
2012-10-12 03:38:24 +04:00
nsAutoPtr < nsDisplayItemGeometry > aGeometry )
2010-07-16 01:07:51 +04:00
{
if ( aLayer - > Manager ( ) ! = mRetainingManager )
2012-12-14 02:50:57 +04:00
return ;
2012-10-12 03:38:24 +04:00
2012-10-12 06:39:46 +04:00
DisplayItemData * data = StoreDataForFrame ( aItem , aLayer , aLayerState ) ;
2012-08-29 09:47:15 +04:00
ThebesLayer * t = aLayer - > AsThebesLayer ( ) ;
if ( t ) {
2012-10-12 03:38:24 +04:00
data - > mGeometry = aGeometry ;
2012-08-29 09:48:43 +04:00
data - > mClip = aClip ;
2012-08-29 09:47:15 +04:00
}
data - > mInactiveManager = aManager ;
2010-07-16 01:07:51 +04:00
}
2011-05-18 09:48:43 +04:00
nsIntPoint
FrameLayerBuilder : : GetLastPaintOffset ( ThebesLayer * aLayer )
2011-05-17 03:05:56 +04:00
{
ThebesLayerItemsEntry * entry = mThebesLayerItems . PutEntry ( aLayer ) ;
2012-07-23 07:00:36 +04:00
if ( entry ) {
2012-09-12 01:17:26 +04:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2012-07-23 07:00:36 +04:00
if ( entry - > mHasExplicitLastPaintOffset )
return entry - > mLastPaintOffset ;
}
2011-05-18 09:48:43 +04:00
return GetTranslationForThebesLayer ( aLayer ) ;
2011-05-17 03:05:56 +04:00
}
void
2011-05-18 09:48:43 +04:00
FrameLayerBuilder : : SaveLastPaintOffset ( ThebesLayer * aLayer )
2011-05-17 03:05:56 +04:00
{
ThebesLayerItemsEntry * entry = mThebesLayerItems . PutEntry ( aLayer ) ;
if ( entry ) {
2012-09-12 01:17:26 +04:00
if ( entry - > mContainerLayerGeneration = = 0 ) {
entry - > mContainerLayerGeneration = mContainerLayerGeneration ;
}
2011-05-18 09:48:43 +04:00
entry - > mLastPaintOffset = GetTranslationForThebesLayer ( aLayer ) ;
2011-10-17 18:59:28 +04:00
entry - > mHasExplicitLastPaintOffset = true ;
2011-05-17 03:05:56 +04:00
}
}
2010-07-16 01:07:51 +04:00
void
2010-07-16 01:08:03 +04:00
ContainerState : : CollectOldLayers ( )
2010-07-16 01:07:51 +04:00
{
for ( Layer * layer = mContainerLayer - > GetFirstChild ( ) ; layer ;
layer = layer - > GetNextSibling ( ) ) {
2012-02-08 02:26:40 +04:00
NS_ASSERTION ( ! layer - > HasUserData ( & gMaskLayerUserData ) ,
" Mask layer in layer tree; could not be recycled. " ) ;
2012-08-20 14:00:49 +04:00
if ( layer - > HasUserData ( & gThebesDisplayItemLayerUserData ) ) {
2010-07-16 01:08:03 +04:00
NS_ASSERTION ( layer - > AsThebesLayer ( ) , " Wrong layer type " ) ;
mRecycledThebesLayers . AppendElement ( static_cast < ThebesLayer * > ( layer ) ) ;
2010-07-16 01:07:51 +04:00
}
2012-02-08 02:26:40 +04:00
if ( Layer * maskLayer = layer - > GetMaskLayer ( ) ) {
NS_ASSERTION ( maskLayer - > GetType ( ) = = Layer : : TYPE_IMAGE ,
" Could not recycle mask layer, unsupported layer type. " ) ;
mRecycledMaskImageLayers . Put ( layer , static_cast < ImageLayer * > ( maskLayer ) ) ;
}
2010-07-16 01:07:51 +04:00
}
}
void
2012-08-29 09:47:15 +04:00
ContainerState : : Finish ( uint32_t * aTextContentFlags , LayerManagerData * aData )
2010-07-16 01:07:51 +04:00
{
while ( ! mThebesLayerDataStack . IsEmpty ( ) ) {
PopThebesLayerData ( ) ;
}
2012-10-12 03:38:24 +04:00
2012-08-22 19:56:38 +04:00
uint32_t textContentFlags = 0 ;
2010-12-20 04:26:14 +03:00
2012-08-29 14:53:06 +04:00
// Make sure that current/existing layers are added to the parent and are
// in the correct order.
Layer * layer = nullptr ;
for ( uint32_t i = 0 ; i < mNewChildLayers . Length ( ) ; + + i ) {
Layer * prevChild = i = = 0 ? nullptr : mNewChildLayers [ i - 1 ] . get ( ) ;
layer = mNewChildLayers [ i ] ;
2012-10-12 03:38:24 +04:00
2012-08-29 14:53:06 +04:00
if ( ! layer - > GetVisibleRegion ( ) . IsEmpty ( ) ) {
textContentFlags | = layer - > GetContentFlags ( ) & Layer : : CONTENT_COMPONENT_ALPHA ;
2010-07-16 01:07:51 +04:00
}
2012-08-29 14:53:06 +04:00
if ( ! layer - > GetParent ( ) ) {
// This is not currently a child of the container, so just add it
// now.
mContainerLayer - > InsertAfter ( layer , prevChild ) ;
continue ;
2010-07-16 01:07:51 +04:00
}
2012-08-29 14:53:06 +04:00
NS_ASSERTION ( layer - > GetParent ( ) = = mContainerLayer ,
" Layer shouldn't be the child of some other container " ) ;
2013-03-22 06:17:29 +04:00
if ( layer - > GetPrevSibling ( ) ! = prevChild ) {
mContainerLayer - > RepositionChild ( layer , prevChild ) ;
}
2012-08-29 14:53:06 +04:00
}
// Remove old layers that have become unused.
if ( ! layer ) {
layer = mContainerLayer - > GetFirstChild ( ) ;
} else {
layer = layer - > GetNextSibling ( ) ;
}
while ( layer ) {
Layer * layerToRemove = layer ;
layer = layer - > GetNextSibling ( ) ;
mContainerLayer - > RemoveChild ( layerToRemove ) ;
2010-07-16 01:07:51 +04:00
}
2010-12-20 04:26:14 +03:00
* aTextContentFlags = textContentFlags ;
2010-07-16 01:07:51 +04:00
}
2010-05-21 07:20:48 +04:00
2013-05-13 03:12:19 +04:00
static inline gfxSize RoundToFloatPrecision ( const gfxSize & aSize )
{
return gfxSize ( float ( aSize . width ) , float ( aSize . height ) ) ;
}
2013-03-21 06:33:00 +04:00
static bool
2011-06-22 16:11:27 +04:00
ChooseScaleAndSetTransform ( FrameLayerBuilder * aLayerBuilder ,
2012-09-17 02:25:33 +04:00
nsDisplayListBuilder * aDisplayListBuilder ,
2011-06-22 16:11:27 +04:00
nsIFrame * aContainerFrame ,
const gfx3DMatrix * aTransform ,
2013-09-27 10:01:16 +04:00
const ContainerLayerParameters & aIncomingScale ,
2012-09-17 02:25:33 +04:00
ContainerLayer * aLayer ,
2013-03-21 06:33:00 +04:00
LayerState aState ,
2013-09-27 10:01:16 +04:00
ContainerLayerParameters & aOutgoingScale )
2011-06-22 16:11:27 +04:00
{
2012-09-17 02:25:33 +04:00
nsIntPoint offset ;
2011-06-22 16:11:27 +04:00
gfx3DMatrix transform =
2011-08-27 04:06:03 +04:00
gfx3DMatrix : : ScalingMatrix ( aIncomingScale . mXScale , aIncomingScale . mYScale , 1.0 ) ;
2011-06-22 16:11:27 +04:00
if ( aTransform ) {
// aTransform is applied first, then the scale is applied to the result
transform = ( * aTransform ) * transform ;
2012-08-25 08:41:46 +04: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.
transform . NudgeToIntegers ( ) ;
2012-12-04 10:04:20 +04:00
}
gfxMatrix transform2d ;
if ( aContainerFrame & &
2013-09-06 13:28:02 +04:00
( aState = = LAYER_INACTIVE | | aState = = LAYER_SVG_EFFECTS ) & &
2012-12-04 10:04:20 +04:00
( ! aTransform | | ( aTransform - > Is2D ( & transform2d ) & &
! transform2d . HasNonTranslation ( ) ) ) ) {
2012-09-17 02:25:33 +04:00
// When we have an inactive ContainerLayer, translate the container by the offset to the
// reference frame (and offset all child layers by the reverse) so that the coordinate
// space of the child layers isn't affected by scrolling.
2012-12-04 10:04:20 +04:00
// This gets confusing for complicated transform (since we'd have to compute the scale
// factors for the matrix), so we don't bother. Any frames that are building an nsDisplayTransform
// for a css transform would have 0,0 as their offset to the reference frame, so this doesn't
// matter.
2012-09-17 02:25:33 +04:00
nsPoint appUnitOffset = aDisplayListBuilder - > ToReferenceFrame ( aContainerFrame ) ;
nscoord appUnitsPerDevPixel = aContainerFrame - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
offset = nsIntPoint (
2013-09-06 13:28:34 +04:00
NS_lround ( NSAppUnitsToDoublePixels ( appUnitOffset . x , appUnitsPerDevPixel ) * aIncomingScale . mXScale ) ,
NS_lround ( NSAppUnitsToDoublePixels ( appUnitOffset . y , appUnitsPerDevPixel ) * aIncomingScale . mYScale ) ) ;
2012-09-17 02:25:33 +04:00
}
2012-12-18 09:58:44 +04:00
transform = transform * gfx3DMatrix : : Translation ( offset . x + aIncomingScale . mOffset . x , offset . y + aIncomingScale . mOffset . y , 0 ) ;
2012-12-04 10:04:20 +04:00
2013-03-21 06:33:00 +04:00
if ( transform . IsSingular ( ) ) {
return false ;
}
2011-06-22 16:11:27 +04:00
2012-02-23 22:03:27 +04:00
bool canDraw2D = transform . CanDraw2D ( & transform2d ) ;
2011-06-22 16:11:27 +04:00
gfxSize scale ;
2012-01-11 15:26:33 +04:00
// XXX Should we do something for 3D transforms?
2013-12-16 09:37:47 +04:00
if ( canDraw2D ) {
2012-12-22 01:58:17 +04:00
// If the container's transform is animated off main thread, then use the
// maximum scale.
if ( aContainerFrame - > GetContent ( ) & &
nsLayoutUtils : : HasAnimationsForCompositor (
aContainerFrame - > GetContent ( ) , eCSSProperty_transform ) ) {
scale = nsLayoutUtils : : GetMaximumAnimatedScale ( aContainerFrame - > GetContent ( ) ) ;
} else {
2013-09-04 15:30:57 +04:00
// Scale factors are normalized to a power of 2 to reduce the number of resolution changes
2013-05-13 03:12:19 +04:00
scale = RoundToFloatPrecision ( transform2d . ScaleFactors ( true ) ) ;
2012-12-22 01:58:17 +04: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 15:30:57 +04:00
if ( ActiveLayerTracker : : IsStyleAnimated ( aContainerFrame , eCSSProperty_transform ) & &
2012-12-22 01:58:17 +04: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 ;
gfxMatrix oldFrameTransform2d ;
if ( aLayer - > GetBaseTransform ( ) . Is2D ( & oldFrameTransform2d ) ) {
2013-05-13 03:12:19 +04:00
gfxSize oldScale = RoundToFloatPrecision ( oldFrameTransform2d . ScaleFactors ( true ) ) ;
2012-12-22 01:58:17 +04:00
if ( oldScale = = scale | | oldScale = = gfxSize ( 1.0 , 1.0 ) ) {
clamp = false ;
}
2012-12-07 03:58:12 +04:00
}
2012-12-22 01:58:17 +04: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-08 03:12:41 +04:00
}
2011-06-22 16:11:27 +04:00
}
// If the scale factors are too small, just use 1.0. The content is being
// scaled out of sight anyway.
2011-06-22 16:11:28 +04:00
if ( fabs ( scale . width ) < 1e-8 | | fabs ( scale . height ) < 1e-8 ) {
2012-04-30 01:41:13 +04:00
scale = gfxSize ( 1.0 , 1.0 ) ;
2011-06-22 16:11:27 +04:00
}
} else {
scale = gfxSize ( 1.0 , 1.0 ) ;
}
2012-08-04 01:29:22 +04:00
// Store the inverse of our resolution-scale on the layer
2012-07-31 06:20:00 +04:00
aLayer - > SetBaseTransform ( transform ) ;
2012-08-04 01:29:22 +04:00
aLayer - > SetPreScale ( 1.0f / float ( scale . width ) ,
1.0f / float ( scale . height ) ) ;
2013-01-08 13:39:12 +04:00
aLayer - > SetInheritedScale ( aIncomingScale . mXScale ,
aIncomingScale . mYScale ) ;
2011-06-22 16:11:28 +04:00
2013-09-27 10:01:16 +04:00
aOutgoingScale =
ContainerLayerParameters ( scale . width , scale . height , - offset , aIncomingScale ) ;
2011-06-22 16:11:28 +04:00
if ( aTransform ) {
2013-03-21 06:33:00 +04:00
aOutgoingScale . mInTransformedSubtree = true ;
2013-09-04 15:30:57 +04:00
if ( ActiveLayerTracker : : IsStyleAnimated ( aContainerFrame , eCSSProperty_transform ) ) {
2013-03-21 06:33:00 +04:00
aOutgoingScale . mInActiveTransformedSubtree = true ;
2011-06-22 16:11:28 +04:00
}
}
2013-12-16 09:37:47 +04:00
bool isRetained = aLayer - > Manager ( ) - > IsWidgetLayerManager ( ) ;
2012-02-23 22:03:27 +04:00
if ( isRetained & & ( ! canDraw2D | | transform2d . HasNonIntegerTranslation ( ) ) ) {
2013-03-21 06:33:00 +04:00
aOutgoingScale . mDisableSubpixelAntialiasingInDescendants = true ;
2012-01-11 15:26:33 +04:00
}
2013-03-21 06:33:00 +04:00
return true ;
2011-06-22 16:11:27 +04:00
}
2012-07-23 07:00:36 +04:00
/* static */ PLDHashOperator
2012-10-12 06:39:46 +04:00
FrameLayerBuilder : : RestoreDisplayItemData ( nsRefPtrHashKey < DisplayItemData > * aEntry , void * aUserArg )
2012-07-23 07:00:36 +04:00
{
2012-10-12 06:39:46 +04:00
DisplayItemData * data = aEntry - > GetKey ( ) ;
2012-08-22 19:56:38 +04:00
uint32_t * generation = static_cast < uint32_t * > ( aUserArg ) ;
2012-07-23 07:00:36 +04:00
2012-10-12 06:39:46 +04:00
if ( data - > mUsed & & data - > mContainerLayerGeneration > = * generation ) {
2012-07-23 07:00:36 +04:00
return PL_DHASH_REMOVE ;
}
return PL_DHASH_NEXT ;
}
/* static */ PLDHashOperator
FrameLayerBuilder : : RestoreThebesLayerItemEntries ( ThebesLayerItemsEntry * aEntry , void * aUserArg )
{
2012-08-22 19:56:38 +04:00
uint32_t * generation = static_cast < uint32_t * > ( aUserArg ) ;
2012-07-23 07:00:36 +04:00
if ( aEntry - > mContainerLayerGeneration > = * generation ) {
2012-10-12 06:39:46 +04: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 07:00:36 +04:00
return PL_DHASH_REMOVE ;
}
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < aEntry - > mItems . Length ( ) ; i + + ) {
2012-07-23 07:00:36 +04:00
if ( aEntry - > mItems [ i ] . mContainerLayerGeneration > = * generation ) {
aEntry - > mItems . TruncateLength ( i ) ;
return PL_DHASH_NEXT ;
}
}
return PL_DHASH_NEXT ;
}
2010-09-04 00:10:45 +04:00
already_AddRefed < ContainerLayer >
2010-07-16 01:07:51 +04:00
FrameLayerBuilder : : BuildContainerLayerFor ( nsDisplayListBuilder * aBuilder ,
LayerManager * aManager ,
nsIFrame * aContainerFrame ,
nsDisplayItem * aContainerItem ,
2011-06-22 16:11:27 +04:00
const nsDisplayList & aChildren ,
2013-09-27 10:01:16 +04:00
const ContainerLayerParameters & aParameters ,
2013-03-22 06:17:29 +04:00
const gfx3DMatrix * aTransform ,
uint32_t aFlags )
2010-07-16 01:07:51 +04:00
{
2012-08-22 19:56:38 +04:00
uint32_t containerDisplayItemKey =
2012-11-19 14:54:50 +04:00
aContainerItem ? aContainerItem - > GetPerFrameKey ( ) : nsDisplayItem : : TYPE_ZERO ;
2010-07-16 01:07:51 +04:00
NS_ASSERTION ( aContainerFrame , " Container display items here should have a frame " ) ;
NS_ASSERTION ( ! aContainerItem | |
2013-04-19 16:02:13 +04:00
aContainerItem - > Frame ( ) = = aContainerFrame ,
2010-07-16 01:07:51 +04:00
" Container display item must match given frame " ) ;
2013-03-06 00:04:40 +04:00
if ( ! aParameters . mXScale | | ! aParameters . mYScale ) {
return nullptr ;
}
2010-07-16 01:07:51 +04:00
nsRefPtr < ContainerLayer > containerLayer ;
2012-07-04 04:24:55 +04:00
if ( aManager = = mRetainingManager ) {
2012-08-29 14:53:27 +04:00
// Using GetOldLayerFor will search merged frames, as well as the underlying
// frame. The underlying frame can change when a page scrolls, so this
// avoids layer recreation in the situation that a new underlying frame is
// picked for a layer.
2012-08-29 09:47:15 +04:00
Layer * oldLayer = nullptr ;
if ( aContainerItem ) {
oldLayer = GetOldLayerFor ( aContainerItem ) ;
} else {
DisplayItemData * data = GetOldLayerForFrame ( aContainerFrame , containerDisplayItemKey ) ;
if ( data ) {
oldLayer = data - > mLayer ;
}
}
2012-08-29 14:53:20 +04:00
2012-07-04 04:24:55 +04:00
if ( oldLayer ) {
NS_ASSERTION ( oldLayer - > Manager ( ) = = aManager , " Wrong manager " ) ;
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 18:20:58 +04:00
containerLayer - > SetMaskLayer ( nullptr ) ;
2012-07-04 04:24:55 +04:00
}
2010-07-16 01:07:51 +04:00
}
}
if ( ! containerLayer ) {
// No suitable existing layer was found.
containerLayer = aManager - > CreateContainerLayer ( ) ;
if ( ! containerLayer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2010-05-21 07:20:48 +04:00
2012-09-17 02:25:33 +04:00
LayerState state = aContainerItem ? aContainerItem - > GetLayerState ( aBuilder , aManager , aParameters ) : LAYER_ACTIVE ;
2012-11-23 03:29:05 +04:00
if ( state = = LAYER_INACTIVE & &
nsDisplayItem : : ForceActiveLayers ( ) ) {
state = LAYER_ACTIVE ;
}
2012-09-17 02:25:33 +04:00
if ( aContainerItem & & state = = LAYER_ACTIVE_EMPTY ) {
2011-05-19 02:54:31 +04:00
// Empty layers only have metadata and should never have display items. We
// early exit because later, invalidation will walk up the frame tree to
// determine which thebes layer gets invalidated. Since an empty layer
// should never have anything to paint, it should never be invalidated.
NS_ASSERTION ( aChildren . IsEmpty ( ) , " Should have no children " ) ;
return containerLayer . forget ( ) ;
}
2013-09-27 10:01:16 +04:00
ContainerLayerParameters scaleParameters ;
2013-03-21 06:33:00 +04:00
if ( ! ChooseScaleAndSetTransform ( this , aBuilder , aContainerFrame , aTransform , aParameters ,
containerLayer , state , scaleParameters ) ) {
return nullptr ;
}
2010-05-21 07:20:48 +04:00
2012-08-22 19:56:38 +04:00
uint32_t oldGeneration = mContainerLayerGeneration ;
2012-07-23 07:00:36 +04:00
mContainerLayerGeneration = + + mMaxContainerLayerGeneration ;
2012-07-30 18:20:58 +04:00
nsRefPtr < RefCountedRegion > thebesLayerInvalidRegion = nullptr ;
2012-08-29 09:47:15 +04:00
if ( mRetainingManager ) {
2012-10-12 03:38:24 +04:00
if ( aContainerItem ) {
2012-10-12 06:39:46 +04:00
StoreDataForFrame ( aContainerItem , containerLayer , LAYER_ACTIVE ) ;
} else {
StoreDataForFrame ( aContainerFrame , containerDisplayItemKey , containerLayer , LAYER_ACTIVE ) ;
2012-10-12 03:38:24 +04:00
}
2012-07-23 07:00:36 +04:00
}
2012-10-12 06:39:46 +04:00
LayerManagerData * data = static_cast < LayerManagerData * >
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-07-23 07:00:36 +04:00
nsRect bounds ;
nsIntRect pixBounds ;
2012-08-22 19:56:38 +04:00
int32_t appUnitsPerDevPixel ;
2012-11-22 09:34:32 +04:00
uint32_t stateFlags = 0 ;
if ( ( aContainerFrame - > GetStateBits ( ) & NS_FRAME_NO_COMPONENT_ALPHA ) & &
mRetainingManager & & ! mRetainingManager - > AreComponentAlphaLayersEnabled ( ) ) {
stateFlags = ContainerState : : NO_COMPONENT_ALPHA ;
}
2012-08-22 19:56:38 +04:00
uint32_t flags ;
2012-07-23 07:00:36 +04:00
while ( true ) {
2012-08-21 08:06:46 +04:00
ContainerState state ( aBuilder , aManager , aManager - > GetLayerBuilder ( ) ,
2012-09-28 15:19:39 +04:00
aContainerFrame , aContainerItem ,
containerLayer , scaleParameters ) ;
2012-08-29 09:47:15 +04:00
2013-03-04 13:56:02 +04:00
state . ProcessDisplayItems ( aChildren , stateFlags ) ;
2012-08-04 01:29:22 +04:00
2012-07-23 07:00:36 +04:00
// Set CONTENT_COMPONENT_ALPHA if any of our children have it.
// This is suboptimal ... a child could have text that's over transparent
// pixels in its own layer, but over opaque parts of previous siblings.
2012-08-29 09:47:15 +04:00
state . Finish ( & flags , data ) ;
2012-07-23 07:00:36 +04:00
bounds = state . GetChildrenBounds ( ) ;
pixBounds = state . ScaleToOutsidePixels ( bounds , false ) ;
appUnitsPerDevPixel = state . GetAppUnitsPerDevPixel ( ) ;
if ( ( flags & Layer : : CONTENT_COMPONENT_ALPHA ) & &
mRetainingManager & &
! mRetainingManager - > AreComponentAlphaLayersEnabled ( ) & &
! 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 06:39:46 +04:00
data - > mDisplayItems . EnumerateEntries ( RestoreDisplayItemData ,
2012-07-23 07:00:36 +04:00
& mContainerLayerGeneration ) ;
mThebesLayerItems . EnumerateEntries ( RestoreThebesLayerItemEntries ,
& mContainerLayerGeneration ) ;
aContainerFrame - > AddStateBits ( NS_FRAME_NO_COMPONENT_ALPHA ) ;
continue ;
}
break ;
}
2010-12-20 04:26:14 +03:00
2011-04-19 07:07:23 +04:00
NS_ASSERTION ( bounds . IsEqualInterior ( aChildren . GetBounds ( aBuilder ) ) , " Wrong bounds " ) ;
2012-09-17 02:25:33 +04:00
pixBounds . MoveBy ( nsIntPoint ( scaleParameters . mOffset . x , scaleParameters . mOffset . y ) ) ;
2013-03-22 06:17:29 +04:00
if ( aParameters . mAncestorClipRect & & ! ( aFlags & CONTAINER_NOT_CLIPPED_BY_ANCESTORS ) ) {
SetVisibleRegionForLayer ( containerLayer , nsIntRegion ( pixBounds ) ,
* aParameters . mAncestorClipRect ) ;
} else {
containerLayer - > SetVisibleRegion ( pixBounds ) ;
}
2011-02-23 08:38:09 +03:00
// Make sure that rounding the visible region out didn't add any area
// we won't paint
2011-06-22 16:11:27 +04:00
if ( aChildren . IsOpaque ( ) & & ! aChildren . NeedsTransparentSurface ( ) ) {
bounds . ScaleRoundIn ( scaleParameters . mXScale , scaleParameters . mYScale ) ;
2012-07-23 07:00:36 +04:00
if ( bounds . Contains ( pixBounds . ToAppUnits ( appUnitsPerDevPixel ) ) ) {
2011-06-22 16:11:27 +04:00
// Clear CONTENT_COMPONENT_ALPHA
flags = Layer : : CONTENT_OPAQUE ;
}
2010-12-20 04:26:14 +03:00
}
2010-09-02 13:18:40 +04:00
containerLayer - > SetContentFlags ( flags ) ;
2010-12-20 04:26:14 +03:00
2012-07-23 07:00:36 +04:00
mContainerLayerGeneration = oldGeneration ;
2013-08-14 15:33:03 +04:00
nsPresContext : : ClearNotifySubDocInvalidationData ( containerLayer ) ;
2012-08-29 09:47:18 +04:00
2010-08-06 02:11:23 +04:00
return containerLayer . forget ( ) ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:46 +04:00
Layer *
FrameLayerBuilder : : GetLeafLayerFor ( nsDisplayListBuilder * aBuilder ,
nsDisplayItem * aItem )
{
2012-08-29 09:47:15 +04:00
Layer * layer = GetOldLayerFor ( aItem ) ;
2010-07-16 01:07:51 +04:00
if ( ! layer )
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-09-02 13:18:39 +04:00
if ( layer - > HasUserData ( & gThebesDisplayItemLayerUserData ) ) {
2010-07-16 01:07:51 +04:00
// This layer was created to render Thebes-rendered content for this
// display item. The display item should not use it for its own
// layer rendering.
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:51 +04:00
}
2012-07-30 18:20:58 +04:00
layer - > SetMaskLayer ( nullptr ) ;
2010-07-16 01:07:51 +04:00
return layer ;
2010-07-16 01:07:46 +04:00
}
2012-09-27 19:34:46 +04:00
/* static */ void
FrameLayerBuilder : : InvalidateAllLayers ( LayerManager * aManager )
{
LayerManagerData * data = static_cast < LayerManagerData * >
( aManager - > GetUserData ( & gLayerManagerUserData ) ) ;
2012-08-29 09:48:45 +04:00
if ( data ) {
data - > mInvalidateAllLayers = true ;
}
}
2012-08-29 09:48:45 +04:00
/* static */ void
FrameLayerBuilder : : InvalidateAllLayersForFrame ( nsIFrame * aFrame )
{
2012-10-12 03:38:24 +04:00
nsTArray < DisplayItemData * > * array =
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 09:48:45 +04:00
}
}
2010-07-16 01:07:53 +04:00
/* static */
2011-03-28 03:59:47 +04:00
Layer *
2012-08-22 19:56:38 +04:00
FrameLayerBuilder : : GetDedicatedLayer ( nsIFrame * aFrame , uint32_t aDisplayItemKey )
2010-07-16 01:07:53 +04:00
{
2012-08-29 09:48:41 +04:00
//TODO: This isn't completely correct, since a frame could exist as a layer
// in the normal widget manager, and as a different layer (or no layer)
// in the secondary manager
2012-10-12 03:38:24 +04:00
nsTArray < DisplayItemData * > * array =
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( array ) {
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2012-10-12 06:39:46 +04:00
DisplayItemData * element = array - > ElementAt ( i ) ;
if ( ! element - > mParent - > mLayerManager - > IsWidgetLayerManager ( ) ) {
continue ;
}
if ( element - > mDisplayItemKey = = aDisplayItemKey ) {
if ( element - > mOptLayer ) {
return element - > mOptLayer ;
2012-10-12 03:38:24 +04:00
}
2012-09-25 00:31:30 +04:00
2012-10-12 06:39:46 +04:00
Layer * layer = element - > mLayer ;
2012-10-12 03:38:24 +04:00
if ( ! layer - > HasUserData ( & gColorLayerUserData ) & &
! layer - > HasUserData ( & gImageLayerUserData ) & &
! layer - > HasUserData ( & gThebesDisplayItemLayerUserData ) ) {
return layer ;
}
}
}
2010-07-16 01:07:53 +04:00
}
2012-07-30 18:20:58 +04:00
return nullptr ;
2010-07-16 01:07:53 +04:00
}
2012-08-04 16:26:38 +04:00
static gfxSize
PredictScaleForContent ( nsIFrame * aFrame , nsIFrame * aAncestorWithScale ,
const gfxSize & aScale )
2012-05-10 09:24:18 +04:00
{
2012-08-04 16:26:38 +04:00
gfx3DMatrix transform =
gfx3DMatrix : : ScalingMatrix ( aScale . width , aScale . height , 1.0 ) ;
2012-11-11 12:17:16 +04: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 16:26:38 +04:00
gfxMatrix transform2d ;
if ( transform . CanDraw2D ( & transform2d ) ) {
return transform2d . ScaleFactors ( true ) ;
}
return gfxSize ( 1.0 , 1.0 ) ;
}
gfxSize
FrameLayerBuilder : : GetThebesLayerScaleForFrame ( nsIFrame * aFrame )
{
nsIFrame * last ;
for ( nsIFrame * f = aFrame ; f ; f = nsLayoutUtils : : GetCrossDocParentFrame ( f ) ) {
last = f ;
2012-11-11 12:17:16 +04: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 ;
}
2012-10-12 03:38:24 +04:00
nsTArray < DisplayItemData * > * array =
reinterpret_cast < nsTArray < DisplayItemData * > * > ( aFrame - > Properties ( ) . Get ( LayerManagerDataProperty ( ) ) ) ;
if ( ! array ) {
2012-08-29 09:48:41 +04:00
continue ;
2012-10-12 03:38:24 +04:00
}
for ( uint32_t i = 0 ; i < array - > Length ( ) ; i + + ) {
2012-08-29 09:47:15 +04:00
Layer * layer = array - > ElementAt ( i ) - > mLayer ;
ContainerLayer * container = layer - > AsContainerLayer ( ) ;
2012-10-12 03:38:24 +04:00
if ( ! container | |
! layer - > Manager ( ) - > IsWidgetLayerManager ( ) ) {
2012-08-29 09:47:15 +04: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 16:26:38 +04:00
}
2012-08-05 17:35:08 +04:00
}
}
}
2012-08-04 16:26:38 +04:00
return PredictScaleForContent ( aFrame , last ,
last - > PresContext ( ) - > PresShell ( ) - > GetResolution ( ) ) ;
2012-05-10 09:24:18 +04:00
}
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
static void DebugPaintItem ( nsRenderingContext * aDest , nsDisplayItem * aItem , nsDisplayListBuilder * aBuilder )
{
2012-04-10 15:24:18 +04:00
bool snap ;
nsRect appUnitBounds = aItem - > GetBounds ( aBuilder , & snap ) ;
2012-03-05 22:09:05 +04:00
gfxRect bounds ( appUnitBounds . x , appUnitBounds . y , appUnitBounds . width , appUnitBounds . height ) ;
bounds . ScaleInverse ( aDest - > AppUnitsPerDevPixel ( ) ) ;
2012-07-31 21:28:21 +04:00
nsRefPtr < gfxASurface > surf =
gfxPlatform : : GetPlatform ( ) - > CreateOffscreenSurface ( gfxIntSize ( bounds . width , bounds . height ) ,
2013-09-25 00:45:13 +04:00
GFX_CONTENT_COLOR_ALPHA ) ;
2012-03-05 22:09:05 +04:00
surf - > SetDeviceOffset ( - bounds . TopLeft ( ) ) ;
nsRefPtr < gfxContext > context = new gfxContext ( surf ) ;
nsRefPtr < nsRenderingContext > ctx = new nsRenderingContext ( ) ;
ctx - > Init ( aDest - > DeviceContext ( ) , context ) ;
aItem - > Paint ( aBuilder , ctx ) ;
DumpPaintedImage ( aItem , surf ) ;
aItem - > SetPainted ( ) ;
2012-07-31 21:28:21 +04:00
2012-03-05 22:09:05 +04:00
surf - > SetDeviceOffset ( gfxPoint ( 0 , 0 ) ) ;
aDest - > ThebesContext ( ) - > SetSource ( surf , bounds . TopLeft ( ) ) ;
aDest - > ThebesContext ( ) - > Rectangle ( bounds ) ;
aDest - > ThebesContext ( ) - > Fill ( ) ;
}
# endif
2010-05-21 07:20:48 +04:00
/* static */ void
2013-11-06 23:10:49 +04:00
FrameLayerBuilder : : RecomputeVisibilityForItems ( nsTArray < ClippedDisplayItem > & aItems ,
nsDisplayListBuilder * aBuilder ,
const nsIntRegion & aRegionToDraw ,
const nsIntPoint & aOffset ,
int32_t aAppUnitsPerDevPixel ,
float aXScale ,
float aYScale )
2010-05-21 07:20:48 +04:00
{
2012-08-22 19:56:38 +04:00
uint32_t i ;
2012-12-14 02:50:57 +04:00
// Update visible regions. We need perform visibility analysis again
// because we may be asked to draw into part of a ThebesLayer that
// isn't actually visible in the window (e.g., because a ThebesLayer
// expanded its visible region to a rectangle internally), in which
// case the mVisibleRect stored in the display item may be wrong.
2013-11-06 23:10:49 +04:00
nsRegion visible = aRegionToDraw . ToAppUnits ( aAppUnitsPerDevPixel ) ;
visible . MoveBy ( NSIntPixelsToAppUnits ( aOffset . x , aAppUnitsPerDevPixel ) ,
NSIntPixelsToAppUnits ( aOffset . y , aAppUnitsPerDevPixel ) ) ;
visible . ScaleInverseRoundOut ( aXScale , aYScale ) ;
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:49 +04:00
for ( i = aItems . Length ( ) ; i > 0 ; - - i ) {
ClippedDisplayItem * cdi = & aItems [ i - 1 ] ;
2013-03-04 13:56:02 +04:00
const DisplayItemClip & clip = cdi - > mItem - > GetClip ( ) ;
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:49 +04:00
NS_ASSERTION ( AppUnitsPerDevPixel ( cdi - > mItem ) = = aAppUnitsPerDevPixel ,
2010-08-08 22:49:07 +04:00
" a thebes layer should contain items only at the same zoom " ) ;
2010-07-16 01:07:51 +04:00
2013-03-04 13:56:02 +04:00
NS_ABORT_IF_FALSE ( clip . HasClip ( ) | |
clip . GetRoundedRectCount ( ) = = 0 ,
2010-09-09 19:21:46 +04:00
" If we have rounded rects, we must have a clip rect " ) ;
2013-03-04 13:56:02 +04:00
if ( ! clip . IsRectAffectedByClip ( visible . GetBounds ( ) ) ) {
2013-11-06 23:10:49 +04:00
cdi - > mItem - > RecomputeVisibility ( aBuilder , & visible ) ;
2012-12-14 02:50:57 +04:00
continue ;
}
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped ;
2013-03-04 13:56:02 +04:00
clipped . And ( visible , clip . NonRoundedIntersection ( ) ) ;
2012-12-14 02:50:57 +04:00
nsRegion finalClipped = clipped ;
2013-11-06 23:10:49 +04:00
cdi - > mItem - > RecomputeVisibility ( aBuilder , & finalClipped ) ;
2012-12-14 02:50:57 +04:00
// If we have rounded clip rects, don't subtract from the visible
// region since we aren't displaying everything inside the rect.
2013-03-04 13:56:02 +04:00
if ( clip . GetRoundedRectCount ( ) = = 0 ) {
2012-12-14 02:50:57 +04:00
nsRegion removed ;
removed . Sub ( clipped , finalClipped ) ;
nsRegion newVisible ;
newVisible . Sub ( visible , removed ) ;
// Don't let the visible region get too complex.
if ( newVisible . GetNumRects ( ) < = 15 ) {
visible = newVisible ;
2010-09-09 19:21:46 +04:00
}
2011-01-26 21:36:11 +03:00
}
2010-07-16 01:07:51 +04:00
}
2013-11-06 23:10:49 +04:00
}
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:49 +04:00
void
FrameLayerBuilder : : PaintItems ( nsTArray < ClippedDisplayItem > & aItems ,
2013-11-06 23:10:50 +04:00
const nsIntRect & aRect ,
2013-11-06 23:10:49 +04:00
gfxContext * aContext ,
nsRenderingContext * aRC ,
nsDisplayListBuilder * aBuilder ,
nsPresContext * aPresContext ,
2013-11-06 23:10:50 +04:00
const nsIntPoint & aOffset ,
float aXScale , float aYScale ,
2013-11-06 23:10:49 +04:00
int32_t aCommonClipCount )
{
2013-11-06 23:10:50 +04: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 13:55:59 +04:00
DisplayItemClip currentClip ;
2013-03-04 13:56:00 +04:00
bool currentClipIsSetInContext = false ;
2013-03-04 13:56:02 +04:00
DisplayItemClip tmpClip ;
2010-08-08 22:49:07 +04:00
2013-11-06 23:10:49 +04:00
for ( uint32_t i = 0 ; i < aItems . Length ( ) ; + + i ) {
ClippedDisplayItem * cdi = & aItems [ i ] ;
2010-07-16 01:07:51 +04:00
2013-11-06 23:10:50 +04:00
nsRect paintRect = cdi - > mItem - > GetVisibleRect ( ) . Intersect ( boundRect ) ;
if ( paintRect . IsEmpty ( ) )
2010-07-16 01:07:51 +04:00
continue ;
2010-05-21 07:20:48 +04:00
// If the new desired clip state is different from the current state,
// update the clip.
2013-03-04 13:56:02 +04:00
const DisplayItemClip * clip = & cdi - > mItem - > GetClip ( ) ;
if ( clip - > GetRoundedRectCount ( ) > 0 & &
! clip - > IsRectClippedByRoundedCorner ( cdi - > mItem - > GetVisibleRect ( ) ) ) {
tmpClip = * clip ;
tmpClip . RemoveRoundedCorners ( ) ;
clip = & tmpClip ;
}
if ( currentClipIsSetInContext ! = clip - > HasClip ( ) | |
( clip - > HasClip ( ) & & * clip ! = currentClip ) ) {
2013-03-04 13:56:00 +04:00
if ( currentClipIsSetInContext ) {
2010-05-21 07:20:48 +04:00
aContext - > Restore ( ) ;
}
2013-03-04 13:56:02 +04:00
currentClipIsSetInContext = clip - > HasClip ( ) ;
2013-03-04 13:56:00 +04:00
if ( currentClipIsSetInContext ) {
2013-03-04 13:56:02 +04:00
currentClip = * clip ;
2010-05-21 07:20:48 +04:00
aContext - > Save ( ) ;
2013-11-06 23:10:49 +04:00
NS_ASSERTION ( aCommonClipCount < 100 ,
2012-02-08 02:27:44 +04:00
" Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong. " ) ;
2013-11-06 23:10:49 +04:00
currentClip . ApplyTo ( aContext , aPresContext , aCommonClipCount ) ;
2013-09-19 09:23:30 +04:00
aContext - > NewPath ( ) ;
2010-05-21 07:20:48 +04:00
}
}
2010-07-16 01:07:51 +04:00
2012-10-23 15:05:14 +04:00
if ( cdi - > mInactiveLayerManager ) {
2013-11-06 23:10:49 +04:00
PaintInactiveLayer ( aBuilder , cdi - > mInactiveLayerManager , cdi - > mItem , aContext , aRC ) ;
2010-07-16 01:08:05 +04:00
} else {
2013-04-19 16:02:13 +04:00
nsIFrame * frame = cdi - > mItem - > Frame ( ) ;
2013-04-19 16:01:41 +04:00
frame - > AddStateBits ( NS_FRAME_PAINTED_THEBES ) ;
2012-03-05 22:09:05 +04:00
# ifdef MOZ_DUMP_PAINTING
if ( gfxUtils : : sDumpPainting ) {
2013-11-06 23:10:49 +04:00
DebugPaintItem ( aRC , cdi - > mItem , aBuilder ) ;
2012-03-05 22:09:05 +04:00
} else {
# else
{
# endif
2013-11-06 23:10:49 +04:00
cdi - > mItem - > Paint ( aBuilder , aRC ) ;
2012-03-05 22:09:05 +04:00
}
2010-05-21 07:20:48 +04:00
}
2010-09-17 23:09:08 +04:00
2013-11-06 23:10:49 +04:00
if ( CheckDOMModified ( ) )
2010-09-17 23:09:08 +04:00
break ;
2010-05-21 07:20:48 +04:00
}
2010-07-16 01:07:51 +04:00
2013-03-04 13:56:00 +04:00
if ( currentClipIsSetInContext ) {
2010-05-21 07:20:48 +04:00
aContext - > Restore ( ) ;
}
2013-11-06 23:10:49 +04:00
}
2013-11-06 23:10:50 +04:00
/**
* Returns true if it is preferred to draw the list of display
* items separately for each rect in the visible region rather
* than clipping to a complex region .
*/
static bool ShouldDrawRectsSeparately ( gfxContext * aContext , DrawRegionClip aClip )
{
2013-11-14 04:46:19 +04:00
static bool sPaintRectsSeparately ;
static bool sPaintRectsSeparatelyPrefCached = false ;
if ( ! sPaintRectsSeparatelyPrefCached ) {
2013-11-17 08:24:53 +04:00
mozilla : : Preferences : : AddBoolVarCache ( & sPaintRectsSeparately , " layout.paint_rects_separately " , false ) ;
2013-11-14 04:46:19 +04:00
sPaintRectsSeparatelyPrefCached = true ;
}
if ( ! sPaintRectsSeparately | |
aContext - > IsCairo ( ) | |
aClip = = CLIP_NONE ) {
2013-11-06 23:10:50 +04:00
return false ;
}
2013-11-14 04:46:19 +04:00
2013-11-06 23:10:50 +04:00
DrawTarget * dt = aContext - > GetDrawTarget ( ) ;
return dt - > GetType ( ) = = BACKEND_DIRECT2D ;
}
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 23:10:49 +04: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 23:10:50 +04:00
DrawRegionClip aClip ,
2013-11-06 23:10:49 +04:00
const nsIntRegion & aRegionToInvalidate ,
void * aCallbackData )
{
PROFILER_LABEL ( " gfx " , " DrawThebesLayer " ) ;
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 23:10:50 +04:00
2013-11-06 23:10:49 +04:00
ThebesDisplayItemLayerUserData * userData =
static_cast < ThebesDisplayItemLayerUserData * >
( aLayer - > GetUserData ( & gThebesDisplayItemLayerUserData ) ) ;
NS_ASSERTION ( userData , " where did our user data go? " ) ;
2013-11-06 23:10:50 +04:00
bool shouldDrawRectsSeparately = ShouldDrawRectsSeparately ( aContext , aClip ) ;
if ( ! shouldDrawRectsSeparately ) {
if ( aClip = = CLIP_DRAW_SNAPPED ) {
gfxUtils : : ClipToRegionSnapped ( aContext , aRegionToDraw ) ;
} else if ( aClip = = CLIP_DRAW ) {
gfxUtils : : ClipToRegion ( aContext , aRegionToDraw ) ;
}
DrawForcedBackgroundColor ( aContext , aLayer , userData - > mForcedBackgroundColor ) ;
2013-11-06 23:10:49 +04: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 ( ) ;
int32_t appUnitsPerDevPixel = presContext - > AppUnitsPerDevPixel ( ) ;
RecomputeVisibilityForItems ( entry - > mItems , builder , aRegionToDraw ,
offset , appUnitsPerDevPixel ,
userData - > mXScale , userData - > mYScale ) ;
nsRefPtr < nsRenderingContext > rc = new nsRenderingContext ( ) ;
rc - > Init ( presContext - > DeviceContext ( ) , aContext ) ;
2013-11-06 23:10:50 +04:00
if ( shouldDrawRectsSeparately ) {
nsIntRegionRectIterator it ( aRegionToDraw ) ;
while ( const nsIntRect * iterRect = it . Next ( ) ) {
gfxContextAutoSaveRestore save ( aContext ) ;
aContext - > NewPath ( ) ;
aContext - > Rectangle ( * iterRect , aClip = = CLIP_DRAW_SNAPPED ) ;
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 23:10:50 +04:00
layerBuilder - > PaintItems ( entry - > mItems , * iterRect , aContext , rc ,
2013-11-06 23:10:50 +04:00
builder , presContext ,
2013-11-06 23:10:50 +04:00
offset , userData - > mXScale , userData - > mYScale ,
2013-11-06 23:10:50 +04:00
entry - > mCommonClipCount ) ;
}
} 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 23:10:50 +04:00
layerBuilder - > PaintItems ( entry - > mItems , aRegionToDraw . GetBounds ( ) , aContext , rc ,
2013-11-06 23:10:50 +04:00
builder , presContext ,
2013-11-06 23:10:50 +04:00
offset , userData - > mXScale , userData - > mYScale ,
2013-11-06 23:10:50 +04:00
entry - > mCommonClipCount ) ;
}
2011-11-15 08:59:03 +04:00
2013-07-22 19:51:38 +04:00
if ( presContext - > GetPaintFlashing ( ) ) {
2013-03-12 22:01:00 +04:00
FlashPaint ( aContext ) ;
}
2012-08-29 09:47:18 +04:00
if ( ! aRegionToInvalidate . IsEmpty ( ) ) {
aLayer - > AddInvalidRect ( aRegionToInvalidate . GetBounds ( ) ) ;
}
2010-05-21 07:20:48 +04:00
}
2011-09-29 10:19:26 +04:00
bool
2010-09-17 23:09:08 +04:00
FrameLayerBuilder : : CheckDOMModified ( )
{
2010-09-18 22:43:17 +04:00
if ( ! mRootPresContext | |
2010-09-17 23:09:08 +04:00
mInitialDOMGeneration = = mRootPresContext - > GetDOMGeneration ( ) )
2011-10-17 18:59:28 +04:00
return false ;
2010-09-17 23:09:08 +04:00
if ( mDetectedDOMModification ) {
// Don't spam the console with extra warnings
2011-10-17 18:59:28 +04:00
return true ;
2010-09-17 23:09:08 +04:00
}
2011-10-17 18:59:28 +04:00
mDetectedDOMModification = true ;
2010-09-17 23:09:08 +04:00
// Painting is not going to complete properly. There's not much
// we can do here though. Invalidating the window to get another repaint
// is likely to lead to an infinite repaint loop.
NS_WARNING ( " Detected DOM modification during paint, bailing out! " ) ;
2011-10-17 18:59:28 +04:00
return true ;
2010-09-17 23:09:08 +04:00
}
2011-11-17 07:44:16 +04:00
# ifdef MOZ_DUMP_PAINTING
2012-07-17 21:03:51 +04:00
/* static */ void
2012-08-07 21:57:26 +04:00
FrameLayerBuilder : : DumpRetainedLayerTree ( LayerManager * aManager , FILE * aFile , bool aDumpHtml )
2010-07-16 01:07:51 +04:00
{
2012-08-07 21:57:26 +04:00
aManager - > Dump ( aFile , " " , aDumpHtml ) ;
2010-07-16 01:07:51 +04:00
}
# endif
2013-12-30 03:35:53 +04:00
gfx : : Rect
2013-03-04 13:55:59 +04:00
CalculateBounds ( const nsTArray < DisplayItemClip : : RoundedRect > & aRects , int32_t A2D )
2012-02-08 02:27:44 +04:00
{
2012-06-26 06:43:30 +04:00
nsRect bounds = aRects [ 0 ] . mRect ;
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 1 ; i < aRects . Length ( ) ; + + i ) {
2012-06-26 06:43:30 +04:00
bounds . UnionRect ( bounds , aRects [ i ] . mRect ) ;
}
2013-12-30 03:35:53 +04:00
return gfx : : ToRect ( nsLayoutUtils : : RectToGfxRect ( bounds , A2D ) ) ;
2012-02-08 02:27:44 +04:00
}
2012-09-04 05:02:56 +04:00
static void
SetClipCount ( ThebesDisplayItemLayerUserData * aThebesData ,
uint32_t aClipCount )
{
if ( aThebesData ) {
aThebesData - > mMaskClipCount = aClipCount ;
}
}
2012-02-08 02:27:44 +04:00
void
2013-03-04 13:55:59 +04:00
ContainerState : : SetupMaskLayer ( Layer * aLayer , const DisplayItemClip & aClip ,
2012-08-22 19:56:38 +04:00
uint32_t aRoundedRectClipCount )
2012-02-08 02:27:44 +04:00
{
2012-09-04 05:02:56 +04:00
// if the number of clips we are going to mask has decreased, then aLayer might have
// cached graphics which assume the existence of a soon-to-be non-existent mask layer
// in that case, invalidate the whole layer.
ThebesDisplayItemLayerUserData * thebesData = GetThebesDisplayItemLayerUserData ( aLayer ) ;
if ( thebesData & &
aRoundedRectClipCount < thebesData - > mMaskClipCount ) {
ThebesLayer * thebes = aLayer - > AsThebesLayer ( ) ;
thebes - > InvalidateRegion ( thebes - > GetValidRegion ( ) . GetBounds ( ) ) ;
}
2012-02-08 02:27:44 +04:00
// don't build an unnecessary mask
2012-06-26 06:43:30 +04:00
nsIntRect layerBounds = aLayer - > GetVisibleRegion ( ) . GetBounds ( ) ;
2013-03-04 13:56:00 +04:00
if ( aClip . GetRoundedRectCount ( ) = = 0 | |
2012-09-04 05:02:56 +04:00
aRoundedRectClipCount = = 0 | |
2012-06-26 06:43:30 +04:00
layerBounds . IsEmpty ( ) ) {
2012-09-04 05:02:56 +04:00
SetClipCount ( thebesData , 0 ) ;
2012-02-08 02:27:44 +04:00
return ;
}
// check if we can re-use the mask layer
nsRefPtr < ImageLayer > maskLayer = CreateOrRecycleMaskImageLayerFor ( aLayer ) ;
MaskLayerUserData * userData = GetMaskLayerUserData ( maskLayer ) ;
2012-06-26 06:43:30 +04:00
MaskLayerUserData newData ;
2013-03-04 13:56:00 +04:00
aClip . AppendRoundedRects ( & newData . mRoundedClipRects , aRoundedRectClipCount ) ;
2012-06-26 06:43:30 +04:00
newData . mScaleX = mParameters . mXScale ;
newData . mScaleY = mParameters . mYScale ;
2013-04-04 06:59:24 +04:00
newData . mOffset = mParameters . mOffset ;
2013-08-09 13:42:05 +04:00
newData . mAppUnitsPerDevPixel = mContainerFrame - > PresContext ( ) - > AppUnitsPerDevPixel ( ) ;
2012-06-26 01:44:41 +04:00
2012-06-26 06:43:30 +04:00
if ( * userData = = newData ) {
aLayer - > SetMaskLayer ( maskLayer ) ;
2012-09-04 05:02:56 +04:00
SetClipCount ( thebesData , aRoundedRectClipCount ) ;
2012-06-26 02:54:05 +04:00
return ;
}
2012-07-31 21:28:21 +04:00
2012-06-26 06:43:30 +04:00
// calculate a more precise bounding rect
2013-12-30 03:35:53 +04:00
gfx : : Rect boundingRect = CalculateBounds ( newData . mRoundedClipRects ,
newData . mAppUnitsPerDevPixel ) ;
2012-06-26 06:43:30 +04:00
boundingRect . Scale ( mParameters . mXScale , mParameters . mYScale ) ;
2012-08-22 19:56:38 +04:00
uint32_t maxSize = mManager - > GetMaxTextureSize ( ) ;
2012-05-17 02:30:10 +04:00
NS_ASSERTION ( maxSize > 0 , " Invalid max texture size " ) ;
2013-12-30 03:35:53 +04:00
gfx : : Size surfaceSize ( std : : min < gfx : : Float > ( boundingRect . Width ( ) , maxSize ) ,
std : : min < gfx : : Float > ( boundingRect . Height ( ) , maxSize ) ) ;
2012-05-17 02:30:10 +04:00
2012-06-26 06:43:30 +04:00
// maskTransform is applied to the clip when it is painted into the mask (as a
// component of imageTransform), and its inverse used when the mask is used for
// masking.
// It is the transform from the masked layer's space to mask space
2013-12-30 03:35:53 +04:00
gfx : : Matrix maskTransform ;
2013-04-05 07:16:38 +04:00
maskTransform . Scale ( surfaceSize . width / boundingRect . Width ( ) ,
surfaceSize . height / boundingRect . Height ( ) ) ;
2013-12-30 03:35:53 +04:00
gfx : : Point p = boundingRect . TopLeft ( ) ;
maskTransform . Translate ( - p . x , - p . y ) ;
2012-06-26 06:43:30 +04:00
// imageTransform is only used when the clip is painted to the mask
2013-12-30 03:35:53 +04:00
gfx : : Matrix imageTransform = maskTransform ;
2012-06-26 06:43:30 +04:00
imageTransform . Scale ( mParameters . mXScale , mParameters . mYScale ) ;
2012-09-04 05:02:56 +04:00
nsAutoPtr < MaskLayerImageCache : : MaskLayerImageKey > newKey (
2012-12-12 01:57:52 +04:00
new MaskLayerImageCache : : MaskLayerImageKey ( ) ) ;
2012-09-04 05:02:56 +04:00
2012-06-26 06:43:30 +04:00
// copy and transform the rounded rects
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < newData . mRoundedClipRects . Length ( ) ; + + i ) {
2012-09-04 05:02:56 +04:00
newKey - > mRoundedClipRects . AppendElement (
2012-06-26 06:43:30 +04:00
MaskLayerImageCache : : PixelRoundedRect ( newData . mRoundedClipRects [ i ] ,
mContainerFrame - > PresContext ( ) ) ) ;
2012-09-04 05:02:56 +04:00
newKey - > mRoundedClipRects [ i ] . ScaleAndTranslate ( imageTransform ) ;
2012-02-08 02:27:44 +04:00
}
2013-12-30 03:35:53 +04:00
2012-09-04 05:02:56 +04:00
const MaskLayerImageCache : : MaskLayerImageKey * lookupKey = newKey ;
2012-09-03 14:47:51 +04:00
2012-09-04 05:02:56 +04:00
// check to see if we can reuse a mask image
2012-06-26 06:43:30 +04:00
nsRefPtr < ImageContainer > container =
GetMaskLayerImageCache ( ) - > FindImageFor ( & lookupKey ) ;
2012-09-04 05:02:56 +04:00
if ( ! container ) {
2013-04-05 07:16:38 +04:00
nsIntSize surfaceSizeInt = nsIntSize ( NSToIntCeil ( surfaceSize . width ) ,
NSToIntCeil ( surfaceSize . height ) ) ;
2012-06-26 06:43:30 +04:00
// no existing mask image, so build a new one
nsRefPtr < gfxASurface > surface =
2013-04-05 07:16:38 +04:00
aLayer - > Manager ( ) - > CreateOptimalMaskSurface ( surfaceSizeInt ) ;
2012-06-26 06:43:30 +04:00
// fail if we can't get the right surface
if ( ! surface | | surface - > CairoStatus ( ) ) {
NS_WARNING ( " Could not create surface for mask layer. " ) ;
2012-09-04 05:02:56 +04:00
SetClipCount ( thebesData , 0 ) ;
2012-06-26 06:43:30 +04:00
return ;
}
2012-02-08 02:27:44 +04:00
2012-06-26 06:43:30 +04:00
nsRefPtr < gfxContext > context = new gfxContext ( surface ) ;
2013-12-30 03:35:53 +04:00
context - > Multiply ( ThebesMatrix ( imageTransform ) ) ;
2012-02-08 02:27:44 +04:00
2012-06-26 06:43:30 +04:00
// paint the clipping rects with alpha to create the mask
2012-06-26 06:43:31 +04:00
context - > SetColor ( gfxRGBA ( 1 , 1 , 1 , 1 ) ) ;
2013-08-09 13:42:05 +04:00
aClip . DrawRoundedRectsTo ( context ,
newData . mAppUnitsPerDevPixel ,
0 ,
aRoundedRectClipCount ) ;
2012-02-08 02:27:44 +04:00
2012-06-26 06:43:30 +04:00
// build the image and container
container = aLayer - > Manager ( ) - > CreateImageContainer ( ) ;
NS_ASSERTION ( container , " Could not create image container for mask layer. " ) ;
2012-08-20 06:39:10 +04:00
static const ImageFormat format = CAIRO_SURFACE ;
2012-06-26 06:43:30 +04:00
nsRefPtr < Image > image = container - > CreateImage ( & format , 1 ) ;
NS_ASSERTION ( image , " Could not create image container for mask layer. " ) ;
CairoImage : : Data data ;
data . mSurface = surface ;
2013-04-05 07:16:38 +04:00
data . mSize = surfaceSizeInt ;
2012-06-26 06:43:30 +04:00
static_cast < CairoImage * > ( image . get ( ) ) - > SetData ( data ) ;
2012-07-26 22:11:22 +04:00
container - > SetCurrentImageInTransaction ( image ) ;
2012-06-26 02:54:05 +04:00
2012-09-04 05:02:56 +04:00
GetMaskLayerImageCache ( ) - > PutImage ( newKey . forget ( ) , container ) ;
2012-06-26 06:43:30 +04:00
}
2012-06-26 01:44:41 +04:00
2012-06-26 02:54:05 +04:00
maskLayer - > SetContainer ( container ) ;
2013-12-30 03:35:53 +04:00
maskTransform . Invert ( ) ;
gfx3DMatrix matrix = gfx3DMatrix : : From2D ( ThebesMatrix ( maskTransform ) ) ;
2012-09-17 02:25:33 +04:00
matrix . Translate ( gfxPoint3D ( mParameters . mOffset . x , mParameters . mOffset . y , 0 ) ) ;
maskLayer - > SetBaseTransform ( matrix ) ;
2012-06-26 06:43:30 +04:00
2012-02-08 02:27:44 +04:00
// save the details of the clip in user data
2012-06-26 06:43:30 +04:00
userData - > mScaleX = newData . mScaleX ;
userData - > mScaleY = newData . mScaleY ;
userData - > mRoundedClipRects . SwapElements ( newData . mRoundedClipRects ) ;
2012-09-04 05:02:56 +04:00
userData - > mImageKey = lookupKey ;
2012-02-08 02:27:44 +04:00
aLayer - > SetMaskLayer ( maskLayer ) ;
2012-09-04 05:02:56 +04:00
SetClipCount ( thebesData , aRoundedRectClipCount ) ;
2012-02-08 02:27:44 +04:00
return ;
}
2010-05-21 07:20:48 +04:00
} // namespace mozilla