OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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/glue/plugins/pepper_image_data.h" | |
6 | |
7 #include <algorithm> | |
8 #include <limits> | |
9 | |
10 #include "base/logging.h" | |
11 #include "base/scoped_ptr.h" | |
12 #include "skia/ext/platform_canvas.h" | |
13 #include "ppapi/c/pp_instance.h" | |
14 #include "ppapi/c/pp_module.h" | |
15 #include "ppapi/c/pp_resource.h" | |
16 #include "ppapi/c/ppb_image_data.h" | |
17 #include "ppapi/c/trusted/ppb_image_data_trusted.h" | |
18 #include "third_party/skia/include/core/SkColorPriv.h" | |
19 #include "webkit/glue/plugins/pepper_common.h" | |
20 #include "webkit/glue/plugins/pepper_plugin_instance.h" | |
21 #include "webkit/glue/plugins/pepper_plugin_module.h" | |
22 | |
23 namespace pepper { | |
24 | |
25 namespace { | |
26 | |
27 PP_ImageDataFormat GetNativeImageDataFormat() { | |
28 return ImageData::GetNativeImageDataFormat(); | |
29 } | |
30 | |
31 PP_Bool IsImageDataFormatSupported(PP_ImageDataFormat format) { | |
32 return BoolToPPBool(ImageData::IsImageDataFormatSupported(format)); | |
33 } | |
34 | |
35 PP_Resource Create(PP_Module module_id, | |
36 PP_ImageDataFormat format, | |
37 const PP_Size* size, | |
38 PP_Bool init_to_zero) { | |
39 PluginModule* module = ResourceTracker::Get()->GetModule(module_id); | |
40 if (!module) | |
41 return 0; | |
42 | |
43 scoped_refptr<ImageData> data(new ImageData(module)); | |
44 if (!data->Init(format, | |
45 size->width, | |
46 size->height, | |
47 PPBoolToBool(init_to_zero))) { | |
48 return 0; | |
49 } | |
50 | |
51 return data->GetReference(); | |
52 } | |
53 | |
54 PP_Bool IsImageData(PP_Resource resource) { | |
55 return BoolToPPBool(!!Resource::GetAs<ImageData>(resource)); | |
56 } | |
57 | |
58 PP_Bool Describe(PP_Resource resource, PP_ImageDataDesc* desc) { | |
59 // Give predictable values on failure. | |
60 memset(desc, 0, sizeof(PP_ImageDataDesc)); | |
61 | |
62 scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); | |
63 if (!image_data) | |
64 return PP_FALSE; | |
65 image_data->Describe(desc); | |
66 return PP_TRUE; | |
67 } | |
68 | |
69 void* Map(PP_Resource resource) { | |
70 scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); | |
71 if (!image_data) | |
72 return NULL; | |
73 return image_data->Map(); | |
74 } | |
75 | |
76 void Unmap(PP_Resource resource) { | |
77 scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); | |
78 if (image_data) | |
79 image_data->Unmap(); | |
80 } | |
81 | |
82 int32_t GetSharedMemory(PP_Resource resource, | |
83 int* handle, | |
84 uint32_t* byte_count) { | |
85 scoped_refptr<ImageData> image_data(Resource::GetAs<ImageData>(resource)); | |
86 if (image_data) { | |
87 *handle = image_data->GetSharedMemoryHandle(byte_count); | |
88 return PP_OK; | |
89 } | |
90 return PP_ERROR_BADRESOURCE; | |
91 } | |
92 | |
93 const PPB_ImageData ppb_imagedata = { | |
94 &GetNativeImageDataFormat, | |
95 &IsImageDataFormatSupported, | |
96 &Create, | |
97 &IsImageData, | |
98 &Describe, | |
99 &Map, | |
100 &Unmap, | |
101 }; | |
102 | |
103 const PPB_ImageDataTrusted ppb_imagedata_trusted = { | |
104 &GetSharedMemory, | |
105 }; | |
106 | |
107 } // namespace | |
108 | |
109 ImageData::ImageData(PluginModule* module) | |
110 : Resource(module), | |
111 format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL), | |
112 width_(0), | |
113 height_(0) { | |
114 } | |
115 | |
116 ImageData::~ImageData() { | |
117 } | |
118 | |
119 // static | |
120 const PPB_ImageData* ImageData::GetInterface() { | |
121 return &ppb_imagedata; | |
122 } | |
123 | |
124 // static | |
125 const PPB_ImageDataTrusted* ImageData::GetTrustedInterface() { | |
126 return &ppb_imagedata_trusted; | |
127 } | |
128 | |
129 // static | |
130 PP_ImageDataFormat ImageData::GetNativeImageDataFormat() { | |
131 if (SK_B32_SHIFT == 0) | |
132 return PP_IMAGEDATAFORMAT_BGRA_PREMUL; | |
133 else if (SK_R32_SHIFT == 0) | |
134 return PP_IMAGEDATAFORMAT_RGBA_PREMUL; | |
135 else | |
136 return PP_IMAGEDATAFORMAT_BGRA_PREMUL; // Default to something on failure. | |
137 } | |
138 | |
139 // static | |
140 bool ImageData::IsImageDataFormatSupported(PP_ImageDataFormat format) { | |
141 return format == PP_IMAGEDATAFORMAT_BGRA_PREMUL || | |
142 format == PP_IMAGEDATAFORMAT_RGBA_PREMUL; | |
143 } | |
144 | |
145 ImageData* ImageData::AsImageData() { | |
146 return this; | |
147 } | |
148 | |
149 bool ImageData::Init(PP_ImageDataFormat format, | |
150 int width, int height, | |
151 bool init_to_zero) { | |
152 // TODO(brettw) this should be called only on the main thread! | |
153 // TODO(brettw) use init_to_zero when we implement caching. | |
154 if (!IsImageDataFormatSupported(format)) | |
155 return false; // Only support this one format for now. | |
156 if (width <= 0 || height <= 0) | |
157 return false; | |
158 if (static_cast<int64>(width) * static_cast<int64>(height) >= | |
159 std::numeric_limits<int32>::max()) | |
160 return false; // Prevent overflow of signed 32-bit ints. | |
161 | |
162 platform_image_.reset( | |
163 module()->GetSomeInstance()->delegate()->CreateImage2D(width, height)); | |
164 format_ = format; | |
165 width_ = width; | |
166 height_ = height; | |
167 return !!platform_image_.get(); | |
168 } | |
169 | |
170 void ImageData::Describe(PP_ImageDataDesc* desc) const { | |
171 desc->format = format_; | |
172 desc->size.width = width_; | |
173 desc->size.height = height_; | |
174 desc->stride = width_ * 4; | |
175 } | |
176 | |
177 void* ImageData::Map() { | |
178 if (!mapped_canvas_.get()) { | |
179 mapped_canvas_.reset(platform_image_->Map()); | |
180 if (!mapped_canvas_.get()) | |
181 return NULL; | |
182 } | |
183 const SkBitmap& bitmap = | |
184 mapped_canvas_->getTopPlatformDevice().accessBitmap(true); | |
185 | |
186 // Our platform bitmaps are set to opaque by default, which we don't want. | |
187 const_cast<SkBitmap&>(bitmap).setIsOpaque(false); | |
188 | |
189 bitmap.lockPixels(); | |
190 return bitmap.getAddr32(0, 0); | |
191 } | |
192 | |
193 void ImageData::Unmap() { | |
194 // This is currently unimplemented, which is OK. The data will just always | |
195 // be around once it's mapped. Chrome's TransportDIB isn't currently | |
196 // unmappable without freeing it, but this may be something we want to support | |
197 // in the future to save some memory. | |
198 } | |
199 | |
200 int ImageData::GetSharedMemoryHandle(uint32* byte_count) const { | |
201 return platform_image_->GetSharedMemoryHandle(byte_count); | |
202 } | |
203 | |
204 const SkBitmap* ImageData::GetMappedBitmap() const { | |
205 if (!mapped_canvas_.get()) | |
206 return NULL; | |
207 return &mapped_canvas_->getTopPlatformDevice().accessBitmap(false); | |
208 } | |
209 | |
210 void ImageData::Swap(ImageData* other) { | |
211 swap(other->platform_image_, platform_image_); | |
212 swap(other->mapped_canvas_, mapped_canvas_); | |
213 std::swap(other->format_, format_); | |
214 std::swap(other->width_, width_); | |
215 std::swap(other->height_, height_); | |
216 } | |
217 | |
218 } // namespace pepper | |
OLD | NEW |