| Index: webkit/glue/plugins/pepper_device_context_2d.cc
|
| ===================================================================
|
| --- webkit/glue/plugins/pepper_device_context_2d.cc (revision 49795)
|
| +++ webkit/glue/plugins/pepper_device_context_2d.cc (working copy)
|
| @@ -185,7 +185,8 @@
|
| DeviceContext2D::DeviceContext2D(PluginModule* module)
|
| : Resource(module),
|
| bound_instance_(NULL),
|
| - flushed_any_data_(false) {
|
| + flushed_any_data_(false),
|
| + offscreen_flush_pending_(false) {
|
| }
|
|
|
| DeviceContext2D::~DeviceContext2D() {
|
| @@ -292,14 +293,15 @@
|
|
|
| bool DeviceContext2D::Flush(PPB_DeviceContext2D_FlushCallback callback,
|
| void* callback_data) {
|
| + // Don't allow more than one pending flush at a time.
|
| + if (HasPendingFlush())
|
| + return false;
|
| +
|
| // TODO(brettw) check that the current thread is not the main one and
|
| // implement blocking flushes in this case.
|
| if (!callback)
|
| return false;
|
|
|
| - if (queued_operations_.empty())
|
| - return true; // Nothing to do.
|
| -
|
| gfx::Rect changed_rect;
|
| for (size_t i = 0; i < queued_operations_.size(); i++) {
|
| QueuedOperation& operation = queued_operations_[i];
|
| @@ -334,8 +336,8 @@
|
| visible_changed_rect = bound_instance_->clip().Intersect(changed_rect);
|
|
|
| if (bound_instance_ && !visible_changed_rect.IsEmpty()) {
|
| - unpainted_flush_callbacks_.push_back(FlushCallbackData(callback,
|
| - callback_data));
|
| + unpainted_flush_callback_.reset(new FlushCallbackData(callback,
|
| + callback_data));
|
| bound_instance_->InvalidateRect(visible_changed_rect);
|
| } else {
|
| // There's nothing visible to invalidate so just schedule the callback to
|
| @@ -396,12 +398,14 @@
|
| // When the device is detached, we'll not get any more paint callbacks so
|
| // we need to clear the list, but we still want to issue any pending
|
| // callbacks to the plugin.
|
| - for (size_t i = 0; i < unpainted_flush_callbacks_.size(); i++)
|
| - ScheduleOffscreenCallback(unpainted_flush_callbacks_[i]);
|
| - for (size_t i = 0; i < painted_flush_callbacks_.size(); i++)
|
| - ScheduleOffscreenCallback(painted_flush_callbacks_[i]);
|
| - unpainted_flush_callbacks_.clear();
|
| - painted_flush_callbacks_.clear();
|
| + if (unpainted_flush_callback_.get()) {
|
| + ScheduleOffscreenCallback(*unpainted_flush_callback_.get());
|
| + unpainted_flush_callback_.reset();
|
| + }
|
| + if (painted_flush_callback_.get()) {
|
| + ScheduleOffscreenCallback(*painted_flush_callback_.get());
|
| + painted_flush_callback_.reset();
|
| + }
|
| } else if (flushed_any_data_) {
|
| // Only schedule a paint if this backing store has had any data flushed to
|
| // it. This is an optimization. A "normal" plugin will first allocated a
|
| @@ -463,20 +467,25 @@
|
| }
|
|
|
| void DeviceContext2D::ViewInitiatedPaint() {
|
| - // Move all "unpainted" callbacks to the painted state. See
|
| - // |unpainted_flush_callbacks_| in the header for more.
|
| - std::copy(unpainted_flush_callbacks_.begin(),
|
| - unpainted_flush_callbacks_.end(),
|
| - std::back_inserter(painted_flush_callbacks_));
|
| - unpainted_flush_callbacks_.clear();
|
| + // Move any "unpainted" callback to the painted state. See
|
| + // |unpainted_flush_callback_| in the header for more.
|
| + if (unpainted_flush_callback_.get()) {
|
| + DCHECK(!painted_flush_callback_.get());
|
| + painted_flush_callback_.swap(unpainted_flush_callback_);
|
| + }
|
| }
|
|
|
| void DeviceContext2D::ViewFlushedPaint() {
|
| - // Notify all "painted" callbacks. See |unpainted_flush_callbacks_| in the
|
| + // Notify any "painted" callback. See |unpainted_flush_callback_| in the
|
| // header for more.
|
| - for (size_t i = 0; i < painted_flush_callbacks_.size(); i++)
|
| - painted_flush_callbacks_[i].Execute(GetResource());
|
| - painted_flush_callbacks_.clear();
|
| + if (painted_flush_callback_.get()) {
|
| + // We must clear this variable before issuing the callback. It will be
|
| + // common for the plugin to issue another invalidate in response to a flush
|
| + // callback, and we don't want to think that a callback is already pending.
|
| + scoped_ptr<FlushCallbackData> callback;
|
| + callback.swap(painted_flush_callback_);
|
| + callback->Execute(GetResource());
|
| + }
|
| }
|
|
|
| void DeviceContext2D::ExecutePaintImageData(ImageData* image,
|
| @@ -512,7 +521,7 @@
|
|
|
| void DeviceContext2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
|
| gfx::Rect* invalidated_rect) {
|
| - // FIXME(brettw)
|
| + // TODO(brettw): implement this.
|
| }
|
|
|
| void DeviceContext2D::ExecuteReplaceContents(ImageData* image,
|
| @@ -524,6 +533,8 @@
|
|
|
| void DeviceContext2D::ScheduleOffscreenCallback(
|
| const FlushCallbackData& callback) {
|
| + DCHECK(!HasPendingFlush());
|
| + offscreen_flush_pending_ = true;
|
| MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| NewRunnableMethod(this,
|
| @@ -532,7 +543,18 @@
|
| }
|
|
|
| void DeviceContext2D::ExecuteOffscreenCallback(FlushCallbackData data) {
|
| + DCHECK(offscreen_flush_pending_);
|
| +
|
| + // We must clear this flag before issuing the callback. It will be
|
| + // common for the plugin to issue another invalidate in response to a flush
|
| + // callback, and we don't want to think that a callback is already pending.
|
| + offscreen_flush_pending_ = false;
|
| data.Execute(GetResource());
|
| }
|
|
|
| +bool DeviceContext2D::HasPendingFlush() const {
|
| + return unpainted_flush_callback_.get() || painted_flush_callback_.get() ||
|
| + offscreen_flush_pending_;
|
| +}
|
| +
|
| } // namespace pepper
|
|
|