Home | History | Annotate | Download | only in graphics
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef PPAPI_UTILITY_GRAPHICS_PAINT_AGGREGATOR_H_
      6 #define PPAPI_UTILITY_GRAPHICS_PAINT_AGGREGATOR_H_
      7 
      8 #include <stddef.h>
      9 #include <vector>
     10 
     11 #include "ppapi/cpp/point.h"
     12 #include "ppapi/cpp/rect.h"
     13 
     14 /// @file
     15 /// This file defines the API to aggregate multiple invalidation and scroll
     16 /// commands to produce a scroll and repaint sequence.
     17 namespace pp {
     18 
     19 /// This class is responsible for aggregating multiple invalidation and scroll
     20 /// commands to produce a scroll and repaint sequence. You can use this manually
     21 /// to track your updates, but most applications will use the PaintManager to
     22 /// additionally handle the necessary callbacks on top of the PaintAggregator
     23 /// functionality.
     24 ///
     25 /// Refer to <code>http://code.google.com/p/ppapi/wiki/2DPaintingModel</code>
     26 /// for further information.
     27 class PaintAggregator {
     28  public:
     29   struct PaintUpdate {
     30     /// Default constructor for creating an is_null() <code>PaintUpdate</code>
     31     /// object.
     32     PaintUpdate();
     33 
     34     /// Destructor.
     35     ~PaintUpdate();
     36 
     37     /// True if there is a scroll applied. This indicates that the scroll delta
     38     /// and scroll_rect are nonzero (just as a convenience).
     39     bool has_scroll;
     40 
     41     /// The amount to scroll by. Either the X or Y may be nonzero to indicate a
     42     /// scroll in that direction, but there will never be a scroll in both
     43     /// directions at the same time (this will be converted to a paint of the
     44     /// region instead).
     45     ///
     46     /// If there is no scroll, this will be (0, 0).
     47     Point scroll_delta;
     48 
     49     /// The rectangle that should be scrolled by the scroll_delta. If there is
     50     /// no scroll, this will be (0, 0, 0, 0). We only track one scroll command
     51     /// at once. If there are multiple ones, they will be converted to
     52     /// invalidates.
     53     Rect scroll_rect;
     54 
     55     /// A list of all the individual dirty rectangles. This is an aggregated
     56     /// list of all invalidate calls. Different rectangles may be unified to
     57     /// produce a minimal list with no overlap that is more efficient to paint.
     58     /// This list also contains the region exposed by any scroll command.
     59     std::vector<Rect> paint_rects;
     60 
     61     /// The union of all paint_rects.
     62     Rect paint_bounds;
     63   };
     64 
     65   /// Default constructor.
     66   PaintAggregator();
     67 
     68   /// Setter function setting the max ratio of paint rect area to scroll rect
     69   /// area that we will tolerate before downgrading the scroll into a repaint.
     70   ///
     71   /// If the combined area of paint rects contained within the scroll
     72   /// rect grows too large, then we might as well just treat
     73   /// the scroll rect as a paint rect.
     74   ///
     75   /// @param[in] area The max ratio of paint rect area to scroll rect area that
     76   /// we will tolerate before downgrading the scroll into a repaint.
     77   void set_max_redundant_paint_to_scroll_area(float area) {
     78     max_redundant_paint_to_scroll_area_ = area;
     79   }
     80 
     81   /// Setter function for setting the maximum number of paint rects. If we
     82   /// exceed this limit, then we'll start combining paint rects (see
     83   /// CombinePaintRects). This limiting can be important since there is
     84   /// typically some overhead in deciding what to paint. If your module is fast
     85   /// at doing these computations, raise this threshold, if your module is
     86   /// slow, lower it (probably requires some tuning to find the right value).
     87   ///
     88   /// @param[in] max_rects The maximum number of paint rects.
     89   void set_max_paint_rects(size_t max_rects) {
     90     max_paint_rects_ = max_rects;
     91   }
     92 
     93   /// This function determines if there is a pending update. There is a
     94   /// PendingUpdate if InvalidateRect or ScrollRect were called and
     95   /// ClearPendingUpdate was not called.
     96   ///
     97   /// @return true if there is a pending update, otherwise false.
     98   bool HasPendingUpdate() const;
     99 
    100   /// This function clears a pending update.
    101   void ClearPendingUpdate();
    102 
    103   /// This function gets a pending update.
    104   ///
    105   /// @return A PaintUpdate containing the pending update.
    106   PaintUpdate GetPendingUpdate() const;
    107 
    108   /// This function invalidates the rect so it will be repainted.
    109   ///
    110   /// @param[in] rect A rect to be repainted.
    111   void InvalidateRect(const Rect& rect);
    112 
    113   /// This function adds a pending scroll update.
    114   ///
    115   /// @param[in] clip_rect The rect to scroll.
    116   /// @param[in] amount A Point amount to scroll <code>rect</code>.
    117   void ScrollRect(const Rect& clip_rect, const Point& amount);
    118 
    119  private:
    120   // This structure is an internal version of PaintUpdate. It's different in
    121   // two respects:
    122   //
    123   //  - The scroll damange (area exposed by the scroll operation, if any) is
    124   //    maintained separately from the dirty rects generated by calling
    125   //    InvalidateRect. We need to know this distinction for some operations.
    126   //
    127   //  - The paint bounds union is computed on the fly so we don't have to keep
    128   //    a rectangle up-to-date as we do different operations.
    129   class InternalPaintUpdate {
    130    public:
    131     InternalPaintUpdate();
    132     ~InternalPaintUpdate();
    133 
    134     // Computes the rect damaged by scrolling within |scroll_rect| by
    135     // |scroll_delta|. This rect must be repainted. It is not included in
    136     // paint_rects or in the rect returned by GetPaintBounds.
    137     Rect GetScrollDamage() const;
    138 
    139     // Returns the smallest rect containing all paint rects, not including the
    140     // scroll damage rect.
    141     Rect GetPaintBounds() const;
    142 
    143     Point scroll_delta;
    144     Rect scroll_rect;
    145 
    146     // Does not include the scroll damage rect.
    147     std::vector<Rect> paint_rects;
    148   };
    149 
    150   Rect ScrollPaintRect(const Rect& paint_rect, const Point& amount) const;
    151   bool ShouldInvalidateScrollRect(const Rect& rect) const;
    152   void InvalidateScrollRect();
    153   void CombinePaintRects();
    154 
    155   InternalPaintUpdate update_;
    156 
    157   // If the combined area of paint rects contained within the scroll rect grows
    158   // too large, then we might as well just treat the scroll rect as a paint
    159   // rect. This constant sets the max ratio of paint rect area to scroll rect
    160   // area that we will tolerate before downgrading the scroll into a repaint.
    161   float max_redundant_paint_to_scroll_area_;
    162 
    163   // The maximum number of paint rects. If we exceed this limit, then we'll
    164   // start combining paint rects (see CombinePaintRects). This limiting can be
    165   // important since there is typically some overhead in deciding what to
    166   // paint. If your plugin is fast at doing these computations, raise this
    167   // threshold, if your plugin is slow, lower it (probably requires some
    168   // tuning to find the right value).
    169   size_t max_paint_rects_;
    170 };
    171 
    172 }  // namespace pp
    173 
    174 #endif  // PPAPI_UTILITY_PAINT_AGGREGATOR_H_
    175