diff options
-rw-r--r-- | webkit/glue/plugins/pepper_graphics_2d.cc | 106 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_image_data.cc | 28 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_image_data.h | 16 | ||||
-rw-r--r-- | webkit/glue/plugins/pepper_private.cc | 2 |
4 files changed, 124 insertions, 28 deletions
diff --git a/webkit/glue/plugins/pepper_graphics_2d.cc b/webkit/glue/plugins/pepper_graphics_2d.cc index 864b138d..a75da85 100644 --- a/webkit/glue/plugins/pepper_graphics_2d.cc +++ b/webkit/glue/plugins/pepper_graphics_2d.cc @@ -63,6 +63,53 @@ 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(static_cast<int>(src_rect.fLeft), + static_cast<int>(src_rect.fTop)), + src_rect.width() * src_rect.height(), + dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft), + static_cast<int>(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(static_cast<int>(src_rect.fLeft), + static_cast<int>(src_rect.fTop + y)), + src_rect.width(), + dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft), + static_cast<int>(dest_rect.fTop + y))); + } + } +} + PP_Resource Create(PP_Module module_id, const PP_Size* size, bool is_always_opaque) { @@ -186,8 +233,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 +312,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 +384,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 +402,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 +411,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 +558,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 +582,19 @@ 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 = { SkIntToScalar(0), + SkIntToScalar(0), + SkIntToScalar(image_data_->width()), + SkIntToScalar(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; } |