blob: 8247336d49e96d3d7698dbb8bdaf61a1a9498b41 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2007 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
herbb906daf2015-09-29 09:37:59 -07008#include "SkAtomics.h"
mtklein9db912c2015-05-19 11:11:26 -07009#include "SkMessageBus.h"
10#include "SkPicture.h"
robertphillipsdb539902014-07-01 08:47:04 -070011#include "SkPictureData.h"
robertphillipsce4dd3d2014-07-07 13:46:35 -070012#include "SkPicturePlayback.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkPictureRecord.h"
mtklein73734562014-06-24 12:28:34 -070014#include "SkPictureRecorder.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015
hendrikw446ee672015-06-16 09:28:37 -070016#if defined(SK_DISALLOW_CROSSPROCESS_PICTUREIMAGEFILTERS) || \
17 defined(SK_ENABLE_PICTURE_IO_SECURITY_PRECAUTIONS)
18static bool g_AllPictureIOSecurityPrecautionsEnabled = true;
19#else
20static bool g_AllPictureIOSecurityPrecautionsEnabled = false;
21#endif
22
mtklein04c96952014-11-24 08:20:57 -080023DECLARE_SKMESSAGEBUS_MESSAGE(SkPicture::DeletionMessage);
24
mtklein9db912c2015-05-19 11:11:26 -070025/* SkPicture impl. This handles generic responsibilities like unique IDs and serialization. */
commit-bot@chromium.org8f831f22014-04-23 22:35:42 +000026
mtklein9db912c2015-05-19 11:11:26 -070027SkPicture::SkPicture() : fUniqueID(0) {}
reed6be2aa92014-11-18 11:08:05 -080028
robertphillipsd771f6b2014-07-22 10:18:06 -070029SkPicture::~SkPicture() {
mtklein9db912c2015-05-19 11:11:26 -070030 // TODO: move this to ~SkBigPicture() only?
31
mtkleine35268e2015-04-07 06:34:05 -070032 // If the ID is still zero, no one has read it, so no need to send this message.
33 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
34 if (id != 0) {
mtklein9db912c2015-05-19 11:11:26 -070035 SkPicture::DeletionMessage msg = { (int32_t)id };
mtkleine35268e2015-04-07 06:34:05 -070036 SkMessageBus<SkPicture::DeletionMessage>::Post(msg);
37 }
robertphillipsd771f6b2014-07-22 10:18:06 -070038}
reed@android.com8a1c16f2008-12-17 15:59:43 +000039
mtklein9db912c2015-05-19 11:11:26 -070040uint32_t SkPicture::uniqueID() const {
41 static uint32_t gNextID = 1;
42 uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
43 while (id == 0) {
44 uint32_t next = sk_atomic_fetch_add(&gNextID, 1u);
45 if (sk_atomic_compare_exchange(&fUniqueID, &id, next,
46 sk_memory_order_relaxed,
47 sk_memory_order_relaxed)) {
48 id = next;
49 } else {
50 // sk_atomic_compare_exchange replaced id with the current value of fUniqueID.
51 }
reedb7ed8562015-05-07 17:30:13 -070052 }
mtklein9db912c2015-05-19 11:11:26 -070053 return id;
reedb7ed8562015-05-07 17:30:13 -070054}
55
reedb7ed8562015-05-07 17:30:13 -070056static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
57
mtklein9db912c2015-05-19 11:11:26 -070058SkPictInfo SkPicture::createHeader() const {
59 SkPictInfo info;
60 // Copy magic bytes at the beginning of the header
61 static_assert(sizeof(kMagic) == 8, "");
62 static_assert(sizeof(kMagic) == sizeof(info.fMagic), "");
63 memcpy(info.fMagic, kMagic, sizeof(kMagic));
64
65 // Set picture info after magic bytes in the header
66 info.fVersion = CURRENT_PICTURE_VERSION;
67 info.fCullRect = this->cullRect();
68 info.fFlags = SkPictInfo::kCrossProcess_Flag;
69 // TODO: remove this flag, since we're always float (now)
70 info.fFlags |= SkPictInfo::kScalarIsFloat_Flag;
71
72 if (8 == sizeof(void*)) {
73 info.fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
74 }
75 return info;
76}
77
reedb7ed8562015-05-07 17:30:13 -070078bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
79 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
80 return false;
81 }
mtklein9db912c2015-05-19 11:11:26 -070082 if (info.fVersion < MIN_PICTURE_VERSION || info.fVersion > CURRENT_PICTURE_VERSION) {
reedb7ed8562015-05-07 17:30:13 -070083 return false;
84 }
reedb7ed8562015-05-07 17:30:13 -070085 return true;
86}
87
88bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
mtklein9db912c2015-05-19 11:11:26 -070089 if (!stream) {
reedb7ed8562015-05-07 17:30:13 -070090 return false;
91 }
92
reedb7ed8562015-05-07 17:30:13 -070093 SkPictInfo info;
94 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
reedb7ed8562015-05-07 17:30:13 -070095 if (!stream->read(&info.fMagic, sizeof(kMagic))) {
96 return false;
97 }
98
mtklein9db912c2015-05-19 11:11:26 -070099 info.fVersion = stream->readU32();
100 info.fCullRect.fLeft = stream->readScalar();
101 info.fCullRect.fTop = stream->readScalar();
102 info.fCullRect.fRight = stream->readScalar();
reedb7ed8562015-05-07 17:30:13 -0700103 info.fCullRect.fBottom = stream->readScalar();
mtklein9db912c2015-05-19 11:11:26 -0700104 info.fFlags = stream->readU32();
reedb7ed8562015-05-07 17:30:13 -0700105
mtklein9db912c2015-05-19 11:11:26 -0700106 if (IsValidPictInfo(info)) {
107 if (pInfo) { *pInfo = info; }
108 return true;
reedb7ed8562015-05-07 17:30:13 -0700109 }
mtklein9db912c2015-05-19 11:11:26 -0700110 return false;
reedb7ed8562015-05-07 17:30:13 -0700111}
112
113bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo) {
reedb7ed8562015-05-07 17:30:13 -0700114 SkPictInfo info;
115 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
reedb7ed8562015-05-07 17:30:13 -0700116 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
117 return false;
118 }
119
120 info.fVersion = buffer->readUInt();
121 buffer->readRect(&info.fCullRect);
122 info.fFlags = buffer->readUInt();
123
mtklein9db912c2015-05-19 11:11:26 -0700124 if (IsValidPictInfo(info)) {
125 if (pInfo) { *pInfo = info; }
126 return true;
reedb7ed8562015-05-07 17:30:13 -0700127 }
mtklein9db912c2015-05-19 11:11:26 -0700128 return false;
reedb7ed8562015-05-07 17:30:13 -0700129}
130
131SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* data) {
132 if (!data) {
mtklein9db912c2015-05-19 11:11:26 -0700133 return nullptr;
reedb7ed8562015-05-07 17:30:13 -0700134 }
135 SkPicturePlayback playback(data);
136 SkPictureRecorder r;
fmalita2ecc0002015-07-14 13:12:25 -0700137 playback.draw(r.beginRecording(info.fCullRect), nullptr/*no callback*/);
reedb7ed8562015-05-07 17:30:13 -0700138 return r.endRecording();
139}
140
141SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc proc) {
mtklein0c263fa2015-08-18 08:29:59 -0700142 return CreateFromStream(stream, proc, nullptr);
143}
144
145SkPicture* SkPicture::CreateFromStream(SkStream* stream,
146 InstallPixelRefProc proc,
147 SkTypefacePlayback* typefaces) {
reedb7ed8562015-05-07 17:30:13 -0700148 SkPictInfo info;
149 if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
mtklein9db912c2015-05-19 11:11:26 -0700150 return nullptr;
reedb7ed8562015-05-07 17:30:13 -0700151 }
mtklein0c263fa2015-08-18 08:29:59 -0700152 SkAutoTDelete<SkPictureData> data(
153 SkPictureData::CreateFromStream(stream, info, proc, typefaces));
reedb7ed8562015-05-07 17:30:13 -0700154 return Forwardport(info, data);
155}
156
157SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
158 SkPictInfo info;
159 if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) {
mtklein9db912c2015-05-19 11:11:26 -0700160 return nullptr;
reedb7ed8562015-05-07 17:30:13 -0700161 }
162 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, info));
163 return Forwardport(info, data);
164}
165
mtklein9db912c2015-05-19 11:11:26 -0700166SkPictureData* SkPicture::backport() const {
167 SkPictInfo info = this->createHeader();
reedb7ed8562015-05-07 17:30:13 -0700168 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/);
169 rec.beginRecording();
mtklein9db912c2015-05-19 11:11:26 -0700170 this->playback(&rec);
reedb7ed8562015-05-07 17:30:13 -0700171 rec.endRecording();
halcanary385fe4d2015-08-26 13:07:48 -0700172 return new SkPictureData(rec, info, false /*deep copy ops?*/);
reedb7ed8562015-05-07 17:30:13 -0700173}
174
175void SkPicture::serialize(SkWStream* stream, SkPixelSerializer* pixelSerializer) const {
mtklein0c263fa2015-08-18 08:29:59 -0700176 this->serialize(stream, pixelSerializer, nullptr);
177}
178
179void SkPicture::serialize(SkWStream* stream,
180 SkPixelSerializer* pixelSerializer,
181 SkRefCntSet* typefaceSet) const {
mtklein9db912c2015-05-19 11:11:26 -0700182 SkPictInfo info = this->createHeader();
183 SkAutoTDelete<SkPictureData> data(this->backport());
reedb7ed8562015-05-07 17:30:13 -0700184
185 stream->write(&info, sizeof(info));
186 if (data) {
187 stream->writeBool(true);
mtklein0c263fa2015-08-18 08:29:59 -0700188 data->serialize(stream, pixelSerializer, typefaceSet);
reedb7ed8562015-05-07 17:30:13 -0700189 } else {
190 stream->writeBool(false);
191 }
192}
193
194void SkPicture::flatten(SkWriteBuffer& buffer) const {
mtklein9db912c2015-05-19 11:11:26 -0700195 SkPictInfo info = this->createHeader();
196 SkAutoTDelete<SkPictureData> data(this->backport());
reedb7ed8562015-05-07 17:30:13 -0700197
198 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
199 buffer.writeUInt(info.fVersion);
200 buffer.writeRect(info.fCullRect);
201 buffer.writeUInt(info.fFlags);
202 if (data) {
203 buffer.writeBool(true);
204 data->flatten(buffer);
205 } else {
206 buffer.writeBool(false);
207 }
208}
209
mtklein9db912c2015-05-19 11:11:26 -0700210bool SkPicture::suitableForGpuRasterization(GrContext*, const char** whyNot) const {
211 if (this->numSlowPaths() > 5) {
212 if (whyNot) { *whyNot = "Too many slow paths (either concave or dashed)."; }
213 return false;
mtkleine35268e2015-04-07 06:34:05 -0700214 }
mtklein9db912c2015-05-19 11:11:26 -0700215 return true;
mtkleine35268e2015-04-07 06:34:05 -0700216}
hendrikw446ee672015-06-16 09:28:37 -0700217
218// Global setting to disable security precautions for serialization.
219void SkPicture::SetPictureIOSecurityPrecautionsEnabled_Dangerous(bool set) {
220 g_AllPictureIOSecurityPrecautionsEnabled = set;
221}
222
223bool SkPicture::PictureIOSecurityPrecautionsEnabled() {
224 return g_AllPictureIOSecurityPrecautionsEnabled;
225}