| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "webkit/plugins/ppapi/ppb_image_data_impl.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <limits> | |
| 9 | |
| 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/thunk/thunk.h" | |
| 17 #include "third_party/skia/include/core/SkColorPriv.h" | |
| 18 #include "webkit/plugins/ppapi/common.h" | |
| 19 #include "webkit/plugins/ppapi/resource_helper.h" | |
| 20 | |
| 21 using ::ppapi::thunk::PPB_ImageData_API; | |
| 22 | |
| 23 namespace webkit { | |
| 24 namespace ppapi { | |
| 25 | |
| 26 PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance, | |
| 27 PPB_ImageData_Shared::ImageDataType type) | |
| 28 : Resource(::ppapi::OBJECT_IS_IMPL, instance), | |
| 29 format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL), | |
| 30 width_(0), | |
| 31 height_(0) { | |
| 32 switch (type) { | |
| 33 case PPB_ImageData_Shared::PLATFORM: | |
| 34 backend_.reset(new ImageDataPlatformBackend); | |
| 35 return; | |
| 36 case PPB_ImageData_Shared::SIMPLE: | |
| 37 backend_.reset(new ImageDataSimpleBackend); | |
| 38 return; | |
| 39 // No default: so that we get a compiler warning if any types are added. | |
| 40 } | |
| 41 NOTREACHED(); | |
| 42 } | |
| 43 | |
| 44 PPB_ImageData_Impl::~PPB_ImageData_Impl() { | |
| 45 } | |
| 46 | |
| 47 bool PPB_ImageData_Impl::Init(PP_ImageDataFormat format, | |
| 48 int width, int height, | |
| 49 bool init_to_zero) { | |
| 50 // TODO(brettw) this should be called only on the main thread! | |
| 51 if (!IsImageDataFormatSupported(format)) | |
| 52 return false; // Only support this one format for now. | |
| 53 if (width <= 0 || height <= 0) | |
| 54 return false; | |
| 55 if (static_cast<int64>(width) * static_cast<int64>(height) >= | |
| 56 std::numeric_limits<int32>::max() / 4) | |
| 57 return false; // Prevent overflow of signed 32-bit ints. | |
| 58 | |
| 59 format_ = format; | |
| 60 width_ = width; | |
| 61 height_ = height; | |
| 62 return backend_->Init(this, format, width, height, init_to_zero); | |
| 63 } | |
| 64 | |
| 65 // static | |
| 66 PP_Resource PPB_ImageData_Impl::Create(PP_Instance instance, | |
| 67 PPB_ImageData_Shared::ImageDataType type, | |
| 68 PP_ImageDataFormat format, | |
| 69 const PP_Size& size, | |
| 70 PP_Bool init_to_zero) { | |
| 71 scoped_refptr<PPB_ImageData_Impl> | |
| 72 data(new PPB_ImageData_Impl(instance, type)); | |
| 73 if (!data->Init(format, size.width, size.height, !!init_to_zero)) | |
| 74 return 0; | |
| 75 return data->GetReference(); | |
| 76 } | |
| 77 | |
| 78 PPB_ImageData_API* PPB_ImageData_Impl::AsPPB_ImageData_API() { | |
| 79 return this; | |
| 80 } | |
| 81 | |
| 82 bool PPB_ImageData_Impl::IsMapped() const { | |
| 83 return backend_->IsMapped(); | |
| 84 } | |
| 85 | |
| 86 PluginDelegate::PlatformImage2D* PPB_ImageData_Impl::PlatformImage() const { | |
| 87 return backend_->PlatformImage(); | |
| 88 } | |
| 89 | |
| 90 PP_Bool PPB_ImageData_Impl::Describe(PP_ImageDataDesc* desc) { | |
| 91 desc->format = format_; | |
| 92 desc->size.width = width_; | |
| 93 desc->size.height = height_; | |
| 94 desc->stride = width_ * 4; | |
| 95 return PP_TRUE; | |
| 96 } | |
| 97 | |
| 98 void* PPB_ImageData_Impl::Map() { | |
| 99 return backend_->Map(); | |
| 100 } | |
| 101 | |
| 102 void PPB_ImageData_Impl::Unmap() { | |
| 103 backend_->Unmap(); | |
| 104 } | |
| 105 | |
| 106 int32_t PPB_ImageData_Impl::GetSharedMemory(int* handle, uint32_t* byte_count) { | |
| 107 return backend_->GetSharedMemory(handle, byte_count); | |
| 108 } | |
| 109 | |
| 110 skia::PlatformCanvas* PPB_ImageData_Impl::GetPlatformCanvas() { | |
| 111 return backend_->GetPlatformCanvas(); | |
| 112 } | |
| 113 | |
| 114 SkCanvas* PPB_ImageData_Impl::GetCanvas() { | |
| 115 return backend_->GetCanvas(); | |
| 116 } | |
| 117 | |
| 118 void PPB_ImageData_Impl::SetIsCandidateForReuse() { | |
| 119 // Nothing to do since we don't support image data re-use in-process. | |
| 120 } | |
| 121 | |
| 122 const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const { | |
| 123 return backend_->GetMappedBitmap(); | |
| 124 } | |
| 125 | |
| 126 // ImageDataPlatformBackend ---------------------------------------------------- | |
| 127 | |
| 128 ImageDataPlatformBackend::ImageDataPlatformBackend() { | |
| 129 } | |
| 130 | |
| 131 ImageDataPlatformBackend::~ImageDataPlatformBackend() { | |
| 132 } | |
| 133 | |
| 134 bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl, | |
| 135 PP_ImageDataFormat format, | |
| 136 int width, int height, | |
| 137 bool init_to_zero) { | |
| 138 PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(impl); | |
| 139 if (!plugin_delegate) | |
| 140 return false; | |
| 141 | |
| 142 // TODO(brettw) use init_to_zero when we implement caching. | |
| 143 platform_image_.reset(plugin_delegate->CreateImage2D(width, height)); | |
| 144 return !!platform_image_.get(); | |
| 145 } | |
| 146 | |
| 147 bool ImageDataPlatformBackend::IsMapped() const { | |
| 148 return !!mapped_canvas_.get(); | |
| 149 } | |
| 150 | |
| 151 PluginDelegate::PlatformImage2D* | |
| 152 ImageDataPlatformBackend::PlatformImage() const { | |
| 153 return platform_image_.get(); | |
| 154 } | |
| 155 | |
| 156 void* ImageDataPlatformBackend::Map() { | |
| 157 if (!mapped_canvas_) { | |
| 158 mapped_canvas_.reset(platform_image_->Map()); | |
| 159 if (!mapped_canvas_) | |
| 160 return NULL; | |
| 161 } | |
| 162 const SkBitmap& bitmap = | |
| 163 skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true); | |
| 164 | |
| 165 // Our platform bitmaps are set to opaque by default, which we don't want. | |
| 166 const_cast<SkBitmap&>(bitmap).setIsOpaque(false); | |
| 167 | |
| 168 bitmap.lockPixels(); | |
| 169 return bitmap.getAddr32(0, 0); | |
| 170 } | |
| 171 | |
| 172 void ImageDataPlatformBackend::Unmap() { | |
| 173 // This is currently unimplemented, which is OK. The data will just always | |
| 174 // be around once it's mapped. Chrome's TransportDIB isn't currently | |
| 175 // unmappable without freeing it, but this may be something we want to support | |
| 176 // in the future to save some memory. | |
| 177 } | |
| 178 | |
| 179 int32_t ImageDataPlatformBackend::GetSharedMemory(int* handle, | |
| 180 uint32_t* byte_count) { | |
| 181 *handle = platform_image_->GetSharedMemoryHandle(byte_count); | |
| 182 return PP_OK; | |
| 183 } | |
| 184 | |
| 185 skia::PlatformCanvas* ImageDataPlatformBackend::GetPlatformCanvas() { | |
| 186 return mapped_canvas_.get(); | |
| 187 } | |
| 188 | |
| 189 SkCanvas* ImageDataPlatformBackend::GetCanvas() { | |
| 190 return mapped_canvas_.get(); | |
| 191 } | |
| 192 | |
| 193 const SkBitmap* ImageDataPlatformBackend::GetMappedBitmap() const { | |
| 194 if (!mapped_canvas_) | |
| 195 return NULL; | |
| 196 return &skia::GetTopDevice(*mapped_canvas_)->accessBitmap(false); | |
| 197 } | |
| 198 | |
| 199 // ImageDataSimpleBackend ------------------------------------------------------ | |
| 200 | |
| 201 ImageDataSimpleBackend::ImageDataSimpleBackend() | |
| 202 : map_count_(0) { | |
| 203 } | |
| 204 | |
| 205 ImageDataSimpleBackend::~ImageDataSimpleBackend() { | |
| 206 } | |
| 207 | |
| 208 bool ImageDataSimpleBackend::Init(PPB_ImageData_Impl* impl, | |
| 209 PP_ImageDataFormat format, | |
| 210 int width, int height, | |
| 211 bool init_to_zero) { | |
| 212 skia_bitmap_.setConfig(SkBitmap::kARGB_8888_Config, | |
| 213 impl->width(), impl->height()); | |
| 214 PluginDelegate* plugin_delegate = ResourceHelper::GetPluginDelegate(impl); | |
| 215 if (!plugin_delegate) | |
| 216 return false; | |
| 217 shared_memory_.reset( | |
| 218 plugin_delegate->CreateAnonymousSharedMemory(skia_bitmap_.getSize())); | |
| 219 return !!shared_memory_.get(); | |
| 220 } | |
| 221 | |
| 222 bool ImageDataSimpleBackend::IsMapped() const { | |
| 223 return map_count_ > 0; | |
| 224 } | |
| 225 | |
| 226 PluginDelegate::PlatformImage2D* ImageDataSimpleBackend::PlatformImage() const { | |
| 227 return NULL; | |
| 228 } | |
| 229 | |
| 230 void* ImageDataSimpleBackend::Map() { | |
| 231 DCHECK(shared_memory_.get()); | |
| 232 if (map_count_++ == 0) { | |
| 233 shared_memory_->Map(skia_bitmap_.getSize()); | |
| 234 skia_bitmap_.setPixels(shared_memory_->memory()); | |
| 235 // Our platform bitmaps are set to opaque by default, which we don't want. | |
| 236 skia_bitmap_.setIsOpaque(false); | |
| 237 skia_canvas_.reset(new SkCanvas(skia_bitmap_)); | |
| 238 return skia_bitmap_.getAddr32(0, 0); | |
| 239 } | |
| 240 return shared_memory_->memory(); | |
| 241 } | |
| 242 | |
| 243 void ImageDataSimpleBackend::Unmap() { | |
| 244 if (--map_count_ == 0) | |
| 245 shared_memory_->Unmap(); | |
| 246 } | |
| 247 | |
| 248 int32_t ImageDataSimpleBackend::GetSharedMemory(int* handle, | |
| 249 uint32_t* byte_count) { | |
| 250 *byte_count = skia_bitmap_.getSize(); | |
| 251 #if defined(OS_POSIX) | |
| 252 *handle = shared_memory_->handle().fd; | |
| 253 #elif defined(OS_WIN) | |
| 254 *handle = reinterpret_cast<int>(shared_memory_->handle()); | |
| 255 #else | |
| 256 #error "Platform not supported." | |
| 257 #endif | |
| 258 return PP_OK; | |
| 259 } | |
| 260 | |
| 261 skia::PlatformCanvas* ImageDataSimpleBackend::GetPlatformCanvas() { | |
| 262 return NULL; | |
| 263 } | |
| 264 | |
| 265 SkCanvas* ImageDataSimpleBackend::GetCanvas() { | |
| 266 if (!IsMapped()) | |
| 267 return NULL; | |
| 268 return skia_canvas_.get(); | |
| 269 } | |
| 270 | |
| 271 const SkBitmap* ImageDataSimpleBackend::GetMappedBitmap() const { | |
| 272 if (!IsMapped()) | |
| 273 return NULL; | |
| 274 return &skia_bitmap_; | |
| 275 } | |
| 276 | |
| 277 } // namespace ppapi | |
| 278 } // namespace webkit | |
| OLD | NEW |