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

Unified Diff: webkit/glue/plugins/pepper_device_context_2d.cc

Issue 2712002: First pass at implementing real Flush callbacks. This does not currently... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/glue/plugins/pepper_device_context_2d.h ('k') | webkit/glue/plugins/pepper_plugin_instance.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/glue/plugins/pepper_device_context_2d.cc
===================================================================
--- webkit/glue/plugins/pepper_device_context_2d.cc (revision 49266)
+++ webkit/glue/plugins/pepper_device_context_2d.cc (working copy)
@@ -4,7 +4,11 @@
#include "webkit/glue/plugins/pepper_device_context_2d.h"
+#include <iterator>
+
#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "skia/ext/platform_canvas.h"
@@ -14,6 +18,7 @@
#include "third_party/ppapi/c/ppb_device_context_2d.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "webkit/glue/plugins/pepper_image_data.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
#include "webkit/glue/plugins/pepper_plugin_module.h"
#include "webkit/glue/plugins/pepper_resource_tracker.h"
@@ -70,6 +75,12 @@
return context->GetResource();
}
+bool IsDeviceContext2D(PP_Resource resource) {
+ scoped_refptr<DeviceContext2D> context(
+ ResourceTracker::Get()->GetAsDeviceContext2D(resource));
+ return !!context.get();
+}
+
bool Describe(PP_Resource device_context,
int32_t* width, int32_t* height, bool* is_always_opaque) {
scoped_refptr<DeviceContext2D> context(
@@ -120,6 +131,7 @@
const PPB_DeviceContext2D ppb_devicecontext2d = {
&Create,
+ &IsDeviceContext2D,
&Describe,
&PaintImageData,
&Scroll,
@@ -159,9 +171,23 @@
scoped_refptr<ImageData> replace_image;
};
-DeviceContext2D::DeviceContext2D(PluginModule* module) : Resource(module) {
+DeviceContext2D::FlushCallbackData::FlushCallbackData(
+ PPB_DeviceContext2D_FlushCallback c,
+ void* d)
+ : callback_(c),
+ callback_data_(d) {
}
+void DeviceContext2D::FlushCallbackData::Execute(PP_Resource device_context) {
+ callback_(device_context, callback_data_);
+}
+
+DeviceContext2D::DeviceContext2D(PluginModule* module)
+ : Resource(module),
+ bound_instance_(NULL),
+ flushed_any_data_(false) {
+}
+
DeviceContext2D::~DeviceContext2D() {
}
@@ -266,42 +292,57 @@
bool DeviceContext2D::Flush(PPB_DeviceContext2D_FlushCallback callback,
void* callback_data) {
+ // 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];
+ gfx::Rect op_rect;
switch (operation.type) {
case QueuedOperation::PAINT:
ExecutePaintImageData(operation.paint_image.get(),
operation.paint_x, operation.paint_y,
- operation.paint_src_rect);
+ operation.paint_src_rect,
+ &op_rect);
break;
case QueuedOperation::SCROLL:
ExecuteScroll(operation.scroll_clip_rect,
- operation.scroll_dx, operation.scroll_dy);
+ operation.scroll_dx, operation.scroll_dy,
+ &op_rect);
break;
case QueuedOperation::REPLACE:
- ExecuteReplaceContents(operation.replace_image.get());
+ ExecuteReplaceContents(operation.replace_image.get(), &op_rect);
break;
}
+ changed_rect = changed_rect.Union(op_rect);
}
queued_operations_.clear();
- // TODO(brettw) implement invalidate and callbacks!
+ flushed_any_data_ = true;
- // Cause the updated part of the screen to be repainted. This will happen
- // asynchronously.
- /*
- gfx::Rect dest_gfx_rect(src_rect->left, src_rect->top,
- src_rect->right - src_rect->left,
- src_rect->bottom - src_rect->top);
+ // We need the rect to be in terms of the current clip rect of the plugin
+ // since that's what will actually be painted. If we issue an invalidate
+ // for a clipped-out region, WebKit will do nothing and we won't get any
+ // ViewInitiatedPaint/ViewFlushedPaint calls, leaving our callback stranded.
+ gfx::Rect visible_changed_rect;
+ if (bound_instance_ && !changed_rect.IsEmpty())
+ visible_changed_rect = bound_instance_->clip().Intersect(changed_rect);
- plugin_delegate_->instance()->webplugin()->InvalidateRect(dest_gfx_rect);
-
- // Save the callback to execute later. See |unpainted_flush_callbacks_| in
- // the header file.
- if (callback) {
- unpainted_flush_callbacks_.push_back(
- FlushCallbackData(callback, id, context, user_data));
+ if (bound_instance_ && !visible_changed_rect.IsEmpty()) {
+ unpainted_flush_callbacks_.push_back(FlushCallbackData(callback,
+ callback_data));
+ bound_instance_->InvalidateRect(visible_changed_rect);
+ } else {
+ // There's nothing visible to invalidate so just schedule the callback to
+ // execute in the next round of the message loop.
+ ScheduleOffscreenCallback(
+ FlushCallbackData(callback, callback_data));
}
-*/
return true;
}
@@ -345,6 +386,38 @@
return true;
}
+bool DeviceContext2D::BindToInstance(PluginInstance* new_instance) {
+ if (bound_instance_ == new_instance)
+ return true; // Rebinding the same device, nothing to do.
+ if (bound_instance_ && new_instance)
+ return false; // Can't change a bound device.
+
+ if (!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();
+ } 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
+ // backing store, bind it, and then execute their normal painting and
+ // update loop. If binding a device always invalidated, it would mean we
+ // would get one paint for the bind, and one for the first time the plugin
+ // actually painted something. By not bothering to schedule an invalidate
+ // when an empty device is initially bound, we can save an extra paint for
+ // many plugins during the critical page initialization phase.
+ new_instance->InvalidateRect(gfx::Rect());
+ }
+
+ bound_instance_ = new_instance;
+ return true;
+}
+
void DeviceContext2D::Paint(WebKit::WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const gfx::Rect& paint_rect) {
@@ -389,27 +462,47 @@
#endif
}
+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();
+}
+
+void DeviceContext2D::ViewFlushedPaint() {
+ // Notify all "painted" callbacks. See |unpainted_flush_callbacks_| 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();
+}
+
void DeviceContext2D::ExecutePaintImageData(ImageData* image,
int x, int y,
- const gfx::Rect& src_rect) {
+ const gfx::Rect& src_rect,
+ gfx::Rect* invalidated_rect) {
+ // Ensure the source image is mapped to read from it.
+ ImageDataAutoMapper auto_mapper(image);
+ if (!auto_mapper.is_valid())
+ return;
+
// Portion within the source image to cut out.
SkIRect src_irect = { src_rect.x(), src_rect.y(),
src_rect.right(), src_rect.bottom() };
// Location within the backing store to copy to.
- SkRect dest_rect = { SkIntToScalar(x + src_rect.x()),
- SkIntToScalar(y + src_rect.y()),
- SkIntToScalar(x + src_rect.right()),
- SkIntToScalar(y + src_rect.bottom()) };
+ *invalidated_rect = src_rect;
+ invalidated_rect->Offset(x, y);
+ SkRect dest_rect = { SkIntToScalar(invalidated_rect->x()),
+ SkIntToScalar(invalidated_rect->y()),
+ SkIntToScalar(invalidated_rect->right()),
+ SkIntToScalar(invalidated_rect->bottom()) };
// We're guaranteed to have a mapped canvas since we mapped it in Init().
skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas();
- // Ensure the source image is mapped to read from it.
- ImageDataAutoMapper auto_mapper(image);
- if (!auto_mapper.is_valid())
- return;
-
// We want to replace the contents of the bitmap rather than blend.
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
@@ -417,12 +510,29 @@
&src_irect, dest_rect, &paint);
}
-void DeviceContext2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy) {
+void DeviceContext2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
+ gfx::Rect* invalidated_rect) {
// FIXME(brettw)
}
-void DeviceContext2D::ExecuteReplaceContents(ImageData* image) {
+void DeviceContext2D::ExecuteReplaceContents(ImageData* image,
+ gfx::Rect* invalidated_rect) {
image_data_->Swap(image);
+ *invalidated_rect = gfx::Rect(0, 0,
+ image_data_->width(), image_data_->height());
}
+void DeviceContext2D::ScheduleOffscreenCallback(
+ const FlushCallbackData& callback) {
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &DeviceContext2D::ExecuteOffscreenCallback,
+ callback));
+}
+
+void DeviceContext2D::ExecuteOffscreenCallback(FlushCallbackData data) {
+ data.Execute(GetResource());
+}
+
} // namespace pepper
« no previous file with comments | « webkit/glue/plugins/pepper_device_context_2d.h ('k') | webkit/glue/plugins/pepper_plugin_instance.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698