1 // Copyright (c) 2012 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.
5 #ifndef PPAPI_UTILITY_GRAPHICS_PAINT_MANAGER_H_
6 #define PPAPI_UTILITY_GRAPHICS_PAINT_MANAGER_H_
10 #include "ppapi/cpp/graphics_2d.h"
11 #include "ppapi/utility/completion_callback_factory.h"
12 #include "ppapi/utility/graphics/paint_aggregator.h"
15 /// This file defines the API to convert the "plugin push" model of painting
16 /// in PPAPI to a paint request at a later time.
25 /// This class converts the "instance push" model of painting in PPAPI to a
26 /// paint request at a later time. Usage is that you call Invalidate and
27 /// Scroll, and implement the Client interface. Your OnPaint handler will
28 /// then get called with coalesced paint events.
30 /// This class is basically a <code>PaintAggregator</code> that groups updates,
31 /// plus management of callbacks for scheduling paints.
33 /// <strong>Example:</strong>
37 /// class MyClass : public pp::Instance, public PaintManager::Client {
40 /// paint_manager_.Initialize(this, this, false);
43 /// void ViewChanged(const pp::Rect& position, const pp::Rect& clip) {
44 /// paint_manager_.SetSize(position.size());
47 /// void DoSomething() {
48 /// // This function does something like respond to an event that causes
49 /// // the screen to need updating.
50 /// paint_manager_.InvalidateRect(some_rect);
53 /// // Implementation of PaintManager::Client
54 /// virtual bool OnPaint(pp::Graphics2D& device,
55 /// const pp::PaintUpdate& update) {
56 /// // If our app needed scrolling, we would apply that first here.
58 /// // Then we would either repaint the area returned by GetPaintBounds or
59 /// // iterate through all the paint_rects.
61 /// // The caller will call Flush() for us, so don't do that here.
66 /// pp::PaintManager paint_manager_;
73 /// OnPaint() paints the given invalid area of the instance to the given
74 /// graphics device. Returns true if anything was painted.
76 /// You are given the list of rects to paint in <code>paint_rects</code>,
77 /// and the union of all of these rects in <code>paint_bounds</code>. You
78 /// only have to paint the area inside each of the
79 /// <code>paint_rects</code>, but can paint more if you want (some apps may
80 /// just want to paint the union).
82 /// Do not call Flush() on the graphics device, this will be done
83 /// automatically if you return true from this function since the
84 /// <code>PaintManager</code> needs to handle the callback.
86 /// It is legal for you to cause invalidates inside of Paint which will
87 /// then get executed as soon as the Flush for this update has completed.
88 /// However, this is not very nice to the host system since it will spin the
89 /// CPU, possibly updating much faster than necessary. It is best to have a
90 /// 1/60 second timer to do an invalidate instead. This will limit your
91 /// animation to the slower of 60Hz or "however fast Flush can complete."
93 /// @param[in] graphics A <code>Graphics2D</code> to be painted.
94 /// @param[in] paint_rects A list of rects to paint.
95 /// @param[in] paint_bounds A union of the rects to paint.
97 /// @return true if successful, otherwise false.
98 virtual bool OnPaint(Graphics2D& graphics,
99 const std::vector<Rect>& paint_rects,
100 const Rect& paint_bounds) = 0;
103 // You shouldn't be doing deleting through this interface.
107 /// Default constructor for creating an is_null() <code>PaintManager</code>
108 /// object. If you use this version of the constructor, you must call
109 /// Initialize() below.
112 /// A constructor to create a new <code>PaintManager</code> with an instance
115 /// <strong>Note:</strong> You will need to call SetSize() before this class
116 /// will do anything. Normally you do this from the <code>ViewChanged</code>
117 /// method of your instance.
119 /// @param instance The instance using this paint manager to do its
120 /// painting. Painting will automatically go to this instance and you don't
121 /// have to manually bind any device context (this is all handled by the
124 /// @param client A non-owning pointer and must remain valid (normally the
125 /// object implementing the Client interface will own the paint manager).
127 /// @param is_always_opaque A flag passed to the device contexts that this
128 /// class creates. Set this to true if your instance always draws an opaque
129 /// image to the device. This is used as a hint to the browser that it does
130 /// not need to do alpha blending, which speeds up painting. If you generate
131 /// non-opqaue pixels or aren't sure, set this to false for more general
134 /// If you set is_always_opaque, your alpha channel should always be set to
135 /// 0xFF or there may be painting artifacts. Being opaque will allow the
136 /// browser to do a memcpy rather than a blend to paint the plugin, and this
137 /// means your alpha values will get set on the page backing store. If these
138 /// values are incorrect, it could mess up future blending. If you aren't
139 /// sure, it is always correct to specify that it it not opaque.
140 PaintManager(Instance* instance, Client* client, bool is_always_opaque);
145 /// Initialize() must be called if you are using the 0-arg constructor.
147 /// @param instance The instance using this paint manager to do its
148 /// painting. Painting will automatically go to this instance and you don't
149 /// have to manually bind any device context (this is all handled by the
151 /// @param client A non-owning pointer and must remain valid (normally the
152 /// object implementing the Client interface will own the paint manager).
153 /// @param is_always_opaque A flag passed to the device contexts that this
154 /// class creates. Set this to true if your instance always draws an opaque
155 /// image to the device. This is used as a hint to the browser that it does
156 /// not need to do alpha blending, which speeds up painting. If you generate
157 /// non-opqaue pixels or aren't sure, set this to false for more general
160 /// If you set <code>is_always_opaque</code>, your alpha channel should
161 /// always be set to <code>0xFF</code> or there may be painting artifacts.
162 /// Being opaque will allow the browser to do a memcpy rather than a blend
163 /// to paint the plugin, and this means your alpha values will get set on the
164 /// page backing store. If these values are incorrect, it could mess up
165 /// future blending. If you aren't sure, it is always correct to specify that
166 /// it it not opaque.
167 void Initialize(Instance* instance, Client* client, bool is_always_opaque);
169 /// Setter function setting the max ratio of paint rect area to scroll rect
170 /// area that we will tolerate before downgrading the scroll into a repaint.
172 /// If the combined area of paint rects contained within the scroll
173 /// rect grows too large, then we might as well just treat
174 /// the scroll rect as a paint rect.
176 /// @param[in] area The max ratio of paint rect area to scroll rect area that
177 /// we will tolerate before downgrading the scroll into a repaint.
178 void set_max_redundant_paint_to_scroll_area(float area) {
179 aggregator_.set_max_redundant_paint_to_scroll_area(area);
182 /// Setter function for setting the maximum number of paint rects. If we
183 /// exceed this limit, then we'll start combining paint rects (refer to
184 /// CombinePaintRects() for further information). This limiting can be
185 /// important since there is typically some overhead in deciding what to
186 /// paint. If your module is fast at doing these computations, raise this
187 /// threshold, if your module is slow, lower it (probably requires some
188 /// tuning to find the right value).
190 /// @param[in] max_rects The maximum number of paint rects.
191 void set_max_paint_rects(size_t max_rects) {
192 aggregator_.set_max_paint_rects(max_rects);
195 /// SetSize() sets the size of the instance. If the size is the same as the
196 /// previous call, this will be a NOP. If the size has changed, a new device
197 /// will be allocated to the given size and a paint to that device will be
200 /// This function is intended to be called from <code>ViewChanged</code> with
201 /// the size of the instance. Since it tracks the old size and only allocates
202 /// when the size changes, you can always call this function without worrying
203 /// about whether the size changed or ViewChanged() is called for another
204 /// reason (like the position changed).
206 /// @param new_size The new size for the instance.
207 void SetSize(const Size& new_size);
209 /// This function provides access to the underlying device in case you need
210 /// it. If you have done a SetSize(), note that the graphics context won't be
211 /// updated until right before the next call to OnPaint().
213 /// <strong>Note:</strong> If you call Flush on this device the paint manager
214 /// will get very confused, don't do this!
215 const Graphics2D& graphics() const { return graphics_; }
217 /// This function provides access to the underlying device in case you need
218 /// it. If you have done a SetSize(), note that the graphics context won't be
219 /// updated until right before the next call to OnPaint().
221 /// <strong>Note:</strong> If you call Flush on this device the paint manager
222 /// will get very confused, don't do this!
223 Graphics2D& graphics() { return graphics_; }
225 /// Invalidate() invalidate the entire instance.
228 /// InvalidateRect() Invalidate the provided rect.
230 /// @param[in] rect The <code>Rect</code> to be invalidated.
231 void InvalidateRect(const Rect& rect);
233 /// ScrollRect() scrolls the provided <code>clip_rect</code> by the
234 /// <code>amount</code> argument.
236 /// @param clip_rect The clip rectangle to scroll.
237 /// @param amount The amount to scroll <code>clip_rect</code>.
238 void ScrollRect(const Rect& clip_rect, const Point& amount);
240 /// GetEffectiveSize() returns the size of the graphics context for the
241 /// next paint operation. This is the pending size if a resize is pending
242 /// (the instance has called SetSize() but we haven't actually painted it
243 /// yet), or the current size of no resize is pending.
245 /// @return The effective size.
246 Size GetEffectiveSize() const;
249 // Disallow copy and assign (these are unimplemented).
250 PaintManager(const PaintManager&);
251 PaintManager& operator=(const PaintManager&);
253 // Makes sure there is a callback that will trigger a paint at a later time.
254 // This will be either a Flush callback telling us we're allowed to generate
255 // more data, or, if there's no flush callback pending, a manual call back
256 // to the message loop via ExecuteOnMainThread.
257 void EnsureCallbackPending();
259 // Does the client paint and executes a Flush if necessary.
262 // Callback for asynchronous completion of Flush.
263 void OnFlushComplete(int32_t result);
265 // Callback for manual scheduling of paints when there is no flush callback
267 void OnManualCallbackComplete(int32_t);
271 // Non-owning pointer. See the constructor.
274 bool is_always_opaque_;
276 CompletionCallbackFactory<PaintManager> callback_factory_;
278 // This graphics device will be is_null() if no graphics has been manually
280 Graphics2D graphics_;
282 PaintAggregator aggregator_;
284 // See comment for EnsureCallbackPending for more on how these work.
285 bool manual_callback_pending_;
288 // When we get a resize, we don't bind right away (see SetSize). The
289 // has_pending_resize_ tells us that we need to do a resize for the next
290 // paint operation. When true, the new size is in pending_size_.
291 bool has_pending_resize_;
297 #endif // PPAPI_UTILITY_GRAPHICS_PAINT_MANAGER_H_