Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: dm/DMSrcSink.cpp

Issue 788243008: Sketch DM refactor. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: better failure messages, disable a few things temporarily to try to go green Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « dm/DMSrcSink.h ('k') | dm/DMTask.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "SkPictureRecorder.h"
8 #include "SkRandom.h"
9 #include "SkTLS.h"
10
11 namespace DM {
12
13 void SafeUnref(SkPicture* p) { SkSafeUnref(p); }
14 void SafeUnref(SkData* d) { SkSafeUnref(d); }
15
16 // FIXME: the GM objects themselves are not threadsafe, so we create and destroy them as needed.
17
18 GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
19
20 Error GMSrc::draw(SkCanvas* canvas) const {
21 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
22 canvas->concat(gm->getInitialTransform());
23 gm->draw(canvas);
24 return "";
25 }
26
27 SkISize GMSrc::size() const {
28 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
29 return gm->getISize();
30 }
31
32 Name GMSrc::name() const {
33 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
34 return gm->getName();
35 }
36
37 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
38
39 // The first call to draw() or size() will mmap the file to an SkData. ~ImageSr c unrefs it.
40 struct LazyLoadImage {
41 LazyLoadImage(const char* path) : path(path) {}
42 const char* path;
43
44 SkData* operator()() const { return SkData::NewFromFileName(path); }
45 };
46
47 ImageSrc::ImageSrc(SkString path, int subsets) : fPath(path), fSubsets(subsets) {}
48
49 Error ImageSrc::draw(SkCanvas* canvas) const {
50 const SkData* encoded = fEncoded.get(LazyLoadImage(fPath.c_str()));
51 if (!encoded) {
52 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
53 }
54 if (fSubsets == 0) {
55 // Decode the full image.
56 SkBitmap bitmap;
57 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bit map)) {
58 return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
59 }
60 canvas->drawBitmap(bitmap, 0,0);
61 return "";
62 }
63 // Decode random subsets. This is a little involved.
64 SkMemoryStream stream(encoded->data(), encoded->size());
65 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
66 if (!decoder) {
67 return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str() );
68 }
69 int w,h;
70 if (!decoder->buildTileIndex(&stream, &w, &h) || w*h == 1) {
71 return ""; // Not an error. Subset decoding is not always supported.
72 }
73 SkRandom rand;
74 for (int i = 0; i < fSubsets; i++) {
75 SkIRect rect;
76 do {
77 rect.fLeft = rand.nextULessThan(w);
78 rect.fTop = rand.nextULessThan(h);
79 rect.fRight = rand.nextULessThan(w);
80 rect.fBottom = rand.nextULessThan(h);
81 rect.sort();
82 } while (rect.isEmpty());
83 SkBitmap subset;
84 if (!decoder->decodeSubset(&subset, rect, kUnknown_SkColorType/*use best fit*/)) {
85 return SkStringPrintf("Could not decode subset %d.\n", i);
86 }
87 canvas->drawBitmap(subset, SkIntToScalar(rect.fLeft), SkIntToScalar(rect .fTop));
88 }
89 return "";
90 }
91
92 SkISize ImageSrc::size() const {
93 const SkData* encoded = fEncoded.get(LazyLoadImage(fPath.c_str()));
94 SkBitmap bitmap;
95 if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
96 encoded->size(),
97 &bitmap,
98 kUnknown_SkColorType,
99 SkImageDecoder::kDecodeBounds_ Mode)) {
100 return SkISize::Make(0,0);
101 }
102 return bitmap.dimensions();
103 }
104
105 Name ImageSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
106
107 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
108
109 static const SkRect kSKPViewport = {0,0, 1000,1000};
110
111 // The first call to draw() or size() will read the file into an SkPicture. ~SK PSrc unrefs it.
112 struct LazyLoadPicture {
113 LazyLoadPicture(const char* path) : path(path) {}
114 const char* path;
115
116 SkPicture* operator()() const {
117 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
118 if (!stream) {
119 return NULL;
120 }
121 return SkPicture::CreateFromStream(stream);
122 }
123 };
124
125 SKPSrc::SKPSrc(SkString path) : fPath(path) {}
126
127 Error SKPSrc::draw(SkCanvas* canvas) const {
128 const SkPicture* pic = fPic.get(LazyLoadPicture(fPath.c_str()));
129 if (!pic) {
130 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
131 }
132 canvas->clipRect(kSKPViewport);
133 canvas->drawPicture(pic);
134 return "";
135 }
136
137 SkISize SKPSrc::size() const {
138 const SkPicture* pic = fPic.get(LazyLoadPicture(fPath.c_str()));
139 if (!pic) {
140 return SkISize::Make(0,0);
141 }
142 SkRect cull = pic->cullRect();
143 if (!cull.intersect(kSKPViewport)) {
144 sk_throw();
145 }
146 SkIRect bounds;
147 cull.roundOut(&bounds);
148 SkISize size = { bounds.width(), bounds.height() };
149 return size;
150 }
151
152 Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
153
154 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
155
156 DEFINE_string(gpu_threading, "none",
157 "none: single thread,\n"
158 "tls: any thread, GrContextFactory in TLS (crashy),\n"
159 "stack: any thread, GrContextFactory on stack (less crashy, differently so)");
160
161 GPUSink::GPUSink(GrContextFactory::GLContextType ct, GrGLStandard api, int sampl es, bool dfText)
162 : fContextType(ct)
163 , fGpuAPI(api)
164 , fSampleCount(samples)
165 , fUseDFText(dfText) {}
166
167 int GPUSink::enclave() const {
168 return FLAGS_gpu_threading.contains("none") ? kGPUSink_Enclave : kAnyThread_ Enclave;
169 }
170
171 static void* CreateGrFactory() { return new GrContextFactory; }
172 static void DeleteGrFactory(void* p) { delete (GrContextFactory*)p; }
173
174 Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
175 GrContextFactory local, *factory = &local;
176 if (!FLAGS_gpu_threading.contains("stack")) {
177 factory = (GrContextFactory*)SkTLS::Get(CreateGrFactory, DeleteGrFactory );
178 }
179 // Does abandoning / resetting contexts make any sense if we have stack-scop ed factories?
180 if (FLAGS_abandonGpuContext) {
181 factory->abandonContexts();
182 }
183 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) {
184 factory->destroyContexts();
185 }
186 const SkISize size = src.size();
187 const SkImageInfo info =
188 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul _SkAlphaType);
189 SkAutoTUnref<SkSurface> surface(
190 NewGpuSurface(factory, fContextType, fGpuAPI, info, fSampleCount, fU seDFText));
191 if (!surface) {
192 return "Could not create a surface.";
193 }
194 SkCanvas* canvas = surface->getCanvas();
195 Error err = src.draw(canvas);
196 if (!err.isEmpty()) {
197 return err;
198 }
199 canvas->flush();
200 dst->allocPixels(info);
201 canvas->readPixels(dst, 0,0);
202 return "";
203 }
204
205 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
206
207 PDFSink::PDFSink() {}
208
209 Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst) const {
210 SkSize size;
211 size = src.size();
212 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
213 SkCanvas* canvas = doc->beginPage(size.width(), size.height());
214
215 Error err = src.draw(canvas);
216 if (!err.isEmpty()) {
217 return err;
218 }
219 canvas->flush();
220 doc->endPage();
221 doc->close();
222 return "";
223 }
224
225 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
226
227 RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
228
229 Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*) const {
230 const SkISize size = src.size();
231 // If there's an appropriate alpha type for this color type, use it, otherwi se use premul.
232 SkAlphaType alphaType = kPremul_SkAlphaType;
233 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
234
235 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
236 dst->eraseColor(SK_ColorTRANSPARENT);
237 SkCanvas canvas(*dst);
238 return src.draw(&canvas);
239 }
240
241 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
242
243 ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
244
245 Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
246 // We turn our arguments into a Src, then draw that Src into our Sink to fil l bitmap or stream.
247 struct ProxySrc : public Src {
248 const Src& fSrc;
249 SkMatrix fMatrix;
250 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) { }
251
252 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
253 canvas->concat(fMatrix);
254 return fSrc.draw(canvas);
255 }
256 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
257 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one shou ld be calling this.
258 } proxy(src, fMatrix);
259 return fSink->draw(proxy, bitmap, stream);
260 }
261
262 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
263
264 ViaPipe::ViaPipe(int flags, Sink* sink) : fFlags((SkGPipeWriter::Flags)flags), f Sink(sink) {}
265
266 Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
267 // We turn our arguments into a Src, then draw that Src into our Sink to fil l bitmap or stream.
268 struct ProxySrc : public Src {
269 const Src& fSrc;
270 SkGPipeWriter::Flags fFlags;
271 ProxySrc(const Src& src, SkGPipeWriter::Flags flags) : fSrc(src), fFlags (flags) {}
272
273 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
274 SkISize size = this->size();
275 // TODO: is DecodeMemory really required? Might help RAM usage to be lazy if we can.
276 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
277 SkGPipeWriter pipe;
278 return fSrc.draw(pipe.startRecording(&controller, fFlags, size.width (), size.height()));
279 }
280 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
281 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one shou ld be calling this.
282 } proxy(src, fFlags);
283 return fSink->draw(proxy, bitmap, stream);
284 }
285
286 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
287
288 ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
289
290 Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream ) const {
291 // Record our Src into a picture.
292 SkSize size;
293 size = src.size();
294 SkPictureRecorder recorder;
295 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
296 if (!err.isEmpty()) {
297 return err;
298 }
299 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
300
301 // Serialize it and then deserialize it.
302 SkDynamicMemoryWStream wStream;
303 pic->serialize(&wStream);
304 SkAutoTUnref<SkStream> rStream(wStream.detachAsStream());
305 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
306
307 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
308 struct ProxySrc : public Src {
309 const SkPicture* fPic;
310 const SkISize fSize;
311 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
312
313 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
314 canvas->drawPicture(fPic);
315 return "";
316 }
317 SkISize size() const SK_OVERRIDE { return fSize; }
318 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one shou ld be calling this.
319 } proxy(deserialized, src.size());
320 return fSink->draw(proxy, bitmap, stream);
321 }
322
323 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
324
325 ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
326 : fW(w)
327 , fH(h)
328 , fFactory(factory)
329 , fSink(sink) {}
330
331 Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream) const {
332 // Record our Src into a picture.
333 SkSize size;
334 size = src.size();
335 SkPictureRecorder recorder;
336 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fF actory.get()));
337 if (!err.isEmpty()) {
338 return err;
339 }
340 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
341
342 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
343 struct ProxySrc : public Src {
344 const int fW, fH;
345 const SkPicture* fPic;
346 const SkISize fSize;
347 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
348 : fW(w), fH(h), fPic(pic), fSize(size) {}
349
350 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
351 const int xTiles = (fSize.width() + fW - 1) / fW,
352 yTiles = (fSize.height() + fH - 1) / fH;
353 SkMultiPictureDraw mpd(xTiles*yTiles);
354 SkTDArray<SkSurface*> surfaces;
355 surfaces.setReserve(xTiles*yTiles);
356
357 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
358 for (int j = 0; j < yTiles; j++) {
359 for (int i = 0; i < xTiles; i++) {
360 // This lets our ultimate Sink determine the best kind of su rface.
361 // E.g., if it's a GpuSink, the surfaces and images are text ures.
362 SkSurface* s = canvas->newSurface(info);
363 if (!s) {
364 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
365 }
366 surfaces.push(s);
367 SkCanvas* c = s->getCanvas();
368 c->translate(SkIntToScalar(-i * fW),
369 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
370 mpd.add(c, fPic);
371 }
372 }
373 mpd.draw();
374 for (int j = 0; j < yTiles; j++) {
375 for (int i = 0; i < xTiles; i++) {
376 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSn apshot());
377 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar( j*fH));
378 }
379 }
380 surfaces.unrefAll();
381 return "";
382 }
383 SkISize size() const SK_OVERRIDE { return fSize; }
384 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one shou ld be calling this.
385 } proxy(fW, fH, pic, src.size());
386 return fSink->draw(proxy, bitmap, stream);
387 }
388
389 } // namespace DM
OLDNEW
« no previous file with comments | « dm/DMSrcSink.h ('k') | dm/DMTask.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698