summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-14 19:10:48 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-14 19:10:48 +0000
commit95ff077352e9cf1f78b79b2aa86e5675cbafae1d (patch)
tree47f32ccbfcda90df866fb1f5be1bf237f791c16d
parent6c8bece66bb899bd9395a5d23d4442a344e74cc0 (diff)
downloadchromium_src-95ff077352e9cf1f78b79b2aa86e5675cbafae1d.zip
chromium_src-95ff077352e9cf1f78b79b2aa86e5675cbafae1d.tar.gz
chromium_src-95ff077352e9cf1f78b79b2aa86e5675cbafae1d.tar.bz2
Implement new painting API in Chrome. This also makes some minor tweaks and improvements to resource management in the Chrome Pepper layer.
TEST=none BUG=none Review URL: http://codereview.chromium.org/2096002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47294 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--DEPS2
-rw-r--r--webkit/glue/plugins/pepper_device_context_2d.cc303
-rw-r--r--webkit/glue/plugins/pepper_device_context_2d.h29
-rw-r--r--webkit/glue/plugins/pepper_image_data.cc44
-rw-r--r--webkit/glue/plugins/pepper_image_data.h18
-rw-r--r--webkit/glue/plugins/pepper_resource_tracker.cc24
-rw-r--r--webkit/glue/plugins/pepper_resource_tracker.h15
7 files changed, 341 insertions, 94 deletions
diff --git a/DEPS b/DEPS
index 7dfc658..a61edcc 100644
--- a/DEPS
+++ b/DEPS
@@ -143,7 +143,7 @@ deps = {
Var("ffmpeg_revision"),
"src/third_party/ppapi":
- "http://ppapi.googlecode.com/svn/trunk@11",
+ "http://ppapi.googlecode.com/svn/trunk@26",
}
diff --git a/webkit/glue/plugins/pepper_device_context_2d.cc b/webkit/glue/plugins/pepper_device_context_2d.cc
index 964c605..926d194 100644
--- a/webkit/glue/plugins/pepper_device_context_2d.cc
+++ b/webkit/glue/plugins/pepper_device_context_2d.cc
@@ -26,43 +26,129 @@ namespace pepper {
namespace {
-PP_Resource Create(PP_Module module_id, int32_t width, int32_t height) {
+// Converts a rect inside an image of the given dimensions. The rect may be
+// NULL to indicate it should be the entire image. If the rect is outside of
+// the image, this will do nothing and return false.
+bool ValidateAndConvertRect(const PP_Rect* rect,
+ int image_width, int image_height,
+ gfx::Rect* dest) {
+ if (!rect) {
+ // Use the entire image area.
+ *dest = gfx::Rect(0, 0, image_width, image_height);
+ } else {
+ // Validate the passed-in area.
+ if (rect->point.x < 0 || rect->point.y < 0 ||
+ rect->size.width <= 0 || rect->size.height <= 0)
+ return false;
+
+ // Check the max bounds, being careful of overflow.
+ if (static_cast<int64>(rect->point.x) +
+ static_cast<int64>(rect->size.width) >
+ static_cast<int64>(image_width))
+ return false;
+ if (static_cast<int64>(rect->point.y) +
+ static_cast<int64>(rect->size.height) >
+ static_cast<int64>(image_height))
+ return false;
+
+ *dest = gfx::Rect(rect->point.x, rect->point.y,
+ rect->size.width, rect->size.height);
+ }
+ return true;
+}
+
+PP_Resource Create(PP_Module module_id, int32_t width, int32_t height,
+ bool is_always_opaque) {
PluginModule* module = PluginModule::FromPPModule(module_id);
if (!module)
return NullPPResource();
scoped_refptr<DeviceContext2D> context(new DeviceContext2D(module));
- if (!context->Init(width, height))
+ if (!context->Init(width, height, is_always_opaque))
return NullPPResource();
context->AddRef(); // AddRef for the caller.
return context->GetResource();
}
-void PaintImageData(PP_Resource device_context,
+bool PaintImageData(PP_Resource device_context,
PP_Resource image,
int32_t x, int32_t y,
- const PP_Rect* dirty,
- uint32_t dirty_rect_count,
- PPB_DeviceContext2D_PaintCallback callback,
- void* callback_data) {
- scoped_refptr<Resource> device_resource =
- ResourceTracker::Get()->GetResource(device_context);
- if (!device_resource.get())
- return;
- DeviceContext2D* context = device_resource->AsDeviceContext2D();
- if (!context)
- return;
- context->PaintImageData(image, x, y, dirty, dirty_rect_count,
- callback, callback_data);
+ const PP_Rect* src_rect) {
+ scoped_refptr<DeviceContext2D> context(
+ ResourceTracker::Get()->GetAsDeviceContext2D(device_context));
+ if (!context.get())
+ return false;
+ return context->PaintImageData(image, x, y, src_rect);
+}
+
+bool Scroll(PP_Resource device_context,
+ const PP_Rect* clip_rect,
+ int32_t dx, int32_t dy) {
+ scoped_refptr<DeviceContext2D> context(
+ ResourceTracker::Get()->GetAsDeviceContext2D(device_context));
+ if (!context.get())
+ return false;
+ return context->Scroll(clip_rect, dx, dy);
+}
+
+bool ReplaceContents(PP_Resource device_context, PP_Resource image) {
+ scoped_refptr<DeviceContext2D> context(
+ ResourceTracker::Get()->GetAsDeviceContext2D(device_context));
+ if (!context.get())
+ return false;
+ return context->ReplaceContents(image);
+}
+
+bool Flush(PP_Resource device_context,
+ PPB_DeviceContext2D_FlushCallback callback,
+ void* callback_data) {
+ scoped_refptr<DeviceContext2D> context(
+ ResourceTracker::Get()->GetAsDeviceContext2D(device_context));
+ if (!context.get())
+ return false;
+ return context->Flush(callback, callback_data);
}
const PPB_DeviceContext2D ppb_devicecontext2d = {
&Create,
&PaintImageData,
+ &Scroll,
+ &ReplaceContents,
+ &Flush
};
} // namespace
+struct DeviceContext2D::QueuedOperation {
+ enum Type {
+ PAINT,
+ SCROLL,
+ REPLACE
+ };
+
+ QueuedOperation(Type t)
+ : type(t),
+ paint_x(0),
+ paint_y(0),
+ scroll_dx(0),
+ scroll_dy(0) {
+ }
+
+ Type type;
+
+ // Valid when type == PAINT.
+ scoped_refptr<ImageData> paint_image;
+ int paint_x, paint_y;
+ gfx::Rect paint_src_rect;
+
+ // Valid when type == SCROLL.
+ gfx::Rect scroll_clip_rect;
+ int scroll_dx, scroll_dy;
+
+ // Valid when type == REPLACE.
+ scoped_refptr<ImageData> replace_image;
+};
+
DeviceContext2D::DeviceContext2D(PluginModule* module) : Resource(module) {
}
@@ -74,9 +160,9 @@ const PPB_DeviceContext2D* DeviceContext2D::GetInterface() {
return &ppb_devicecontext2d;
}
-bool DeviceContext2D::Init(int width, int height) {
+bool DeviceContext2D::Init(int width, int height, bool is_always_opaque) {
image_data_ = new ImageData(module());
- if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height) ||
+ if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height, true) ||
!image_data_->Map()) {
image_data_ = NULL;
return false;
@@ -85,61 +171,115 @@ bool DeviceContext2D::Init(int width, int height) {
return true;
}
-void DeviceContext2D::PaintImageData(PP_Resource image,
+bool DeviceContext2D::PaintImageData(PP_Resource image,
int32_t x, int32_t y,
- const PP_Rect* dirty,
- uint32_t dirty_rect_count,
- PPB_DeviceContext2D_PaintCallback callback,
- void* callback_data) {
- scoped_refptr<Resource> image_resource =
- ResourceTracker::Get()->GetResource(image);
- if (!image_resource.get())
- return;
- ImageData* new_image_data = image_resource->AsImageData();
- if (!new_image_data)
- return;
-
- const SkBitmap& new_image_bitmap = new_image_data->GetMappedBitmap();
-
- // TODO(brettw) handle multiple dirty rects.
- DCHECK(dirty_rect_count <= 1);
-
- // Draw the bitmap to the backing store.
- SkIRect src_rect;
- if (dirty_rect_count == 0 || !dirty) {
- // Default to the entire bitmap.
- src_rect.fLeft = 0;
- src_rect.fTop = 0;
- src_rect.fRight = new_image_bitmap.width();
- src_rect.fBottom = new_image_bitmap.height();
- } else {
- src_rect.fLeft = dirty->point.x;
- src_rect.fTop = dirty->point.y;
- src_rect.fRight = dirty->point.x + dirty->size.width;
- src_rect.fBottom = dirty->point.y + dirty->size.height;
- }
- SkRect dest_rect = { SkIntToScalar(src_rect.fLeft),
- SkIntToScalar(src_rect.fTop),
- SkIntToScalar(src_rect.fRight),
- SkIntToScalar(src_rect.fBottom) };
+ const PP_Rect* src_rect) {
+ scoped_refptr<ImageData> image_resource(
+ ResourceTracker::Get()->GetAsImageData(image));
+ if (!image_resource.get() || !image_resource->is_valid())
+ return false;
- // We're guaranteed to have a mapped canvas since we mapped it in Init().
- skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas();
+ const SkBitmap& new_image_bitmap = image_resource->GetMappedBitmap();
- // We want to replace the contents of the bitmap rather than blend.
- SkPaint paint;
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- backing_canvas->drawBitmapRect(new_image_bitmap,
- &src_rect, dest_rect, &paint);
+ QueuedOperation operation(QueuedOperation::PAINT);
+ operation.paint_image = image_resource;
+ if (!ValidateAndConvertRect(src_rect, new_image_bitmap.width(),
+ new_image_bitmap.height(),
+ &operation.paint_src_rect))
+ return false;
+
+ // Validate the bitmap position using the previously-validated rect.
+ if (x < 0 ||
+ static_cast<int64>(x) +
+ static_cast<int64>(operation.paint_src_rect.right()) >
+ image_data_->width())
+ return false;
+ if (y < 0 ||
+ static_cast<int64>(y) +
+ static_cast<int64>(operation.paint_src_rect.bottom()) >
+ image_data_->height())
+ return false;
+ operation.paint_x = x;
+ operation.paint_y = y;
- // TODO(brettw) implement invalidate and callbacks!
+ queued_operations_.push_back(operation);
+ return true;
+}
+
+bool DeviceContext2D::Scroll(const PP_Rect* clip_rect,
+ int32_t dx, int32_t dy) {
+ QueuedOperation operation(QueuedOperation::SCROLL);
+ if (!ValidateAndConvertRect(clip_rect,
+ image_data_->width(),
+ image_data_->height(),
+ &operation.scroll_clip_rect))
+ return false;
+
+ // If we're being asked to scroll by more than the clip rect size, just
+ // ignore this scroll command and say it worked.
+ if (dx <= -image_data_->width() || dx >= image_data_->width() ||
+ dx <= -image_data_->height() || dy >= image_data_->height())
+ return true;
+
+ operation.scroll_dx = dx;
+ operation.scroll_dy = dy;
+
+ queued_operations_.push_back(operation);
+ return false;
+}
+
+bool DeviceContext2D::ReplaceContents(PP_Resource image) {
+ scoped_refptr<ImageData> image_resource(
+ ResourceTracker::Get()->GetAsImageData(image));
+ if (!image_resource.get() || !image_resource->is_valid())
+ return false;
+
+ if (image_resource->width() != image_data_->width() ||
+ image_resource->height() != image_data_->height())
+ return false;
+
+ QueuedOperation operation(QueuedOperation::REPLACE);
+ operation.replace_image = new ImageData(image_resource->module());
+ queued_operations_.push_back(operation);
+
+ // Swap the input image data with the new one we just made in the
+ // QueuedOperation. This way the plugin still gets to manage the reference
+ // count of the old object without having memory released out from under it.
+ // But it ensures that after this, if the plugin does try to use the image
+ // it gave us, those operations will fail.
+ operation.replace_image->Swap(image_resource.get());
+
+ return false;
+}
+
+bool DeviceContext2D::Flush(PPB_DeviceContext2D_FlushCallback callback,
+ void* callback_data) {
+ for (size_t i = 0; i < queued_operations_.size(); i++) {
+ QueuedOperation& operation = queued_operations_[i];
+ switch (operation.type) {
+ case QueuedOperation::PAINT:
+ ExecutePaintImageData(operation.paint_image.get(),
+ operation.paint_x, operation.paint_y,
+ operation.paint_src_rect);
+ break;
+ case QueuedOperation::SCROLL:
+ ExecuteScroll(operation.scroll_clip_rect,
+ operation.scroll_dx, operation.scroll_dy);
+ break;
+ case QueuedOperation::REPLACE:
+ ExecuteReplaceContents(operation.replace_image.get());
+ break;
+ }
+ }
+ queued_operations_.clear();
+ // TODO(brettw) implement invalidate and callbacks!
// Cause the updated part of the screen to be repainted. This will happen
// asynchronously.
/*
- gfx::Rect dest_gfx_rect(dirty->left, dirty->top,
- dirty->right - dirty->left,
- dirty->bottom - dirty->top);
+ gfx::Rect dest_gfx_rect(src_rect->left, src_rect->top,
+ src_rect->right - src_rect->left,
+ src_rect->bottom - src_rect->top);
plugin_delegate_->instance()->webplugin()->InvalidateRect(dest_gfx_rect);
@@ -150,6 +290,7 @@ void DeviceContext2D::PaintImageData(PP_Resource image,
FlushCallbackData(callback, id, context, user_data));
}
*/
+ return true;
}
void DeviceContext2D::Paint(WebKit::WebCanvas* canvas,
@@ -196,4 +337,36 @@ void DeviceContext2D::Paint(WebKit::WebCanvas* canvas,
#endif
}
+
+void DeviceContext2D::ExecutePaintImageData(const ImageData* image,
+ int x, int y,
+ const gfx::Rect& src_rect) {
+ // 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()) };
+
+ // We're guaranteed to have a mapped canvas since we mapped it in Init().
+ skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas();
+
+ // We want to replace the contents of the bitmap rather than blend.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ backing_canvas->drawBitmapRect(image->GetMappedBitmap(),
+ &src_irect, dest_rect, &paint);
+}
+
+void DeviceContext2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy) {
+ // FIXME(brettw)
+}
+
+void DeviceContext2D::ExecuteReplaceContents(ImageData* image) {
+ image_data_->Swap(image);
+}
+
} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_device_context_2d.h b/webkit/glue/plugins/pepper_device_context_2d.h
index 5e8a877..8036c76 100644
--- a/webkit/glue/plugins/pepper_device_context_2d.h
+++ b/webkit/glue/plugins/pepper_device_context_2d.h
@@ -5,6 +5,8 @@
#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_2D_H_
#define WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_2D_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "third_party/ppapi/c/ppb_device_context_2d.h"
#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h"
@@ -30,25 +32,40 @@ class DeviceContext2D : public Resource {
// exposed to the plugin.
static const PPB_DeviceContext2D* GetInterface();
- bool Init(int width, int height);
+ bool Init(int width, int height, bool is_always_opaque);
// Resource override.
virtual DeviceContext2D* AsDeviceContext2D() { return this; }
- void PaintImageData(PP_Resource image,
+ // PPB_DeviceContext2D functions.
+ bool PaintImageData(PP_Resource image,
int32_t x, int32_t y,
- const PP_Rect* dirty,
- uint32_t dirty_rect_count,
- PPB_DeviceContext2D_PaintCallback callback,
- void* callback_data);
+ const PP_Rect* src_rect);
+ bool Scroll(const PP_Rect* clip_rect, int32_t dx, int32_t dy);
+ bool ReplaceContents(PP_Resource image);
+ bool Flush(PPB_DeviceContext2D_FlushCallback callback,
+ void* callback_data);
void Paint(WebKit::WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const gfx::Rect& paint_rect);
private:
+ // Called internally to execute the different queued commands. The
+ // parameters to these functions will have already been validated.
+ void ExecutePaintImageData(const ImageData* image,
+ int x, int y,
+ const gfx::Rect& src_rect);
+ void ExecuteScroll(const gfx::Rect& clip, int dx, int dy);
+ void ExecuteReplaceContents(ImageData* image);
+
scoped_refptr<ImageData> image_data_;
+ // Keeps track of all drawing commands queued before a Flush call.
+ struct QueuedOperation;
+ typedef std::vector<QueuedOperation> OperationQueue;
+ OperationQueue queued_operations_;
+
DISALLOW_COPY_AND_ASSIGN(DeviceContext2D);
};
diff --git a/webkit/glue/plugins/pepper_image_data.cc b/webkit/glue/plugins/pepper_image_data.cc
index c53c91b..cf86437 100644
--- a/webkit/glue/plugins/pepper_image_data.cc
+++ b/webkit/glue/plugins/pepper_image_data.cc
@@ -4,6 +4,9 @@
#include "webkit/glue/plugins/pepper_image_data.h"
+#include <algorithm>
+
+#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/ppapi/c/pp_instance.h"
@@ -28,14 +31,14 @@ ImageData* ResourceAsImageData(PP_Resource resource) {
PP_Resource Create(PP_Module module_id,
PP_ImageDataFormat format,
- int32_t width,
- int32_t height) {
+ int32_t width, int32_t height,
+ bool init_to_zero) {
PluginModule* module = PluginModule::FromPPModule(module_id);
if (!module)
return NullPPResource();
scoped_refptr<ImageData> data(new ImageData(module));
- if (!data->Init(format, width, height))
+ if (!data->Init(format, width, height, init_to_zero))
return NullPPResource();
data->AddRef(); // AddRef for the caller.
@@ -43,11 +46,7 @@ PP_Resource Create(PP_Module module_id,
}
bool IsImageData(PP_Resource resource) {
- scoped_refptr<Resource> image_resource =
- ResourceTracker::Get()->GetResource(resource);
- if (!image_resource.get())
- return false;
- return !!image_resource->AsImageData();
+ return !!ResourceTracker::Get()->GetAsImageData(resource).get();
}
bool Describe(PP_Resource resource,
@@ -55,22 +54,25 @@ bool Describe(PP_Resource resource,
// Give predictable values on failure.
memset(desc, 0, sizeof(PP_ImageDataDesc));
- ImageData* image_data = ResourceAsImageData(resource);
- if (!image_data)
+ scoped_refptr<ImageData> image_data(
+ ResourceTracker::Get()->GetAsImageData(resource));
+ if (!image_data.get())
return false;
image_data->Describe(desc);
return true;
}
void* Map(PP_Resource resource) {
- ImageData* image_data = ResourceAsImageData(resource);
- if (!image_data)
+ scoped_refptr<ImageData> image_data(
+ ResourceTracker::Get()->GetAsImageData(resource));
+ if (!image_data.get())
return NULL;
return image_data->Map();
}
void Unmap(PP_Resource resource) {
- ImageData* image_data = ResourceAsImageData(resource);
+ scoped_refptr<ImageData> image_data(
+ ResourceTracker::Get()->GetAsImageData(resource));
if (!image_data)
return;
return image_data->Unmap();
@@ -101,9 +103,10 @@ const PPB_ImageData* ImageData::GetInterface() {
}
bool ImageData::Init(PP_ImageDataFormat format,
- int width,
- int height) {
+ int width, int height,
+ bool init_to_zero) {
// TODO(brettw) this should be called only on the main thread!
+ // TODO(brettw) use init_to_zero when we implement caching.
platform_image_.reset(
module()->GetSomeInstance()->delegate()->CreateImage2D(width, height));
width_ = width;
@@ -119,6 +122,9 @@ void ImageData::Describe(PP_ImageDataDesc* desc) const {
}
void* ImageData::Map() {
+ if (!is_valid())
+ return NULL;
+
if (!mapped_canvas_.get()) {
mapped_canvas_.reset(platform_image_->Map());
if (!mapped_canvas_.get())
@@ -142,7 +148,15 @@ void ImageData::Unmap() {
}
const SkBitmap& ImageData::GetMappedBitmap() const {
+ DCHECK(is_valid());
return mapped_canvas_->getTopPlatformDevice().accessBitmap(false);
}
+void ImageData::Swap(ImageData* other) {
+ swap(other->platform_image_, platform_image_);
+ swap(other->mapped_canvas_, mapped_canvas_);
+ std::swap(other->width_, width_);
+ std::swap(other->height_, height_);
+}
+
} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_image_data.h b/webkit/glue/plugins/pepper_image_data.h
index e4af427..d2395b3 100644
--- a/webkit/glue/plugins/pepper_image_data.h
+++ b/webkit/glue/plugins/pepper_image_data.h
@@ -27,6 +27,13 @@ class ImageData : public Resource {
explicit ImageData(PluginModule* module);
virtual ~ImageData();
+ int width() const { return width_; }
+ int height() const { return height_; }
+
+ // Returns true if this image is valid and can be used. False means that the
+ // image is invalid and can't be used.
+ bool is_valid() const { return !!platform_image_.get(); }
+
// Returns a pointer to the interface implementing PPB_ImageData that is
// exposed to the plugin.
static const PPB_ImageData* GetInterface();
@@ -36,8 +43,8 @@ class ImageData : public Resource {
// PPB_ImageData implementation.
bool Init(PP_ImageDataFormat format,
- int width,
- int height);
+ int width, int height,
+ bool init_to_zero);
void Describe(PP_ImageDataDesc* desc) const;
void* Map();
void Unmap();
@@ -46,7 +53,12 @@ class ImageData : public Resource {
const SkBitmap& GetMappedBitmap() const;
+ // Swaps the guts of this image data with another.
+ void Swap(ImageData* other);
+
private:
+ // This will be NULL before initialization, and if this ImageData is
+ // swapped with another.
scoped_ptr<PluginDelegate::PlatformImage2D> platform_image_;
// When the device is mapped, this is the image. Null when umapped.
@@ -54,6 +66,8 @@ class ImageData : public Resource {
int width_;
int height_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageData);
};
} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_resource_tracker.cc b/webkit/glue/plugins/pepper_resource_tracker.cc
index 13c5c2c..8a58256 100644
--- a/webkit/glue/plugins/pepper_resource_tracker.cc
+++ b/webkit/glue/plugins/pepper_resource_tracker.cc
@@ -8,6 +8,8 @@
#include "base/logging.h"
#include "third_party/ppapi/c/pp_resource.h"
+#include "webkit/glue/plugins/pepper_device_context_2d.h"
+#include "webkit/glue/plugins/pepper_image_data.h"
#include "webkit/glue/plugins/pepper_resource.h"
namespace pepper {
@@ -23,12 +25,12 @@ ResourceTracker* ResourceTracker::Get() {
return Singleton<ResourceTracker>::get();
}
-Resource* ResourceTracker::GetResource(PP_Resource res) const {
+scoped_refptr<Resource> ResourceTracker::GetResource(PP_Resource res) const {
AutoLock lock(lock_);
Resource* resource = reinterpret_cast<Resource*>(res.id);
if (live_resources_.find(resource) == live_resources_.end())
- return NULL;
- return resource;
+ return scoped_refptr<Resource>();
+ return scoped_refptr<Resource>(resource);
}
void ResourceTracker::AddResource(Resource* resource) {
@@ -47,4 +49,20 @@ void ResourceTracker::DeleteResource(Resource* resource) {
live_resources_.erase(found);
}
+scoped_refptr<DeviceContext2D> ResourceTracker::GetAsDeviceContext2D(
+ PP_Resource res) const {
+ scoped_refptr<Resource> resource = GetResource(res);
+ if (!resource.get())
+ return scoped_refptr<DeviceContext2D>();
+ return scoped_refptr<DeviceContext2D>(resource->AsDeviceContext2D());
+}
+
+scoped_refptr<ImageData> ResourceTracker::GetAsImageData(
+ PP_Resource res) const {
+ scoped_refptr<Resource> resource = GetResource(res);
+ if (!resource.get())
+ return scoped_refptr<ImageData>();
+ return scoped_refptr<ImageData>(resource->AsImageData());
+}
+
} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_resource_tracker.h b/webkit/glue/plugins/pepper_resource_tracker.h
index f114549..f24afc2 100644
--- a/webkit/glue/plugins/pepper_resource_tracker.h
+++ b/webkit/glue/plugins/pepper_resource_tracker.h
@@ -17,6 +17,8 @@ typedef struct _pp_Resource PP_Resource;
namespace pepper {
+class DeviceContext2D;
+class ImageData;
class Resource;
// This class maintains a global list of all live pepper resources. It allows
@@ -28,8 +30,12 @@ class ResourceTracker {
// Returns the pointer to the singleton object.
static ResourceTracker* Get();
- // The returned pointer will be NULL if there is no resource.
- Resource* GetResource(PP_Resource res) const;
+ // The returned pointer will be NULL if there is no resource. Note that this
+ // return value is a scoped_refptr so that we ensure the resource is valid
+ // from the point of the loopkup to the point that the calling code needs it.
+ // Otherwise, the plugin could Release() the resource on another thread and
+ // the object will get deleted out from under us.
+ scoped_refptr<Resource> GetResource(PP_Resource res) const;
// Adds the given resource to the tracker and assigns it a resource ID. The
// assigned resource ID will be returned.
@@ -37,6 +43,11 @@ class ResourceTracker {
void DeleteResource(Resource* resource);
+ // Helpers for converting resources to a specific type. Returns NULL if the
+ // resource is invalid or is a different type.
+ scoped_refptr<DeviceContext2D> GetAsDeviceContext2D(PP_Resource res) const;
+ scoped_refptr<ImageData> GetAsImageData(PP_Resource res) const;
+
private:
friend struct DefaultSingletonTraits<ResourceTracker>;