DMSrcSink.cpp revision 441b10eac09a1f44983e35da827a6b438a409e63
1#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 "SkPictureData.h"
8#include "SkPictureRecorder.h"
9#include "SkRandom.h"
10#include "SkStream.h"
11
12namespace DM {
13
14GMSrc::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
35ImageSrc::ImageSrc(SkString path, int subsets) : fPath(path), fSubsets(subsets) {}
36
37Error ImageSrc::draw(SkCanvas* canvas) const {
38    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
39    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        }
48        encoded.reset((SkData*)NULL);  // Might as well drop this when we're done with it.
49        canvas->drawBitmap(bitmap, 0,0);
50        return "";
51    }
52    // Decode random subsets.  This is a little involved.
53    SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
54    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get()));
55    if (!decoder) {
56        return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
57    }
58    stream->rewind();
59    int w,h;
60    if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) {
61        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 {
83    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
84    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
95Name 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}
102
103/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
104
105SKPSrc::SKPSrc(SkString path) : fPath(path) {}
106
107Error SKPSrc::draw(SkCanvas* canvas) const {
108    SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
109    if (!stream) {
110        return SkStringPrintf("Couldn't read %s.", fPath.c_str());
111    }
112    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.
117    canvas->drawPicture(pic);
118    return "";
119}
120
121SkISize SKPSrc::size() const {
122    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();
128}
129
130Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
131
132/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
133
134static 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
139GPUSink::GPUSink(GrContextFactory::GLContextType ct,
140                 GrGLStandard api,
141                 int samples,
142                 bool dfText,
143                 bool threaded)
144    : fContextType(ct)
145    , fGpuAPI(api)
146    , fSampleCount(samples)
147    , fUseDFText(dfText)
148    , fThreaded(threaded) {}
149
150int GPUSink::enclave() const {
151    return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
152}
153
154Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
155    GrContextFactory factory;
156    const SkISize size = limit_raster_dimensions(src.size());
157    const SkImageInfo info =
158        SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
159    SkAutoTUnref<SkSurface> surface(
160            NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
161    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);
172    if (FLAGS_abandonGpuContext) {
173        factory.abandonContexts();
174    }
175    return "";
176}
177
178/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
179
180PDFSink::PDFSink() {}
181
182Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
183    SkSize size;
184    size = src.size();
185    SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
186    SkCanvas* canvas = doc->beginPage(size.width(), size.height());
187
188    Error err = src.draw(canvas);
189    if (!err.isEmpty()) {
190        return err;
191    }
192    canvas->flush();
193    doc->endPage();
194    doc->close();
195    return "";
196}
197
198/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
199
200RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
201
202Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
203    const SkISize size = limit_raster_dimensions(src.size());
204    // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
205    SkAlphaType alphaType = kPremul_SkAlphaType;
206    (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
207
208    dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
209    dst->eraseColor(SK_ColorTRANSPARENT);
210    SkCanvas canvas(*dst);
211    return src.draw(&canvas);
212}
213
214/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
215
216ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
217
218Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
219    // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
220    struct ProxySrc : public Src {
221        const Src& fSrc;
222        SkMatrix fMatrix;
223        ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {}
224
225        Error draw(SkCanvas* canvas) const SK_OVERRIDE {
226            canvas->concat(fMatrix);
227            return fSrc.draw(canvas);
228        }
229        SkISize size() const SK_OVERRIDE { return fSrc.size(); }
230        Name name() const SK_OVERRIDE { sk_throw(); return ""; }  // No one should be calling this.
231    } proxy(src, fMatrix);
232    return fSink->draw(proxy, bitmap, stream);
233}
234
235/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
236
237ViaPipe::ViaPipe(Sink* sink) : fSink(sink) {}
238
239Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
240    // We turn ourselves into another Src that draws our argument into bitmap/stream via pipe.
241    struct ProxySrc : public Src {
242        const Src& fSrc;
243        ProxySrc(const Src& src) : fSrc(src) {}
244
245        Error draw(SkCanvas* canvas) const SK_OVERRIDE {
246            SkISize size = this->size();
247            PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
248            SkGPipeWriter pipe;
249            const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
250            return fSrc.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
251        }
252        SkISize size() const SK_OVERRIDE { return fSrc.size(); }
253        Name name() const SK_OVERRIDE { sk_throw(); return ""; }  // No one should be calling this.
254    } proxy(src);
255    return fSink->draw(proxy, bitmap, stream);
256}
257
258/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
259
260ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
261
262Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
263    // Record our Src into a picture.
264    SkSize size;
265    size = src.size();
266    SkPictureRecorder recorder;
267    Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
268    if (!err.isEmpty()) {
269        return err;
270    }
271    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
272
273    // Serialize it and then deserialize it.
274    SkDynamicMemoryWStream wStream;
275    pic->serialize(&wStream);
276    SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
277    SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
278
279    // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
280    struct ProxySrc : public Src {
281        const SkPicture* fPic;
282        const SkISize fSize;
283        ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
284
285        Error draw(SkCanvas* canvas) const SK_OVERRIDE {
286            canvas->drawPicture(fPic);
287            return "";
288        }
289        SkISize size() const SK_OVERRIDE { return fSize; }
290        Name name() const SK_OVERRIDE { sk_throw(); return ""; }  // No one should be calling this.
291    } proxy(deserialized, src.size());
292    return fSink->draw(proxy, bitmap, stream);
293}
294
295/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
296
297ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
298    : fW(w)
299    , fH(h)
300    , fFactory(factory)
301    , fSink(sink) {}
302
303Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
304    // Record our Src into a picture.
305    SkSize size;
306    size = src.size();
307    SkPictureRecorder recorder;
308    Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
309    if (!err.isEmpty()) {
310        return err;
311    }
312    SkAutoTUnref<SkPicture> pic(recorder.endRecording());
313
314    // Turn that picture into a Src that draws into our Sink via tiles + MPD.
315    struct ProxySrc : public Src {
316        const int fW, fH;
317        const SkPicture* fPic;
318        const SkISize fSize;
319        ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
320            : fW(w), fH(h), fPic(pic), fSize(size) {}
321
322        Error draw(SkCanvas* canvas) const SK_OVERRIDE {
323            const int xTiles = (fSize.width()  + fW - 1) / fW,
324                      yTiles = (fSize.height() + fH - 1) / fH;
325            SkMultiPictureDraw mpd(xTiles*yTiles);
326            SkTDArray<SkSurface*> surfaces;
327            surfaces.setReserve(xTiles*yTiles);
328
329            SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
330            for (int j = 0; j < yTiles; j++) {
331                for (int i = 0; i < xTiles; i++) {
332                    // This lets our ultimate Sink determine the best kind of surface.
333                    // E.g., if it's a GpuSink, the surfaces and images are textures.
334                    SkSurface* s = canvas->newSurface(info);
335                    if (!s) {
336                        s = SkSurface::NewRaster(info);  // Some canvases can't create surfaces.
337                    }
338                    surfaces.push(s);
339                    SkCanvas* c = s->getCanvas();
340                    c->translate(SkIntToScalar(-i * fW),
341                                 SkIntToScalar(-j * fH));  // Line up the canvas with this tile.
342                    mpd.add(c, fPic);
343                }
344            }
345            mpd.draw();
346            for (int j = 0; j < yTiles; j++) {
347                for (int i = 0; i < xTiles; i++) {
348                    SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
349                    canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
350                }
351            }
352            surfaces.unrefAll();
353            return "";
354        }
355        SkISize size() const SK_OVERRIDE { return fSize; }
356        Name name() const SK_OVERRIDE { sk_throw(); return ""; }  // No one should be calling this.
357    } proxy(fW, fH, pic, src.size());
358    return fSink->draw(proxy, bitmap, stream);
359}
360
361}  // namespace DM
362