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