blob: fd9943533bc8964ed1a4586b59f08778c5cfa066 [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 {
mtklein82d28432015-01-15 12:46:02 -0800144 return fThreaded ? kAnyThread_Enclave : kGPUSink_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 {
mtklein82d28432015-01-15 12:46:02 -0800148 GrContextFactory* factory = GetThreadLocalGrContextFactory();
mtklein748ca3b2015-01-15 10:56:12 -0800149 if (FLAGS_abandonGpuContext) {
150 factory->abandonContexts();
151 }
152 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
153 factory->destroyContexts();
154 }
155 const SkISize size = src.size();
156 const SkImageInfo info =
157 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
158 SkAutoTUnref<SkSurface> surface(
159 NewGpuSurface(factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
160 if (!surface) {
161 return "Could not create a surface.";
162 }
163 SkCanvas* canvas = surface->getCanvas();
164 Error err = src.draw(canvas);
165 if (!err.isEmpty()) {
166 return err;
167 }
168 canvas->flush();
169 dst->allocPixels(info);
170 canvas->readPixels(dst, 0,0);
171 return "";
172}
173
174/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
175
176PDFSink::PDFSink() {}
177
178Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
179 SkSize size;
180 size = src.size();
181 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
182 SkCanvas* canvas = doc->beginPage(size.width(), size.height());
183
184 Error err = src.draw(canvas);
185 if (!err.isEmpty()) {
186 return err;
187 }
188 canvas->flush();
189 doc->endPage();
190 doc->close();
191 return "";
192}
193
194/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
195
196RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
197
198Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
199 const SkISize size = src.size();
200 // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
201 SkAlphaType alphaType = kPremul_SkAlphaType;
202 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
203
204 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
205 dst->eraseColor(SK_ColorTRANSPARENT);
206 SkCanvas canvas(*dst);
207 return src.draw(&canvas);
208}
209
210/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
211
212ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
213
214Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
215 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
216 struct ProxySrc : public Src {
217 const Src& fSrc;
218 SkMatrix fMatrix;
219 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {}
220
221 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
222 canvas->concat(fMatrix);
223 return fSrc.draw(canvas);
224 }
225 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
226 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
227 } proxy(src, fMatrix);
228 return fSink->draw(proxy, bitmap, stream);
229}
230
231/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
232
233ViaPipe::ViaPipe(int flags, Sink* sink) : fFlags((SkGPipeWriter::Flags)flags), fSink(sink) {}
234
235Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
236 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
237 struct ProxySrc : public Src {
238 const Src& fSrc;
239 SkGPipeWriter::Flags fFlags;
240 ProxySrc(const Src& src, SkGPipeWriter::Flags flags) : fSrc(src), fFlags(flags) {}
241
242 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
243 SkISize size = this->size();
244 // TODO: is DecodeMemory really required? Might help RAM usage to be lazy if we can.
245 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
246 SkGPipeWriter pipe;
247 return fSrc.draw(pipe.startRecording(&controller, fFlags, size.width(), size.height()));
248 }
249 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
250 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
251 } proxy(src, fFlags);
252 return fSink->draw(proxy, bitmap, stream);
253}
254
255/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
256
257ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
258
259Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
260 // Record our Src into a picture.
261 SkSize size;
262 size = src.size();
263 SkPictureRecorder recorder;
264 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
265 if (!err.isEmpty()) {
266 return err;
267 }
268 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
269
270 // Serialize it and then deserialize it.
271 SkDynamicMemoryWStream wStream;
272 pic->serialize(&wStream);
scroggoa1193e42015-01-21 12:09:53 -0800273 SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
mtklein748ca3b2015-01-15 10:56:12 -0800274 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
275
276 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
277 struct ProxySrc : public Src {
278 const SkPicture* fPic;
279 const SkISize fSize;
280 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
281
282 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
283 canvas->drawPicture(fPic);
284 return "";
285 }
286 SkISize size() const SK_OVERRIDE { return fSize; }
287 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
288 } proxy(deserialized, src.size());
289 return fSink->draw(proxy, bitmap, stream);
290}
291
292/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
293
294ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
295 : fW(w)
296 , fH(h)
297 , fFactory(factory)
298 , fSink(sink) {}
299
300Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
301 // Record our Src into a picture.
302 SkSize size;
303 size = src.size();
304 SkPictureRecorder recorder;
305 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
306 if (!err.isEmpty()) {
307 return err;
308 }
309 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
310
311 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
312 struct ProxySrc : public Src {
313 const int fW, fH;
314 const SkPicture* fPic;
315 const SkISize fSize;
316 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
317 : fW(w), fH(h), fPic(pic), fSize(size) {}
318
319 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
320 const int xTiles = (fSize.width() + fW - 1) / fW,
321 yTiles = (fSize.height() + fH - 1) / fH;
322 SkMultiPictureDraw mpd(xTiles*yTiles);
323 SkTDArray<SkSurface*> surfaces;
324 surfaces.setReserve(xTiles*yTiles);
325
326 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
327 for (int j = 0; j < yTiles; j++) {
328 for (int i = 0; i < xTiles; i++) {
329 // This lets our ultimate Sink determine the best kind of surface.
330 // E.g., if it's a GpuSink, the surfaces and images are textures.
331 SkSurface* s = canvas->newSurface(info);
332 if (!s) {
333 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
334 }
335 surfaces.push(s);
336 SkCanvas* c = s->getCanvas();
337 c->translate(SkIntToScalar(-i * fW),
338 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
339 mpd.add(c, fPic);
340 }
341 }
342 mpd.draw();
343 for (int j = 0; j < yTiles; j++) {
344 for (int i = 0; i < xTiles; i++) {
345 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
346 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
347 }
348 }
349 surfaces.unrefAll();
350 return "";
351 }
352 SkISize size() const SK_OVERRIDE { return fSize; }
353 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
354 } proxy(fW, fH, pic, src.size());
355 return fSink->draw(proxy, bitmap, stream);
356}
357
358} // namespace DM