Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: ppapi/cpp/paint_manager.cc

Issue 7215030: Don't copy the Graphics2D when binding a new one. This brings the (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/cpp/paint_manager.h ('k') | ppapi/examples/2d/paint_manager_example.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/cpp/paint_manager.h" 5 #include "ppapi/cpp/paint_manager.h"
6 6
7 #include "ppapi/c/pp_errors.h" 7 #include "ppapi/c/pp_errors.h"
8 #include "ppapi/cpp/instance.h" 8 #include "ppapi/cpp/instance.h"
9 #include "ppapi/cpp/logging.h" 9 #include "ppapi/cpp/logging.h"
10 #include "ppapi/cpp/module.h" 10 #include "ppapi/cpp/module.h"
11 11
12 namespace pp { 12 namespace pp {
13 13
14 PaintManager::PaintManager() 14 PaintManager::PaintManager()
15 : instance_(NULL), 15 : instance_(NULL),
16 client_(NULL), 16 client_(NULL),
17 is_always_opaque_(false), 17 is_always_opaque_(false),
18 callback_factory_(NULL), 18 callback_factory_(NULL),
19 manual_callback_pending_(false), 19 manual_callback_pending_(false),
20 flush_pending_(false) { 20 flush_pending_(false),
21 has_pending_resize_(false) {
21 // Set the callback object outside of the initializer list to avoid a 22 // Set the callback object outside of the initializer list to avoid a
22 // compiler warning about using "this" in an initializer list. 23 // compiler warning about using "this" in an initializer list.
23 callback_factory_.Initialize(this); 24 callback_factory_.Initialize(this);
24 } 25 }
25 26
26 PaintManager::PaintManager(Instance* instance, 27 PaintManager::PaintManager(Instance* instance,
27 Client* client, 28 Client* client,
28 bool is_always_opaque) 29 bool is_always_opaque)
29 : instance_(instance), 30 : instance_(instance),
30 client_(client), 31 client_(client),
31 is_always_opaque_(is_always_opaque), 32 is_always_opaque_(is_always_opaque),
32 callback_factory_(NULL), 33 callback_factory_(NULL),
33 manual_callback_pending_(false), 34 manual_callback_pending_(false),
34 flush_pending_(false) { 35 flush_pending_(false),
36 has_pending_resize_(false) {
35 // Set the callback object outside of the initializer list to avoid a 37 // Set the callback object outside of the initializer list to avoid a
36 // compiler warning about using "this" in an initializer list. 38 // compiler warning about using "this" in an initializer list.
37 callback_factory_.Initialize(this); 39 callback_factory_.Initialize(this);
38 40
39 // You can not use a NULL client pointer. 41 // You can not use a NULL client pointer.
40 PP_DCHECK(client); 42 PP_DCHECK(client);
41 } 43 }
42 44
43 PaintManager::~PaintManager() { 45 PaintManager::~PaintManager() {
44 } 46 }
45 47
46 void PaintManager::Initialize(Instance* instance, 48 void PaintManager::Initialize(Instance* instance,
47 Client* client, 49 Client* client,
48 bool is_always_opaque) { 50 bool is_always_opaque) {
49 PP_DCHECK(!instance_ && !client_); // Can't initialize twice. 51 PP_DCHECK(!instance_ && !client_); // Can't initialize twice.
50 instance_ = instance; 52 instance_ = instance;
51 client_ = client; 53 client_ = client;
52 is_always_opaque_ = is_always_opaque; 54 is_always_opaque_ = is_always_opaque;
53 } 55 }
54 56
55 void PaintManager::SetSize(const Size& new_size) { 57 void PaintManager::SetSize(const Size& new_size) {
56 if (new_size == graphics_.size()) 58 if (GetEffectiveSize() == new_size)
57 return; 59 return;
58 60
59 graphics_ = Graphics2D(instance_, new_size, is_always_opaque_); 61 has_pending_resize_ = true;
60 if (graphics_.is_null()) 62 pending_size_ = new_size;
61 return;
62 instance_->BindGraphics(graphics_);
63
64 manual_callback_pending_ = false;
65 flush_pending_ = false;
66 callback_factory_.CancelAll();
67 63
68 Invalidate(); 64 Invalidate();
69 } 65 }
70 66
71 void PaintManager::Invalidate() { 67 void PaintManager::Invalidate() {
72 // You must call SetDevice before using. 68 // You must call SetSize before using.
73 PP_DCHECK(!graphics_.is_null()); 69 PP_DCHECK(!graphics_.is_null() || has_pending_resize_);
74 70
75 EnsureCallbackPending(); 71 EnsureCallbackPending();
76 aggregator_.InvalidateRect(Rect(graphics_.size())); 72 aggregator_.InvalidateRect(Rect(GetEffectiveSize()));
77 } 73 }
78 74
79 void PaintManager::InvalidateRect(const Rect& rect) { 75 void PaintManager::InvalidateRect(const Rect& rect) {
80 // You must call SetDevice before using. 76 // You must call SetSize before using.
81 PP_DCHECK(!graphics_.is_null()); 77 PP_DCHECK(!graphics_.is_null() || has_pending_resize_);
82 78
83 // Clip the rect to the device area. 79 // Clip the rect to the device area.
84 Rect clipped_rect = rect.Intersect(Rect(graphics_.size())); 80 Rect clipped_rect = rect.Intersect(Rect(GetEffectiveSize()));
85 if (clipped_rect.IsEmpty()) 81 if (clipped_rect.IsEmpty())
86 return; // Nothing to do. 82 return; // Nothing to do.
87 83
88 EnsureCallbackPending(); 84 EnsureCallbackPending();
89 aggregator_.InvalidateRect(clipped_rect); 85 aggregator_.InvalidateRect(clipped_rect);
90 } 86 }
91 87
92 void PaintManager::ScrollRect(const Rect& clip_rect, const Point& amount) { 88 void PaintManager::ScrollRect(const Rect& clip_rect, const Point& amount) {
93 // You must call SetDevice before using. 89 // You must call SetSize before using.
94 PP_DCHECK(!graphics_.is_null()); 90 PP_DCHECK(!graphics_.is_null() || has_pending_resize_);
95 91
96 EnsureCallbackPending(); 92 EnsureCallbackPending();
97 aggregator_.ScrollRect(clip_rect, amount); 93 aggregator_.ScrollRect(clip_rect, amount);
98 } 94 }
99 95
96 Size PaintManager::GetEffectiveSize() const {
97 return has_pending_resize_ ? pending_size_ : graphics_.size();
98 }
99
100 void PaintManager::EnsureCallbackPending() { 100 void PaintManager::EnsureCallbackPending() {
101 // The best way for us to do the next update is to get a notification that 101 // The best way for us to do the next update is to get a notification that
102 // a previous one has completed. So if we're already waiting for one, we 102 // a previous one has completed. So if we're already waiting for one, we
103 // don't have to do anything differently now. 103 // don't have to do anything differently now.
104 if (flush_pending_) 104 if (flush_pending_)
105 return; 105 return;
106 106
107 // If no flush is pending, we need to do a manual call to get back to the 107 // If no flush is pending, we need to do a manual call to get back to the
108 // main thread. We may have one already pending, or we may need to schedule. 108 // main thread. We may have one already pending, or we may need to schedule.
109 if (manual_callback_pending_) 109 if (manual_callback_pending_)
110 return; 110 return;
111 111
112 Module::Get()->core()->CallOnMainThread( 112 Module::Get()->core()->CallOnMainThread(
113 0, 113 0,
114 callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete), 114 callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete),
115 0); 115 0);
116 manual_callback_pending_ = true; 116 manual_callback_pending_ = true;
117 } 117 }
118 118
119 void PaintManager::DoPaint() { 119 void PaintManager::DoPaint() {
120 PP_DCHECK(aggregator_.HasPendingUpdate()); 120 PP_DCHECK(aggregator_.HasPendingUpdate());
121 121
122 // Make a copy of the pending update and clear the pending update flag before 122 // Make a copy of the pending update and clear the pending update flag before
123 // actually painting. A plugin might cause invalidates in its Paint code, and 123 // actually painting. A plugin might cause invalidates in its Paint code, and
124 // we want those to go to the *next* paint. 124 // we want those to go to the *next* paint.
125 PaintAggregator::PaintUpdate update = aggregator_.GetPendingUpdate(); 125 PaintAggregator::PaintUpdate update = aggregator_.GetPendingUpdate();
126 aggregator_.ClearPendingUpdate(); 126 aggregator_.ClearPendingUpdate();
127 127
128 // Apply any pending resize. Setting the graphics to this class must happen
129 // before asking the plugin to paint in case it requests the Graphics2D during
130 // painting. However, the bind must not happen until afterward since we don't
131 // want to have an unpainted device bound. The needs_binding flag tells us
132 // whether to do this later.
133 bool needs_binding = false;
134 if (has_pending_resize_) {
135 graphics_ = Graphics2D(instance_, pending_size_, is_always_opaque_);
136 needs_binding = true;
137
138 // Since we're binding a new one, all of the callbacks have been canceled.
139 manual_callback_pending_ = false;
140 flush_pending_ = false;
141 callback_factory_.CancelAll();
142
143 // This must be cleared before calling into the plugin since it may do
144 // additional invalidation or sizing operations.
145 has_pending_resize_ = false;
146 pending_size_ = Size();
147 }
148
128 // Apply any scroll before asking the client to paint. 149 // Apply any scroll before asking the client to paint.
129 if (update.has_scroll) 150 if (update.has_scroll)
130 graphics_.Scroll(update.scroll_rect, update.scroll_delta); 151 graphics_.Scroll(update.scroll_rect, update.scroll_delta);
131 152
132 if (!client_->OnPaint(graphics_, update.paint_rects, update.paint_bounds)) 153 if (client_->OnPaint(graphics_, update.paint_rects, update.paint_bounds)) {
133 return; // Nothing was painted, don't schedule a flush. 154 // Something was painted, schedule a flush.
155 int32_t result = graphics_.Flush(
156 callback_factory_.NewCallback(&PaintManager::OnFlushComplete));
134 157
135 int32_t result = graphics_.Flush( 158 // If you trigger this assertion, then your plugin has called Flush()
136 callback_factory_.NewCallback(&PaintManager::OnFlushComplete)); 159 // manually. When using the PaintManager, you should not call Flush, it
160 // will handle that for you because it needs to know when it can do the
161 // next paint by implementing the flush callback.
162 //
163 // Another possible cause of this assertion is re-using devices. If you
164 // use one device, swap it with another, then swap it back, we won't know
165 // that we've already scheduled a Flush on the first device. It's best to
166 // not re-use devices in this way.
167 PP_DCHECK(result != PP_ERROR_INPROGRESS);
137 168
138 // If you trigger this assertion, then your plugin has called Flush() 169 if (result == PP_OK_COMPLETIONPENDING) {
139 // manually. When using the PaintManager, you should not call Flush, it will 170 flush_pending_ = true;
140 // handle that for you because it needs to know when it can do the next paint 171 } else {
141 // by implementing the flush callback. 172 PP_DCHECK(result == PP_OK); // Catch all other errors in debug mode.
142 // 173 }
143 // Another possible cause of this assertion is re-using devices. If you 174 }
144 // use one device, swap it with another, then swap it back, we won't know
145 // that we've already scheduled a Flush on the first device. It's best to not
146 // re-use devices in this way.
147 PP_DCHECK(result != PP_ERROR_INPROGRESS);
148 175
149 if (result == PP_OK_COMPLETIONPENDING) { 176 if (needs_binding)
150 flush_pending_ = true; 177 instance_->BindGraphics(graphics_);
151 } else {
152 PP_DCHECK(result == PP_OK); // Catch all other errors in debug mode.
153 }
154 } 178 }
155 179
156 void PaintManager::OnFlushComplete(int32_t) { 180 void PaintManager::OnFlushComplete(int32_t) {
157 PP_DCHECK(flush_pending_); 181 PP_DCHECK(flush_pending_);
158 flush_pending_ = false; 182 flush_pending_ = false;
159 183
160 // If more paints were enqueued while we were waiting for the flush to 184 // If more paints were enqueued while we were waiting for the flush to
161 // complete, execute them now. 185 // complete, execute them now.
162 if (aggregator_.HasPendingUpdate()) 186 if (aggregator_.HasPendingUpdate())
163 DoPaint(); 187 DoPaint();
164 } 188 }
165 189
166 void PaintManager::OnManualCallbackComplete(int32_t) { 190 void PaintManager::OnManualCallbackComplete(int32_t) {
167 PP_DCHECK(manual_callback_pending_); 191 PP_DCHECK(manual_callback_pending_);
168 manual_callback_pending_ = false; 192 manual_callback_pending_ = false;
169 193
170 // Just because we have a manual callback doesn't mean there are actually any 194 // Just because we have a manual callback doesn't mean there are actually any
171 // invalid regions. Even though we only schedule this callback when something 195 // invalid regions. Even though we only schedule this callback when something
172 // is pending, a Flush callback could have come in before this callback was 196 // is pending, a Flush callback could have come in before this callback was
173 // executed and that could have cleared the queue. 197 // executed and that could have cleared the queue.
174 if (aggregator_.HasPendingUpdate() && !flush_pending_) 198 if (aggregator_.HasPendingUpdate() && !flush_pending_)
175 DoPaint(); 199 DoPaint();
176 } 200 }
177 201
202
178 } // namespace pp 203 } // namespace pp
OLDNEW
« no previous file with comments | « ppapi/cpp/paint_manager.h ('k') | ppapi/examples/2d/paint_manager_example.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698