Add a few more entries to CFI blacklist.
[chromium-blink-merge.git] / content / renderer / pepper / ppb_image_data_impl.cc
blob64d269adda9c9b0d5fca1c9a73099c2b57bd7fda
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.
5 #include "content/renderer/pepper/ppb_image_data_impl.h"
7 #include <algorithm>
8 #include <limits>
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "content/common/pepper_file_util.h"
13 #include "content/common/view_messages.h"
14 #include "content/renderer/render_thread_impl.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/pp_instance.h"
17 #include "ppapi/c/pp_resource.h"
18 #include "ppapi/c/ppb_image_data.h"
19 #include "ppapi/thunk/thunk.h"
20 #include "skia/ext/platform_canvas.h"
21 #include "third_party/skia/include/core/SkColorPriv.h"
22 #include "ui/surface/transport_dib.h"
24 using ppapi::thunk::PPB_ImageData_API;
26 namespace content {
28 PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
29 PPB_ImageData_Shared::ImageDataType type)
30 : Resource(ppapi::OBJECT_IS_IMPL, instance),
31 format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
32 width_(0),
33 height_(0) {
34 switch (type) {
35 case PPB_ImageData_Shared::PLATFORM:
36 backend_.reset(new ImageDataPlatformBackend());
37 return;
38 case PPB_ImageData_Shared::SIMPLE:
39 backend_.reset(new ImageDataSimpleBackend);
40 return;
41 // No default: so that we get a compiler warning if any types are added.
43 NOTREACHED();
46 PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance, ForTest)
47 : Resource(ppapi::OBJECT_IS_IMPL, instance),
48 format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
49 width_(0),
50 height_(0) {
51 backend_.reset(new ImageDataPlatformBackend());
54 PPB_ImageData_Impl::~PPB_ImageData_Impl() {}
56 bool PPB_ImageData_Impl::Init(PP_ImageDataFormat format,
57 int width,
58 int height,
59 bool init_to_zero) {
60 // TODO(brettw) this should be called only on the main thread!
61 if (!IsImageDataFormatSupported(format))
62 return false; // Only support this one format for now.
63 if (width <= 0 || height <= 0)
64 return false;
65 if (static_cast<int64>(width) * static_cast<int64>(height) >=
66 std::numeric_limits<int32>::max() / 4)
67 return false; // Prevent overflow of signed 32-bit ints.
69 format_ = format;
70 width_ = width;
71 height_ = height;
72 return backend_->Init(this, format, width, height, init_to_zero);
75 // static
76 PP_Resource PPB_ImageData_Impl::Create(PP_Instance instance,
77 PPB_ImageData_Shared::ImageDataType type,
78 PP_ImageDataFormat format,
79 const PP_Size& size,
80 PP_Bool init_to_zero) {
81 scoped_refptr<PPB_ImageData_Impl> data(
82 new PPB_ImageData_Impl(instance, type));
83 if (!data->Init(format, size.width, size.height, !!init_to_zero))
84 return 0;
85 return data->GetReference();
88 PPB_ImageData_API* PPB_ImageData_Impl::AsPPB_ImageData_API() { return this; }
90 bool PPB_ImageData_Impl::IsMapped() const { return backend_->IsMapped(); }
92 TransportDIB* PPB_ImageData_Impl::GetTransportDIB() const {
93 return backend_->GetTransportDIB();
96 PP_Bool PPB_ImageData_Impl::Describe(PP_ImageDataDesc* desc) {
97 desc->format = format_;
98 desc->size.width = width_;
99 desc->size.height = height_;
100 desc->stride = width_ * 4;
101 return PP_TRUE;
104 void* PPB_ImageData_Impl::Map() { return backend_->Map(); }
106 void PPB_ImageData_Impl::Unmap() { backend_->Unmap(); }
108 int32_t PPB_ImageData_Impl::GetSharedMemory(base::SharedMemory** shm,
109 uint32_t* byte_count) {
110 return backend_->GetSharedMemory(shm, byte_count);
113 skia::PlatformCanvas* PPB_ImageData_Impl::GetPlatformCanvas() {
114 return backend_->GetPlatformCanvas();
117 SkCanvas* PPB_ImageData_Impl::GetCanvas() { return backend_->GetCanvas(); }
119 void PPB_ImageData_Impl::SetIsCandidateForReuse() {
120 // Nothing to do since we don't support image data re-use in-process.
123 const SkBitmap* PPB_ImageData_Impl::GetMappedBitmap() const {
124 return backend_->GetMappedBitmap();
127 // ImageDataPlatformBackend ----------------------------------------------------
129 ImageDataPlatformBackend::ImageDataPlatformBackend() : width_(0), height_(0) {
132 ImageDataPlatformBackend::~ImageDataPlatformBackend() {
135 bool ImageDataPlatformBackend::Init(PPB_ImageData_Impl* impl,
136 PP_ImageDataFormat format,
137 int width,
138 int height,
139 bool init_to_zero) {
140 // TODO(brettw) use init_to_zero when we implement caching.
141 width_ = width;
142 height_ = height;
143 uint32 buffer_size = width_ * height_ * 4;
144 scoped_ptr<base::SharedMemory> shared_memory =
145 RenderThread::Get()->HostAllocateSharedMemoryBuffer(buffer_size);
146 if (!shared_memory)
147 return false;
149 // The TransportDIB is always backed by shared memory, so give the shared
150 // memory handle to it.
151 base::SharedMemoryHandle handle;
152 if (!shared_memory->GiveToProcess(base::GetCurrentProcessHandle(), &handle))
153 return false;
155 dib_.reset(TransportDIB::CreateWithHandle(handle));
157 return !!dib_;
160 bool ImageDataPlatformBackend::IsMapped() const {
161 return !!mapped_canvas_.get();
164 TransportDIB* ImageDataPlatformBackend::GetTransportDIB() const {
165 return dib_.get();
168 void* ImageDataPlatformBackend::Map() {
169 if (!mapped_canvas_) {
170 mapped_canvas_.reset(dib_->GetPlatformCanvas(width_, height_));
171 if (!mapped_canvas_)
172 return NULL;
174 const SkBitmap& bitmap =
175 skia::GetTopDevice(*mapped_canvas_)->accessBitmap(true);
177 // Our platform bitmaps are set to opaque by default, which we don't want.
178 const_cast<SkBitmap&>(bitmap).setAlphaType(kPremul_SkAlphaType);
180 bitmap.lockPixels();
181 return bitmap.getAddr32(0, 0);
184 void ImageDataPlatformBackend::Unmap() {
185 // This is currently unimplemented, which is OK. The data will just always
186 // be around once it's mapped. Chrome's TransportDIB isn't currently
187 // unmappable without freeing it, but this may be something we want to support
188 // in the future to save some memory.
191 int32_t ImageDataPlatformBackend::GetSharedMemory(base::SharedMemory** shm,
192 uint32_t* byte_count) {
193 *byte_count = dib_->size();
194 *shm = dib_->shared_memory();
195 return PP_OK;
198 skia::PlatformCanvas* ImageDataPlatformBackend::GetPlatformCanvas() {
199 return mapped_canvas_.get();
202 SkCanvas* ImageDataPlatformBackend::GetCanvas() { return mapped_canvas_.get(); }
204 const SkBitmap* ImageDataPlatformBackend::GetMappedBitmap() const {
205 if (!mapped_canvas_)
206 return NULL;
207 return &skia::GetTopDevice(*mapped_canvas_)->accessBitmap(false);
210 // ImageDataSimpleBackend ------------------------------------------------------
212 ImageDataSimpleBackend::ImageDataSimpleBackend() : map_count_(0) {}
214 ImageDataSimpleBackend::~ImageDataSimpleBackend() {}
216 bool ImageDataSimpleBackend::Init(PPB_ImageData_Impl* impl,
217 PP_ImageDataFormat format,
218 int width,
219 int height,
220 bool init_to_zero) {
221 skia_bitmap_.setInfo(
222 SkImageInfo::MakeN32Premul(impl->width(), impl->height()));
223 shared_memory_.reset(
224 RenderThread::Get()
225 ->HostAllocateSharedMemoryBuffer(skia_bitmap_.getSize())
226 .release());
227 return !!shared_memory_.get();
230 bool ImageDataSimpleBackend::IsMapped() const { return map_count_ > 0; }
232 TransportDIB* ImageDataSimpleBackend::GetTransportDIB() const { return NULL; }
234 void* ImageDataSimpleBackend::Map() {
235 DCHECK(shared_memory_.get());
236 if (map_count_++ == 0) {
237 shared_memory_->Map(skia_bitmap_.getSize());
238 skia_bitmap_.setPixels(shared_memory_->memory());
239 // Our platform bitmaps are set to opaque by default, which we don't want.
240 skia_bitmap_.setAlphaType(kPremul_SkAlphaType);
241 skia_canvas_.reset(new SkCanvas(skia_bitmap_));
242 return skia_bitmap_.getAddr32(0, 0);
244 return shared_memory_->memory();
247 void ImageDataSimpleBackend::Unmap() {
248 if (--map_count_ == 0)
249 shared_memory_->Unmap();
252 int32_t ImageDataSimpleBackend::GetSharedMemory(base::SharedMemory** shm,
253 uint32_t* byte_count) {
254 *byte_count = skia_bitmap_.getSize();
255 *shm = shared_memory_.get();
256 return PP_OK;
259 skia::PlatformCanvas* ImageDataSimpleBackend::GetPlatformCanvas() {
260 return NULL;
263 SkCanvas* ImageDataSimpleBackend::GetCanvas() {
264 if (!IsMapped())
265 return NULL;
266 return skia_canvas_.get();
269 const SkBitmap* ImageDataSimpleBackend::GetMappedBitmap() const {
270 if (!IsMapped())
271 return NULL;
272 return &skia_bitmap_;
275 } // namespace content