DMSrcSink.cpp revision 709d2c3e5062c5b57f91273bfc11a751f5b2bb88
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 11namespace DM { 12 13void SafeUnref(SkPicture* p) { SkSafeUnref(p); } 14void SafeUnref(SkData* d) { SkSafeUnref(d); } 15 16// FIXME: the GM objects themselves are not threadsafe, so we create and destroy them as needed. 17 18GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {} 19 20Error 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 27SkISize GMSrc::size() const { 28 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL)); 29 return gm->getISize(); 30} 31 32Name 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. ~ImageSrc unrefs it. 40struct LazyLoadImage { 41 LazyLoadImage(const char* path) : path(path) {} 42 const char* path; 43 44 SkData* operator()() const { return SkData::NewFromFileName(path); } 45}; 46 47ImageSrc::ImageSrc(SkString path, int subsets) : fPath(path), fSubsets(subsets) {} 48 49Error 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(), &bitmap)) { 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 92SkISize 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 105Name ImageSrc::name() const { return SkOSPath::Basename(fPath.c_str()); } 106 107/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 108 109static const SkRect kSKPViewport = {0,0, 1000,1000}; 110 111// The first call to draw() or size() will read the file into an SkPicture. ~SKPSrc unrefs it. 112struct 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 125SKPSrc::SKPSrc(SkString path) : fPath(path) {} 126 127Error 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 137SkISize 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 152Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); } 153 154/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 155 156DEFINE_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 161GPUSink::GPUSink(GrContextFactory::GLContextType ct, GrGLStandard api, int samples, bool dfText) 162 : fContextType(ct) 163 , fGpuAPI(api) 164 , fSampleCount(samples) 165 , fUseDFText(dfText) {} 166 167int GPUSink::enclave() const { 168 return FLAGS_gpu_threading.contains("none") ? kGPUSink_Enclave : kAnyThread_Enclave; 169} 170 171static void* CreateGrFactory() { return new GrContextFactory; } 172static void DeleteGrFactory(void* p) { delete (GrContextFactory*)p; } 173 174Error 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-scoped 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, fUseDFText)); 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 207PDFSink::PDFSink() {} 208 209Error 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 227RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {} 228 229Error 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, otherwise 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 243ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {} 244 245Error 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 fill 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 should be calling this. 258 } proxy(src, fMatrix); 259 return fSink->draw(proxy, bitmap, stream); 260} 261 262/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 263 264ViaPipe::ViaPipe(int flags, Sink* sink) : fFlags((SkGPipeWriter::Flags)flags), fSink(sink) {} 265 266Error 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 fill 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 should be calling this. 282 } proxy(src, fFlags); 283 return fSink->draw(proxy, bitmap, stream); 284} 285 286/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 287 288ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {} 289 290Error 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 should be calling this. 319 } proxy(deserialized, src.size()); 320 return fSink->draw(proxy, bitmap, stream); 321} 322 323/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 324 325ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink) 326 : fW(w) 327 , fH(h) 328 , fFactory(factory) 329 , fSink(sink) {} 330 331Error 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(), fFactory.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 surface. 361 // E.g., if it's a GpuSink, the surfaces and images are textures. 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]->newImageSnapshot()); 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 should be calling this. 385 } proxy(fW, fH, pic, src.size()); 386 return fSink->draw(proxy, bitmap, stream); 387} 388 389} // namespace DM 390