summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorklobag@chromium.org <klobag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-21 17:41:59 +0000
committerklobag@chromium.org <klobag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-21 17:41:59 +0000
commit02a791689967ea7779376b41dc4515aed1434c60 (patch)
tree75eb7d5df41488f2f6362d0b04836d952c536299 /webkit
parent1e6b480fd87cb95ddb217dc734984589ca6f87af (diff)
downloadchromium_src-02a791689967ea7779376b41dc4515aed1434c60.zip
chromium_src-02a791689967ea7779376b41dc4515aed1434c60.tar.gz
chromium_src-02a791689967ea7779376b41dc4515aed1434c60.tar.bz2
Add the support of PP_IMAGEDATAFORMAT_RGBA_PREMUL in the browser.
If the plugin format and the browser format do not match, the browser will handle the proper conversion to ensure it uses the correct format. Review URL: http://codereview.chromium.org/3859004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63375 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/plugins/pepper_graphics_2d.cc99
-rw-r--r--webkit/glue/plugins/pepper_image_data.cc28
-rw-r--r--webkit/glue/plugins/pepper_image_data.h16
-rw-r--r--webkit/glue/plugins/pepper_private.cc2
4 files changed, 117 insertions, 28 deletions
diff --git a/webkit/glue/plugins/pepper_graphics_2d.cc b/webkit/glue/plugins/pepper_graphics_2d.cc
index 864b138d..876c14b 100644
--- a/webkit/glue/plugins/pepper_graphics_2d.cc
+++ b/webkit/glue/plugins/pepper_graphics_2d.cc
@@ -63,6 +63,49 @@ bool ValidateAndConvertRect(const PP_Rect* rect,
return true;
}
+// Converts BGRA <-> RGBA.
+void ConvertBetweenBGRAandRGBA(const uint32_t* input,
+ int pixel_length,
+ uint32_t* output) {
+ for (int i = 0; i < pixel_length; i++) {
+ const unsigned char* pixel_in =
+ reinterpret_cast<const unsigned char*>(&input[i]);
+ unsigned char* pixel_out = reinterpret_cast<unsigned char*>(&output[i]);
+ pixel_out[0] = pixel_in[2];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[0];
+ pixel_out[3] = pixel_in[3];
+ }
+}
+
+// Converts ImageData from PP_IMAGEDATAFORMAT_BGRA_PREMUL to
+// PP_IMAGEDATAFORMAT_RGBA_PREMUL, or reverse.
+void ConvertImageData(ImageData* src_image, const SkIRect& src_rect,
+ ImageData* dest_image, const SkRect& dest_rect) {
+ DCHECK(src_image->format() != dest_image->format());
+ DCHECK(ImageData::IsImageDataFormatSupported(src_image->format()));
+ DCHECK(ImageData::IsImageDataFormatSupported(dest_image->format()));
+
+ const SkBitmap* src_bitmap = src_image->GetMappedBitmap();
+ const SkBitmap* dest_bitmap = dest_image->GetMappedBitmap();
+ if (src_rect.width() == src_image->width() &&
+ dest_rect.width() == dest_image->width()) {
+ // Fast path if the full line needs to be converted.
+ ConvertBetweenBGRAandRGBA(
+ src_bitmap->getAddr32(src_rect.fLeft, src_rect.fTop),
+ src_rect.width() * src_rect.height(),
+ dest_bitmap->getAddr32(dest_rect.fLeft, dest_rect.fTop));
+ } else {
+ // Slow path where we convert line by line.
+ for (int y = 0; y < src_rect.height(); y++) {
+ ConvertBetweenBGRAandRGBA(
+ src_bitmap->getAddr32(src_rect.fLeft, src_rect.fTop + y),
+ src_rect.width(),
+ dest_bitmap->getAddr32(dest_rect.fLeft, dest_rect.fTop + y));
+ }
+ }
+}
+
PP_Resource Create(PP_Module module_id,
const PP_Size* size,
bool is_always_opaque) {
@@ -186,8 +229,8 @@ const PPB_Graphics2D* Graphics2D::GetInterface() {
bool Graphics2D::Init(int width, int height, bool is_always_opaque) {
// The underlying ImageData will validate the dimensions.
image_data_ = new ImageData(module());
- if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height, true) ||
- !image_data_->Map()) {
+ if (!image_data_->Init(ImageData::GetNativeImageDataFormat(), width, height,
+ true) || !image_data_->Map()) {
image_data_ = NULL;
return false;
}
@@ -265,7 +308,7 @@ void Graphics2D::ReplaceContents(PP_Resource image_data) {
Resource::GetAs<ImageData>(image_data));
if (!image_resource)
return;
- if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL)
+ if (!ImageData::IsImageDataFormatSupported(image_resource->format()))
return;
if (image_resource->width() != image_data_->width() ||
@@ -337,7 +380,7 @@ bool Graphics2D::ReadImageData(PP_Resource image,
scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image));
if (!image_resource)
return false;
- if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL)
+ if (!ImageData::IsImageDataFormatSupported(image_resource->format()))
return false; // Must be in the right format.
// Validate the bitmap position.
@@ -355,7 +398,6 @@ bool Graphics2D::ReadImageData(PP_Resource image,
ImageDataAutoMapper auto_mapper(image_resource);
if (!auto_mapper.is_valid())
return false;
- skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas();
SkIRect src_irect = { x, y,
x + image_resource->width(),
@@ -365,11 +407,18 @@ bool Graphics2D::ReadImageData(PP_Resource image,
SkIntToScalar(image_resource->width()),
SkIntToScalar(image_resource->height()) };
- // We want to replace the contents of the bitmap rather than blend.
- SkPaint paint;
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- dest_canvas->drawBitmapRect(*image_data_->GetMappedBitmap(),
- &src_irect, dest_rect, &paint);
+ if (image_resource->format() != image_data_->format()) {
+ // Convert the image data if the format does not match.
+ ConvertImageData(image_data_, src_irect, image_resource.get(), dest_rect);
+ } else {
+ skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas();
+
+ // We want to replace the contents of the bitmap rather than blend.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ dest_canvas->drawBitmapRect(*image_data_->GetMappedBitmap(),
+ &src_irect, dest_rect, &paint);
+ }
return true;
}
@@ -505,14 +554,19 @@ void Graphics2D::ExecutePaintImageData(ImageData* image,
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();
+ if (image->format() != image_data_->format()) {
+ // Convert the image data if the format does not match.
+ ConvertImageData(image, src_irect, image_data_, dest_rect);
+ } else {
+ // 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);
+ // 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 Graphics2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
@@ -524,7 +578,16 @@ void Graphics2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
void Graphics2D::ExecuteReplaceContents(ImageData* image,
gfx::Rect* invalidated_rect) {
- image_data_->Swap(image);
+ if (image->format() != image_data_->format()) {
+ DCHECK(image->width() == image_data_->width() &&
+ image->height() == image_data_->height());
+ // Convert the image data if the format does not match.
+ SkIRect src_irect = { 0, 0, image->width(), image->height() };
+ SkRect dest_rect = { 0, 0, image_data_->width(), image_data_->height() };
+ ConvertImageData(image, src_irect, image_data_, dest_rect);
+ } else {
+ image_data_->Swap(image);
+ }
*invalidated_rect = gfx::Rect(0, 0,
image_data_->width(), image_data_->height());
}
diff --git a/webkit/glue/plugins/pepper_image_data.cc b/webkit/glue/plugins/pepper_image_data.cc
index 8c9bc08..2ee8b21 100644
--- a/webkit/glue/plugins/pepper_image_data.cc
+++ b/webkit/glue/plugins/pepper_image_data.cc
@@ -15,6 +15,7 @@
#include "third_party/ppapi/c/pp_resource.h"
#include "third_party/ppapi/c/ppb_image_data.h"
#include "third_party/ppapi/c/trusted/ppb_image_data_trusted.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
#include "webkit/glue/plugins/pepper_plugin_instance.h"
#include "webkit/glue/plugins/pepper_plugin_module.h"
@@ -23,11 +24,11 @@ namespace pepper {
namespace {
PP_ImageDataFormat GetNativeImageDataFormat() {
- return PP_IMAGEDATAFORMAT_BGRA_PREMUL;
+ return ImageData::GetNativeImageDataFormat();
}
bool IsImageDataFormatSupported(PP_ImageDataFormat format) {
- return format == PP_IMAGEDATAFORMAT_BGRA_PREMUL;
+ return ImageData::IsImageDataFormatSupported(format);
}
PP_Resource Create(PP_Module module_id,
@@ -98,6 +99,7 @@ const PPB_ImageDataTrusted ppb_imagedata_trusted = {
ImageData::ImageData(PluginModule* module)
: Resource(module),
+ format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
width_(0),
height_(0) {
}
@@ -115,12 +117,28 @@ const PPB_ImageDataTrusted* ImageData::GetTrustedInterface() {
return &ppb_imagedata_trusted;
}
+// static
+PP_ImageDataFormat ImageData::GetNativeImageDataFormat() {
+ if (SK_B32_SHIFT == 0)
+ return PP_IMAGEDATAFORMAT_BGRA_PREMUL;
+ else if (SK_R32_SHIFT == 0)
+ return PP_IMAGEDATAFORMAT_RGBA_PREMUL;
+ else
+ return PP_IMAGEDATAFORMAT_BGRA_PREMUL; // Default to something on failure.
+}
+
+// static
+bool ImageData::IsImageDataFormatSupported(PP_ImageDataFormat format) {
+ return format == PP_IMAGEDATAFORMAT_BGRA_PREMUL ||
+ format == PP_IMAGEDATAFORMAT_RGBA_PREMUL;
+}
+
bool ImageData::Init(PP_ImageDataFormat format,
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.
- if (format != PP_IMAGEDATAFORMAT_BGRA_PREMUL)
+ if (!IsImageDataFormatSupported(format))
return false; // Only support this one format for now.
if (width <= 0 || height <= 0)
return false;
@@ -130,13 +148,14 @@ bool ImageData::Init(PP_ImageDataFormat format,
platform_image_.reset(
module()->GetSomeInstance()->delegate()->CreateImage2D(width, height));
+ format_ = format;
width_ = width;
height_ = height;
return !!platform_image_.get();
}
void ImageData::Describe(PP_ImageDataDesc* desc) const {
- desc->format = PP_IMAGEDATAFORMAT_BGRA_PREMUL;
+ desc->format = format_;
desc->size.width = width_;
desc->size.height = height_;
desc->stride = width_ * 4;
@@ -178,6 +197,7 @@ const SkBitmap* ImageData::GetMappedBitmap() const {
void ImageData::Swap(ImageData* other) {
swap(other->platform_image_, platform_image_);
swap(other->mapped_canvas_, mapped_canvas_);
+ std::swap(other->format_, format_);
std::swap(other->width_, width_);
std::swap(other->height_, height_);
}
diff --git a/webkit/glue/plugins/pepper_image_data.h b/webkit/glue/plugins/pepper_image_data.h
index f2a110b..f8c713a 100644
--- a/webkit/glue/plugins/pepper_image_data.h
+++ b/webkit/glue/plugins/pepper_image_data.h
@@ -28,11 +28,8 @@ class ImageData : public Resource {
int width() const { return width_; }
int height() const { return height_; }
- // Returns the image format. Currently there is only one format so this
- // always returns the same thing. But if you care about the formation, you
- // should probably check this so when we support multiple formats, we can't
- // forget to update your code.
- PP_ImageDataFormat format() const { return PP_IMAGEDATAFORMAT_BGRA_PREMUL; }
+ // Returns the image format.
+ PP_ImageDataFormat format() const { return format_; }
// Returns true if this image is mapped. False means that the image is either
// invalid or not mapped. See ImageDataAutoMapper below.
@@ -47,6 +44,14 @@ class ImageData : public Resource {
static const PPB_ImageData* GetInterface();
static const PPB_ImageDataTrusted* GetTrustedInterface();
+ // Returns the image data format used by the browser. If the plugin uses the
+ // same format, there is no conversion. Otherwise the browser will be in
+ // charge of converting from a supported format to its native format.
+ static PP_ImageDataFormat GetNativeImageDataFormat();
+
+ // Returns true if the format is supported by the browser.
+ static bool IsImageDataFormatSupported(PP_ImageDataFormat format);
+
// Resource overrides.
virtual ImageData* AsImageData() { return this; }
@@ -76,6 +81,7 @@ class ImageData : public Resource {
// When the device is mapped, this is the image. Null when umapped.
scoped_ptr<skia::PlatformCanvas> mapped_canvas_;
+ PP_ImageDataFormat format_;
int width_;
int height_;
diff --git a/webkit/glue/plugins/pepper_private.cc b/webkit/glue/plugins/pepper_private.cc
index 8ee2020..0bf5328 100644
--- a/webkit/glue/plugins/pepper_private.cc
+++ b/webkit/glue/plugins/pepper_private.cc
@@ -118,7 +118,7 @@ PP_Resource GetResourceImage(PP_Module module_id, PP_ResourceImage image_id) {
if (!module)
return 0;
scoped_refptr<pepper::ImageData> image_data(new pepper::ImageData(module));
- if (!image_data->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL,
+ if (!image_data->Init(ImageData::GetNativeImageDataFormat(),
res_bitmap->width(), res_bitmap->height(), false)) {
return 0;
}