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 |