OLD | NEW |
| (Empty) |
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_CPP_PAINT_MANAGER_H_ | |
6 #define PPAPI_CPP_PAINT_MANAGER_H_ | |
7 | |
8 #include <vector> | |
9 | |
10 #include "ppapi/cpp/completion_callback.h" | |
11 #include "ppapi/cpp/graphics_2d.h" | |
12 #include "ppapi/cpp/paint_aggregator.h" | |
13 | |
14 /// @file | |
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. | |
17 | |
18 namespace pp { | |
19 | |
20 class Graphics2D; | |
21 class Instance; | |
22 class Point; | |
23 class Rect; | |
24 | |
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. | |
29 /// | |
30 /// This class is basically a <code>PaintAggregator</code> that groups updates, | |
31 /// plus management of callbacks for scheduling paints. | |
32 /// | |
33 /// <strong>Example:</strong> | |
34 /// | |
35 /// <code> | |
36 /// | |
37 /// class MyClass : public pp::Instance, public PaintManager::Client { | |
38 /// public: | |
39 /// MyClass() { | |
40 /// paint_manager_.Initialize(this, this, false); | |
41 /// } | |
42 /// | |
43 /// void ViewChanged(const pp::Rect& position, const pp::Rect& clip) { | |
44 /// paint_manager_.SetSize(position.size()); | |
45 /// } | |
46 /// | |
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); | |
51 /// } | |
52 /// | |
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. | |
57 /// | |
58 /// // Then we would either repaint the area returned by GetPaintBounds or | |
59 /// // iterate through all the paint_rects. | |
60 /// | |
61 /// // The caller will call Flush() for us, so don't do that here. | |
62 /// return true; | |
63 /// } | |
64 /// | |
65 /// private: | |
66 /// pp::PaintManager paint_manager_; | |
67 /// }; | |
68 /// </code> | |
69 class PaintManager { | |
70 public: | |
71 class Client { | |
72 public: | |
73 /// OnPaint() paints the given invalid area of the instance to the given | |
74 /// graphics device. Returns true if anything was painted. | |
75 /// | |
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). | |
81 /// | |
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. | |
85 /// | |
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." | |
92 /// | |
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. | |
96 /// | |
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; | |
101 | |
102 protected: | |
103 // You shouldn't be doing deleting through this interface. | |
104 virtual ~Client() {} | |
105 }; | |
106 | |
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. | |
110 PaintManager(); | |
111 | |
112 /// A constructor to create a new <code>PaintManager</code> with an instance | |
113 /// and client. | |
114 /// | |
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. | |
118 /// | |
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 | |
122 /// paint manager). | |
123 /// | |
124 /// @param client A non-owning pointer and must remain valid (normally the | |
125 /// object implementing the Client interface will own the paint manager). | |
126 /// | |
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 | |
132 /// blending. | |
133 /// | |
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); | |
141 | |
142 /// Destructor. | |
143 ~PaintManager(); | |
144 | |
145 /// Initialize() must be called if you are using the 0-arg constructor. | |
146 /// | |
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 | |
150 /// paint manager). | |
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 | |
158 /// blending. | |
159 /// | |
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); | |
168 | |
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. | |
171 /// | |
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. | |
175 /// | |
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); | |
180 } | |
181 | |
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). | |
189 /// | |
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); | |
193 } | |
194 | |
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 | |
198 /// scheduled. | |
199 /// | |
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). | |
205 /// | |
206 /// @param new_size The new size for the instance. | |
207 void SetSize(const Size& new_size); | |
208 | |
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(). | |
212 /// | |
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_; } | |
216 | |
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(). | |
220 /// | |
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_; } | |
224 | |
225 /// Invalidate() invalidate the entire instance. | |
226 void Invalidate(); | |
227 | |
228 /// InvalidateRect() Invalidate the provided rect. | |
229 /// | |
230 /// @param[in] rect The <code>Rect</code> to be invalidated. | |
231 void InvalidateRect(const Rect& rect); | |
232 | |
233 /// ScrollRect() scrolls the provided <code>clip_rect</code> by the | |
234 /// <code>amount</code> argument. | |
235 /// | |
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); | |
239 | |
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. | |
244 /// | |
245 /// @return The effective size. | |
246 Size GetEffectiveSize() const; | |
247 | |
248 private: | |
249 // Disallow copy and assign (these are unimplemented). | |
250 PaintManager(const PaintManager&); | |
251 PaintManager& operator=(const PaintManager&); | |
252 | |
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(); | |
258 | |
259 // Does the client paint and executes a Flush if necessary. | |
260 void DoPaint(); | |
261 | |
262 // Callback for asynchronous completion of Flush. | |
263 void OnFlushComplete(int32_t); | |
264 | |
265 // Callback for manual scheduling of paints when there is no flush callback | |
266 // pending. | |
267 void OnManualCallbackComplete(int32_t); | |
268 | |
269 Instance* instance_; | |
270 | |
271 // Non-owning pointer. See the constructor. | |
272 Client* client_; | |
273 | |
274 bool is_always_opaque_; | |
275 | |
276 CompletionCallbackFactory<PaintManager> callback_factory_; | |
277 | |
278 // This graphics device will be is_null() if no graphics has been manually | |
279 // set yet. | |
280 Graphics2D graphics_; | |
281 | |
282 PaintAggregator aggregator_; | |
283 | |
284 // See comment for EnsureCallbackPending for more on how these work. | |
285 bool manual_callback_pending_; | |
286 bool flush_pending_; | |
287 | |
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_; | |
292 Size pending_size_; | |
293 }; | |
294 | |
295 } // namespace pp | |
296 | |
297 #endif // PPAPI_CPP_PAINT_MANAGER_H_ | |
OLD | NEW |