blob: cf72a3cacaf7bc9ff3250915152f3d5ac9df4101 [file] [log] [blame]
mtklein748ca3b2015-01-15 10:56:12 -08001#include "DMSrcSink.h"
2#include "SamplePipeControllers.h"
3#include "SkCommonFlags.h"
4#include "SkDocument.h"
5#include "SkMultiPictureDraw.h"
6#include "SkOSFile.h"
7#include "SkPictureRecorder.h"
8#include "SkRandom.h"
mtklein748ca3b2015-01-15 10:56:12 -08009
10namespace DM {
11
mtklein748ca3b2015-01-15 10:56:12 -080012GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
13
14Error GMSrc::draw(SkCanvas* canvas) const {
15 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
16 canvas->concat(gm->getInitialTransform());
17 gm->draw(canvas);
18 return "";
19}
20
21SkISize GMSrc::size() const {
22 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
23 return gm->getISize();
24}
25
26Name GMSrc::name() const {
27 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
28 return gm->getName();
29}
30
31/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
32
mtklein748ca3b2015-01-15 10:56:12 -080033ImageSrc::ImageSrc(SkString path, int subsets) : fPath(path), fSubsets(subsets) {}
34
35Error ImageSrc::draw(SkCanvas* canvas) const {
mtklein75d98fd2015-01-18 07:05:01 -080036 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080037 if (!encoded) {
38 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
39 }
40 if (fSubsets == 0) {
41 // Decode the full image.
42 SkBitmap bitmap;
43 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap)) {
44 return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
45 }
mtklein75d98fd2015-01-18 07:05:01 -080046 encoded.reset((SkData*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -080047 canvas->drawBitmap(bitmap, 0,0);
48 return "";
49 }
50 // Decode random subsets. This is a little involved.
51 SkMemoryStream stream(encoded->data(), encoded->size());
52 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
53 if (!decoder) {
54 return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
55 }
56 int w,h;
57 if (!decoder->buildTileIndex(&stream, &w, &h) || w*h == 1) {
58 return ""; // Not an error. Subset decoding is not always supported.
59 }
60 SkRandom rand;
61 for (int i = 0; i < fSubsets; i++) {
62 SkIRect rect;
63 do {
64 rect.fLeft = rand.nextULessThan(w);
65 rect.fTop = rand.nextULessThan(h);
66 rect.fRight = rand.nextULessThan(w);
67 rect.fBottom = rand.nextULessThan(h);
68 rect.sort();
69 } while (rect.isEmpty());
70 SkBitmap subset;
71 if (!decoder->decodeSubset(&subset, rect, kUnknown_SkColorType/*use best fit*/)) {
72 return SkStringPrintf("Could not decode subset %d.\n", i);
73 }
74 canvas->drawBitmap(subset, SkIntToScalar(rect.fLeft), SkIntToScalar(rect.fTop));
75 }
76 return "";
77}
78
79SkISize ImageSrc::size() const {
mtklein75d98fd2015-01-18 07:05:01 -080080 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080081 SkBitmap bitmap;
82 if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
83 encoded->size(),
84 &bitmap,
85 kUnknown_SkColorType,
86 SkImageDecoder::kDecodeBounds_Mode)) {
87 return SkISize::Make(0,0);
88 }
89 return bitmap.dimensions();
90}
91
92Name ImageSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
93
94/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
95
96static const SkRect kSKPViewport = {0,0, 1000,1000};
97
mtklein748ca3b2015-01-15 10:56:12 -080098SKPSrc::SKPSrc(SkString path) : fPath(path) {}
99
100Error SKPSrc::draw(SkCanvas* canvas) const {
mtklein75d98fd2015-01-18 07:05:01 -0800101 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
102 if (!stream) {
mtklein748ca3b2015-01-15 10:56:12 -0800103 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
104 }
mtklein75d98fd2015-01-18 07:05:01 -0800105 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream));
106 if (!pic) {
107 return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
108 }
109 stream.reset((SkStream*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -0800110 canvas->clipRect(kSKPViewport);
111 canvas->drawPicture(pic);
112 return "";
113}
114
115SkISize SKPSrc::size() const {
mtklein75d98fd2015-01-18 07:05:01 -0800116 // This may be unnecessarily large.
117 return kSKPViewport.roundOut().size();
mtklein748ca3b2015-01-15 10:56:12 -0800118}
119
120Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
121
122/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
123
mtklein82d28432015-01-15 12:46:02 -0800124GPUSink::GPUSink(GrContextFactory::GLContextType ct,
125 GrGLStandard api,
126 int samples,
127 bool dfText,
128 bool threaded)
mtklein748ca3b2015-01-15 10:56:12 -0800129 : fContextType(ct)
130 , fGpuAPI(api)
131 , fSampleCount(samples)
mtklein82d28432015-01-15 12:46:02 -0800132 , fUseDFText(dfText)
133 , fThreaded(threaded) {}
mtklein748ca3b2015-01-15 10:56:12 -0800134
135int GPUSink::enclave() const {
mtklein82d28432015-01-15 12:46:02 -0800136 return fThreaded ? kAnyThread_Enclave : kGPUSink_Enclave;
mtklein748ca3b2015-01-15 10:56:12 -0800137}
138
mtklein748ca3b2015-01-15 10:56:12 -0800139Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
mtklein82d28432015-01-15 12:46:02 -0800140 GrContextFactory* factory = GetThreadLocalGrContextFactory();
mtklein748ca3b2015-01-15 10:56:12 -0800141 if (FLAGS_abandonGpuContext) {
142 factory->abandonContexts();
143 }
144 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
145 factory->destroyContexts();
146 }
147 const SkISize size = src.size();
148 const SkImageInfo info =
149 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
150 SkAutoTUnref<SkSurface> surface(
151 NewGpuSurface(factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
152 if (!surface) {
153 return "Could not create a surface.";
154 }
155 SkCanvas* canvas = surface->getCanvas();
156 Error err = src.draw(canvas);
157 if (!err.isEmpty()) {
158 return err;
159 }
160 canvas->flush();
161 dst->allocPixels(info);
162 canvas->readPixels(dst, 0,0);
163 return "";
164}
165
166/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
167
168PDFSink::PDFSink() {}
169
170Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
171 SkSize size;
172 size = src.size();
173 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
174 SkCanvas* canvas = doc->beginPage(size.width(), size.height());
175
176 Error err = src.draw(canvas);
177 if (!err.isEmpty()) {
178 return err;
179 }
180 canvas->flush();
181 doc->endPage();
182 doc->close();
183 return "";
184}
185
186/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
187
188RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
189
190Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
191 const SkISize size = src.size();
192 // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
193 SkAlphaType alphaType = kPremul_SkAlphaType;
194 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
195
196 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
197 dst->eraseColor(SK_ColorTRANSPARENT);
198 SkCanvas canvas(*dst);
199 return src.draw(&canvas);
200}
201
202/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
203
204ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
205
206Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
207 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
208 struct ProxySrc : public Src {
209 const Src& fSrc;
210 SkMatrix fMatrix;
211 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {}
212
213 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
214 canvas->concat(fMatrix);
215 return fSrc.draw(canvas);
216 }
217 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
218 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
219 } proxy(src, fMatrix);
220 return fSink->draw(proxy, bitmap, stream);
221}
222
223/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
224
225ViaPipe::ViaPipe(int flags, Sink* sink) : fFlags((SkGPipeWriter::Flags)flags), fSink(sink) {}
226
227Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
228 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
229 struct ProxySrc : public Src {
230 const Src& fSrc;
231 SkGPipeWriter::Flags fFlags;
232 ProxySrc(const Src& src, SkGPipeWriter::Flags flags) : fSrc(src), fFlags(flags) {}
233
234 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
235 SkISize size = this->size();
236 // TODO: is DecodeMemory really required? Might help RAM usage to be lazy if we can.
237 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
238 SkGPipeWriter pipe;
239 return fSrc.draw(pipe.startRecording(&controller, fFlags, size.width(), size.height()));
240 }
241 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
242 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
243 } proxy(src, fFlags);
244 return fSink->draw(proxy, bitmap, stream);
245}
246
247/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
248
249ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
250
251Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
252 // Record our Src into a picture.
253 SkSize size;
254 size = src.size();
255 SkPictureRecorder recorder;
256 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
257 if (!err.isEmpty()) {
258 return err;
259 }
260 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
261
262 // Serialize it and then deserialize it.
263 SkDynamicMemoryWStream wStream;
264 pic->serialize(&wStream);
265 SkAutoTUnref<SkStream> rStream(wStream.detachAsStream());
266 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
267
268 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
269 struct ProxySrc : public Src {
270 const SkPicture* fPic;
271 const SkISize fSize;
272 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
273
274 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
275 canvas->drawPicture(fPic);
276 return "";
277 }
278 SkISize size() const SK_OVERRIDE { return fSize; }
279 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
280 } proxy(deserialized, src.size());
281 return fSink->draw(proxy, bitmap, stream);
282}
283
284/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
285
286ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
287 : fW(w)
288 , fH(h)
289 , fFactory(factory)
290 , fSink(sink) {}
291
292Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
293 // Record our Src into a picture.
294 SkSize size;
295 size = src.size();
296 SkPictureRecorder recorder;
297 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
298 if (!err.isEmpty()) {
299 return err;
300 }
301 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
302
303 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
304 struct ProxySrc : public Src {
305 const int fW, fH;
306 const SkPicture* fPic;
307 const SkISize fSize;
308 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
309 : fW(w), fH(h), fPic(pic), fSize(size) {}
310
311 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
312 const int xTiles = (fSize.width() + fW - 1) / fW,
313 yTiles = (fSize.height() + fH - 1) / fH;
314 SkMultiPictureDraw mpd(xTiles*yTiles);
315 SkTDArray<SkSurface*> surfaces;
316 surfaces.setReserve(xTiles*yTiles);
317
318 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
319 for (int j = 0; j < yTiles; j++) {
320 for (int i = 0; i < xTiles; i++) {
321 // This lets our ultimate Sink determine the best kind of surface.
322 // E.g., if it's a GpuSink, the surfaces and images are textures.
323 SkSurface* s = canvas->newSurface(info);
324 if (!s) {
325 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
326 }
327 surfaces.push(s);
328 SkCanvas* c = s->getCanvas();
329 c->translate(SkIntToScalar(-i * fW),
330 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
331 mpd.add(c, fPic);
332 }
333 }
334 mpd.draw();
335 for (int j = 0; j < yTiles; j++) {
336 for (int i = 0; i < xTiles; i++) {
337 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
338 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
339 }
340 }
341 surfaces.unrefAll();
342 return "";
343 }
344 SkISize size() const SK_OVERRIDE { return fSize; }
345 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
346 } proxy(fW, fH, pic, src.size());
347 return fSink->draw(proxy, bitmap, stream);
348}
349
350} // namespace DM