blob: 3fd1a4d25da88f2754a674bf82bbf54dba2c29c5 [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"
mtklein441b10e2015-01-28 11:12:25 -08007#include "SkPictureData.h"
mtklein748ca3b2015-01-15 10:56:12 -08008#include "SkPictureRecorder.h"
9#include "SkRandom.h"
scroggoa1193e42015-01-21 12:09:53 -080010#include "SkStream.h"
mtklein748ca3b2015-01-15 10:56:12 -080011
12namespace DM {
13
mtklein748ca3b2015-01-15 10:56:12 -080014GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
15
16Error GMSrc::draw(SkCanvas* canvas) const {
17 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
18 canvas->concat(gm->getInitialTransform());
19 gm->draw(canvas);
20 return "";
21}
22
23SkISize GMSrc::size() const {
24 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
25 return gm->getISize();
26}
27
28Name GMSrc::name() const {
29 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
30 return gm->getName();
31}
32
33/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
34
mtklein748ca3b2015-01-15 10:56:12 -080035ImageSrc::ImageSrc(SkString path, int subsets) : fPath(path), fSubsets(subsets) {}
36
37Error ImageSrc::draw(SkCanvas* canvas) const {
mtklein75d98fd2015-01-18 07:05:01 -080038 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080039 if (!encoded) {
40 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
41 }
42 if (fSubsets == 0) {
43 // Decode the full image.
44 SkBitmap bitmap;
45 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap)) {
46 return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
47 }
mtklein75d98fd2015-01-18 07:05:01 -080048 encoded.reset((SkData*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -080049 canvas->drawBitmap(bitmap, 0,0);
50 return "";
51 }
52 // Decode random subsets. This is a little involved.
scroggoa1193e42015-01-21 12:09:53 -080053 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
54 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get()));
mtklein748ca3b2015-01-15 10:56:12 -080055 if (!decoder) {
56 return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
57 }
scroggoa1193e42015-01-21 12:09:53 -080058 stream->rewind();
mtklein748ca3b2015-01-15 10:56:12 -080059 int w,h;
scroggoa1193e42015-01-21 12:09:53 -080060 if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) {
mtklein748ca3b2015-01-15 10:56:12 -080061 return ""; // Not an error. Subset decoding is not always supported.
62 }
63 SkRandom rand;
64 for (int i = 0; i < fSubsets; i++) {
65 SkIRect rect;
66 do {
67 rect.fLeft = rand.nextULessThan(w);
68 rect.fTop = rand.nextULessThan(h);
69 rect.fRight = rand.nextULessThan(w);
70 rect.fBottom = rand.nextULessThan(h);
71 rect.sort();
72 } while (rect.isEmpty());
73 SkBitmap subset;
74 if (!decoder->decodeSubset(&subset, rect, kUnknown_SkColorType/*use best fit*/)) {
75 return SkStringPrintf("Could not decode subset %d.\n", i);
76 }
77 canvas->drawBitmap(subset, SkIntToScalar(rect.fLeft), SkIntToScalar(rect.fTop));
78 }
79 return "";
80}
81
82SkISize ImageSrc::size() const {
mtklein75d98fd2015-01-18 07:05:01 -080083 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080084 SkBitmap bitmap;
85 if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
86 encoded->size(),
87 &bitmap,
88 kUnknown_SkColorType,
89 SkImageDecoder::kDecodeBounds_Mode)) {
90 return SkISize::Make(0,0);
91 }
92 return bitmap.dimensions();
93}
94
mtklein9264a952015-01-20 10:11:53 -080095Name ImageSrc::name() const {
96 Name name = SkOSPath::Basename(fPath.c_str());
97 if (fSubsets > 0) {
98 name.appendf("-%d-subsets", fSubsets);
99 }
100 return name;
101}
mtklein748ca3b2015-01-15 10:56:12 -0800102
103/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
104
mtklein748ca3b2015-01-15 10:56:12 -0800105SKPSrc::SKPSrc(SkString path) : fPath(path) {}
106
107Error SKPSrc::draw(SkCanvas* canvas) const {
scroggoa1193e42015-01-21 12:09:53 -0800108 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
mtklein75d98fd2015-01-18 07:05:01 -0800109 if (!stream) {
mtklein748ca3b2015-01-15 10:56:12 -0800110 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
111 }
mtklein75d98fd2015-01-18 07:05:01 -0800112 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream));
113 if (!pic) {
114 return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
115 }
116 stream.reset((SkStream*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -0800117 canvas->drawPicture(pic);
118 return "";
119}
120
121SkISize SKPSrc::size() const {
mtklein441b10e2015-01-28 11:12:25 -0800122 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
123 SkPictInfo info;
124 if (!stream || !SkPicture::InternalOnly_StreamIsSKP(stream, &info)) {
125 return SkISize::Make(0,0);
126 }
127 return info.fCullRect.roundOut().size();
mtklein748ca3b2015-01-15 10:56:12 -0800128}
129
130Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
131
132/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
133
mtklein441b10e2015-01-28 11:12:25 -0800134static SkISize limit_raster_dimensions(const SkISize& size) {
135 // This fits within a typical maximum texture, and puts a reasonable 16MB cap on raster bitmaps.
136 return SkISize::Make(SkTMin(2048, size.width()), SkTMin(2048, size.height()));
137}
138
mtklein82d28432015-01-15 12:46:02 -0800139GPUSink::GPUSink(GrContextFactory::GLContextType ct,
140 GrGLStandard api,
141 int samples,
142 bool dfText,
143 bool threaded)
mtklein748ca3b2015-01-15 10:56:12 -0800144 : fContextType(ct)
145 , fGpuAPI(api)
146 , fSampleCount(samples)
mtklein82d28432015-01-15 12:46:02 -0800147 , fUseDFText(dfText)
148 , fThreaded(threaded) {}
mtklein748ca3b2015-01-15 10:56:12 -0800149
150int GPUSink::enclave() const {
mtklein55e88b22015-01-21 15:50:13 -0800151 return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
mtklein748ca3b2015-01-15 10:56:12 -0800152}
153
mtklein748ca3b2015-01-15 10:56:12 -0800154Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
mtklein55e88b22015-01-21 15:50:13 -0800155 GrContextFactory factory;
mtklein441b10e2015-01-28 11:12:25 -0800156 const SkISize size = limit_raster_dimensions(src.size());
mtklein748ca3b2015-01-15 10:56:12 -0800157 const SkImageInfo info =
158 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
159 SkAutoTUnref<SkSurface> surface(
mtklein55e88b22015-01-21 15:50:13 -0800160 NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
mtklein748ca3b2015-01-15 10:56:12 -0800161 if (!surface) {
162 return "Could not create a surface.";
163 }
164 SkCanvas* canvas = surface->getCanvas();
165 Error err = src.draw(canvas);
166 if (!err.isEmpty()) {
167 return err;
168 }
169 canvas->flush();
170 dst->allocPixels(info);
171 canvas->readPixels(dst, 0,0);
mtklein55e88b22015-01-21 15:50:13 -0800172 if (FLAGS_abandonGpuContext) {
173 factory.abandonContexts();
174 }
mtklein748ca3b2015-01-15 10:56:12 -0800175 return "";
176}
177
178/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
179
180PDFSink::PDFSink() {}
181
182Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
halcanaryfd4a9932015-01-28 11:45:58 -0800183 // Print the given DM:Src to a PDF, breaking on 8.5x11 pages.
mtklein748ca3b2015-01-15 10:56:12 -0800184 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
mtklein748ca3b2015-01-15 10:56:12 -0800185
halcanaryfd4a9932015-01-28 11:45:58 -0800186 int width = src.size().width(),
187 height = src.size().height();
188
189 const int kLetterWidth = 612, // 8.5 * 72
190 kLetterHeight = 792; // 11 * 72
191 const SkRect letter = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
192 SkIntToScalar(kLetterHeight));
193
194 int xPages = ((width - 1) / kLetterWidth) + 1;
195 int yPages = ((height - 1) / kLetterHeight) + 1;
196
197 for (int y = 0; y < yPages; ++y) {
198 for (int x = 0; x < xPages; ++x) {
199 int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
200 int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
201 SkCanvas* canvas =
202 doc->beginPage(SkIntToScalar(w), SkIntToScalar(h));
203 canvas->clipRect(letter);
204 canvas->translate(-letter.width() * x, -letter.height() * y);
205 Error err = src.draw(canvas);
206 if (!err.isEmpty()) {
207 return err;
208 }
209 doc->endPage();
210 }
mtklein748ca3b2015-01-15 10:56:12 -0800211 }
mtklein748ca3b2015-01-15 10:56:12 -0800212 doc->close();
halcanaryfd4a9932015-01-28 11:45:58 -0800213 dst->flush();
mtklein748ca3b2015-01-15 10:56:12 -0800214 return "";
215}
216
217/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
218
mtklein9c3f17d2015-01-28 11:35:18 -0800219SKPSink::SKPSink() {}
220
221Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
222 SkSize size;
223 size = src.size();
224 SkPictureRecorder recorder;
225 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
226 if (!err.isEmpty()) {
227 return err;
228 }
229 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
230 pic->serialize(dst);
231 return "";
232}
233
234/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
235
mtklein748ca3b2015-01-15 10:56:12 -0800236RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
237
238Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
mtklein441b10e2015-01-28 11:12:25 -0800239 const SkISize size = limit_raster_dimensions(src.size());
mtklein748ca3b2015-01-15 10:56:12 -0800240 // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
241 SkAlphaType alphaType = kPremul_SkAlphaType;
242 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
243
244 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
245 dst->eraseColor(SK_ColorTRANSPARENT);
246 SkCanvas canvas(*dst);
247 return src.draw(&canvas);
248}
249
250/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
251
252ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
253
254Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
255 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
256 struct ProxySrc : public Src {
257 const Src& fSrc;
258 SkMatrix fMatrix;
259 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {}
260
261 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
262 canvas->concat(fMatrix);
263 return fSrc.draw(canvas);
264 }
265 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
266 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
267 } proxy(src, fMatrix);
268 return fSink->draw(proxy, bitmap, stream);
269}
270
271/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
272
mtklein7edca212015-01-21 13:18:51 -0800273ViaPipe::ViaPipe(Sink* sink) : fSink(sink) {}
mtklein748ca3b2015-01-15 10:56:12 -0800274
275Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
mtklein7edca212015-01-21 13:18:51 -0800276 // We turn ourselves into another Src that draws our argument into bitmap/stream via pipe.
mtklein748ca3b2015-01-15 10:56:12 -0800277 struct ProxySrc : public Src {
278 const Src& fSrc;
mtklein7edca212015-01-21 13:18:51 -0800279 ProxySrc(const Src& src) : fSrc(src) {}
mtklein748ca3b2015-01-15 10:56:12 -0800280
281 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
282 SkISize size = this->size();
mtklein748ca3b2015-01-15 10:56:12 -0800283 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
284 SkGPipeWriter pipe;
mtklein7edca212015-01-21 13:18:51 -0800285 const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
286 return fSrc.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
mtklein748ca3b2015-01-15 10:56:12 -0800287 }
288 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
289 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
mtklein7edca212015-01-21 13:18:51 -0800290 } proxy(src);
mtklein748ca3b2015-01-15 10:56:12 -0800291 return fSink->draw(proxy, bitmap, stream);
292}
293
294/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
295
296ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
297
298Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
299 // Record our Src into a picture.
300 SkSize size;
301 size = src.size();
302 SkPictureRecorder recorder;
303 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
304 if (!err.isEmpty()) {
305 return err;
306 }
307 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
308
309 // Serialize it and then deserialize it.
310 SkDynamicMemoryWStream wStream;
311 pic->serialize(&wStream);
scroggoa1193e42015-01-21 12:09:53 -0800312 SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
mtklein748ca3b2015-01-15 10:56:12 -0800313 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
314
315 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
316 struct ProxySrc : public Src {
317 const SkPicture* fPic;
318 const SkISize fSize;
319 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
320
321 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
322 canvas->drawPicture(fPic);
323 return "";
324 }
325 SkISize size() const SK_OVERRIDE { return fSize; }
326 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
327 } proxy(deserialized, src.size());
328 return fSink->draw(proxy, bitmap, stream);
329}
330
331/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
332
333ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
334 : fW(w)
335 , fH(h)
336 , fFactory(factory)
337 , fSink(sink) {}
338
339Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
340 // Record our Src into a picture.
341 SkSize size;
342 size = src.size();
343 SkPictureRecorder recorder;
344 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
345 if (!err.isEmpty()) {
346 return err;
347 }
348 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
349
350 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
351 struct ProxySrc : public Src {
352 const int fW, fH;
353 const SkPicture* fPic;
354 const SkISize fSize;
355 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
356 : fW(w), fH(h), fPic(pic), fSize(size) {}
357
358 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
359 const int xTiles = (fSize.width() + fW - 1) / fW,
360 yTiles = (fSize.height() + fH - 1) / fH;
361 SkMultiPictureDraw mpd(xTiles*yTiles);
362 SkTDArray<SkSurface*> surfaces;
363 surfaces.setReserve(xTiles*yTiles);
364
365 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
366 for (int j = 0; j < yTiles; j++) {
367 for (int i = 0; i < xTiles; i++) {
368 // This lets our ultimate Sink determine the best kind of surface.
369 // E.g., if it's a GpuSink, the surfaces and images are textures.
370 SkSurface* s = canvas->newSurface(info);
371 if (!s) {
372 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
373 }
374 surfaces.push(s);
375 SkCanvas* c = s->getCanvas();
376 c->translate(SkIntToScalar(-i * fW),
377 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
378 mpd.add(c, fPic);
379 }
380 }
381 mpd.draw();
382 for (int j = 0; j < yTiles; j++) {
383 for (int i = 0; i < xTiles; i++) {
384 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
385 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
386 }
387 }
388 surfaces.unrefAll();
389 return "";
390 }
391 SkISize size() const SK_OVERRIDE { return fSize; }
392 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
393 } proxy(fW, fH, pic, src.size());
394 return fSink->draw(proxy, bitmap, stream);
395}
396
397} // namespace DM