Commit 16b7b278 authored by dmichael@chromium.org's avatar dmichael@chromium.org

PPAPI/NaCl: Make ImageData for NaCl just use shared memory

BUG=116317
TEST=
TBR=ben@chromium.org
ben for ui/gfx OWNERS

Review URL: https://chromiumcodereview.appspot.com/10790063

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148427 0039d316-1c4b-4281-b951-d872f2087c98
parent 16c10d7d
......@@ -170,7 +170,9 @@ PP_Resource GetResourceImage(PP_Instance instance_id,
if (!content::GetHostGlobals()->GetInstance(instance_id))
return 0;
scoped_refptr<webkit::ppapi::PPB_ImageData_Impl> image_data(
new webkit::ppapi::PPB_ImageData_Impl(instance_id));
new webkit::ppapi::PPB_ImageData_Impl(
instance_id,
webkit::ppapi::PPB_ImageData_Impl::PLATFORM));
if (!image_data->Init(
webkit::ppapi::PPB_ImageData_Impl::GetNativeImageDataFormat(),
res_bitmap->width(), res_bitmap->height(), false)) {
......
......@@ -909,6 +909,14 @@ IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_PPBImageData_Create,
ppapi::HostResource /* result_resource */,
std::string /* image_data_desc */,
ppapi::proxy::ImageHandle /* result */)
IPC_SYNC_MESSAGE_ROUTED4_3(PpapiHostMsg_PPBImageData_CreateNaCl,
PP_Instance /* instance */,
int32 /* format */,
PP_Size /* size */,
PP_Bool /* init_to_zero */,
ppapi::HostResource /* result_resource */,
std::string /* image_data_desc */,
base::SharedMemoryHandle /* result */)
// PPB_Instance.
IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBInstance_GetWindowObject,
......
......@@ -29,7 +29,6 @@ Buffer::Buffer(const HostResource& resource,
: Resource(OBJECT_IS_PROXY, resource),
shm_(shm_handle, false),
size_(size),
mapped_data_(NULL),
map_count_(0) {
}
......@@ -47,7 +46,7 @@ PP_Bool Buffer::Describe(uint32_t* size_in_bytes) {
}
PP_Bool Buffer::IsMapped() {
return PP_FromBool(!!mapped_data_);
return PP_FromBool(map_count_ > 0);
}
void* Buffer::Map() {
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -36,7 +36,6 @@ class Buffer : public thunk::PPB_Buffer_API, public Resource {
private:
base::SharedMemory shm_;
uint32_t size_;
void* mapped_data_;
int map_count_;
DISALLOW_COPY_AND_ASSIGN(Buffer);
......
......@@ -13,6 +13,7 @@
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_resource_tracker.h"
#include "ppapi/proxy/ppapi_messages.h"
......@@ -29,21 +30,30 @@
namespace ppapi {
namespace proxy {
#if !defined(OS_NACL)
ImageData::ImageData(const HostResource& resource,
const PP_ImageDataDesc& desc,
ImageHandle handle)
: Resource(OBJECT_IS_PROXY, resource),
desc_(desc) {
#if defined(OS_NACL)
// TODO(brettw) implement NaCl ImageData. This will involve just
// memory-mapping the handle as raw memory rather than as a transport DIB.
NOTIMPLEMENTED();
#elif defined(OS_WIN)
#if defined(OS_WIN)
transport_dib_.reset(TransportDIB::CreateWithHandle(handle));
#else
transport_dib_.reset(TransportDIB::Map(handle));
#endif
#endif // defined(OS_WIN)
}
#else // !defined(OS_NACL)
ImageData::ImageData(const HostResource& resource,
const PP_ImageDataDesc& desc,
const base::SharedMemoryHandle& handle)
: Resource(OBJECT_IS_PROXY, resource),
desc_(desc),
shm_(handle, false /* read_only */),
size_(desc.size.width * desc.size.height * 4),
map_count_(0) {
}
#endif // !defined(OS_NACL)
ImageData::~ImageData() {
}
......@@ -59,7 +69,9 @@ PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) {
void* ImageData::Map() {
#if defined(OS_NACL)
NOTIMPLEMENTED();
if (map_count_++ == 0)
shm_.Map(size_);
return shm_.memory();
#else
if (!mapped_canvas_.get()) {
mapped_canvas_.reset(transport_dib_->GetPlatformCanvas(desc_.size.width,
......@@ -77,7 +89,8 @@ void* ImageData::Map() {
void ImageData::Unmap() {
#if defined(OS_NACL)
NOTIMPLEMENTED();
if (--map_count_ == 0)
shm_.Unmap();
#else
// TODO(brettw) have a way to unmap a TransportDIB. Currently this isn't
// possible since deleting the TransportDIB also frees all the handles.
......@@ -100,6 +113,15 @@ skia::PlatformCanvas* ImageData::GetPlatformCanvas() {
#endif
}
SkCanvas* ImageData::GetCanvas() {
#if defined(OS_NACL)
return NULL; // No canvas in NaCl.
#else
return mapped_canvas_.get();
#endif
}
#if !defined(OS_NACL)
// static
ImageHandle ImageData::NullHandle() {
#if defined(OS_WIN)
......@@ -120,6 +142,7 @@ ImageHandle ImageData::HandleFromInt(int32_t i) {
return static_cast<ImageHandle>(i);
#endif
}
#endif // !defined(OS_NACL)
PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher)
: InterfaceProxy(dispatcher) {
......@@ -139,10 +162,17 @@ PP_Resource PPB_ImageData_Proxy::CreateProxyResource(PP_Instance instance,
HostResource result;
std::string image_data_desc;
#if defined(OS_NACL)
base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateNaCl(
kApiID, instance, format, size, init_to_zero,
&result, &image_data_desc, &image_handle));
#else
ImageHandle image_handle = ImageData::NullHandle();
dispatcher->Send(new PpapiHostMsg_PPBImageData_Create(
kApiID, instance, format, size, init_to_zero,
&result, &image_data_desc, &image_handle));
#endif
if (result.is_null() || image_data_desc.size() != sizeof(PP_ImageDataDesc))
return 0;
......@@ -158,6 +188,8 @@ bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_Create, OnHostMsgCreate)
IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateNaCl,
OnHostMsgCreateNaCl)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
......@@ -170,6 +202,11 @@ void PPB_ImageData_Proxy::OnHostMsgCreate(PP_Instance instance,
HostResource* result,
std::string* image_data_desc,
ImageHandle* result_image_handle) {
#if defined(OS_NACL)
// This message should never be received in untrusted code. To minimize the
// size of the IRT, we just don't handle it.
return;
#else
*result_image_handle = ImageData::NullHandle();
thunk::EnterResourceCreation enter(instance);
......@@ -200,8 +237,67 @@ void PPB_ImageData_Proxy::OnHostMsgCreate(PP_Instance instance,
*result_image_handle = dispatcher()->ShareHandleWithRemote(ih, false);
#else
*result_image_handle = ImageData::HandleFromInt(handle);
#endif
#endif // defined(OS_WIN)
}
#endif // defined(OS_NACL)
}
void PPB_ImageData_Proxy::OnHostMsgCreateNaCl(
PP_Instance instance,
int32_t format,
const PP_Size& size,
PP_Bool init_to_zero,
HostResource* result,
std::string* image_data_desc,
base::SharedMemoryHandle* result_image_handle) {
#if defined(OS_NACL)
// This message should never be received in untrusted code. To minimize the
// size of the IRT, we just don't handle it.
return;
#else
*result_image_handle = base::SharedMemory::NULLHandle();
HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
if (!dispatcher)
return;
thunk::EnterResourceCreation enter(instance);
if (enter.failed())
return;
PP_Resource resource = enter.functions()->CreateImageDataNaCl(
instance, static_cast<PP_ImageDataFormat>(format), size, init_to_zero);
if (!resource)
return;
result->SetHostResource(instance, resource);
// Get the description, it's just serialized as a string.
thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_resource(
resource, false);
if (enter_resource.failed())
return;
PP_ImageDataDesc desc;
if (enter_resource.object()->Describe(&desc) == PP_TRUE) {
image_data_desc->resize(sizeof(PP_ImageDataDesc));
memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc));
}
int local_fd;
uint32_t byte_count;
if (enter_resource.object()->GetSharedMemory(&local_fd, &byte_count) != PP_OK)
return;
// TODO(dmichael): Change trusted interface to return a PP_FileHandle, those
// casts are ugly.
base::PlatformFile platform_file =
#if defined(OS_WIN)
reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd));
#elif defined(OS_POSIX)
local_fd;
#else
#error Not implemented.
#endif // defined(OS_WIN)
*result_image_handle =
dispatcher->ShareHandleWithRemote(platform_file, false);
#endif // defined(OS_NACL)
}
} // namespace proxy
......
......@@ -6,6 +6,7 @@
#define PPAPI_PPB_IMAGE_DATA_PROXY_H_
#include "base/memory/scoped_ptr.h"
#include "base/shared_memory.h"
#include "build/build_config.h"
#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_completion_callback.h"
......@@ -32,9 +33,19 @@ class ImageData : public ppapi::Resource,
public ppapi::thunk::PPB_ImageData_API,
public ppapi::PPB_ImageData_Shared {
public:
#if !defined(OS_NACL)
ImageData(const ppapi::HostResource& resource,
const PP_ImageDataDesc& desc,
ImageHandle handle);
#else
// In NaCl, we only allow creating an ImageData using a SharedMemoryHandle.
// ImageHandle can differ by host platform. We need something that is
// more consistent across platforms for NaCl, so that we can communicate to
// the host OS in a consistent way.
ImageData(const ppapi::HostResource& resource,
const PP_ImageDataDesc& desc,
const base::SharedMemoryHandle& handle);
#endif
virtual ~ImageData();
// Resource overrides.
......@@ -46,17 +57,22 @@ class ImageData : public ppapi::Resource,
virtual void Unmap() OVERRIDE;
virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
virtual skia::PlatformCanvas* GetPlatformCanvas() OVERRIDE;
virtual SkCanvas* GetCanvas() OVERRIDE;
const PP_ImageDataDesc& desc() const { return desc_; }
#if !defined(OS_NACL)
static ImageHandle NullHandle();
static ImageHandle HandleFromInt(int32_t i);
#endif
private:
PP_ImageDataDesc desc_;
#if defined(OS_NACL)
// TODO(brettw) implement this (see .cc file).
base::SharedMemory shm_;
uint32 size_;
int map_count_;
#else
scoped_ptr<TransportDIB> transport_dib_;
......@@ -83,7 +99,7 @@ class PPB_ImageData_Proxy : public InterfaceProxy {
static const ApiID kApiID = API_ID_PPB_IMAGE_DATA;
private:
// Message handler.
// Message handlers.
void OnHostMsgCreate(PP_Instance instance,
int32_t format,
const PP_Size& size,
......@@ -91,6 +107,13 @@ class PPB_ImageData_Proxy : public InterfaceProxy {
HostResource* result,
std::string* image_data_desc,
ImageHandle* result_image_handle);
void OnHostMsgCreateNaCl(PP_Instance instance,
int32_t format,
const PP_Size& size,
PP_Bool init_to_zero,
HostResource* result,
std::string* image_data_desc,
base::SharedMemoryHandle* result_image_handle);
DISALLOW_COPY_AND_ASSIGN(PPB_ImageData_Proxy);
};
......
......@@ -189,6 +189,17 @@ PP_Resource ResourceCreationProxy::CreateImageData(PP_Instance instance,
init_to_zero);
}
PP_Resource ResourceCreationProxy::CreateImageDataNaCl(
PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) {
// These really only are different on the host side. On the plugin side, we
// always request a "platform" ImageData if we're trusted, or a "NaCl" one
// if we're untrusted (see PPB_ImageData_Proxy::CreateProxyResource()).
return CreateImageData(instance, format, size, init_to_zero);
}
PP_Resource ResourceCreationProxy::CreateGraphics2D(PP_Instance instance,
const PP_Size& size,
PP_Bool is_always_opaque) {
......
......@@ -98,6 +98,10 @@ class ResourceCreationProxy : public InterfaceProxy,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) OVERRIDE;
virtual PP_Resource CreateImageDataNaCl(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) OVERRIDE;
virtual PP_Resource CreateGraphics2D(PP_Instance pp_instance,
const PP_Size& size,
PP_Bool is_always_opaque) OVERRIDE;
......
......@@ -12,6 +12,8 @@ namespace skia {
class PlatformCanvas;
}
class SkCanvas;
namespace ppapi {
namespace thunk {
......@@ -26,9 +28,24 @@ class PPB_ImageData_API {
// Trusted inteface.
virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) = 0;
// The canvas will be NULL if the image is not mapped and under Native
// Client (which does not have skia).
// Get the platform-specific canvas that backs this ImageData, if there is
// one.
// The canvas will be NULL:
// * If the image is not mapped.
// * Within untrusted code (which does not have skia).
// * If the ImageData is not backed by a platform-specific image buffer.
// This will be the case for ImageDatas created for use in NaCl.
// For this last reason, you should prefer GetCanvas any time you don't need
// a platform-specific canvas (e.g., for use with platform-specific APIs).
// Anything that relies on having a PlatformCanvas will not work for ImageDat
// objects created from NaCl.
virtual skia::PlatformCanvas* GetPlatformCanvas() = 0;
// Get the canvas that backs this ImageData, if there is one.
// The canvas will be NULL:
// * If the image is not mapped.
// * Within untrusted code (which does not have skia).
virtual SkCanvas* GetCanvas() = 0;
};
} // namespace thunk
......
......@@ -103,6 +103,10 @@ class ResourceCreationAPI {
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) = 0;
virtual PP_Resource CreateImageDataNaCl(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) = 0;
virtual PP_Resource CreateGraphics2D(PP_Instance instance,
const PP_Size& size,
PP_Bool is_always_opaque) = 0;
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -126,30 +126,27 @@ void BlitCanvasToCanvas(SkCanvas *dst_canvas,
skia::EndPlatformPaint(dst_canvas);
}
#if defined(OS_WIN) && !defined(USE_AURA)
void ScrollCanvas(SkCanvas* canvas,
const gfx::Rect& clip,
const gfx::Point& amount) {
DCHECK(!HasClipOrTransform(*canvas)); // Don't support special stuff.
DCHECK(skia::SupportsPlatformPaint(canvas));
skia::ScopedPlatformPaint scoped_platform_paint(canvas);
HDC hdc = scoped_platform_paint.GetPlatformSurface();
RECT damaged_rect;
RECT r = clip.ToRECT();
ScrollDC(hdc, amount.x(), amount.y(), NULL, &r, NULL, &damaged_rect);
}
#elif defined(OS_POSIX) || defined(USE_AURA)
// Cairo has no nice scroll function so we do our own. On Mac it's possible to
// use platform scroll code, but it's complex so we just use the same path
// here. Either way it will be software-only, so it shouldn't matter much.
void ScrollCanvas(SkCanvas* canvas,
const gfx::Rect& in_clip,
const gfx::Point& amount) {
DCHECK(!HasClipOrTransform(*canvas)); // Don't support special stuff.
#if defined(OS_WIN)
// If we have a PlatformCanvas, we should use ScrollDC. Otherwise, fall
// through to the software implementation.
if (skia::SupportsPlatformPaint(canvas)) {
skia::ScopedPlatformPaint scoped_platform_paint(canvas);
HDC hdc = scoped_platform_paint.GetPlatformSurface();
RECT damaged_rect;
RECT r = in_clip.ToRECT();
ScrollDC(hdc, amount.x(), amount.y(), NULL, &r, NULL, &damaged_rect);
return;
}
#endif // defined(OS_WIN)
// For non-windows, always do scrolling in software.
// Cairo has no nice scroll function so we do our own. On Mac it's possible to
// use platform scroll code, but it's complex so we just use the same path
// here. Either way it will be software-only, so it shouldn't matter much.
SkBitmap& bitmap = const_cast<SkBitmap&>(
skia::GetTopDevice(*canvas)->accessBitmap(true));
SkAutoLockPixels lock(bitmap);
......@@ -196,6 +193,4 @@ void ScrollCanvas(SkCanvas* canvas,
}
}
#endif
} // namespace gfx
......@@ -853,6 +853,10 @@ bool PluginInstance::GetBitmapForOptimizedPluginPaint(
// store when seeing if we cover the given paint bounds, since the backing
// store could be smaller than the declared plugin area.
PPB_ImageData_Impl* image_data = GetBoundGraphics2D()->image_data();
// ImageDatas created by NaCl don't have a PlatformImage, so can't be
// optimized this way.
if (!image_data->PlatformImage())
return false;
gfx::Rect plugin_backing_store_rect(
PP_ToGfxPoint(view_data_.rect.point),
gfx::Size(image_data->width(), image_data->height()));
......@@ -863,7 +867,7 @@ bool PluginInstance::GetBitmapForOptimizedPluginPaint(
if (!plugin_paint_rect.Contains(paint_bounds))
return false;
*dib = image_data->platform_image()->GetTransportDIB();
*dib = image_data->PlatformImage()->GetTransportDIB();
*location = plugin_backing_store_rect;
*clip = clip_page;
return true;
......
......@@ -195,7 +195,8 @@ PP_Resource PPB_Graphics2D_Impl::Create(PP_Instance instance,
bool PPB_Graphics2D_Impl::Init(int width, int height, bool is_always_opaque) {
// The underlying PPB_ImageData_Impl will validate the dimensions.
image_data_ = new PPB_ImageData_Impl(pp_instance());
image_data_ = new PPB_ImageData_Impl(pp_instance(),
PPB_ImageData_Impl::PLATFORM);
if (!image_data_->Init(PPB_ImageData_Impl::GetNativeImageDataFormat(),
width, height, true) ||
!image_data_->Map()) {
......@@ -452,7 +453,7 @@ bool PPB_Graphics2D_Impl::ReadImageData(PP_Resource image,
// Convert the image data if the format does not match.
ConvertImageData(image_data_, src_irect, image_resource, dest_rect);
} else {
skia::PlatformCanvas* dest_canvas = image_resource->GetPlatformCanvas();
SkCanvas* dest_canvas = image_resource->GetCanvas();
// We want to replace the contents of the bitmap rather than blend.
SkPaint paint;
......@@ -681,7 +682,7 @@ void PPB_Graphics2D_Impl::ExecutePaintImageData(PPB_ImageData_Impl* image,
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_->GetPlatformCanvas();
SkCanvas* backing_canvas = image_data_->GetCanvas();
// We want to replace the contents of the bitmap rather than blend.
SkPaint paint;
......@@ -694,7 +695,7 @@ void PPB_Graphics2D_Impl::ExecutePaintImageData(PPB_ImageData_Impl* image,
void PPB_Graphics2D_Impl::ExecuteScroll(const gfx::Rect& clip,
int dx, int dy,
gfx::Rect* invalidated_rect) {
gfx::ScrollCanvas(image_data_->GetPlatformCanvas(),
gfx::ScrollCanvas(image_data_->GetCanvas(),
clip, gfx::Point(dx, dy));
*invalidated_rect = clip;
}
......
......@@ -25,36 +25,31 @@ using ::ppapi::thunk::PPB_ImageData_API;
namespace webkit {
namespace ppapi {
PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance)
PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
ImageDataType type)
: Resource(::ppapi::OBJECT_IS_IMPL, instance),
format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
width_(0),
height_(0) {
switch (type) {
case PLATFORM:
backend_.reset(new ImageDataPlatformBackend);
return;
case NACL:
backend_.reset(new ImageDataNaClBackend);
return;
// No default: so that we get a compiler warning if any types are added.
}
NOTREACHED();
}
PPB_ImageData_Impl::~PPB_ImageData_Impl() {
}
// static
PP_Resource PPB_ImageData_Impl::Create(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) {
scoped_refptr<PPB_ImageData_Impl> data(new PPB_ImageData_Impl(instance));
if (!data->Init(format, size.width, size.height, !!init_to_zero))
return 0;
return data->GetReference();
}
PPB_ImageData_API* PPB_ImageData_Impl::AsPPB_ImageData_API() {
return this;
}
bool PPB_ImageData_Impl::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 (!IsImageDataFormatSupported(format))
return false; // Only support this one format for now.
if (width <= 0 || height <= 0)
......@@ -63,15 +58,46 @@ bool PPB_ImageData_Impl::Init(PP_ImageDataFormat format,
std::numeric_limits<int32>::max())
return false; // Prevent overflow of signed 32-bit ints.
PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(this);
if (!plugin_delegate)
return false;
platform_image_.reset(plugin_delegate->CreateImage2D(width, height));
format_ = format;
width_ = width;
height_ = height;
return !!platform_image_.get();
return backend_->Init(this, format, width, height, init_to_zero);
}
// static
PP_Resource PPB_ImageData_Impl::CreatePlatform(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) {
scoped_refptr<PPB_ImageData_Impl>
data(new PPB_ImageData_Impl(instance, PLATFORM));
if (!data->Init(format, size.width, size.height, !!init_to_zero))
return 0;
return data->GetReference();
}
// static
PP_Resource PPB_ImageData_Impl::CreateNaCl(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) {
scoped_refptr<PPB_ImageData_Impl>
data(new PPB_ImageData_Impl(instance, NACL));
if (!data->Init(format, size.width, size.height, !!init_to_zero))
return 0;
return data->GetReference();
}
PPB_ImageData_API* PPB_ImageData_Impl::AsPPB_ImageData_API() {
return this;
}
bool PPB_ImageData_Impl::IsMapped() const {
return backend_->IsMapped();
}
PluginDelegate::PlatformImage2D* PPB_ImageData_Impl::PlatformImage() const {
return backend_->PlatformImage();
}
PP_Bool PPB_ImageData_Impl::Describe(PP_ImageDataDesc* desc) {
......@@ -83,6 +109,67 @@ PP_Bool PPB_ImageData_Impl::Describe(PP_ImageDataDesc* desc) {
}
void* PPB_ImageData_Impl::Map() {
return backend_->Map();
}
void PPB_ImageData_Impl::Unmap() {
backend_->Unmap();
}
int32_t PPB_ImageData_Impl::GetSharedMemory(int* handle, uint32_t* byte_count) {
return backend_->GetSharedMemory(handle, byte_count);
}
skia::PlatformCanvas* PPB_ImageData_Impl::GetPlatformCanvas() {
return backend_->GetPlatformCanvas();
}
SkCanvas* PPB_ImageData_Impl::GetCanvas() {
return backend_->GetCanvas();
}
const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const {
return backend_->GetMappedBitmap();
}
void PPB_ImageData_Impl::Swap(PPB_ImageData_Impl* other) {
backend_.swap(other->backend_);
std::swap(other->format_, format_);
std::swap(other->width_, width_);
std::swap(other->height_, height_);
}
// ImageDataPlatformBackend --------------------------------------------------
ImageDataPlatformBackend::ImageDataPlatformBackend() {
}
ImageDataPlatformBackend::~ImageDataPlatformBackend() {
}
bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl,
PP_ImageDataFormat format,
int width, int height,
bool init_to_zero) {
PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(impl);
if (!plugin_delegate)
return false;
// TODO(brettw) use init_to_zero when we implement caching.
platform_image_.reset(plugin_delegate->CreateImage2D(width, height));
return !!platform_image_.get();
}
bool ImageDataPlatformBackend::IsMapped() const {
return !!mapped_canvas_.get();
}
PluginDelegate::PlatformImage2D*
ImageDataPlatformBackend::PlatformImage() const {
return platform_image_.get();
}
void* ImageDataPlatformBackend::Map() {
if (!mapped_canvas_.get()) {
mapped_canvas_.reset(platform_image_->Map());
if (!mapped_canvas_.get())
......@@ -98,35 +185,109 @@ void* PPB_ImageData_Impl::Map() {
return bitmap.getAddr32(0, 0);
}
void PPB_ImageData_Impl::Unmap() {
void ImageDataPlatformBackend::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.
}
int32_t PPB_ImageData_Impl::GetSharedMemory(int* handle,
uint32_t* byte_count) {
int32_t ImageDataPlatformBackend::GetSharedMemory(int* handle,
uint32_t* byte_count) {
*handle = platform_image_->GetSharedMemoryHandle(byte_count);
return PP_OK;
}
skia::PlatformCanvas* PPB_ImageData_Impl::GetPlatformCanvas() {
skia::PlatformCanvas* ImageDataPlatformBackend::GetPlatformCanvas() {
return mapped_canvas_.get();
}
const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const {
SkCanvas* ImageDataPlatformBackend::GetCanvas() {
return mapped_canvas_.get();
}
const SkBitmap* ImageDataPlatformBackend::GetMappedBitmap() const {
if (!mapped_canvas_.get())
return NULL;
return &skia::GetTopDevice(*mapped_canvas_)->accessBitmap(false);
}
void PPB_ImageData_Impl::Swap(PPB_ImageData_Impl* 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_);
// ImageDataNaClBackend ------------------------------------------------------
ImageDataNaClBackend::ImageDataNaClBackend()
: map_count_(0) {
}
ImageDataNaClBackend::~ImageDataNaClBackend() {
}
bool ImageDataNaClBackend::Init(PPB_ImageData_Impl* impl,
PP_ImageDataFormat format,
int width, int height,
bool init_to_zero) {
skia_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
impl->width(), impl->height());
PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(impl);
if (!plugin_delegate)
return false;
shared_memory_.reset(
plugin_delegate->CreateAnonymousSharedMemory(skia_bitmap_.getSize()));
return !!shared_memory_.get();
}
bool ImageDataNaClBackend::IsMapped() const {
return map_count_ > 0;
}
PluginDelegate::PlatformImage2D* ImageDataNaClBackend::PlatformImage() const {
return NULL;
}
void* ImageDataNaClBackend::Map() {
DCHECK(shared_memory_.get());
if (map_count_++ == 0) {
shared_memory_->Map(skia_bitmap_.getSize());
skia_bitmap_.setPixels(shared_memory_->memory());
// Our platform bitmaps are set to opaque by default, which we don't want.
skia_bitmap_.setIsOpaque(false);
skia_canvas_.setBitmapDevice(skia_bitmap_);
return skia_bitmap_.getAddr32(0, 0);
}
return shared_memory_->memory();
}
void ImageDataNaClBackend::Unmap() {
if (--map_count_ == 0)
shared_memory_->Unmap();
}
int32_t ImageDataNaClBackend::GetSharedMemory(int* handle,
uint32_t* byte_count) {
*byte_count = skia_bitmap_.getSize();
#if defined(OS_POSIX)
*handle = shared_memory_->handle().fd;
#elif defined(OS_WIN)
*handle = reinterpret_cast<int>(shared_memory_->handle());
#else
#error "Platform not supported."
#endif
return PP_OK;
}
skia::PlatformCanvas* ImageDataNaClBackend::GetPlatformCanvas() {
return NULL;
}
SkCanvas* ImageDataNaClBackend::GetCanvas() {
if (!IsMapped())
return NULL;
return &skia_canvas_;
}
const SkBitmap* ImageDataNaClBackend::GetMappedBitmap() const {
if (!IsMapped())
return NULL;
return &skia_bitmap_;
}
} // namespace ppapi
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.
......@@ -11,6 +11,7 @@
#include "ppapi/shared_impl/ppb_image_data_shared.h"
#include "ppapi/shared_impl/resource.h"
#include "ppapi/thunk/ppb_image_data_api.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "webkit/plugins/ppapi/plugin_delegate.h"
#include "webkit/plugins/webkit_plugins_export.h"
......@@ -23,24 +24,54 @@ class SkBitmap;
namespace webkit {
namespace ppapi {
class PPB_ImageData_Impl : public ::ppapi::Resource,
public ::ppapi::PPB_ImageData_Shared,
public ::ppapi::thunk::PPB_ImageData_API {
class WEBKIT_PLUGINS_EXPORT PPB_ImageData_Impl
: public ::ppapi::Resource,
public ::ppapi::PPB_ImageData_Shared,
public NON_EXPORTED_BASE(::ppapi::thunk::PPB_ImageData_API) {
public:
// We delegate most of our implementation to a back-end class that either uses
// a PlatformCanvas (for most trusted stuff) or bare shared memory (for use by
// NaCl). This makes it cheap & easy to implement Swap.
class Backend {
public:
virtual ~Backend() {};
virtual bool Init(PPB_ImageData_Impl* impl, PP_ImageDataFormat format,
int width, int height, bool init_to_zero) = 0;
virtual bool IsMapped() const = 0;
virtual PluginDelegate::PlatformImage2D* PlatformImage() const = 0;
virtual void* Map() = 0;
virtual void Unmap() = 0;
virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) = 0;
virtual skia::PlatformCanvas* GetPlatformCanvas() = 0;
virtual SkCanvas* GetCanvas() = 0;
virtual const SkBitmap* GetMappedBitmap() const = 0;
};
// If you call this constructor, you must also call Init before use. Normally
// you should use the static Create function, but this constructor is needed
// for some internal uses of ImageData (like Graphics2D).
WEBKIT_PLUGINS_EXPORT explicit PPB_ImageData_Impl(PP_Instance instance);
enum ImageDataType { PLATFORM, NACL };
PPB_ImageData_Impl(PP_Instance instance, ImageDataType type);
virtual ~PPB_ImageData_Impl();
static PP_Resource Create(PP_Instance pp_instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero);
WEBKIT_PLUGINS_EXPORT bool Init(PP_ImageDataFormat format,
int width, int height,
bool init_to_zero);
bool Init(PP_ImageDataFormat format,
int width, int height,
bool init_to_zero);
// Create an ImageData backed by a PlatformCanvas. You must use this if you
// intend the ImageData to be usable in platform-specific APIs (like font
// rendering or rendering widgets like scrollbars).
static PP_Resource CreatePlatform(PP_Instance pp_instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero);
// Use this to create an ImageData for use with NaCl. This is backed by a
// simple shared memory buffer.
static PP_Resource CreateNaCl(PP_Instance pp_instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero);
int width() const { return width_; }
int height() const { return height_; }
......@@ -50,12 +81,10 @@ class PPB_ImageData_Impl : public ::ppapi::Resource,
// Returns true if this image is mapped. False means that the image is either
// invalid or not mapped. See ImageDataAutoMapper below.
bool is_mapped() const { return !!mapped_canvas_.get(); }
PluginDelegate::PlatformImage2D* platform_image() const {
return platform_image_.get();
}
bool IsMapped() const;
PluginDelegate::PlatformImage2D* PlatformImage() const;
// Resource override.
virtual ::ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
// PPB_ImageData_API implementation.
......@@ -64,12 +93,39 @@ class PPB_ImageData_Impl : public ::ppapi::Resource,
virtual void Unmap() OVERRIDE;
virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
virtual skia::PlatformCanvas* GetPlatformCanvas() OVERRIDE;
virtual SkCanvas* GetCanvas() OVERRIDE;
const SkBitmap* GetMappedBitmap() const;
// Swaps the guts of this image data with another.
void Swap(PPB_ImageData_Impl* other);
private:
PP_ImageDataFormat format_;
int width_;
int height_;
scoped_ptr<Backend> backend_;
DISALLOW_COPY_AND_ASSIGN(PPB_ImageData_Impl);
};
class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
public:
ImageDataPlatformBackend();
virtual ~ImageDataPlatformBackend();
// PPB_ImageData_Impl::Backend implementation.
virtual bool Init(PPB_ImageData_Impl* impl, PP_ImageDataFormat format,
int width, int height, bool init_to_zero) OVERRIDE;
virtual bool IsMapped() const OVERRIDE;
virtual PluginDelegate::PlatformImage2D* PlatformImage() const OVERRIDE;
virtual void* Map() OVERRIDE;
virtual void Unmap() OVERRIDE;
virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
virtual skia::PlatformCanvas* GetPlatformCanvas() OVERRIDE;
virtual SkCanvas* GetCanvas() OVERRIDE;
virtual const SkBitmap* GetMappedBitmap() const OVERRIDE;
private:
// This will be NULL before initialization, and if this PPB_ImageData_Impl is
// swapped with another.
......@@ -78,11 +134,34 @@ class PPB_ImageData_Impl : public ::ppapi::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_;
DISALLOW_COPY_AND_ASSIGN(ImageDataPlatformBackend);
};
DISALLOW_COPY_AND_ASSIGN(PPB_ImageData_Impl);
class ImageDataNaClBackend : public PPB_ImageData_Impl::Backend {
public:
ImageDataNaClBackend();
virtual ~ImageDataNaClBackend();
// PPB_ImageData_Impl::Backend implementation.
bool Init(PPB_ImageData_Impl* impl, PP_ImageDataFormat format,
int width, int height, bool init_to_zero) OVERRIDE;
virtual bool IsMapped() const OVERRIDE;
PluginDelegate::PlatformImage2D* PlatformImage() const OVERRIDE;
virtual void* Map() OVERRIDE;
virtual void Unmap() OVERRIDE;
virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
virtual skia::PlatformCanvas* GetPlatformCanvas() OVERRIDE;
virtual SkCanvas* GetCanvas() OVERRIDE;
virtual const SkBitmap* GetMappedBitmap() const OVERRIDE;
private:
scoped_ptr<base::SharedMemory> shared_memory_;
// skia_bitmap_ is backed by shared_memory_.
SkBitmap skia_bitmap_;
SkCanvas skia_canvas_;
uint32 map_count_;
DISALLOW_COPY_AND_ASSIGN(ImageDataNaClBackend);
};
// Manages mapping an image resource if necessary. Use this to ensure the
......@@ -99,7 +178,7 @@ class ImageDataAutoMapper {
public:
explicit ImageDataAutoMapper(PPB_ImageData_Impl* image_data)
: image_data_(image_data) {
if (image_data_->is_mapped()) {
if (image_data_->IsMapped()) {
is_valid_ = true;
needs_unmap_ = false;
} else {
......
......@@ -174,7 +174,15 @@ PP_Resource ResourceCreationImpl::CreateImageData(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) {
return PPB_ImageData_Impl::Create(instance, format, size, init_to_zero);
return PPB_ImageData_Impl::CreatePlatform(instance, format, size,
init_to_zero);
}
PP_Resource ResourceCreationImpl::CreateImageDataNaCl(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) {
return PPB_ImageData_Impl::CreateNaCl(instance, format, size, init_to_zero);
}
PP_Resource ResourceCreationImpl::CreateIMEInputEvent(
......
......@@ -66,6 +66,10 @@ class WEBKIT_PLUGINS_EXPORT ResourceCreationImpl
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) OVERRIDE;
virtual PP_Resource CreateImageDataNaCl(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size& size,
PP_Bool init_to_zero) OVERRIDE;
virtual PP_Resource CreateIMEInputEvent(PP_Instance instance,
PP_InputEvent_Type type,
PP_TimeTicks time_stamp,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment