1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_RENDERER_PEPPER_PPB_IMAGE_DATA_IMPL_H_
6#define CONTENT_RENDERER_PEPPER_PPB_IMAGE_DATA_IMPL_H_
7
8#include "base/basictypes.h"
9#include "base/memory/scoped_ptr.h"
10#include "content/common/content_export.h"
11#include "ppapi/c/ppb_image_data.h"
12#include "ppapi/shared_impl/ppb_image_data_shared.h"
13#include "ppapi/shared_impl/resource.h"
14#include "ppapi/thunk/ppb_image_data_api.h"
15#include "third_party/skia/include/core/SkCanvas.h"
16
17class SkBitmap;
18class SkCanvas;
19class TransportDIB;
20
21namespace base {
22class SharedMemory;
23}
24
25namespace content {
26
27class CONTENT_EXPORT PPB_ImageData_Impl
28    : public ppapi::Resource,
29      public ppapi::PPB_ImageData_Shared,
30      public NON_EXPORTED_BASE(ppapi::thunk::PPB_ImageData_API) {
31 public:
32  // We delegate most of our implementation to a back-end class that either uses
33  // a PlatformCanvas (for most trusted stuff) or bare shared memory (for use by
34  // NaCl, or trusted plugins when the PlatformCanvas isn't needed). This makes
35  // it cheap & easy to implement Swap.
36  class Backend {
37   public:
38    virtual ~Backend() {};
39    virtual bool Init(PPB_ImageData_Impl* impl,
40                      PP_ImageDataFormat format,
41                      int width,
42                      int height,
43                      bool init_to_zero) = 0;
44    virtual bool IsMapped() const = 0;
45    virtual TransportDIB* GetTransportDIB() const = 0;
46    virtual void* Map() = 0;
47    virtual void Unmap() = 0;
48    virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) = 0;
49    virtual SkCanvas* GetPlatformCanvas() = 0;
50    virtual SkCanvas* GetCanvas() = 0;
51    virtual const SkBitmap* GetMappedBitmap() const = 0;
52  };
53
54  // If you call this constructor, you must also call Init before use. Normally
55  // you should use the static Create function, but this constructor is needed
56  // for some internal uses of ImageData (like Graphics2D).
57  PPB_ImageData_Impl(PP_Instance instance,
58                     PPB_ImageData_Shared::ImageDataType type);
59
60  // Constructor used for unittests. The ImageData is always allocated locally.
61  struct ForTest {};
62  PPB_ImageData_Impl(PP_Instance instance, ForTest);
63
64  bool Init(PP_ImageDataFormat format,
65            int width,
66            int height,
67            bool init_to_zero);
68
69  static PP_Resource Create(PP_Instance pp_instance,
70                            PPB_ImageData_Shared::ImageDataType type,
71                            PP_ImageDataFormat format,
72                            const PP_Size& size,
73                            PP_Bool init_to_zero);
74
75  int width() const { return width_; }
76  int height() const { return height_; }
77
78  // Returns the image format.
79  PP_ImageDataFormat format() const { return format_; }
80
81  // Returns true if this image is mapped. False means that the image is either
82  // invalid or not mapped. See ImageDataAutoMapper below.
83  bool IsMapped() const;
84  TransportDIB* GetTransportDIB() const;
85
86  // Resource override.
87  virtual ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
88
89  // PPB_ImageData_API implementation.
90  virtual PP_Bool Describe(PP_ImageDataDesc* desc) OVERRIDE;
91  virtual void* Map() OVERRIDE;
92  virtual void Unmap() OVERRIDE;
93  virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
94  virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
95  virtual SkCanvas* GetCanvas() OVERRIDE;
96  virtual void SetIsCandidateForReuse() OVERRIDE;
97
98  const SkBitmap* GetMappedBitmap() const;
99
100 private:
101  virtual ~PPB_ImageData_Impl();
102
103  PP_ImageDataFormat format_;
104  int width_;
105  int height_;
106  scoped_ptr<Backend> backend_;
107
108  DISALLOW_COPY_AND_ASSIGN(PPB_ImageData_Impl);
109};
110
111class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
112 public:
113  // |is_browser_allocated| indicates whether the backing shared memory should
114  // be allocated by the browser process.
115  ImageDataPlatformBackend(bool is_browser_allocated);
116  virtual ~ImageDataPlatformBackend();
117
118  // PPB_ImageData_Impl::Backend implementation.
119  virtual bool Init(PPB_ImageData_Impl* impl,
120                    PP_ImageDataFormat format,
121                    int width,
122                    int height,
123                    bool init_to_zero) OVERRIDE;
124  virtual bool IsMapped() const OVERRIDE;
125  virtual TransportDIB* GetTransportDIB() const OVERRIDE;
126  virtual void* Map() OVERRIDE;
127  virtual void Unmap() OVERRIDE;
128  virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
129  virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
130  virtual SkCanvas* GetCanvas() OVERRIDE;
131  virtual const SkBitmap* GetMappedBitmap() const OVERRIDE;
132
133 private:
134  // This will be NULL before initialization, and if this PPB_ImageData_Impl is
135  // swapped with another.
136  int width_;
137  int height_;
138  scoped_ptr<TransportDIB> dib_;
139
140  bool is_browser_allocated_;
141
142  // When the device is mapped, this is the image. Null when umapped.
143  scoped_ptr<SkCanvas> mapped_canvas_;
144
145  DISALLOW_COPY_AND_ASSIGN(ImageDataPlatformBackend);
146};
147
148class ImageDataSimpleBackend : public PPB_ImageData_Impl::Backend {
149 public:
150  ImageDataSimpleBackend();
151  virtual ~ImageDataSimpleBackend();
152
153  // PPB_ImageData_Impl::Backend implementation.
154  virtual bool Init(PPB_ImageData_Impl* impl,
155                    PP_ImageDataFormat format,
156                    int width,
157                    int height,
158                    bool init_to_zero) OVERRIDE;
159  virtual bool IsMapped() const OVERRIDE;
160  virtual TransportDIB* GetTransportDIB() const OVERRIDE;
161  virtual void* Map() OVERRIDE;
162  virtual void Unmap() OVERRIDE;
163  virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
164  virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
165  virtual SkCanvas* GetCanvas() OVERRIDE;
166  virtual const SkBitmap* GetMappedBitmap() const OVERRIDE;
167
168 private:
169  scoped_ptr<base::SharedMemory> shared_memory_;
170  // skia_bitmap_ is backed by shared_memory_.
171  SkBitmap skia_bitmap_;
172  scoped_ptr<SkCanvas> skia_canvas_;
173  uint32 map_count_;
174
175  DISALLOW_COPY_AND_ASSIGN(ImageDataSimpleBackend);
176};
177
178// Manages mapping an image resource if necessary. Use this to ensure the
179// image is mapped. The destructor will put the image back into the previous
180// state. You must check is_valid() to make sure the image was successfully
181// mapped before using it.
182//
183// Example:
184//   ImageDataAutoMapper mapper(image_data);
185//   if (!mapper.is_valid())
186//     return utter_failure;
187//   image_data->mapped_canvas()->blah();  // Guaranteed valid.
188class ImageDataAutoMapper {
189 public:
190  explicit ImageDataAutoMapper(PPB_ImageData_Impl* image_data)
191      : image_data_(image_data) {
192    if (image_data_->IsMapped()) {
193      is_valid_ = true;
194      needs_unmap_ = false;
195    } else {
196      is_valid_ = needs_unmap_ = !!image_data_->Map();
197    }
198  }
199
200  ~ImageDataAutoMapper() {
201    if (needs_unmap_)
202      image_data_->Unmap();
203  }
204
205  // Check this to see if the image was successfully mapped. If this is false,
206  // the image could not be mapped and is unusable.
207  bool is_valid() const { return is_valid_; }
208
209 private:
210  PPB_ImageData_Impl* image_data_;
211  bool is_valid_;
212  bool needs_unmap_;
213
214  DISALLOW_COPY_AND_ASSIGN(ImageDataAutoMapper);
215};
216
217}  // namespace content
218
219#endif  // CONTENT_RENDERER_PEPPER_PPB_IMAGE_DATA_IMPL_H_
220