diff options
Diffstat (limited to 'webkit/glue/plugins/pepper_image_data.cc')
-rw-r--r-- | webkit/glue/plugins/pepper_image_data.cc | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/webkit/glue/plugins/pepper_image_data.cc b/webkit/glue/plugins/pepper_image_data.cc new file mode 100644 index 0000000..8288fe2 --- /dev/null +++ b/webkit/glue/plugins/pepper_image_data.cc @@ -0,0 +1,159 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/glue/plugins/pepper_image_data.h" + +#include <algorithm> +#include <limits> + +#include "base/logging.h" +#include "base/scoped_ptr.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/ppapi/c/pp_instance.h" +#include "third_party/ppapi/c/pp_module.h" +#include "third_party/ppapi/c/pp_resource.h" +#include "third_party/ppapi/c/ppb_image_data.h" +#include "webkit/glue/plugins/pepper_plugin_instance.h" +#include "webkit/glue/plugins/pepper_plugin_module.h" + +namespace pepper { + +namespace { + +PP_ImageDataFormat GetNativeImageDataFormat() { + return PP_IMAGEDATAFORMAT_BGRA_PREMUL; +} + +PP_Resource Create(PP_Module module_id, + PP_ImageDataFormat format, + const PP_Size* size, + bool init_to_zero) { + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return NULL; + + scoped_refptr<ImageData> data(new ImageData(module)); + if (!data->Init(format, size->width, size->height, init_to_zero)) + return NULL; + + return data->GetReference(); +} + +bool IsImageData(PP_Resource resource) { + return !!Resource::GetAs<ImageData>(resource); +} + +bool Describe(PP_Resource resource, PP_ImageDataDesc* desc) { + // Give predictable values on failure. + memset(desc, 0, sizeof(PP_ImageDataDesc)); + + scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); + if (!image_data) + return false; + image_data->Describe(desc); + return true; +} + +void* Map(PP_Resource resource) { + scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); + if (!image_data) + return NULL; + return image_data->Map(); +} + +void Unmap(PP_Resource resource) { + scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); + if (image_data) + image_data->Unmap(); +} + +const PPB_ImageData ppb_imagedata = { + &GetNativeImageDataFormat, + &Create, + &IsImageData, + &Describe, + &Map, + &Unmap, +}; + +} // namespace + +ImageData::ImageData(PluginModule* module) + : Resource(module), + width_(0), + height_(0) { +} + +ImageData::~ImageData() { +} + +// static +const PPB_ImageData* ImageData::GetInterface() { + return &ppb_imagedata; +} + +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) + return false; // Only support this one format for now. + if (width <= 0 || height <= 0) + return false; + if (static_cast<int64>(width) * static_cast<int64>(height) >= + std::numeric_limits<int32>::max()) + return false; // Prevent overflow of signed 32-bit ints. + + platform_image_.reset( + module()->GetSomeInstance()->delegate()->CreateImage2D(width, height)); + width_ = width; + height_ = height; + return !!platform_image_.get(); +} + +void ImageData::Describe(PP_ImageDataDesc* desc) const { + desc->format = PP_IMAGEDATAFORMAT_BGRA_PREMUL; + desc->size.width = width_; + desc->size.height = height_; + desc->stride = width_ * 4; +} + +void* ImageData::Map() { + if (!mapped_canvas_.get()) { + mapped_canvas_.reset(platform_image_->Map()); + if (!mapped_canvas_.get()) + return NULL; + } + const SkBitmap& bitmap = + mapped_canvas_->getTopPlatformDevice().accessBitmap(true); + + // Our platform bitmaps are set to opaque by default, which we don't want. + const_cast<SkBitmap&>(bitmap).setIsOpaque(false); + + bitmap.lockPixels(); + return bitmap.getAddr32(0, 0); +} + +void ImageData::Unmap() { + // This is currently unimplemented, which is OK. The data will just always + // be around once it's mapped. Chrome's TransportDIB isn't currently + // unmappable without freeing it, but this may be something we want to support + // in the future to save some memory. +} + +const SkBitmap* ImageData::GetMappedBitmap() const { + if (!mapped_canvas_.get()) + return NULL; + 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 |