blob: affb844bc6aa39f76d5c2b5150f6c8954ea5fe94 [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
104static 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.
mtklein748ca3b2015-01-15 10:56:12 -0800118 canvas->clipRect(kSKPViewport);
119 canvas->drawPicture(pic);
120 return "";
121}
122
123SkISize SKPSrc::size() const {
mtklein75d98fd2015-01-18 07:05:01 -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;
mtklein748ca3b2015-01-15 10:56:12 -0800149 const SkISize size = src.size();
150 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 {
176 SkSize size;
177 size = src.size();
178 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
179 SkCanvas* canvas = doc->beginPage(size.width(), size.height());
180
181 Error err = src.draw(canvas);
182 if (!err.isEmpty()) {
183 return err;
184 }
185 canvas->flush();
186 doc->endPage();
187 doc->close();
188 return "";
189}
190
191/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
192
193RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
194
195Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
196 const SkISize size = src.size();
197 // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
198 SkAlphaType alphaType = kPremul_SkAlphaType;
199 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
200
201 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
202 dst->eraseColor(SK_ColorTRANSPARENT);
203 SkCanvas canvas(*dst);
204 return src.draw(&canvas);
205}
206
207/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
208
209ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
210
211Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
212 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
213 struct ProxySrc : public Src {
214 const Src& fSrc;
215 SkMatrix fMatrix;
216 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {}
217
218 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
219 canvas->concat(fMatrix);
220 return fSrc.draw(canvas);
221 }
222 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
223 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
224 } proxy(src, fMatrix);
225 return fSink->draw(proxy, bitmap, stream);
226}
227
228/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
229
mtklein7edca212015-01-21 13:18:51 -0800230ViaPipe::ViaPipe(Sink* sink) : fSink(sink) {}
mtklein748ca3b2015-01-15 10:56:12 -0800231
232Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
mtklein7edca212015-01-21 13:18:51 -0800233 // We turn ourselves into another Src that draws our argument into bitmap/stream via pipe.
mtklein748ca3b2015-01-15 10:56:12 -0800234 struct ProxySrc : public Src {
235 const Src& fSrc;
mtklein7edca212015-01-21 13:18:51 -0800236 ProxySrc(const Src& src) : fSrc(src) {}
mtklein748ca3b2015-01-15 10:56:12 -0800237
238 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
239 SkISize size = this->size();
mtklein748ca3b2015-01-15 10:56:12 -0800240 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
241 SkGPipeWriter pipe;
mtklein7edca212015-01-21 13:18:51 -0800242 const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
243 return fSrc.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
mtklein748ca3b2015-01-15 10:56:12 -0800244 }
245 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
246 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
mtklein7edca212015-01-21 13:18:51 -0800247 } proxy(src);
mtklein748ca3b2015-01-15 10:56:12 -0800248 return fSink->draw(proxy, bitmap, stream);
249}
250
251/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
252
253ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
254
255Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
256 // Record our Src into a picture.
257 SkSize size;
258 size = src.size();
259 SkPictureRecorder recorder;
260 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
261 if (!err.isEmpty()) {
262 return err;
263 }
264 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
265
266 // Serialize it and then deserialize it.
267 SkDynamicMemoryWStream wStream;
268 pic->serialize(&wStream);
scroggoa1193e42015-01-21 12:09:53 -0800269 SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
mtklein748ca3b2015-01-15 10:56:12 -0800270 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
271
272 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
273 struct ProxySrc : public Src {
274 const SkPicture* fPic;
275 const SkISize fSize;
276 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
277
278 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
279 canvas->drawPicture(fPic);
280 return "";
281 }
282 SkISize size() const SK_OVERRIDE { return fSize; }
283 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
284 } proxy(deserialized, src.size());
285 return fSink->draw(proxy, bitmap, stream);
286}
287
288/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
289
290ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
291 : fW(w)
292 , fH(h)
293 , fFactory(factory)
294 , fSink(sink) {}
295
296Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
297 // Record our Src into a picture.
298 SkSize size;
299 size = src.size();
300 SkPictureRecorder recorder;
301 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
302 if (!err.isEmpty()) {
303 return err;
304 }
305 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
306
307 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
308 struct ProxySrc : public Src {
309 const int fW, fH;
310 const SkPicture* fPic;
311 const SkISize fSize;
312 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
313 : fW(w), fH(h), fPic(pic), fSize(size) {}
314
315 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
316 const int xTiles = (fSize.width() + fW - 1) / fW,
317 yTiles = (fSize.height() + fH - 1) / fH;
318 SkMultiPictureDraw mpd(xTiles*yTiles);
319 SkTDArray<SkSurface*> surfaces;
320 surfaces.setReserve(xTiles*yTiles);
321
322 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
323 for (int j = 0; j < yTiles; j++) {
324 for (int i = 0; i < xTiles; i++) {
325 // This lets our ultimate Sink determine the best kind of surface.
326 // E.g., if it's a GpuSink, the surfaces and images are textures.
327 SkSurface* s = canvas->newSurface(info);
328 if (!s) {
329 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
330 }
331 surfaces.push(s);
332 SkCanvas* c = s->getCanvas();
333 c->translate(SkIntToScalar(-i * fW),
334 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
335 mpd.add(c, fPic);
336 }
337 }
338 mpd.draw();
339 for (int j = 0; j < yTiles; j++) {
340 for (int i = 0; i < xTiles; i++) {
341 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
342 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
343 }
344 }
345 surfaces.unrefAll();
346 return "";
347 }
348 SkISize size() const SK_OVERRIDE { return fSize; }
349 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
350 } proxy(fW, fH, pic, src.size());
351 return fSink->draw(proxy, bitmap, stream);
352}
353
354} // namespace DM