| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ObjectPaintInvalidator_h |
| #define ObjectPaintInvalidator_h |
| |
| #include "core/CoreExport.h" |
| #include "platform/graphics/PaintInvalidationReason.h" |
| #include "wtf/Allocator.h" |
| #include "wtf/AutoReset.h" |
| |
| namespace blink { |
| |
| class DisplayItemClient; |
| class LayoutBoxModelObject; |
| class LayoutObject; |
| class LayoutRect; |
| struct PaintInvalidatorContext; |
| |
| class CORE_EXPORT ObjectPaintInvalidator { |
| STACK_ALLOCATED(); |
| |
| public: |
| ObjectPaintInvalidator(const LayoutObject& object) : m_object(object) {} |
| |
| static void objectWillBeDestroyed(const LayoutObject&); |
| |
| // This calls paintingLayer() which walks up the tree. |
| // If possible, use the faster |
| // PaintInvalidatorContext.paintingLayer.setNeedsRepaint(). |
| void slowSetPaintingLayerNeedsRepaint(); |
| |
| // TODO(wangxianzhu): Change the call sites to use the faster version if |
| // possible. |
| void slowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient( |
| const DisplayItemClient& client, |
| PaintInvalidationReason reason) { |
| slowSetPaintingLayerNeedsRepaint(); |
| invalidateDisplayItemClient(client, reason); |
| } |
| |
| void invalidateDisplayItemClientsIncludingNonCompositingDescendants( |
| PaintInvalidationReason); |
| |
| void invalidatePaintOfPreviousPaintInvalidationRect( |
| const LayoutBoxModelObject& paintInvalidationContainer, |
| PaintInvalidationReason); |
| |
| // The caller should ensure the painting layer has been setNeedsRepaint before |
| // calling this function. |
| void invalidateDisplayItemClient(const DisplayItemClient&, |
| PaintInvalidationReason); |
| |
| // Actually do the paint invalidate of rect r for this object which has been |
| // computed in the coordinate space of the GraphicsLayer backing of |
| // |paintInvalidationContainer|. Note that this coordinaten space is not the |
| // same as the local coordinate space of |paintInvalidationContainer| in the |
| // presence of layer squashing. |
| void invalidatePaintUsingContainer( |
| const LayoutBoxModelObject& paintInvalidationContainer, |
| const LayoutRect&, |
| PaintInvalidationReason); |
| |
| // Invalidate the paint of a specific subrectangle within a given object. The |
| // rect is in the object's coordinate space. If a DisplayItemClient is |
| // specified, that client is invalidated rather than |m_object|. |
| // Returns the visual rect that was invalidated (i.e, invalidation in the |
| // space of the GraphicsLayer backing this LayoutObject). |
| LayoutRect invalidatePaintRectangle(const LayoutRect&, DisplayItemClient*); |
| |
| void invalidatePaintIncludingNonCompositingDescendants(); |
| void invalidatePaintIncludingNonSelfPaintingLayerDescendants( |
| const LayoutBoxModelObject& paintInvalidationContainer); |
| |
| private: |
| void invalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal( |
| const LayoutBoxModelObject& paintInvalidationContainer); |
| void setBackingNeedsPaintInvalidationInRect( |
| const LayoutBoxModelObject& paintInvalidationContainer, |
| const LayoutRect&, |
| PaintInvalidationReason); |
| |
| protected: |
| const LayoutObject& m_object; |
| }; |
| |
| class ObjectPaintInvalidatorWithContext : public ObjectPaintInvalidator { |
| public: |
| ObjectPaintInvalidatorWithContext(const LayoutObject& object, |
| const PaintInvalidatorContext& context) |
| : ObjectPaintInvalidator(object), m_context(context) {} |
| |
| PaintInvalidationReason invalidatePaintIfNeeded() { |
| return invalidatePaintIfNeededWithComputedReason( |
| computePaintInvalidationReason()); |
| } |
| |
| PaintInvalidationReason computePaintInvalidationReason(); |
| PaintInvalidationReason invalidatePaintIfNeededWithComputedReason( |
| PaintInvalidationReason); |
| |
| // This function tries to minimize the amount of invalidation generated by |
| // invalidating the "difference" between |m_context.oldBounds| and |
| // |m_context.newBounds|. This means invalidating the union of the previous |
| // rectangles but not their intersection. The use case is when an element only |
| // requires a paint invalidation (which means that its content didn't change) |
| // and its bounds changed but its location didn't. If we don't meet the |
| // criteria for an incremental paint, the alternative is a full paint |
| // invalidation. Returns true if any paint invalidation is done. |
| bool incrementallyInvalidatePaint(); |
| |
| private: |
| void invalidateSelectionIfNeeded(PaintInvalidationReason); |
| |
| // This function generates a full invalidation, which means invalidating both |
| // |oldBounds| and |newBounds|. This is the default choice when generating an |
| // invalidation, as it is always correct, albeit it may force some extra |
| // painting. |
| void fullyInvalidatePaint(PaintInvalidationReason, |
| const LayoutRect& oldBounds, |
| const LayoutRect& newBounds); |
| |
| const PaintInvalidatorContext& m_context; |
| }; |
| |
| // TODO(crbug.com/457415): We should not allow paint invalidation out of paint |
| // invalidation state. |
| class DisablePaintInvalidationStateAsserts { |
| STACK_ALLOCATED(); |
| WTF_MAKE_NONCOPYABLE(DisablePaintInvalidationStateAsserts); |
| |
| public: |
| DisablePaintInvalidationStateAsserts(); |
| |
| private: |
| AutoReset<bool> m_disabler; |
| }; |
| |
| } // namespace blink |
| |
| #endif |