15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppb_image_data_proxy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>  // For memcpy
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_completion_callback.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_resource.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/enter_proxy.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/host_dispatcher.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_dispatcher.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_globals.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_resource_tracker.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/host_resource.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/shared_impl/proxy_lock.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/shared_impl/scoped_pp_resource.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/enter.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/thunk.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_NACL)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/platform_canvas.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/surface/transport_dib.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::PPB_ImageData_API;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// How ImageData re-use works
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------------
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// When animating plugins (like video), re-creating image datas for each frame
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// and mapping the memory has a high overhead. So we try to re-use these when
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// possible.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 1. Plugin makes an asynchronous call that transfers an ImageData to the
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    implementation of some API.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Plugin frees its ImageData reference. If it doesn't do this we can't
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    re-use it.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. When the last plugin ref of an ImageData is released, we don't actually
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    delete it. Instead we put it on a queue where we hold onto it in the
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    plugin process for a short period of time.
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 4. The API implementation that received the ImageData finishes using it.
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    Without our caching system it would get deleted at this point.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5. The proxy in the renderer will send NotifyUnusedImageData back to the
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    plugin process. We check if the given resource is in the queue and mark
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    it as usable.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 6. When the plugin requests a new image data, we check our queue and if there
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    is a usable ImageData of the right size and format, we'll return it
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    instead of making a new one. It's important that caching is only requested
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    when the size is unlikely to change, so cache hits are high.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some notes:
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//  - We only re-use image data when the plugin and host are rapidly exchanging
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    them and the size is likely to remain constant. It should be clear that
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    the plugin is promising that it's done with the image.
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//  - Theoretically we could re-use them in other cases but the lifetime
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    becomes more difficult to manage. The plugin could have used an ImageData
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    in an arbitrary number of queued up PaintImageData calls which we would
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    have to check.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - If a flush takes a long time or there are many released image datas
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    accumulating in our queue such that some are deleted, we will have
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    released our reference by the time the renderer notifies us of an unused
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    image data. In this case we just give up.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - We maintain a per-instance cache. Some pages have many instances of
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    Flash, for example, each of a different size. If they're all animating we
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    want each to get its own image data re-use.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  - We generate new resource IDs when re-use happens to try to avoid weird
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    problems if the plugin messes up its refcounting.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keep a cache entry for this many seconds before expiring it. We get an entry
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// back from the renderer after an ImageData is swapped out, so it means the
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// plugin has to be painting at least two frames for this time interval to
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// get caching.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxAgeSeconds = 2;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ImageDataCacheEntry ---------------------------------------------------------
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ImageDataCacheEntry {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageDataCacheEntry() : added_time(), usable(false), image() {}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageDataCacheEntry(ImageData* i)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : added_time(base::TimeTicks::Now()),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        usable(false),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        image(i) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks added_time;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to true when the renderer tells us that it's OK to re-use this iamge.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool usable;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ImageData> image;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ImageDataInstanceCache ------------------------------------------------------
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Per-instance cache of image datas.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ImageDataInstanceCache {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageDataInstanceCache() : next_insertion_point_(0) {}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These functions have the same spec as the ones in ImageDataCache.
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_refptr<ImageData> Get(PPB_ImageData_Shared::ImageDataType type,
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                               int width, int height,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PP_ImageDataFormat format);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Add(ImageData* image_data);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ImageDataUsable(ImageData* image_data);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Expires old entries. Returns true if there are still entries in the list,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // false if this instance cache is now empty.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ExpireEntries();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void IncrementInsertionPoint();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll store this many ImageDatas per instance.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const static int kCacheSize = 2;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageDataCacheEntry images_[kCacheSize];
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Index into cache where the next item will go.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int next_insertion_point_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_refptr<ImageData> ImageDataInstanceCache::Get(
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PPB_ImageData_Shared::ImageDataType type,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int width, int height,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_ImageDataFormat format) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Just do a brute-force search since the cache is so small.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kCacheSize; i++) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!images_[i].usable)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (images_[i].image->type() != type)
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      continue;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_ImageDataDesc& desc = images_[i].image->desc();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (desc.format == format &&
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        desc.size.width == width && desc.size.height == height) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<ImageData> ret(images_[i].image);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      images_[i] = ImageDataCacheEntry();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Since we just removed an item, this entry is the best place to insert
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a subsequent one.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_insertion_point_ = i;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ret;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scoped_refptr<ImageData>();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ImageDataInstanceCache::Add(ImageData* image_data) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  images_[next_insertion_point_] = ImageDataCacheEntry(image_data);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IncrementInsertionPoint();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ImageDataInstanceCache::ImageDataUsable(ImageData* image_data) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kCacheSize; i++) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (images_[i].image.get() == image_data) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      images_[i].usable = true;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This test is important. The renderer doesn't guarantee how many image
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // datas it has or when it notifies us when one is usable. Its possible
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to get into situations where it's always telling us the old one is
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // usable, and then the older one immediately gets expired. Therefore,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // if the next insertion would overwrite this now-usable entry, make the
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // next insertion overwrite some other entry to avoid the replacement.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (next_insertion_point_ == i)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IncrementInsertionPoint();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ImageDataInstanceCache::ExpireEntries() {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks threshold_time =
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeTicks::Now() - base::TimeDelta::FromSeconds(kMaxAgeSeconds);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_entry = false;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kCacheSize; i++) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (images_[i].image.get()) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Entry present.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (images_[i].added_time <= threshold_time) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Found an entry to expire.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        images_[i] = ImageDataCacheEntry();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_insertion_point_ = i;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Found an entry that we're keeping.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        has_entry = true;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return has_entry;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ImageDataInstanceCache::IncrementInsertionPoint() {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Go to the next location, wrapping around to get LRU.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_insertion_point_++;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_insertion_point_ >= kCacheSize)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_insertion_point_ = 0;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ImageDataCache --------------------------------------------------------------
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ImageDataCache {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ImageDataCache() : weak_factory_(this) {}
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ImageDataCache() {}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ImageDataCache* GetInstance();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Retrieves an image data from the cache of the specified type, size and
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // format if one exists. If one doesn't exist, this will return a null refptr.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ImageData> Get(PP_Instance instance,
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                               PPB_ImageData_Shared::ImageDataType type,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               int width, int height,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PP_ImageDataFormat format);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds the given image data to the cache. There should be no plugin
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // references to it. This may delete an older item from the cache.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Add(ImageData* image_data);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notification from the renderer that the given image data is usable.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ImageDataUsable(ImageData* image_data);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DidDeleteInstance(PP_Instance instance);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct LeakySingletonTraits<ImageDataCache>;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Timer callback to expire entries for the given instance.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnTimer(PP_Instance instance);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  typedef std::map<PP_Instance, ImageDataInstanceCache> CacheMap;
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CacheMap cache_;
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This class does timer calls and we don't want to run these outside of the
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // scope of the object. Technically, since this class is a leaked static,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this will never happen and this factory is unnecessary. However, it's
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // probably better not to make assumptions about the lifetime of this class.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ImageDataCache> weak_factory_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ImageDataCache);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageDataCache* ImageDataCache::GetInstance() {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<ImageDataCache,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   LeakySingletonTraits<ImageDataCache> >::get();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)scoped_refptr<ImageData> ImageDataCache::Get(
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_Instance instance,
2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PPB_ImageData_Shared::ImageDataType type,
2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int width, int height,
2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_ImageDataFormat format) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheMap::iterator found = cache_.find(instance);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == cache_.end())
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return scoped_refptr<ImageData>();
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return found->second.Get(type, width, height, format);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ImageDataCache::Add(ImageData* image_data) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache_[image_data->pp_instance()].Add(image_data);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule a timer to invalidate this entry.
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RunWhileLocked(base::Bind(&ImageDataCache::OnTimer,
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                weak_factory_.GetWeakPtr(),
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                image_data->pp_instance())),
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromSeconds(kMaxAgeSeconds));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ImageDataCache::ImageDataUsable(ImageData* image_data) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheMap::iterator found = cache_.find(image_data->pp_instance());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found != cache_.end())
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found->second.ImageDataUsable(image_data);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ImageDataCache::DidDeleteInstance(PP_Instance instance) {
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cache_.erase(instance);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ImageDataCache::OnTimer(PP_Instance instance) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CacheMap::iterator found = cache_.find(instance);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found == cache_.end())
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!found->second.ExpireEntries()) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There are no more entries for this instance, remove it from the cache.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache_.erase(found);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ImageData -------------------------------------------------------------------
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageData::ImageData(const HostResource& resource,
3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     PPB_ImageData_Shared::ImageDataType type,
3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                     const PP_ImageDataDesc& desc)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Resource(OBJECT_IS_PROXY, resource),
3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      type_(type),
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      desc_(desc),
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      is_candidate_for_reuse_(false) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageData::~ImageData() {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_ImageData_API* ImageData::AsPPB_ImageData_API() {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ImageData::LastPluginRefWasDeleted() {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The plugin no longer needs this ImageData, add it to our cache if it's
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // been used in a ReplaceContents. These are the ImageDatas that the renderer
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will send back ImageDataUsable messages for.
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (is_candidate_for_reuse_)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImageDataCache::GetInstance()->Add(this);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ImageData::InstanceWasDeleted() {
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ImageDataCache::GetInstance()->DidDeleteInstance(pp_instance());
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool ImageData::Describe(PP_ImageDataDesc* desc) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(desc, &desc_, sizeof(PP_ImageDataDesc));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)int32_t ImageData::GetSharedMemory(int* /* handle */,
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                   uint32_t* /* byte_count */) {
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Not supported in the proxy (this method is for actually implementing the
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // proxy in the host).
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return PP_ERROR_NOACCESS;
3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ImageData::SetIsCandidateForReuse() {
3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  is_candidate_for_reuse_ = true;
3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ImageData::RecycleToPlugin(bool zero_contents) {
3627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  is_candidate_for_reuse_ = false;
3637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (zero_contents) {
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    void* data = Map();
3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    memset(data, 0, desc_.stride * desc_.size.height);
3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    Unmap();
3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
3687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// PlatformImageData -----------------------------------------------------------
3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if !defined(OS_NACL)
3737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PlatformImageData::PlatformImageData(const HostResource& resource,
3747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     const PP_ImageDataDesc& desc,
3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     ImageHandle handle)
3767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : ImageData(resource, PPB_ImageData_Shared::PLATFORM, desc) {
3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if defined(OS_WIN)
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  transport_dib_.reset(TransportDIB::CreateWithHandle(handle));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  transport_dib_.reset(TransportDIB::Map(handle));
3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif  // defined(OS_WIN)
3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PlatformImageData::~PlatformImageData() {
3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void* PlatformImageData::Map() {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mapped_canvas_.get()) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mapped_canvas_.reset(transport_dib_->GetPlatformCanvas(desc_.size.width,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                           desc_.size.height));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!mapped_canvas_.get())
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkBitmap& bitmap =
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap.lockPixels();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bitmap.getAddr(0, 0);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void PlatformImageData::Unmap() {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(brettw) have a way to unmap a TransportDIB. Currently this isn't
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // possible since deleting the TransportDIB also frees all the handles.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to add a method to TransportDIB to release the handles.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SkCanvas* PlatformImageData::GetPlatformCanvas() {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return mapped_canvas_.get();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SkCanvas* PlatformImageData::GetCanvas() {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return mapped_canvas_.get();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ImageHandle PlatformImageData::NullHandle() {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return ImageHandle();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ImageHandle PlatformImageData::HandleFromInt(int32_t i) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<ImageHandle>(i);
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ImageHandle(i, false);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_NACL)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// SimpleImageData -------------------------------------------------------------
4347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SimpleImageData::SimpleImageData(const HostResource& resource,
4367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                 const PP_ImageDataDesc& desc,
4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                 const base::SharedMemoryHandle& handle)
4387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : ImageData(resource, PPB_ImageData_Shared::SIMPLE, desc),
4397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      shm_(handle, false /* read_only */),
4407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      size_(desc.size.width * desc.size.height * 4),
4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      map_count_(0) {
4427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SimpleImageData::~SimpleImageData() {
4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void* SimpleImageData::Map() {
4487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (map_count_++ == 0)
4497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    shm_.Map(size_);
4507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return shm_.memory();
4517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void SimpleImageData::Unmap() {
4547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (--map_count_ == 0)
4557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    shm_.Unmap();
4567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SkCanvas* SimpleImageData::GetPlatformCanvas() {
4597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return NULL;  // No canvas available.
4607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SkCanvas* SimpleImageData::GetCanvas() {
4637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return NULL;  // No canvas available.
4647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
4657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PPB_ImageData_Proxy ---------------------------------------------------------
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_ImageData_Proxy::PPB_ImageData_Proxy(Dispatcher* dispatcher)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterfaceProxy(dispatcher) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_ImageData_Proxy::~PPB_ImageData_Proxy() {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)PP_Resource PPB_ImageData_Proxy::CreateProxyResource(
4777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_Instance instance,
4787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PPB_ImageData_Shared::ImageDataType type,
4797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_ImageDataFormat format,
4807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const PP_Size& size,
4817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_Bool init_to_zero) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dispatcher)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the cache.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ImageData> cached_image_data =
4887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ImageDataCache::GetInstance()->Get(instance, type,
4897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                         size.width, size.height, format);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cached_image_data.get()) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have one we can re-use rather than allocating a new one.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cached_image_data->RecycleToPlugin(PP_ToBool(init_to_zero));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cached_image_data->GetReference();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostResource result;
4977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PP_ImageDataDesc desc;
4987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  switch (type) {
4997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case PPB_ImageData_Shared::SIMPLE: {
5007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ppapi::proxy::SerializedHandle image_handle_wrapper;
5017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      dispatcher->Send(new PpapiHostMsg_PPBImageData_CreateSimple(
5027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kApiID, instance, format, size, init_to_zero,
5037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          &result, &desc, &image_handle_wrapper));
5047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (image_handle_wrapper.is_shmem()) {
5057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::SharedMemoryHandle image_handle = image_handle_wrapper.shmem();
5067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        if (!result.is_null())
5077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          return
5087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              (new SimpleImageData(result, desc, image_handle))->GetReference();
5097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
5107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
5117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
5127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case PPB_ImageData_Shared::PLATFORM: {
5137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#if !defined(OS_NACL)
5147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ImageHandle image_handle = PlatformImageData::NullHandle();
5157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      dispatcher->Send(new PpapiHostMsg_PPBImageData_CreatePlatform(
5167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kApiID, instance, format, size, init_to_zero,
5177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          &result, &desc, &image_handle));
5187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!result.is_null())
5197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return
5207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            (new PlatformImageData(result, desc, image_handle))->GetReference();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
5227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      // PlatformImageData shouldn't be created in untrusted code.
5237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      NOTREACHED();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
5267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
5277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return 0;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PPB_ImageData_Proxy::OnMessageReceived(const IPC::Message& msg) {
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(PPB_ImageData_Proxy, msg)
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_NACL)
5367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreatePlatform,
5377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        OnHostMsgCreatePlatform)
5387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBImageData_CreateSimple,
5397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        OnHostMsgCreateSimple)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiMsg_PPBImageData_NotifyUnusedImageData,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnPluginMsgNotifyUnusedImageData)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_NACL)
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PP_Resource PPB_ImageData_Proxy::CreateImageData(
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PP_Instance instance,
5537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PPB_ImageData_Shared::ImageDataType type,
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PP_ImageDataFormat format,
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const PP_Size& size,
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool init_to_zero,
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PP_ImageDataDesc* desc,
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPC::PlatformFileForTransit* image_handle,
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint32_t* byte_count) {
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!dispatcher)
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thunk::EnterResourceCreation enter(instance);
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (enter.failed())
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Bool pp_init_to_zero = init_to_zero ? PP_TRUE : PP_FALSE;
569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PP_Resource pp_resource = 0;
570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (type) {
571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PPB_ImageData_Shared::SIMPLE: {
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pp_resource = enter.functions()->CreateImageDataSimple(
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          instance, format, &size, pp_init_to_zero);
574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case PPB_ImageData_Shared::PLATFORM: {
577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      pp_resource = enter.functions()->CreateImageData(
578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          instance, format, &size, pp_init_to_zero);
579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!pp_resource)
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ppapi::ScopedPPResource resource(ppapi::ScopedPPResource::PassRef(),
587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   pp_resource);
588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  thunk::EnterResourceNoLock<PPB_ImageData_API> enter_resource(resource.get(),
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                               false);
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (enter_resource.object()->Describe(desc) != PP_TRUE) {
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DVLOG(1) << "CreateImageData failed: could not Describe";
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int local_fd = 0;
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (enter_resource.object()->GetSharedMemory(&local_fd,
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               byte_count) != PP_OK) {
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DVLOG(1) << "CreateImageData failed: could not GetSharedMemory";
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 0;
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_WIN)
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *image_handle = dispatcher->ShareHandleWithRemote(
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false);
60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#elif defined(OS_POSIX)
60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *image_handle = dispatcher->ShareHandleWithRemote(local_fd, false);
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  #error Not implemented.
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return resource.Release();
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void PPB_ImageData_Proxy::OnHostMsgCreatePlatform(
6167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_Instance instance,
6177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int32_t format,
6187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const PP_Size& size,
6197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_Bool init_to_zero,
6207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    HostResource* result,
6217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_ImageDataDesc* desc,
6227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ImageHandle* result_image_handle) {
623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Clear |desc| so we don't send unitialized memory to the plugin.
624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // https://crbug.com/391023.
625116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *desc = PP_ImageDataDesc();
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC::PlatformFileForTransit image_handle;
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint32_t byte_count;
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource resource =
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CreateImageData(instance,
6307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      PPB_ImageData_Shared::PLATFORM,
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      static_cast<PP_ImageDataFormat>(format),
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      size,
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      true /* init_to_zero */,
6347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      desc, &image_handle, &byte_count);
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result->SetHostResource(instance, resource);
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (resource) {
63790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *result_image_handle = image_handle;
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
6397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    *result_image_handle = PlatformImageData::NullHandle();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void PPB_ImageData_Proxy::OnHostMsgCreateSimple(
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Instance instance,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t format,
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PP_Size& size,
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Bool init_to_zero,
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostResource* result,
6497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    PP_ImageDataDesc* desc,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppapi::proxy::SerializedHandle* result_image_handle) {
651116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Clear |desc| so we don't send unitialized memory to the plugin.
652116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // https://crbug.com/391023.
653116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  *desc = PP_ImageDataDesc();
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPC::PlatformFileForTransit image_handle;
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uint32_t byte_count;
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_Resource resource =
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CreateImageData(instance,
6587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      PPB_ImageData_Shared::SIMPLE,
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      static_cast<PP_ImageDataFormat>(format),
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      size,
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      true /* init_to_zero */,
6627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      desc, &image_handle, &byte_count);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->SetHostResource(instance, resource);
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (resource) {
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result_image_handle->set_shmem(image_handle, byte_count);
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    result_image_handle->set_null_shmem();
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // !defined(OS_NACL)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_ImageData_Proxy::OnPluginMsgNotifyUnusedImageData(
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostResource& old_image_data) {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginGlobals* plugin_globals = PluginGlobals::Get();
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!plugin_globals)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // This may happen if the plugin is maliciously sending this
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             // message to the renderer.
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterPluginFromHostResource<PPB_ImageData_API> enter(old_image_data);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.succeeded()) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImageData* image_data = static_cast<ImageData*>(enter.object());
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ImageDataCache::GetInstance()->ImageDataUsable(image_data);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The renderer sent us a reference with the message. If the image data was
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // still cached in our process, the proxy still holds a reference so we can
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // remove the one the renderer just sent is. If the proxy no longer holds a
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference, we released everything and we should also release the one the
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // renderer just sent us.
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dispatcher()->Send(new PpapiHostMsg_PPBCore_ReleaseResource(
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      API_ID_PPB_CORE, old_image_data));
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace proxy
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
697