diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-16 04:25:01 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-16 04:25:01 +0000 |
commit | 53900d507cd50344c2e73bb988671044f1787911 (patch) | |
tree | 7cd58934003dc610f544f8e682ac8c6040715f65 /webkit/glue | |
parent | 047e07212c7da949be3107a70e3fe9ecb160d818 (diff) | |
download | chromium_src-53900d507cd50344c2e73bb988671044f1787911.zip chromium_src-53900d507cd50344c2e73bb988671044f1787911.tar.gz chromium_src-53900d507cd50344c2e73bb988671044f1787911.tar.bz2 |
Implement more of Flush properly. This adds support for waiting on the message
loop so we can now enforce that there is only one pending Flush at a time.
Also removes the ability to have multiple flushes pending at the same time.
TEST=covered by ppapi unit test
BUG=none
Review URL: http://codereview.chromium.org/2862002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49899 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-rw-r--r-- | webkit/glue/plugins/pepper_device_context_2d.cc | 68 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_device_context_2d.h | 31 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_delegate.h | 10 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_instance.cc | 3 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_plugin_module.cc | 16 |
5 files changed, 96 insertions, 32 deletions
diff --git a/webkit/glue/plugins/pepper_device_context_2d.cc b/webkit/glue/plugins/pepper_device_context_2d.cc index e549f0e..9eae9dc 100644 --- a/webkit/glue/plugins/pepper_device_context_2d.cc +++ b/webkit/glue/plugins/pepper_device_context_2d.cc @@ -185,7 +185,8 @@ void DeviceContext2D::FlushCallbackData::Execute(PP_Resource device_context) { 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::ReplaceContents(PP_Resource image) { 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 @@ bool DeviceContext2D::Flush(PPB_DeviceContext2D_FlushCallback callback, 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 @@ bool DeviceContext2D::BindToInstance(PluginInstance* new_instance) { // 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::Paint(WebKit::WebCanvas* canvas, } 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::ExecutePaintImageData(ImageData* image, 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::ExecuteReplaceContents(ImageData* image, 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::ScheduleOffscreenCallback( } 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 diff --git a/webkit/glue/plugins/pepper_device_context_2d.h b/webkit/glue/plugins/pepper_device_context_2d.h index bb488ab..2d5bbb3 100644 --- a/webkit/glue/plugins/pepper_device_context_2d.h +++ b/webkit/glue/plugins/pepper_device_context_2d.h @@ -8,6 +8,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/scoped_ptr.h" #include "third_party/ppapi/c/ppb_device_context_2d.h" #include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h" #include "webkit/glue/plugins/pepper_resource.h" @@ -79,7 +80,6 @@ class DeviceContext2D : public Resource { PPB_DeviceContext2D_FlushCallback callback_; void* callback_data_; }; - typedef std::vector<FlushCallbackData> FlushCallbackVector; // Called internally to execute the different queued commands. The // parameters to these functions will have already been validated. The last @@ -103,6 +103,9 @@ class DeviceContext2D : public Resource { // issues the offscreen callbacks. void ExecuteOffscreenCallback(FlushCallbackData data); + // Returns true if there is any type of flush callback pending. + bool HasPendingFlush() const; + scoped_refptr<ImageData> image_data_; // Non-owning pointer to the plugin instance this device context is currently @@ -119,20 +122,32 @@ class DeviceContext2D : public Resource { // This is initially false and is set to true at the first Flush() call. bool flushed_any_data_; - // The plugin may be constantly giving us paint messages. "Unpainted" ones - // are paint requests which have never been painted. These could have been - // done while the RenderView was already waiting for an ACK from a previous - // paint, so won't generate a new one yet. + // The plugin can give us one "Flush" at a time. This flush will either be in + // the "unpainted" state (in which case unpainted_flush_callback_ will be + // non-NULL) or painted, in which case painted_flush_callback_ will be + // non-NULL). There can also be an offscreen callback which is handled + // separately (see offscreen_callback_pending_). Only one of these three + // things may be set at a time to enforce the "only one pending flush at a + // time" constraint. + // + // "Unpainted" ones are flush requests which have never been painted. These + // could have been done while the RenderView was already waiting for an ACK + // from a previous paint, so won't generate a new one yet. // - // "Painted" ones are those paints that have been painted by RenderView, but + // "Painted" ones are those flushes that have been painted by RenderView, but // for which the ACK from the browser has not yet been received. // // When we get updates from a plugin with a callback, it is first added to // the unpainted callbacks. When the renderer has initiated a paint, we'll // move it to the painted callbacks list. When the renderer receives a flush, // we'll execute the callback and remove it from the list. - FlushCallbackVector unpainted_flush_callbacks_; - FlushCallbackVector painted_flush_callbacks_; + scoped_ptr<FlushCallbackData> unpainted_flush_callback_; + scoped_ptr<FlushCallbackData> painted_flush_callback_; + + // When doing offscreen flushes, we issue a task that issues the callback + // later. This is set when one of those tasks is pending so that we can + // enforce the "only one pending flush at a time" constraint in the API. + bool offscreen_flush_pending_; DISALLOW_COPY_AND_ASSIGN(DeviceContext2D); }; diff --git a/webkit/glue/plugins/pepper_plugin_delegate.h b/webkit/glue/plugins/pepper_plugin_delegate.h index 9515b17..c00a9b3 100644 --- a/webkit/glue/plugins/pepper_plugin_delegate.h +++ b/webkit/glue/plugins/pepper_plugin_delegate.h @@ -13,6 +13,8 @@ class PlatformCanvas; namespace pepper { +class PluginInstance; + // Virtual interface that the browser implements to implement features for // Pepper plugins. class PluginDelegate { @@ -32,6 +34,14 @@ class PluginDelegate { virtual intptr_t GetSharedMemoryHandle() const = 0; }; + // Indicates that the given instance has been created. + virtual void InstanceCreated(pepper::PluginInstance* instance) = 0; + + // Indicates that the given instance is being destroyed. This is called from + // the destructor, so it's important that the instance is not dereferenced + // from this call. + virtual void InstanceDeleted(pepper::PluginInstance* instance) = 0; + // The caller will own the pointer returned from this. virtual PlatformImage2D* CreateImage2D(int width, int height) = 0; }; diff --git a/webkit/glue/plugins/pepper_plugin_instance.cc b/webkit/glue/plugins/pepper_plugin_instance.cc index a2f83b8..d86fffc 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.cc +++ b/webkit/glue/plugins/pepper_plugin_instance.cc @@ -21,6 +21,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h" #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" #include "webkit/glue/plugins/pepper_device_context_2d.h" +#include "webkit/glue/plugins/pepper_plugin_delegate.h" #include "webkit/glue/plugins/pepper_plugin_module.h" #include "webkit/glue/plugins/pepper_resource_tracker.h" #include "webkit/glue/plugins/pepper_var.h" @@ -146,9 +147,11 @@ PluginInstance::PluginInstance(PluginDelegate* delegate, container_(NULL) { DCHECK(delegate); module_->InstanceCreated(this); + delegate_->InstanceCreated(this); } PluginInstance::~PluginInstance() { + delegate_->InstanceDeleted(this); module_->InstanceDeleted(this); } diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc index 99448f2..2eb63a1 100644 --- a/webkit/glue/plugins/pepper_plugin_module.cc +++ b/webkit/glue/plugins/pepper_plugin_module.cc @@ -7,6 +7,7 @@ #include <set> #include "base/command_line.h" +#include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/logging.h" #include "base/scoped_ptr.h" @@ -110,8 +111,21 @@ bool ReadImageData(PP_Resource device_context_2d, return context->ReadImageData(image, x, y); } +void RunMessageLoop() { + bool old_state = MessageLoop::current()->NestableTasksAllowed(); + MessageLoop::current()->SetNestableTasksAllowed(true); + MessageLoop::current()->Run(); + MessageLoop::current()->SetNestableTasksAllowed(old_state); +} + +void QuitMessageLoop() { + MessageLoop::current()->Quit(); +} + const PPB_Testing testing_interface = { - &ReadImageData + &ReadImageData, + &RunMessageLoop, + &QuitMessageLoop, }; // GetInterface ---------------------------------------------------------------- |