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

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

Issue 10880033: Don't overwrit image data case entries that are just marked usable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 3 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
« no previous file with comments | « ppapi/proxy/ppb_image_data_proxy.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <map>
10 #include <vector> 10 #include <vector>
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 scoped_refptr<ImageData> Get(int width, int height, 123 scoped_refptr<ImageData> Get(int width, int height,
124 PP_ImageDataFormat format); 124 PP_ImageDataFormat format);
125 void Add(ImageData* image_data); 125 void Add(ImageData* image_data);
126 void ImageDataUsable(ImageData* image_data); 126 void ImageDataUsable(ImageData* image_data);
127 127
128 // Expires old entries. Returns true if there are still entries in the list, 128 // Expires old entries. Returns true if there are still entries in the list,
129 // false if this instance cache is now empty. 129 // false if this instance cache is now empty.
130 bool ExpireEntries(); 130 bool ExpireEntries();
131 131
132 private: 132 private:
133 void IncrementInsertionPoint();
134
133 // We'll store this many ImageDatas per instance. 135 // We'll store this many ImageDatas per instance.
134 const static int kCacheSize = 2; 136 const static int kCacheSize = 2;
135 137
136 ImageDataCacheEntry images_[kCacheSize]; 138 ImageDataCacheEntry images_[kCacheSize];
137 139
138 // Index into cache where the next item will go. 140 // Index into cache where the next item will go.
139 int next_insertion_point_; 141 int next_insertion_point_;
140 }; 142 };
141 143
142 scoped_refptr<ImageData> ImageDataInstanceCache::Get( 144 scoped_refptr<ImageData> ImageDataInstanceCache::Get(
143 int width, int height, 145 int width, int height,
144 PP_ImageDataFormat format) { 146 PP_ImageDataFormat format) {
145 // Just do a brute-force search since the cache is so small. 147 // Just do a brute-force search since the cache is so small.
146 for (int i = 0; i < kCacheSize; i++) { 148 for (int i = 0; i < kCacheSize; i++) {
147 if (!images_[i].usable) 149 if (!images_[i].usable)
148 continue; 150 continue;
149 const PP_ImageDataDesc& desc = images_[i].image->desc(); 151 const PP_ImageDataDesc& desc = images_[i].image->desc();
150 if (desc.format == format && 152 if (desc.format == format &&
151 desc.size.width == width && desc.size.height == height) { 153 desc.size.width == width && desc.size.height == height) {
152 scoped_refptr<ImageData> ret(images_[i].image); 154 scoped_refptr<ImageData> ret(images_[i].image);
153 images_[i] = ImageDataCacheEntry(); 155 images_[i] = ImageDataCacheEntry();
156
157 // Since we just removed an item, this entry is the best place to insert
158 // a subsequent one.
159 next_insertion_point_ = i;
154 return ret; 160 return ret;
155 } 161 }
156 } 162 }
157 return scoped_refptr<ImageData>(); 163 return scoped_refptr<ImageData>();
158 } 164 }
159 165
160 void ImageDataInstanceCache::Add(ImageData* image_data) { 166 void ImageDataInstanceCache::Add(ImageData* image_data) {
161 images_[next_insertion_point_] = ImageDataCacheEntry(image_data); 167 images_[next_insertion_point_] = ImageDataCacheEntry(image_data);
162 168 IncrementInsertionPoint();
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 } 169 }
168 170
169 void ImageDataInstanceCache::ImageDataUsable(ImageData* image_data) { 171 void ImageDataInstanceCache::ImageDataUsable(ImageData* image_data) {
170 for (int i = 0; i < kCacheSize; i++) { 172 for (int i = 0; i < kCacheSize; i++) {
171 if (images_[i].image.get() == image_data) { 173 if (images_[i].image.get() == image_data) {
172 images_[i].usable = true; 174 images_[i].usable = true;
175
176 // This test is important. The renderer doesn't guarantee how many image
177 // datas it has or when it notifies us when one is usable. Its possible
178 // to get into situations where it's always telling us the old one is
179 // usable, and then the older one immediately gets expired. Therefore,
180 // if the next insertion would overwrite this now-usable entry, make the
181 // next insertion overwrite some other entry to avoid the replacement.
182 if (next_insertion_point_ == i)
183 IncrementInsertionPoint();
173 return; 184 return;
174 } 185 }
175 } 186 }
176 } 187 }
177 188
178 bool ImageDataInstanceCache::ExpireEntries() { 189 bool ImageDataInstanceCache::ExpireEntries() {
179 base::TimeTicks threshold_time = 190 base::TimeTicks threshold_time =
180 base::TimeTicks::Now() - base::TimeDelta::FromSeconds(kMaxAgeSeconds); 191 base::TimeTicks::Now() - base::TimeDelta::FromSeconds(kMaxAgeSeconds);
181 192
182 bool has_entry = false; 193 bool has_entry = false;
183 for (int i = 0; i < kCacheSize; i++) { 194 for (int i = 0; i < kCacheSize; i++) {
184 if (images_[i].image.get()) { 195 if (images_[i].image.get()) {
185 // Entry present. 196 // Entry present.
186 if (images_[i].added_time <= threshold_time) { 197 if (images_[i].added_time <= threshold_time) {
187 // Found an entry to expire. 198 // Found an entry to expire.
188 images_[i] = ImageDataCacheEntry(); 199 images_[i] = ImageDataCacheEntry();
189 next_insertion_point_ = i; 200 next_insertion_point_ = i;
190 } else { 201 } else {
191 // Found an entry that we're keeping. 202 // Found an entry that we're keeping.
192 has_entry = true; 203 has_entry = true;
193 } 204 }
194 } 205 }
195 } 206 }
196 return has_entry; 207 return has_entry;
197 } 208 }
198 209
210 void ImageDataInstanceCache::IncrementInsertionPoint() {
211 // Go to the next location, wrapping around to get LRU.
212 next_insertion_point_++;
213 if (next_insertion_point_ >= kCacheSize)
214 next_insertion_point_ = 0;
215 }
216
199 // ImageDataCache -------------------------------------------------------------- 217 // ImageDataCache --------------------------------------------------------------
200 218
201 class ImageDataCache { 219 class ImageDataCache {
202 public: 220 public:
203 ImageDataCache() : weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} 221 ImageDataCache() : weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {}
204 ~ImageDataCache() {} 222 ~ImageDataCache() {}
205 223
206 static ImageDataCache* GetInstance(); 224 static ImageDataCache* GetInstance();
207 225
208 // Retrieves an image data from the cache of the specified size and format if 226 // Retrieves an image data from the cache of the specified size and format if
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 299
282 } // namespace 300 } // namespace
283 301
284 // ImageData ------------------------------------------------------------------- 302 // ImageData -------------------------------------------------------------------
285 303
286 #if !defined(OS_NACL) 304 #if !defined(OS_NACL)
287 ImageData::ImageData(const HostResource& resource, 305 ImageData::ImageData(const HostResource& resource,
288 const PP_ImageDataDesc& desc, 306 const PP_ImageDataDesc& desc,
289 ImageHandle handle) 307 ImageHandle handle)
290 : Resource(OBJECT_IS_PROXY, resource), 308 : Resource(OBJECT_IS_PROXY, resource),
291 desc_(desc) { 309 desc_(desc),
310 used_in_replace_contents_(false) {
292 #if defined(OS_WIN) 311 #if defined(OS_WIN)
293 transport_dib_.reset(TransportDIB::CreateWithHandle(handle)); 312 transport_dib_.reset(TransportDIB::CreateWithHandle(handle));
294 #else 313 #else
295 transport_dib_.reset(TransportDIB::Map(handle)); 314 transport_dib_.reset(TransportDIB::Map(handle));
296 #endif // defined(OS_WIN) 315 #endif // defined(OS_WIN)
297 } 316 }
298 #else // !defined(OS_NACL) 317 #else // !defined(OS_NACL)
299 318
300 ImageData::ImageData(const HostResource& resource, 319 ImageData::ImageData(const HostResource& resource,
301 const PP_ImageDataDesc& desc, 320 const PP_ImageDataDesc& desc,
302 const base::SharedMemoryHandle& handle) 321 const base::SharedMemoryHandle& handle)
303 : Resource(OBJECT_IS_PROXY, resource), 322 : Resource(OBJECT_IS_PROXY, resource),
304 desc_(desc), 323 desc_(desc),
305 shm_(handle, false /* read_only */), 324 shm_(handle, false /* read_only */),
306 size_(desc.size.width * desc.size.height * 4), 325 size_(desc.size.width * desc.size.height * 4),
307 map_count_(0) { 326 map_count_(0),
327 used_in_replace_contents_(false) {
308 } 328 }
309 #endif // !defined(OS_NACL) 329 #endif // !defined(OS_NACL)
310 330
311 ImageData::~ImageData() { 331 ImageData::~ImageData() {
312 } 332 }
313 333
314 PPB_ImageData_API* ImageData::AsPPB_ImageData_API() { 334 PPB_ImageData_API* ImageData::AsPPB_ImageData_API() {
315 return this; 335 return this;
316 } 336 }
317 337
318 void ImageData::LastPluginRefWasDeleted() { 338 void ImageData::LastPluginRefWasDeleted() {
319 // The plugin no longer needs this ImageData, add it to our cache. 339 // The plugin no longer needs this ImageData, add it to our cache if it's
320 ImageDataCache::GetInstance()->Add(this); 340 // been used in a ReplaceContents. These are the ImageDatas that the renderer
341 // will send back ImageDataUsable messages for.
342 if (used_in_replace_contents_)
343 ImageDataCache::GetInstance()->Add(this);
321 } 344 }
322 345
323 PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) { 346 PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) {
324 memcpy(desc, &desc_, sizeof(PP_ImageDataDesc)); 347 memcpy(desc, &desc_, sizeof(PP_ImageDataDesc));
325 return PP_TRUE; 348 return PP_TRUE;
326 } 349 }
327 350
328 void* ImageData::Map() { 351 void* ImageData::Map() {
329 #if defined(OS_NACL) 352 #if defined(OS_NACL)
330 if (map_count_++ == 0) 353 if (map_count_++ == 0)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 } 395 }
373 396
374 SkCanvas* ImageData::GetCanvas() { 397 SkCanvas* ImageData::GetCanvas() {
375 #if defined(OS_NACL) 398 #if defined(OS_NACL)
376 return NULL; // No canvas in NaCl. 399 return NULL; // No canvas in NaCl.
377 #else 400 #else
378 return mapped_canvas_.get(); 401 return mapped_canvas_.get();
379 #endif 402 #endif
380 } 403 }
381 404
382 void ImageData::ZeroContents() { 405 void ImageData::RecycleToPlugin(bool zero_contents) {
383 void* data = Map(); 406 used_in_replace_contents_ = false;
384 memset(data, 0, desc_.stride * desc_.size.height); 407 if (zero_contents) {
385 Unmap(); 408 void* data = Map();
409 memset(data, 0, desc_.stride * desc_.size.height);
410 Unmap();
411 }
386 } 412 }
387 413
388 #if !defined(OS_NACL) 414 #if !defined(OS_NACL)
389 // static 415 // static
390 ImageHandle ImageData::NullHandle() { 416 ImageHandle ImageData::NullHandle() {
391 #if defined(OS_WIN) 417 #if defined(OS_WIN)
392 return NULL; 418 return NULL;
393 #elif defined(OS_MACOSX) || defined(OS_ANDROID) 419 #elif defined(OS_MACOSX) || defined(OS_ANDROID)
394 return ImageHandle(); 420 return ImageHandle();
395 #else 421 #else
(...skipping 28 matching lines...) Expand all
424 PP_Bool init_to_zero) { 450 PP_Bool init_to_zero) {
425 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); 451 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
426 if (!dispatcher) 452 if (!dispatcher)
427 return 0; 453 return 0;
428 454
429 // Check the cache. 455 // Check the cache.
430 scoped_refptr<ImageData> cached_image_data = 456 scoped_refptr<ImageData> cached_image_data =
431 ImageDataCache::GetInstance()->Get(instance, size.width, size.height, 457 ImageDataCache::GetInstance()->Get(instance, size.width, size.height,
432 format); 458 format);
433 if (cached_image_data.get()) { 459 if (cached_image_data.get()) {
434 // We have one we can re-use rather than allocating a new one. Only zero 460 // We have one we can re-use rather than allocating a new one.
435 // out if requested. 461 cached_image_data->RecycleToPlugin(PP_ToBool(init_to_zero));
436 if (PP_ToBool(init_to_zero))
437 cached_image_data->ZeroContents();
438 return cached_image_data->GetReference(); 462 return cached_image_data->GetReference();
439 } 463 }
440 464
441 HostResource result; 465 HostResource result;
442 std::string image_data_desc; 466 std::string image_data_desc;
443 #if defined(OS_NACL) 467 #if defined(OS_NACL)
444 base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle(); 468 base::SharedMemoryHandle image_handle = base::SharedMemory::NULLHandle();
445 dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateNaCl( 469 dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateNaCl(
446 kApiID, instance, format, size, init_to_zero, 470 kApiID, instance, format, size, init_to_zero,
447 &result, &image_data_desc, &image_handle)); 471 &result, &image_data_desc, &image_handle));
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 // still cached in our process, the proxy still holds a reference so we can 621 // still cached in our process, the proxy still holds a reference so we can
598 // remove the one the renderer just sent is. If the proxy no longer holds a 622 // remove the one the renderer just sent is. If the proxy no longer holds a
599 // reference, we released everything and we should also release the one the 623 // reference, we released everything and we should also release the one the
600 // renderer just sent us. 624 // renderer just sent us.
601 dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource( 625 dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
602 API_ID_PPB_CORE, old_image_data)); 626 API_ID_PPB_CORE, old_image_data));
603 } 627 }
604 628
605 } // namespace proxy 629 } // namespace proxy
606 } // namespace ppapi 630 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/ppb_image_data_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698