Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: ppapi/proxy/ppb_image_data_proxy.cc

Issue 10823378: Cache image data objects. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/ppb_image_data_proxy.h" 5 #include "ppapi/proxy/ppb_image_data_proxy.h"
6 6
7 #include <string.h> // For memcpy 7 #include <string.h> // For memcpy
8 8
9 #include <map>
9 #include <vector> 10 #include <vector>
10 11
11 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/singleton.h"
14 #include "base/memory/weak_ptr.h"
12 #include "build/build_config.h" 15 #include "build/build_config.h"
13 #include "ppapi/c/pp_completion_callback.h" 16 #include "ppapi/c/pp_completion_callback.h"
14 #include "ppapi/c/pp_errors.h" 17 #include "ppapi/c/pp_errors.h"
15 #include "ppapi/c/pp_resource.h" 18 #include "ppapi/c/pp_resource.h"
19 #include "ppapi/proxy/enter_proxy.h"
16 #include "ppapi/proxy/host_dispatcher.h" 20 #include "ppapi/proxy/host_dispatcher.h"
17 #include "ppapi/proxy/plugin_dispatcher.h" 21 #include "ppapi/proxy/plugin_dispatcher.h"
22 #include "ppapi/proxy/plugin_globals.h"
18 #include "ppapi/proxy/plugin_resource_tracker.h" 23 #include "ppapi/proxy/plugin_resource_tracker.h"
19 #include "ppapi/proxy/ppapi_messages.h" 24 #include "ppapi/proxy/ppapi_messages.h"
20 #include "ppapi/shared_impl/host_resource.h" 25 #include "ppapi/shared_impl/host_resource.h"
21 #include "ppapi/shared_impl/resource.h" 26 #include "ppapi/shared_impl/resource.h"
22 #include "ppapi/thunk/enter.h" 27 #include "ppapi/thunk/enter.h"
23 #include "ppapi/thunk/thunk.h" 28 #include "ppapi/thunk/thunk.h"
24 29
25 #if !defined(OS_NACL) 30 #if !defined(OS_NACL)
26 #include "skia/ext/platform_canvas.h" 31 #include "skia/ext/platform_canvas.h"
27 #include "ui/surface/transport_dib.h" 32 #include "ui/surface/transport_dib.h"
28 #endif 33 #endif
29 34
35 using ppapi::thunk::PPB_ImageData_API;
36
30 namespace ppapi { 37 namespace ppapi {
31 namespace proxy { 38 namespace proxy {
32 39
40 namespace {
41
42 // How ImageData re-use works
43 // --------------------------
44 //
45 // When a plugin does ReplaceContents, it transfers the ImageData to the system
46 // for use as the backing store for the instance. When animating plugins (like
47 // video) re-creating image datas for each frame and mapping the memory has a
48 // high overhead. So we try to re-use these when possible.
49 //
50 // 1. Plugin does ReplaceContents and Flush and the proxy queues up an
51 // asynchronous request to the renderer.
52 // 2. Plugin frees its ImageData reference. If it doesn't do this we can't
53 // re-use it.
54 // 3. When the last plugin ref of an ImageData is released, we don't actually
55 // delete it. Instead we put it on a queue where we hold onto it in the
56 // plugin process for a short period of time.
57 // 4. When the Flush for the Graphics2D.ReplaceContents is executed, the proxy
58 // will request the old ImageData. This is the one that's being replaced by
59 // the new contents so is being abandoned, and without our caching system it
60 // would get deleted at this point.
61 // 5. The proxy in the renderer will send NotifyUnusedImageData back to the
62 // plugin process. We check if the given resource is in the queue and mark
63 // is as usable.
yzshen1 2012/08/21 22:07:24 is -> it.
64 // 6. When the plugin requests a new image data, we check our queue and if there
65 // is a usable ImageData of the right size and format, we'll return it
66 // instead of making a new one. Since when you're doing full frame
67 // animations, generally the size doesn't change so cache hits should be
68 // high.
69 //
70 // Some notes:
71 //
72 // - We only re-use image datas when the plugin does ReplaceContents on them.
73 // Theoretically we could re-use them in other cases but the lifetime
74 // becomes more difficult to manage. The plugin could have used an ImageData
75 // in an arbitrary number of queued up PaintImageData calls which we would
76 // have to check. By doing ReplaceContents, the plugin is promising that it's
77 // done with the image, so this is a good signal.
78 //
79 // - If a flush takes a long time or there are many released image datas
80 // accumulating in our queue such that some are deleted, we will have
81 // released our reference by the time the renderer notifies us of an unused
82 // image data. In this case we just give up.
83 //
84 // - We maintain a per-instance cache. Some pages have many instances of
85 // Flash, for example, each of a different size. If they're all animating we
86 // want each to get its own image data re-use.
87 //
88 // - We generate new resource IDs when re-use happens to try to avoid weird
89 // problems if the plugin messes up its refcounting.
90
91 // Keep a cache entry for this many seconds before expiring it. We get an entry
92 // back from the renderer after an ImageData is swapped out, so it means the
93 // plugin has to be painting at at least two frames for this time interfacl to
yzshen1 2012/08/21 22:07:24 interfacl -> interval at at -> at
94 // get caching.
95 static const int kMaxAgeSeconds = 2;
96
97 // ImageDataCacheEntry ---------------------------------------------------------
98
99 struct ImageDataCacheEntry {
100 ImageDataCacheEntry() : added_time(), usable(false), image() {}
101 ImageDataCacheEntry(ImageData* i)
102 : added_time(base::TimeTicks::Now()),
103 usable(false),
104 image(i) {
105 }
106
107 base::TimeTicks added_time;
108
109 // Set to true when the renderer tells us that it's OK to re-use this iamge.
110 bool usable;
111
112 scoped_refptr<ImageData> image;
113 };
114
115 // ImageDataInstanceCache ------------------------------------------------------
116
117 // Per-instance cache of image datas.
118 class ImageDataInstanceCache {
119 public:
120 ImageDataInstanceCache() : next_insertion_point_(0) {}
121
122 // These functions have the same spec as the ones in ImageDataCache.
123 scoped_refptr<ImageData> Get(int width, int height,
124 PP_ImageDataFormat format);
125 void Add(ImageData* image_data);
126 void ImageDataUsable(ImageData* image_data);
127
128 // Expires old entries. Returns true if there are still entries in the list,
129 // false if this instance cache is now empty.
130 bool ExpireEntries();
131
132 private:
133 // We'll store this many ImageDatas per instance.
134 const static int kCacheSize = 2;
135
136 ImageDataCacheEntry images_[kCacheSize];
137
138 // Index into cache where the next item will go.
139 int next_insertion_point_;
140 };
141
142 scoped_refptr<ImageData> ImageDataInstanceCache::Get(
143 int width, int height,
144 PP_ImageDataFormat format) {
145 // Just do a brute-force search since the cache is so small.
146 for (int i = 0; i < kCacheSize; i++) {
147 if (!images_[i].usable)
148 continue;
149 const PP_ImageDataDesc& desc = images_[i].image->desc();
150 if (desc.format == format &&
151 desc.size.width == width && desc.size.height == height) {
152 scoped_refptr<ImageData> ret(images_[i].image);
153 images_[i] = ImageDataCacheEntry();
154 return ret;
155 }
156 }
157 return scoped_refptr<ImageData>();
158 }
159
160 void ImageDataInstanceCache::Add(ImageData* image_data) {
161 images_[next_insertion_point_] = ImageDataCacheEntry(image_data);
162
163 // Go to the next location, wrapping around to get LRU.
164 next_insertion_point_++;
165 if (next_insertion_point_ >= kCacheSize)
166 next_insertion_point_ = 0;
167 }
168
169 void ImageDataInstanceCache::ImageDataUsable(ImageData* image_data) {
170 for (int i = 0; i < kCacheSize; i++) {
171 if (images_[i].image.get() == image_data) {
172 images_[i].usable = true;
173 return;
174 }
175 }
176 }
177
178 bool ImageDataInstanceCache::ExpireEntries() {
179 base::TimeTicks threshold_time =
180 base::TimeTicks::Now() - base::TimeDelta::FromSeconds(kMaxAgeSeconds);
181
182 bool has_entry = false;
183 for (int i = 0; i < kCacheSize; i++) {
184 if (images_[i].image.get()) {
185 // Entry present.
186 if (images_[i].added_time <= threshold_time) {
187 // Found an entry to expire.
188 images_[i] = ImageDataCacheEntry();
189 next_insertion_point_ = i;
190 } else {
191 // Found an entry that we're keeping.
192 has_entry = true;
193 }
194 }
195 }
196 return has_entry;
197 }
198
199 // ImageDataCache --------------------------------------------------------------
200
201 class ImageDataCache {
202 public:
203 ImageDataCache() : weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
204 ~ImageDataCache() {}
205
206 static ImageDataCache* GetInstance();
207
208 // Retrieves an image data from the cache of the specified size and format if
209 // one exists. If one doesn't exist, this will return a null refptr.
210 scoped_refptr<ImageData> Get(PP_Instance instance,
211 int width, int height,
212 PP_ImageDataFormat format);
213
214 // Adds the given image data to the cache. There should be no plugin
215 // references to it. This may delete an older item from the cache.
216 void Add(ImageData* image_data);
217
218 // Notification from the renderer that the given image data is usable.
219 void ImageDataUsable(ImageData* image_data);
220
221 private:
222 friend struct LeakySingletonTraits<ImageDataCache>;
223
224 // Timer callback to expire entries for the given instance.
225 void OnTimer(PP_Instance instance);
226
227 base::WeakPtrFactory<ImageDataCache> weak_factory_;
yzshen1 2012/08/21 22:07:24 Why does it need to be a weak ptr factory?
brettw 2012/08/21 23:24:58 I added a comment
228
229 typedef std::map<PP_Instance, ImageDataInstanceCache> CacheMap;
230 CacheMap cache_;
231
232 DISALLOW_COPY_AND_ASSIGN(ImageDataCache);
233 };
234
235 // static
236 ImageDataCache* ImageDataCache::GetInstance() {
237 return Singleton<ImageDataCache,
238 LeakySingletonTraits<ImageDataCache> >::get();
239 }
240
241 scoped_refptr<ImageData> ImageDataCache::Get(PP_Instance instance,
242 int width, int height,
243 PP_ImageDataFormat format) {
244 CacheMap::iterator found = cache_.find(instance);
245 if (found == cache_.end())
246 return scoped_refptr<ImageData>();
247 return found->second.Get(width, height, format);
248 }
249
250 void ImageDataCache::Add(ImageData* image_data) {
251 cache_[image_data->pp_instance()].Add(image_data);
252
253 // Schedule a timer to invalidate this entry.
254 MessageLoop::current()->PostDelayedTask(
255 FROM_HERE,
256 base::Bind(&ImageDataCache::OnTimer,
257 weak_factory_.GetWeakPtr(),
258 image_data->pp_instance()),
259 base::TimeDelta::FromSeconds(kMaxAgeSeconds));
260 }
261
262 void ImageDataCache::ImageDataUsable(ImageData* image_data) {
263 CacheMap::iterator found = cache_.find(image_data->pp_instance());
264 if (found != cache_.end())
265 found->second.ImageDataUsable(image_data);
266 }
267
268 void ImageDataCache::OnTimer(PP_Instance instance) {
269 CacheMap::iterator found = cache_.find(instance);
270 if (found == cache_.end())
271 return;
272 if (!found->second.ExpireEntries()) {
273 // There are no more entries for this instance, remove it from the cache.
274 cache_.erase(found);
275 }
276 }
277
278 } // namespace
279
280 // ImageData -------------------------------------------------------------------
281
33 #if !defined(OS_NACL) 282 #if !defined(OS_NACL)
34 ImageData::ImageData(const HostResource& resource, 283 ImageData::ImageData(const HostResource& resource,
35 const PP_ImageDataDesc& desc, 284 const PP_ImageDataDesc& desc,
36 ImageHandle handle) 285 ImageHandle handle)
37 : Resource(OBJECT_IS_PROXY, resource), 286 : Resource(OBJECT_IS_PROXY, resource),
38 desc_(desc) { 287 desc_(desc) {
39 #if defined(OS_WIN) 288 #if defined(OS_WIN)
40 transport_dib_.reset(TransportDIB::CreateWithHandle(handle)); 289 transport_dib_.reset(TransportDIB::CreateWithHandle(handle));
41 #else 290 #else
42 transport_dib_.reset(TransportDIB::Map(handle)); 291 transport_dib_.reset(TransportDIB::Map(handle));
43 #endif // defined(OS_WIN) 292 #endif // defined(OS_WIN)
44 } 293 }
45 #else // !defined(OS_NACL) 294 #else // !defined(OS_NACL)
46 295
47 ImageData::ImageData(const HostResource& resource, 296 ImageData::ImageData(const HostResource& resource,
48 const PP_ImageDataDesc& desc, 297 const PP_ImageDataDesc& desc,
49 const base::SharedMemoryHandle& handle) 298 const base::SharedMemoryHandle& handle)
50 : Resource(OBJECT_IS_PROXY, resource), 299 : Resource(OBJECT_IS_PROXY, resource),
51 desc_(desc), 300 desc_(desc),
52 shm_(handle, false /* read_only */), 301 shm_(handle, false /* read_only */),
53 size_(desc.size.width * desc.size.height * 4), 302 size_(desc.size.width * desc.size.height * 4),
54 map_count_(0) { 303 map_count_(0) {
55 } 304 }
56 #endif // !defined(OS_NACL) 305 #endif // !defined(OS_NACL)
57 306
58 ImageData::~ImageData() { 307 ImageData::~ImageData() {
59 } 308 }
60 309
61 thunk::PPB_ImageData_API* ImageData::AsPPB_ImageData_API() { 310 PPB_ImageData_API* ImageData::AsPPB_ImageData_API() {
62 return this; 311 return this;
63 } 312 }
64 313
314 void ImageData::LastPluginRefWasDeleted() {
315 // The plugin no longer needs this ImageData, add it to our cache.
316 ImageDataCache::GetInstance()->Add(this);
317 }
318
65 PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) { 319 PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) {
66 memcpy(desc, &desc_, sizeof(PP_ImageDataDesc)); 320 memcpy(desc, &desc_, sizeof(PP_ImageDataDesc));
67 return PP_TRUE; 321 return PP_TRUE;
68 } 322 }
69 323
70 void* ImageData::Map() { 324 void* ImageData::Map() {
71 #if defined(OS_NACL) 325 #if defined(OS_NACL)
72 if (map_count_++ == 0) 326 if (map_count_++ == 0)
73 shm_.Map(size_); 327 shm_.Map(size_);
74 return shm_.memory(); 328 return shm_.memory();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 } 368 }
115 369
116 SkCanvas* ImageData::GetCanvas() { 370 SkCanvas* ImageData::GetCanvas() {
117 #if defined(OS_NACL) 371 #if defined(OS_NACL)
118 return NULL; // No canvas in NaCl. 372 return NULL; // No canvas in NaCl.
119 #else 373 #else
120 return mapped_canvas_.get(); 374 return mapped_canvas_.get();
121 #endif 375 #endif
122 } 376 }
123 377
378 void ImageData::ZeroContents() {
379 void* data = Map();
380 memset(data, 0, desc_.stride * desc_.size.height);
381 Unmap();
382 }
383
124 #if !defined(OS_NACL) 384 #if !defined(OS_NACL)
125 // static 385 // static
126 ImageHandle ImageData::NullHandle() { 386 ImageHandle ImageData::NullHandle() {
127 #if defined(OS_WIN) 387 #if defined(OS_WIN)
128 return NULL; 388 return NULL;
129 #elif defined(OS_MACOSX) || defined(OS_ANDROID) 389 #elif defined(OS_MACOSX) || defined(OS_ANDROID)
130 return ImageHandle(); 390 return ImageHandle();
131 #else 391 #else
132 return 0; 392 return 0;
133 #endif 393 #endif
134 } 394 }
135 395
136 ImageHandle ImageData::HandleFromInt(int32_t i) { 396 ImageHandle ImageData::HandleFromInt(int32_t i) {
137 #if defined(OS_WIN) 397 #if defined(OS_WIN)
138 return reinterpret_cast<ImageHandle>(i); 398 return reinterpret_cast<ImageHandle>(i);
139 #elif defined(OS_MACOSX) || defined(OS_ANDROID) 399 #elif defined(OS_MACOSX) || defined(OS_ANDROID)
140 return ImageHandle(i, false); 400 return ImageHandle(i, false);
141 #else 401 #else
142 return static_cast<ImageHandle>(i); 402 return static_cast<ImageHandle>(i);
143 #endif 403 #endif
144 } 404 }
145 #endif // !defined(OS_NACL) 405 #endif // !defined(OS_NACL)
146 406
407 // PPB_ImageData_Proxy ---------------------------------------------------------
408
147 PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher) 409 PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher)
148 : InterfaceProxy(dispatcher) { 410 : InterfaceProxy(dispatcher) {
149 } 411 }
150 412
151 PPB_ImageData_Proxy::~PPB_ImageData_Proxy() { 413 PPB_ImageData_Proxy::~PPB_ImageData_Proxy() {
152 } 414 }
153 415
154 // static 416 // static
155 PP_Resource PPB_ImageData_Proxy::CreateProxyResource(PP_Instance instance, 417 PP_Resource PPB_ImageData_Proxy::CreateProxyResource(PP_Instance instance,
156 PP_ImageDataFormat format, 418 PP_ImageDataFormat format,
157 const PP_Size& size, 419 const PP_Size& size,
158 PP_Bool init_to_zero) { 420 PP_Bool init_to_zero) {
159 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); 421 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
160 if (!dispatcher) 422 if (!dispatcher)
161 return 0; 423 return 0;
162 424
425 // Check the cache.
426 scoped_refptr<ImageData> cached_image_data =
427 ImageDataCache::GetInstance()->Get(instance, size.width, size.height,
428 format);
429 if (cached_image_data.get()) {
430 // We have one we can re-use rather than allocating a new one. Only zero
431 // out if requested.
432 if (PP_ToBool(init_to_zero))
433 cached_image_data->ZeroContents();
434 return cached_image_data->GetReference();
435 }
436
163 HostResource result; 437 HostResource result;
164 std::string image_data_desc; 438 std::string image_data_desc;
165 #if defined(OS_NACL) 439 #if defined(OS_NACL)
166 base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle(); 440 base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
167 dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateNaCl( 441 dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateNaCl(
168 kApiID, instance, format, size, init_to_zero, 442 kApiID, instance, format, size, init_to_zero,
169 &result, &image_data_desc, &image_handle)); 443 &result, &image_data_desc, &image_handle));
170 #else 444 #else
171 ImageHandle image_handle = ImageData::NullHandle(); 445 ImageHandle image_handle = ImageData::NullHandle();
172 dispatcher->Send(new PpapiHostMsg_PPBImageData_Create( 446 dispatcher->Send(new PpapiHostMsg_PPBImageData_Create(
(...skipping 10 matching lines...) Expand all
183 457
184 return (new ImageData(result, desc, image_handle))->GetReference(); 458 return (new ImageData(result, desc, image_handle))->GetReference();
185 } 459 }
186 460
187 bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) { 461 bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) {
188 bool handled = true; 462 bool handled = true;
189 IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg) 463 IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg)
190 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_Create, OnHostMsgCreate) 464 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_Create, OnHostMsgCreate)
191 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateNaCl, 465 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateNaCl,
192 OnHostMsgCreateNaCl) 466 OnHostMsgCreateNaCl)
467
468 IPC_MESSAGE_HANDLER(PpapiPluginMsg_PPBImageData_NotifyUnusedImageData,
469 OnPluginMsgNotifyUnusedImageData)
470
193 IPC_MESSAGE_UNHANDLED(handled = false) 471 IPC_MESSAGE_UNHANDLED(handled = false)
194 IPC_END_MESSAGE_MAP() 472 IPC_END_MESSAGE_MAP()
195 return handled; 473 return handled;
196 } 474 }
197 475
198 void PPB_ImageData_Proxy::OnHostMsgCreate(PP_Instance instance, 476 void PPB_ImageData_Proxy::OnHostMsgCreate(PP_Instance instance,
199 int32_t format, 477 int32_t format,
200 const PP_Size& size, 478 const PP_Size& size,
201 PP_Bool init_to_zero, 479 PP_Bool init_to_zero,
202 HostResource* result, 480 HostResource* result,
(...skipping 10 matching lines...) Expand all
213 if (enter.failed()) 491 if (enter.failed())
214 return; 492 return;
215 493
216 PP_Resource resource = enter.functions()->CreateImageData( 494 PP_Resource resource = enter.functions()->CreateImageData(
217 instance, static_cast<PP_ImageDataFormat>(format), size, init_to_zero); 495 instance, static_cast<PP_ImageDataFormat>(format), size, init_to_zero);
218 if (!resource) 496 if (!resource)
219 return; 497 return;
220 result->SetHostResource(instance, resource); 498 result->SetHostResource(instance, resource);
221 499
222 // Get the description, it's just serialized as a string. 500 // Get the description, it's just serialized as a string.
223 thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_resource( 501 thunk::EnterResourceNoLock<PPB_ImageData_API> enter_resource(resource, false);
224 resource, false);
225 PP_ImageDataDesc desc; 502 PP_ImageDataDesc desc;
226 if (enter_resource.object()->Describe(&desc) == PP_TRUE) { 503 if (enter_resource.object()->Describe(&desc) == PP_TRUE) {
227 image_data_desc->resize(sizeof(PP_ImageDataDesc)); 504 image_data_desc->resize(sizeof(PP_ImageDataDesc));
228 memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc)); 505 memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc));
229 } 506 }
230 507
231 // Get the shared memory handle. 508 // Get the shared memory handle.
232 uint32_t byte_count = 0; 509 uint32_t byte_count = 0;
233 int32_t handle = 0; 510 int32_t handle = 0;
234 if (enter_resource.object()->GetSharedMemory(&handle, &byte_count) == PP_OK) { 511 if (enter_resource.object()->GetSharedMemory(&handle, &byte_count) == PP_OK) {
(...skipping 29 matching lines...) Expand all
264 if (enter.failed()) 541 if (enter.failed())
265 return; 542 return;
266 543
267 PP_Resource resource = enter.functions()->CreateImageDataNaCl( 544 PP_Resource resource = enter.functions()->CreateImageDataNaCl(
268 instance, static_cast<PP_ImageDataFormat>(format), size, init_to_zero); 545 instance, static_cast<PP_ImageDataFormat>(format), size, init_to_zero);
269 if (!resource) 546 if (!resource)
270 return; 547 return;
271 result->SetHostResource(instance, resource); 548 result->SetHostResource(instance, resource);
272 549
273 // Get the description, it's just serialized as a string. 550 // Get the description, it's just serialized as a string.
274 thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_resource( 551 thunk::EnterResourceNoLock<PPB_ImageData_API> enter_resource(resource, false);
275 resource, false);
276 if (enter_resource.failed()) 552 if (enter_resource.failed())
277 return; 553 return;
278 PP_ImageDataDesc desc; 554 PP_ImageDataDesc desc;
279 if (enter_resource.object()->Describe(&desc) == PP_TRUE) { 555 if (enter_resource.object()->Describe(&desc) == PP_TRUE) {
280 image_data_desc->resize(sizeof(PP_ImageDataDesc)); 556 image_data_desc->resize(sizeof(PP_ImageDataDesc));
281 memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc)); 557 memcpy(&(*image_data_desc)[0], &desc, sizeof(PP_ImageDataDesc));
282 } 558 }
283 int local_fd; 559 int local_fd;
284 uint32_t byte_count; 560 uint32_t byte_count;
285 if (enter_resource.object()->GetSharedMemory(&local_fd, &byte_count) != PP_OK) 561 if (enter_resource.object()->GetSharedMemory(&local_fd, &byte_count) != PP_OK)
286 return; 562 return;
287 563
288 // TODO(dmichael): Change trusted interface to return a PP_FileHandle, those 564 // TODO(dmichael): Change trusted interface to return a PP_FileHandle, those
289 // casts are ugly. 565 // casts are ugly.
290 base::PlatformFile platform_file = 566 base::PlatformFile platform_file =
291 #if defined(OS_WIN) 567 #if defined(OS_WIN)
292 reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)); 568 reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd));
293 #elif defined(OS_POSIX) 569 #elif defined(OS_POSIX)
294 local_fd; 570 local_fd;
295 #else 571 #else
296 #error Not implemented. 572 #error Not implemented.
297 #endif // defined(OS_WIN) 573 #endif // defined(OS_WIN)
298 *result_image_handle = 574 *result_image_handle =
299 dispatcher->ShareHandleWithRemote(platform_file, false); 575 dispatcher->ShareHandleWithRemote(platform_file, false);
300 #endif // defined(OS_NACL) 576 #endif // defined(OS_NACL)
301 } 577 }
302 578
579 void PPB_ImageData_Proxy::OnPluginMsgNotifyUnusedImageData(
580 const HostResource& old_image_data) {
581 PluginGlobals* plugin_globals = PluginGlobals::Get();
582 if (!plugin_globals)
583 return; // This may happen if the plugin is malixiously sending this
yzshen1 2012/08/21 22:07:24 malixiously -> maliciously
584 // message to the renderer.
585
586 EnterPluginFromHostResource<PPB_ImageData_API> enter(old_image_data);
587 if (enter.succeeded()) {
588 ImageData* image_data = static_cast<ImageData*>(enter.object());
589 ImageDataCache::GetInstance()->ImageDataUsable(image_data);
590 }
591
592 // The renderer sent us a reference with the message. If the image data was
593 // still cached in our process, the proxy still holds a reference so we can
594 // remove the one the renderer just sent is. If the proxy no longer holds a
595 // reference, we released everything and we should also release the one the
596 // renderer just sent us.
597 dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
598 API_ID_PPB_CORE, old_image_data));
599 }
600
303 } // namespace proxy 601 } // namespace proxy
304 } // namespace ppapi 602 } // namespace ppapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698