Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / webkit / plugins / ppapi / ppb_image_data_impl.cc
blob2d28f5e90786213a0c17a3f100cf50a88412b272
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "webkit/plugins/ppapi/ppb_image_data_impl.h"
7 #include <algorithm>
8 #include <limits>
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "skia/ext/platform_canvas.h"
13 #include "ppapi/c/pp_instance.h"
14 #include "ppapi/c/pp_resource.h"
15 #include "ppapi/c/ppb_image_data.h"
16 #include "ppapi/c/trusted/ppb_image_data_trusted.h"
17 #include "ppapi/thunk/thunk.h"
18 #include "third_party/skia/include/core/SkColorPriv.h"
19 #include "webkit/plugins/ppapi/common.h"
20 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
21 #include "webkit/plugins/ppapi/resource_helper.h"
23 using ::ppapi::thunk::PPB_ImageData_API;
25 namespace webkit {
26 namespace ppapi {
28 PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
29 ImageDataType type)
30 : Resource(::ppapi::OBJECT_IS_IMPL, instance),
31 format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
32 width_(0),
33 height_(0) {
34 switch (type) {
35 case PLATFORM:
36 backend_.reset(new ImageDataPlatformBackend);
37 return;
38 case NACL:
39 backend_.reset(new ImageDataNaClBackend);
40 return;
41 // No default: so that we get a compiler warning if any types are added.
43 NOTREACHED();
46 PPB_ImageData_Impl::~PPB_ImageData_Impl() {
49 bool PPB_ImageData_Impl::Init(PP_ImageDataFormat format,
50 int width, int height,
51 bool init_to_zero) {
52 // TODO(brettw) this should be called only on the main thread!
53 if (!IsImageDataFormatSupported(format))
54 return false; // Only support this one format for now.
55 if (width <= 0 || height <= 0)
56 return false;
57 if (static_cast<int64>(width) * static_cast<int64>(height) >=
58 std::numeric_limits<int32>::max() / 4)
59 return false; // Prevent overflow of signed 32-bit ints.
61 format_ = format;
62 width_ = width;
63 height_ = height;
64 return backend_->Init(this, format, width, height, init_to_zero);
67 // static
68 PP_Resource PPB_ImageData_Impl::CreatePlatform(PP_Instance instance,
69 PP_ImageDataFormat format,
70 const PP_Size& size,
71 PP_Bool init_to_zero) {
72 scoped_refptr<PPB_ImageData_Impl>
73 data(new PPB_ImageData_Impl(instance, PLATFORM));
74 if (!data->Init(format, size.width, size.height, !!init_to_zero))
75 return 0;
76 return data->GetReference();
79 // static
80 PP_Resource PPB_ImageData_Impl::CreateNaCl(PP_Instance instance,
81 PP_ImageDataFormat format,
82 const PP_Size& size,
83 PP_Bool init_to_zero) {
84 scoped_refptr<PPB_ImageData_Impl>
85 data(new PPB_ImageData_Impl(instance, NACL));
86 if (!data->Init(format, size.width, size.height, !!init_to_zero))
87 return 0;
88 return data->GetReference();
91 PPB_ImageData_API* PPB_ImageData_Impl::AsPPB_ImageData_API() {
92 return this;
95 bool PPB_ImageData_Impl::IsMapped() const {
96 return backend_->IsMapped();
99 PluginDelegate::PlatformImage2D* PPB_ImageData_Impl::PlatformImage() const {
100 return backend_->PlatformImage();
103 PP_Bool PPB_ImageData_Impl::Describe(PP_ImageDataDesc* desc) {
104 desc->format = format_;
105 desc->size.width = width_;
106 desc->size.height = height_;
107 desc->stride = width_ * 4;
108 return PP_TRUE;
111 void* PPB_ImageData_Impl::Map() {
112 return backend_->Map();
115 void PPB_ImageData_Impl::Unmap() {
116 backend_->Unmap();
119 int32_t PPB_ImageData_Impl::GetSharedMemory(int* handle, uint32_t* byte_count) {
120 return backend_->GetSharedMemory(handle, byte_count);
123 skia::PlatformCanvas* PPB_ImageData_Impl::GetPlatformCanvas() {
124 return backend_->GetPlatformCanvas();
127 SkCanvas* PPB_ImageData_Impl::GetCanvas() {
128 return backend_->GetCanvas();
131 void PPB_ImageData_Impl::SetUsedInReplaceContents() {
132 // Nothing to do since we don't support image data re-use in-process.
135 const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const {
136 return backend_->GetMappedBitmap();
139 // ImageDataPlatformBackend --------------------------------------------------
141 ImageDataPlatformBackend::ImageDataPlatformBackend() {
144 ImageDataPlatformBackend::~ImageDataPlatformBackend() {
147 bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl,
148 PP_ImageDataFormat format,
149 int width, int height,
150 bool init_to_zero) {
151 PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(impl);
152 if (!plugin_delegate)
153 return false;
155 // TODO(brettw) use init_to_zero when we implement caching.
156 platform_image_.reset(plugin_delegate->CreateImage2D(width, height));
157 return !!platform_image_.get();
160 bool ImageDataPlatformBackend::IsMapped() const {
161 return !!mapped_canvas_.get();
164 PluginDelegate::PlatformImage2D*
165 ImageDataPlatformBackend::PlatformImage() const {
166 return platform_image_.get();
169 void* ImageDataPlatformBackend::Map() {
170 if (!mapped_canvas_.get()) {
171 mapped_canvas_.reset(platform_image_->Map());
172 if (!mapped_canvas_.get())
173 return NULL;
175 const SkBitmap& bitmap =
176 skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true);
178 // Our platform bitmaps are set to opaque by default, which we don't want.
179 const_cast<SkBitmap&>(bitmap).setIsOpaque(false);
181 bitmap.lockPixels();
182 return bitmap.getAddr32(0, 0);
185 void ImageDataPlatformBackend::Unmap() {
186 // This is currently unimplemented, which is OK. The data will just always
187 // be around once it's mapped. Chrome's TransportDIB isn't currently
188 // unmappable without freeing it, but this may be something we want to support
189 // in the future to save some memory.
192 int32_t ImageDataPlatformBackend::GetSharedMemory(int* handle,
193 uint32_t* byte_count) {
194 *handle = platform_image_->GetSharedMemoryHandle(byte_count);
195 return PP_OK;
198 skia::PlatformCanvas* ImageDataPlatformBackend::GetPlatformCanvas() {
199 return mapped_canvas_.get();
202 SkCanvas* ImageDataPlatformBackend::GetCanvas() {
203 return mapped_canvas_.get();
206 const SkBitmap* ImageDataPlatformBackend::GetMappedBitmap() const {
207 if (!mapped_canvas_.get())
208 return NULL;
209 return &skia::GetTopDevice(*mapped_canvas_)->accessBitmap(false);
212 // ImageDataNaClBackend ------------------------------------------------------
214 ImageDataNaClBackend::ImageDataNaClBackend()
215 : map_count_(0) {
218 ImageDataNaClBackend::~ImageDataNaClBackend() {
221 bool ImageDataNaClBackend::Init(PPB_ImageData_Impl* impl,
222 PP_ImageDataFormat format,
223 int width, int height,
224 bool init_to_zero) {
225 skia_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
226 impl->width(), impl->height());
227 PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(impl);
228 if (!plugin_delegate)
229 return false;
230 shared_memory_.reset(
231 plugin_delegate->CreateAnonymousSharedMemory(skia_bitmap_.getSize()));
232 return !!shared_memory_.get();
235 bool ImageDataNaClBackend::IsMapped() const {
236 return map_count_ > 0;
239 PluginDelegate::PlatformImage2D* ImageDataNaClBackend::PlatformImage() const {
240 return NULL;
243 void* ImageDataNaClBackend::Map() {
244 DCHECK(shared_memory_.get());
245 if (map_count_++ == 0) {
246 shared_memory_->Map(skia_bitmap_.getSize());
247 skia_bitmap_.setPixels(shared_memory_->memory());
248 // Our platform bitmaps are set to opaque by default, which we don't want.
249 skia_bitmap_.setIsOpaque(false);
250 skia_canvas_.reset(new SkCanvas(skia_bitmap_));
251 return skia_bitmap_.getAddr32(0, 0);
253 return shared_memory_->memory();
256 void ImageDataNaClBackend::Unmap() {
257 if (--map_count_ == 0)
258 shared_memory_->Unmap();
261 int32_t ImageDataNaClBackend::GetSharedMemory(int* handle,
262 uint32_t* byte_count) {
263 *byte_count = skia_bitmap_.getSize();
264 #if defined(OS_POSIX)
265 *handle = shared_memory_->handle().fd;
266 #elif defined(OS_WIN)
267 *handle = reinterpret_cast<int>(shared_memory_->handle());
268 #else
269 #error "Platform not supported."
270 #endif
271 return PP_OK;
274 skia::PlatformCanvas* ImageDataNaClBackend::GetPlatformCanvas() {
275 return NULL;
278 SkCanvas* ImageDataNaClBackend::GetCanvas() {
279 if (!IsMapped())
280 return NULL;
281 return skia_canvas_.get();
284 const SkBitmap* ImageDataNaClBackend::GetMappedBitmap() const {
285 if (!IsMapped())
286 return NULL;
287 return &skia_bitmap_;
290 } // namespace ppapi
291 } // namespace webkit