blob: a57192e8818045a4aeb84c864f5689b9190b2e5a [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"
scroggoa1193e42015-01-21 12:09:53 -08009#include "SkStream.h"
mtklein748ca3b2015-01-15 10:56:12 -080010
11namespace DM {
12
mtklein748ca3b2015-01-15 10:56:12 -080013GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
14
15Error GMSrc::draw(SkCanvas* canvas) const {
16 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
17 canvas->concat(gm->getInitialTransform());
18 gm->draw(canvas);
19 return "";
20}
21
22SkISize GMSrc::size() const {
23 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
24 return gm->getISize();
25}
26
27Name GMSrc::name() const {
28 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
29 return gm->getName();
30}
31
32/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
33
mtklein748ca3b2015-01-15 10:56:12 -080034ImageSrc::ImageSrc(SkString path, int subsets) : fPath(path), fSubsets(subsets) {}
35
36Error ImageSrc::draw(SkCanvas* canvas) const {
mtklein75d98fd2015-01-18 07:05:01 -080037 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080038 if (!encoded) {
39 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
40 }
41 if (fSubsets == 0) {
42 // Decode the full image.
43 SkBitmap bitmap;
44 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap)) {
45 return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
46 }
mtklein75d98fd2015-01-18 07:05:01 -080047 encoded.reset((SkData*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -080048 canvas->drawBitmap(bitmap, 0,0);
49 return "";
50 }
51 // Decode random subsets. This is a little involved.
scroggoa1193e42015-01-21 12:09:53 -080052 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
53 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get()));
mtklein748ca3b2015-01-15 10:56:12 -080054 if (!decoder) {
55 return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
56 }
scroggoa1193e42015-01-21 12:09:53 -080057 stream->rewind();
mtklein748ca3b2015-01-15 10:56:12 -080058 int w,h;
scroggoa1193e42015-01-21 12:09:53 -080059 if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) {
mtklein748ca3b2015-01-15 10:56:12 -080060 return ""; // Not an error. Subset decoding is not always supported.
61 }
62 SkRandom rand;
63 for (int i = 0; i < fSubsets; i++) {
64 SkIRect rect;
65 do {
66 rect.fLeft = rand.nextULessThan(w);
67 rect.fTop = rand.nextULessThan(h);
68 rect.fRight = rand.nextULessThan(w);
69 rect.fBottom = rand.nextULessThan(h);
70 rect.sort();
71 } while (rect.isEmpty());
72 SkBitmap subset;
73 if (!decoder->decodeSubset(&subset, rect, kUnknown_SkColorType/*use best fit*/)) {
74 return SkStringPrintf("Could not decode subset %d.\n", i);
75 }
76 canvas->drawBitmap(subset, SkIntToScalar(rect.fLeft), SkIntToScalar(rect.fTop));
77 }
78 return "";
79}
80
81SkISize ImageSrc::size() const {
mtklein75d98fd2015-01-18 07:05:01 -080082 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080083 SkBitmap bitmap;
84 if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
85 encoded->size(),
86 &bitmap,
87 kUnknown_SkColorType,
88 SkImageDecoder::kDecodeBounds_Mode)) {
89 return SkISize::Make(0,0);
90 }
91 return bitmap.dimensions();
92}
93
mtklein9264a952015-01-20 10:11:53 -080094Name ImageSrc::name() const {
95 Name name = SkOSPath::Basename(fPath.c_str());
96 if (fSubsets > 0) {
97 name.appendf("-%d-subsets", fSubsets);
98 }
99 return name;
100}
mtklein748ca3b2015-01-15 10:56:12 -0800101
102/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
103
mtkleinf4ba3212015-01-28 15:32:24 -0800104static const SkRect kSKPViewport = {0,0, 1000,1000};
105
mtklein748ca3b2015-01-15 10:56:12 -0800106SKPSrc::SKPSrc(SkString path) : fPath(path) {}
107
108Error SKPSrc::draw(SkCanvas* canvas) const {
scroggoa1193e42015-01-21 12:09:53 -0800109 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
mtklein75d98fd2015-01-18 07:05:01 -0800110 if (!stream) {
mtklein748ca3b2015-01-15 10:56:12 -0800111 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
112 }
mtklein75d98fd2015-01-18 07:05:01 -0800113 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream));
114 if (!pic) {
115 return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
116 }
117 stream.reset((SkStream*)NULL); // Might as well drop this when we're done with it.
mtkleinf4ba3212015-01-28 15:32:24 -0800118 canvas->clipRect(kSKPViewport);
mtklein748ca3b2015-01-15 10:56:12 -0800119 canvas->drawPicture(pic);
120 return "";
121}
122
123SkISize SKPSrc::size() const {
mtkleinf4ba3212015-01-28 15:32:24 -0800124 // This may be unnecessarily large.
125 return kSKPViewport.roundOut().size();
mtklein748ca3b2015-01-15 10:56:12 -0800126}
127
128Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
129
130/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
131
mtklein82d28432015-01-15 12:46:02 -0800132GPUSink::GPUSink(GrContextFactory::GLContextType ct,
133 GrGLStandard api,
134 int samples,
135 bool dfText,
136 bool threaded)
mtklein748ca3b2015-01-15 10:56:12 -0800137 : fContextType(ct)
138 , fGpuAPI(api)
139 , fSampleCount(samples)
mtklein82d28432015-01-15 12:46:02 -0800140 , fUseDFText(dfText)
141 , fThreaded(threaded) {}
mtklein748ca3b2015-01-15 10:56:12 -0800142
143int GPUSink::enclave() const {
mtklein55e88b22015-01-21 15:50:13 -0800144 return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
mtklein748ca3b2015-01-15 10:56:12 -0800145}
146
mtklein748ca3b2015-01-15 10:56:12 -0800147Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
mtklein55e88b22015-01-21 15:50:13 -0800148 GrContextFactory factory;
mtkleinf4ba3212015-01-28 15:32:24 -0800149 const SkISize size = src.size();
mtklein748ca3b2015-01-15 10:56:12 -0800150 const SkImageInfo info =
151 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
152 SkAutoTUnref<SkSurface> surface(
mtklein55e88b22015-01-21 15:50:13 -0800153 NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
mtklein748ca3b2015-01-15 10:56:12 -0800154 if (!surface) {
155 return "Could not create a surface.";
156 }
157 SkCanvas* canvas = surface->getCanvas();
158 Error err = src.draw(canvas);
159 if (!err.isEmpty()) {
160 return err;
161 }
162 canvas->flush();
163 dst->allocPixels(info);
164 canvas->readPixels(dst, 0,0);
mtklein55e88b22015-01-21 15:50:13 -0800165 if (FLAGS_abandonGpuContext) {
166 factory.abandonContexts();
167 }
mtklein748ca3b2015-01-15 10:56:12 -0800168 return "";
169}
170
171/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
172
173PDFSink::PDFSink() {}
174
175Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
halcanaryfd4a9932015-01-28 11:45:58 -0800176 // Print the given DM:Src to a PDF, breaking on 8.5x11 pages.
mtklein748ca3b2015-01-15 10:56:12 -0800177 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
mtklein748ca3b2015-01-15 10:56:12 -0800178
halcanaryfd4a9932015-01-28 11:45:58 -0800179 int width = src.size().width(),
180 height = src.size().height();
181
182 const int kLetterWidth = 612, // 8.5 * 72
183 kLetterHeight = 792; // 11 * 72
184 const SkRect letter = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
185 SkIntToScalar(kLetterHeight));
186
187 int xPages = ((width - 1) / kLetterWidth) + 1;
188 int yPages = ((height - 1) / kLetterHeight) + 1;
189
190 for (int y = 0; y < yPages; ++y) {
191 for (int x = 0; x < xPages; ++x) {
192 int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
193 int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
194 SkCanvas* canvas =
195 doc->beginPage(SkIntToScalar(w), SkIntToScalar(h));
196 canvas->clipRect(letter);
197 canvas->translate(-letter.width() * x, -letter.height() * y);
198 Error err = src.draw(canvas);
199 if (!err.isEmpty()) {
200 return err;
201 }
202 doc->endPage();
203 }
mtklein748ca3b2015-01-15 10:56:12 -0800204 }
mtklein748ca3b2015-01-15 10:56:12 -0800205 doc->close();
halcanaryfd4a9932015-01-28 11:45:58 -0800206 dst->flush();
mtklein748ca3b2015-01-15 10:56:12 -0800207 return "";
208}
209
210/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
211
mtklein9c3f17d2015-01-28 11:35:18 -0800212SKPSink::SKPSink() {}
213
214Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
215 SkSize size;
216 size = src.size();
217 SkPictureRecorder recorder;
218 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
219 if (!err.isEmpty()) {
220 return err;
221 }
222 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
223 pic->serialize(dst);
224 return "";
225}
226
227/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
228
mtklein748ca3b2015-01-15 10:56:12 -0800229RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
230
231Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
mtkleinf4ba3212015-01-28 15:32:24 -0800232 const SkISize size = src.size();
mtklein748ca3b2015-01-15 10:56:12 -0800233 // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
234 SkAlphaType alphaType = kPremul_SkAlphaType;
235 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
236
237 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
238 dst->eraseColor(SK_ColorTRANSPARENT);
239 SkCanvas canvas(*dst);
240 return src.draw(&canvas);
241}
242
243/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
244
245ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
246
247Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
248 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
249 struct ProxySrc : public Src {
250 const Src& fSrc;
251 SkMatrix fMatrix;
252 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {}
253
254 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
255 canvas->concat(fMatrix);
256 return fSrc.draw(canvas);
257 }
258 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
259 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
260 } proxy(src, fMatrix);
261 return fSink->draw(proxy, bitmap, stream);
262}
263
264/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
265
mtklein7edca212015-01-21 13:18:51 -0800266ViaPipe::ViaPipe(Sink* sink) : fSink(sink) {}
mtklein748ca3b2015-01-15 10:56:12 -0800267
268Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
mtklein7edca212015-01-21 13:18:51 -0800269 // We turn ourselves into another Src that draws our argument into bitmap/stream via pipe.
mtklein748ca3b2015-01-15 10:56:12 -0800270 struct ProxySrc : public Src {
271 const Src& fSrc;
mtklein7edca212015-01-21 13:18:51 -0800272 ProxySrc(const Src& src) : fSrc(src) {}
mtklein748ca3b2015-01-15 10:56:12 -0800273
274 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
275 SkISize size = this->size();
mtklein748ca3b2015-01-15 10:56:12 -0800276 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
277 SkGPipeWriter pipe;
mtklein7edca212015-01-21 13:18:51 -0800278 const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
279 return fSrc.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
mtklein748ca3b2015-01-15 10:56:12 -0800280 }
281 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
282 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
mtklein7edca212015-01-21 13:18:51 -0800283 } proxy(src);
mtklein748ca3b2015-01-15 10:56:12 -0800284 return fSink->draw(proxy, bitmap, stream);
285}
286
287/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
288
289ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
290
291Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
292 // Record our Src into a picture.
293 SkSize size;
294 size = src.size();
295 SkPictureRecorder recorder;
296 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
297 if (!err.isEmpty()) {
298 return err;
299 }
300 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
301
302 // Serialize it and then deserialize it.
303 SkDynamicMemoryWStream wStream;
304 pic->serialize(&wStream);
scroggoa1193e42015-01-21 12:09:53 -0800305 SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
mtklein748ca3b2015-01-15 10:56:12 -0800306 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
307
308 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
309 struct ProxySrc : public Src {
310 const SkPicture* fPic;
311 const SkISize fSize;
312 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
313
314 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
315 canvas->drawPicture(fPic);
316 return "";
317 }
318 SkISize size() const SK_OVERRIDE { return fSize; }
319 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
320 } proxy(deserialized, src.size());
321 return fSink->draw(proxy, bitmap, stream);
322}
323
324/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
325
326ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
327 : fW(w)
328 , fH(h)
329 , fFactory(factory)
330 , fSink(sink) {}
331
332Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
333 // Record our Src into a picture.
334 SkSize size;
335 size = src.size();
336 SkPictureRecorder recorder;
337 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
338 if (!err.isEmpty()) {
339 return err;
340 }
341 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
342
343 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
344 struct ProxySrc : public Src {
345 const int fW, fH;
346 const SkPicture* fPic;
347 const SkISize fSize;
348 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
349 : fW(w), fH(h), fPic(pic), fSize(size) {}
350
351 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
352 const int xTiles = (fSize.width() + fW - 1) / fW,
353 yTiles = (fSize.height() + fH - 1) / fH;
354 SkMultiPictureDraw mpd(xTiles*yTiles);
355 SkTDArray<SkSurface*> surfaces;
356 surfaces.setReserve(xTiles*yTiles);
357
358 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
359 for (int j = 0; j < yTiles; j++) {
360 for (int i = 0; i < xTiles; i++) {
361 // This lets our ultimate Sink determine the best kind of surface.
362 // E.g., if it's a GpuSink, the surfaces and images are textures.
363 SkSurface* s = canvas->newSurface(info);
364 if (!s) {
365 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
366 }
367 surfaces.push(s);
368 SkCanvas* c = s->getCanvas();
369 c->translate(SkIntToScalar(-i * fW),
370 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
371 mpd.add(c, fPic);
372 }
373 }
374 mpd.draw();
375 for (int j = 0; j < yTiles; j++) {
376 for (int i = 0; i < xTiles; i++) {
377 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
378 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
379 }
380 }
381 surfaces.unrefAll();
382 return "";
383 }
384 SkISize size() const SK_OVERRIDE { return fSize; }
385 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
386 } proxy(fW, fH, pic, src.size());
387 return fSink->draw(proxy, bitmap, stream);
388}
389
390} // namespace DM