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