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

Side by Side Diff: tools/PictureRenderer.cpp

Issue 1457753002: Clean up dead code: PictureRenderer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase? Created 5 years, 1 month 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 | « tools/PictureRenderer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "PictureRenderer.h"
9 #include "picture_utils.h"
10 #include "SamplePipeControllers.h"
11 #include "SkBitmapHasher.h"
12 #include "SkCanvas.h"
13 #include "SkData.h"
14 #include "SkDevice.h"
15 #include "SkDiscardableMemoryPool.h"
16 #include "SkGPipe.h"
17 #if SK_SUPPORT_GPU
18 #include "gl/GrGLDefines.h"
19 #include "SkGpuDevice.h"
20 #endif
21 #include "SkGraphics.h"
22 #include "SkImageEncoder.h"
23 #include "SkMaskFilter.h"
24 #include "SkMatrix.h"
25 #include "SkMultiPictureDraw.h"
26 #include "SkOSFile.h"
27 #include "SkPaintFilterCanvas.h"
28 #include "SkPicture.h"
29 #include "SkPictureRecorder.h"
30 #include "SkPictureUtils.h"
31 #include "SkPixelRef.h"
32 #include "SkPixelSerializer.h"
33 #include "SkScalar.h"
34 #include "SkStream.h"
35 #include "SkString.h"
36 #include "SkSurface.h"
37 #include "SkTemplates.h"
38 #include "SkTDArray.h"
39 #include "SkThreadUtils.h"
40 #include "SkTypes.h"
41 #include "sk_tool_utils.h"
42
43 static inline SkScalar scalar_log2(SkScalar x) {
44 static const SkScalar log2_conversion_factor = SkScalarInvert(SkScalarLog(2) );
45
46 return SkScalarLog(x) * log2_conversion_factor;
47 }
48
49 namespace sk_tools {
50
51 enum {
52 kDefaultTileWidth = 256,
53 kDefaultTileHeight = 256
54 };
55
56 void PictureRenderer::init(const SkPicture* pict,
57 const SkString* writePath,
58 const SkString* mismatchPath,
59 const SkString* inputFilename,
60 bool useChecksumBasedFilenames,
61 bool useMultiPictureDraw) {
62 this->CopyString(&fWritePath, writePath);
63 this->CopyString(&fMismatchPath, mismatchPath);
64 this->CopyString(&fInputFilename, inputFilename);
65 fUseChecksumBasedFilenames = useChecksumBasedFilenames;
66 fUseMultiPictureDraw = useMultiPictureDraw;
67
68 SkASSERT(nullptr == fPicture);
69 SkASSERT(nullptr == fCanvas.get());
70 if (fPicture || fCanvas.get()) {
71 return;
72 }
73
74 SkASSERT(pict != nullptr);
75 if (nullptr == pict) {
76 return;
77 }
78
79 fPicture.reset(SkRef(pict));
80 fCanvas.reset(this->setupCanvas());
81 }
82
83 void PictureRenderer::CopyString(SkString* dest, const SkString* src) {
84 if (src) {
85 dest->set(*src);
86 } else {
87 dest->reset();
88 }
89 }
90
91 class FlagsFilterCanvas : public SkPaintFilterCanvas {
92 public:
93 FlagsFilterCanvas(SkCanvas* canvas, PictureRenderer::DrawFilterFlags* flags)
94 : INHERITED(canvas->imageInfo().width(), canvas->imageInfo().height())
95 , fFlags(flags) {
96 this->addCanvas(canvas);
97 }
98
99 protected:
100 void onFilterPaint(SkPaint* paint, Type t) const override {
101 paint->setFlags(paint->getFlags() & ~fFlags[t] & SkPaint::kAllFlags);
102 if (PictureRenderer::kMaskFilter_DrawFilterFlag & fFlags[t]) {
103 SkMaskFilter* maskFilter = paint->getMaskFilter();
104 if (maskFilter) {
105 paint->setMaskFilter(nullptr);
106 }
107 }
108 if (PictureRenderer::kHinting_DrawFilterFlag & fFlags[t]) {
109 paint->setHinting(SkPaint::kNo_Hinting);
110 } else if (PictureRenderer::kSlightHinting_DrawFilterFlag & fFlags[t]) {
111 paint->setHinting(SkPaint::kSlight_Hinting);
112 }
113 }
114
115 private:
116 const PictureRenderer::DrawFilterFlags* fFlags;
117
118 typedef SkPaintFilterCanvas INHERITED;
119 };
120
121 SkCanvas* PictureRenderer::setupCanvas() {
122 const int width = this->getViewWidth();
123 const int height = this->getViewHeight();
124 return this->setupCanvas(width, height);
125 }
126
127 SkCanvas* PictureRenderer::setupCanvas(int width, int height) {
128 SkAutoTUnref<SkCanvas> canvas;
129
130 switch(fDeviceType) {
131 case kBitmap_DeviceType: {
132 SkBitmap bitmap;
133 sk_tools::setup_bitmap(&bitmap, width, height);
134 canvas.reset(new SkCanvas(bitmap));
135 }
136 break;
137 #if SK_SUPPORT_GPU
138 #if SK_ANGLE
139 case kAngle_DeviceType:
140 // fall through
141 #endif
142 #if SK_COMMAND_BUFFER
143 case kCommandBuffer_DeviceType:
144 // fall through
145 #endif
146 #if SK_MESA
147 case kMesa_DeviceType:
148 // fall through
149 #endif
150 case kGPU_DeviceType:
151 case kNVPR_DeviceType: {
152 SkAutoTUnref<GrSurface> target;
153 if (fGrContext) {
154 // create a render target to back the device
155 GrSurfaceDesc desc;
156 desc.fConfig = kSkia8888_GrPixelConfig;
157 desc.fFlags = kRenderTarget_GrSurfaceFlag;
158 desc.fWidth = width;
159 desc.fHeight = height;
160 desc.fSampleCnt = fSampleCount;
161 target.reset(fGrContext->textureProvider()->createTexture(desc, false, nullptr, 0));
162 }
163
164 uint32_t flags = fUseDFText ? SkSurfaceProps::kUseDeviceIndependentF onts_Flag : 0;
165 SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType );
166 SkAutoTUnref<SkGpuDevice> device(
167 SkGpuDevice::Create(target->asRenderTarget(), &props,
168 SkGpuDevice::kUninit_InitContents));
169 if (!device) {
170 return nullptr;
171 }
172 canvas.reset(new SkCanvas(device));
173 break;
174 }
175 #endif
176 default:
177 SkASSERT(0);
178 return nullptr;
179 }
180
181 if (fHasDrawFilters) {
182 if (fDrawFilters[0] & PictureRenderer::kAAClip_DrawFilterFlag) {
183 canvas->setAllowSoftClip(false);
184 }
185
186 canvas.reset(new FlagsFilterCanvas(canvas.get(), fDrawFilters));
187 }
188
189 this->scaleToScaleFactor(canvas);
190
191 // Pictures often lie about their extent (i.e., claim to be 100x100 but
192 // only ever draw to 90x100). Clear here so the undrawn portion will have
193 // a consistent color
194 canvas->clear(SK_ColorTRANSPARENT);
195 return canvas.detach();
196 }
197
198 void PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) {
199 SkASSERT(canvas != nullptr);
200 if (fScaleFactor != SK_Scalar1) {
201 canvas->scale(fScaleFactor, fScaleFactor);
202 }
203 }
204
205 void PictureRenderer::end() {
206 this->resetState(true);
207 fPicture.reset(nullptr);
208 fCanvas.reset(nullptr);
209 }
210
211 int PictureRenderer::getViewWidth() {
212 SkASSERT(fPicture != nullptr);
213 int width = SkScalarCeilToInt(fPicture->cullRect().width() * fScaleFactor);
214 if (fViewport.width() > 0) {
215 width = SkMin32(width, fViewport.width());
216 }
217 return width;
218 }
219
220 int PictureRenderer::getViewHeight() {
221 SkASSERT(fPicture != nullptr);
222 int height = SkScalarCeilToInt(fPicture->cullRect().height() * fScaleFactor) ;
223 if (fViewport.height() > 0) {
224 height = SkMin32(height, fViewport.height());
225 }
226 return height;
227 }
228
229 /** Converts fPicture to a picture that uses a BBoxHierarchy.
230 * PictureRenderer subclasses that are used to test picture playback
231 * should call this method during init.
232 */
233 void PictureRenderer::buildBBoxHierarchy() {
234 SkASSERT(fPicture);
235 if (kNone_BBoxHierarchyType != fBBoxHierarchyType && fPicture) {
236 SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
237 SkPictureRecorder recorder;
238 uint32_t flags = this->recordFlags();
239 if (fUseMultiPictureDraw) {
240 flags |= SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
241 }
242 SkCanvas* canvas = recorder.beginRecording(fPicture->cullRect().width(),
243 fPicture->cullRect().height() ,
244 factory.get(),
245 flags);
246 fPicture->playback(canvas);
247 fPicture.reset(recorder.endRecording());
248 }
249 }
250
251 void PictureRenderer::resetState(bool callFinish) {
252 #if SK_SUPPORT_GPU
253 SkGLContext* glContext = this->getGLContext();
254 if (nullptr == glContext) {
255 SkASSERT(kBitmap_DeviceType == fDeviceType);
256 return;
257 }
258
259 fGrContext->flush();
260 glContext->swapBuffers();
261 if (callFinish) {
262 SK_GL(*glContext, Finish());
263 }
264 #endif
265 }
266
267 void PictureRenderer::purgeTextures() {
268 SkDiscardableMemoryPool* pool = SkGetGlobalDiscardableMemoryPool();
269
270 pool->dumpPool();
271
272 #if SK_SUPPORT_GPU
273 SkGLContext* glContext = this->getGLContext();
274 if (nullptr == glContext) {
275 SkASSERT(kBitmap_DeviceType == fDeviceType);
276 return;
277 }
278
279 // resetState should've already done this
280 fGrContext->flush();
281
282 fGrContext->purgeAllUnlockedResources();
283 #endif
284 }
285
286 //////////////////////////////////////////////////////////////////////////////// ///////////////
287
288 SkCanvas* RecordPictureRenderer::setupCanvas(int width, int height) {
289 // defer the canvas setup until the render step
290 return nullptr;
291 }
292
293 bool RecordPictureRenderer::render(SkBitmap** out) {
294 SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
295 SkPictureRecorder recorder;
296 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(this->getViewWidth( )),
297 SkIntToScalar(this->getViewHeight ()),
298 factory.get(),
299 this->recordFlags());
300 this->scaleToScaleFactor(canvas);
301 fPicture->playback(canvas);
302 SkAutoTUnref<SkPicture> picture(recorder.endRecording());
303 if (!fWritePath.isEmpty()) {
304 // Record the new picture as a new SKP with PNG encoded bitmaps.
305 SkString skpPath = SkOSPath::Join(fWritePath.c_str(), fInputFilename.c_s tr());
306 SkFILEWStream stream(skpPath.c_str());
307 sk_tool_utils::PngPixelSerializer serializer;
308 picture->serialize(&stream, &serializer);
309 return true;
310 }
311 return false;
312 }
313
314 SkString RecordPictureRenderer::getConfigNameInternal() {
315 return SkString("record");
316 }
317
318 //////////////////////////////////////////////////////////////////////////////// ///////////////
319
320 bool PipePictureRenderer::render(SkBitmap** out) {
321 SkASSERT(fCanvas.get() != nullptr);
322 SkASSERT(fPicture != nullptr);
323 if (nullptr == fCanvas.get() || nullptr == fPicture) {
324 return false;
325 }
326
327 PipeController pipeController(fCanvas.get());
328 SkGPipeWriter writer;
329 SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
330 pipeCanvas->drawPicture(fPicture);
331 writer.endRecording();
332 fCanvas->flush();
333 if (out) {
334 *out = new SkBitmap;
335 setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
336 SkScalarCeilToInt(fPicture->cullRect().height()));
337 fCanvas->readPixels(*out, 0, 0);
338 }
339 return true;
340 }
341
342 SkString PipePictureRenderer::getConfigNameInternal() {
343 return SkString("pipe");
344 }
345
346 //////////////////////////////////////////////////////////////////////////////// ///////////////
347
348 void SimplePictureRenderer::init(const SkPicture* picture, const SkString* write Path,
349 const SkString* mismatchPath, const SkString* i nputFilename,
350 bool useChecksumBasedFilenames, bool useMultiPi ctureDraw) {
351 INHERITED::init(picture, writePath, mismatchPath, inputFilename,
352 useChecksumBasedFilenames, useMultiPictureDraw);
353 this->buildBBoxHierarchy();
354 }
355
356 bool SimplePictureRenderer::render(SkBitmap** out) {
357 SkASSERT(fCanvas.get() != nullptr);
358 SkASSERT(fPicture);
359 if (nullptr == fCanvas.get() || nullptr == fPicture) {
360 return false;
361 }
362
363 if (fUseMultiPictureDraw) {
364 SkMultiPictureDraw mpd;
365
366 mpd.add(fCanvas, fPicture);
367
368 mpd.draw();
369 } else {
370 fCanvas->drawPicture(fPicture);
371 }
372 fCanvas->flush();
373 if (out) {
374 *out = new SkBitmap;
375 setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
376 SkScalarCeilToInt(fPicture->cullRect().height()));
377 fCanvas->readPixels(*out, 0, 0);
378 }
379 return true;
380 }
381
382 SkString SimplePictureRenderer::getConfigNameInternal() {
383 return SkString("simple");
384 }
385
386 //////////////////////////////////////////////////////////////////////////////// ///////////////
387
388 #if SK_SUPPORT_GPU
389 TiledPictureRenderer::TiledPictureRenderer(const GrContextOptions& opts)
390 : INHERITED(opts)
391 , fTileWidth(kDefaultTileWidth)
392 #else
393 TiledPictureRenderer::TiledPictureRenderer()
394 : fTileWidth(kDefaultTileWidth)
395 #endif
396 , fTileHeight(kDefaultTileHeight)
397 , fTileWidthPercentage(0.0)
398 , fTileHeightPercentage(0.0)
399 , fTileMinPowerOf2Width(0)
400 , fCurrentTileOffset(-1)
401 , fTilesX(0)
402 , fTilesY(0) { }
403
404 void TiledPictureRenderer::init(const SkPicture* pict, const SkString* writePath ,
405 const SkString* mismatchPath, const SkString* in putFilename,
406 bool useChecksumBasedFilenames, bool useMultiPic tureDraw) {
407 SkASSERT(pict);
408 SkASSERT(0 == fTileRects.count());
409 if (nullptr == pict || fTileRects.count() != 0) {
410 return;
411 }
412
413 // Do not call INHERITED::init(), which would create a (potentially large) c anvas which is not
414 // used by bench_pictures.
415 fPicture.reset(SkRef(pict));
416 this->CopyString(&fWritePath, writePath);
417 this->CopyString(&fMismatchPath, mismatchPath);
418 this->CopyString(&fInputFilename, inputFilename);
419 fUseChecksumBasedFilenames = useChecksumBasedFilenames;
420 fUseMultiPictureDraw = useMultiPictureDraw;
421 this->buildBBoxHierarchy();
422
423 if (fTileWidthPercentage > 0) {
424 fTileWidth = SkScalarCeilToInt(float(fTileWidthPercentage * fPicture->cu llRect().width() / 100));
425 }
426 if (fTileHeightPercentage > 0) {
427 fTileHeight = SkScalarCeilToInt(float(fTileHeightPercentage * fPicture-> cullRect().height() / 100));
428 }
429
430 if (fTileMinPowerOf2Width > 0) {
431 this->setupPowerOf2Tiles();
432 } else {
433 this->setupTiles();
434 }
435 fCanvas.reset(this->setupCanvas(fTileWidth, fTileHeight));
436 // Initialize to -1 so that the first call to nextTile will set this up to d raw tile 0 on the
437 // first call to drawCurrentTile.
438 fCurrentTileOffset = -1;
439 }
440
441 void TiledPictureRenderer::end() {
442 fTileRects.reset();
443 this->INHERITED::end();
444 }
445
446 void TiledPictureRenderer::setupTiles() {
447 // Only use enough tiles to cover the viewport
448 const int width = this->getViewWidth();
449 const int height = this->getViewHeight();
450
451 fTilesX = fTilesY = 0;
452 for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeigh t) {
453 fTilesY++;
454 for (int tile_x_start = 0; tile_x_start < width; tile_x_start += fTileWi dth) {
455 if (0 == tile_y_start) {
456 // Only count tiles in the X direction on the first pass.
457 fTilesX++;
458 }
459 *fTileRects.append() = SkIRect::MakeXYWH(tile_x_start, tile_y_start,
460 fTileWidth, fTileHeight);
461 }
462 }
463 }
464
465 bool TiledPictureRenderer::tileDimensions(int &x, int &y) {
466 if (fTileRects.count() == 0 || nullptr == fPicture) {
467 return false;
468 }
469 x = fTilesX;
470 y = fTilesY;
471 return true;
472 }
473
474 // The goal of the powers of two tiles is to minimize the amount of wasted tile
475 // space in the width-wise direction and then minimize the number of tiles. The
476 // constraints are that every tile must have a pixel width that is a power of
477 // two and also be of some minimal width (that is also a power of two).
478 //
479 // This is solved by first taking our picture size and rounding it up to the
480 // multiple of the minimal width. The binary representation of this rounded
481 // value gives us the tiles we need: a bit of value one means we need a tile of
482 // that size.
483 void TiledPictureRenderer::setupPowerOf2Tiles() {
484 // Only use enough tiles to cover the viewport
485 const int width = this->getViewWidth();
486 const int height = this->getViewHeight();
487
488 int rounded_value = width;
489 if (width % fTileMinPowerOf2Width != 0) {
490 rounded_value = width - (width % fTileMinPowerOf2Width) + fTileMinPowerO f2Width;
491 }
492
493 int num_bits = SkScalarCeilToInt(scalar_log2(SkIntToScalar(width)));
494 int largest_possible_tile_size = 1 << num_bits;
495
496 fTilesX = fTilesY = 0;
497 // The tile height is constant for a particular picture.
498 for (int tile_y_start = 0; tile_y_start < height; tile_y_start += fTileHeigh t) {
499 fTilesY++;
500 int tile_x_start = 0;
501 int current_width = largest_possible_tile_size;
502 // Set fTileWidth to be the width of the widest tile, so that each canva s is large enough
503 // to draw each tile.
504 fTileWidth = current_width;
505
506 while (current_width >= fTileMinPowerOf2Width) {
507 // It is very important this is a bitwise AND.
508 if (current_width & rounded_value) {
509 if (0 == tile_y_start) {
510 // Only count tiles in the X direction on the first pass.
511 fTilesX++;
512 }
513 *fTileRects.append() = SkIRect::MakeXYWH(tile_x_start, tile_y_st art,
514 current_width, fTileHei ght);
515 tile_x_start += current_width;
516 }
517
518 current_width >>= 1;
519 }
520 }
521 }
522
523 /**
524 * Draw the specified picture to the canvas translated to rectangle provided, so that this mini
525 * canvas represents the rectangle's portion of the overall picture.
526 * Saves and restores so that the initial clip and matrix return to their state before this function
527 * is called.
528 */
529 static void draw_tile_to_canvas(SkCanvas* canvas,
530 const SkIRect& tileRect,
531 const SkPicture* picture) {
532 int saveCount = canvas->save();
533 // Translate so that we draw the correct portion of the picture.
534 // Perform a postTranslate so that the scaleFactor does not interfere with t he positioning.
535 SkMatrix mat(canvas->getTotalMatrix());
536 mat.postTranslate(-SkIntToScalar(tileRect.fLeft), -SkIntToScalar(tileRect.fT op));
537 canvas->setMatrix(mat);
538 canvas->clipRect(SkRect::Make(tileRect));
539 canvas->clear(SK_ColorTRANSPARENT); // Not every picture covers the entirety of every tile
540 canvas->drawPicture(picture);
541 canvas->restoreToCount(saveCount);
542 canvas->flush();
543 }
544
545 //////////////////////////////////////////////////////////////////////////////// ///////////////
546
547 /**
548 * Copies the entirety of the src bitmap (typically a tile) into a portion of th e dst bitmap.
549 * If the src bitmap is too large to fit within the dst bitmap after the x and y
550 * offsets have been applied, any excess will be ignored (so only the top-left p ortion of the
551 * src bitmap will be copied).
552 *
553 * @param src source bitmap
554 * @param dst destination bitmap
555 * @param xOffset x-offset within destination bitmap
556 * @param yOffset y-offset within destination bitmap
557 */
558 static void bitmapCopyAtOffset(const SkBitmap& src, SkBitmap* dst,
559 int xOffset, int yOffset) {
560 for (int y = 0; y <src.height() && y + yOffset < dst->height() ; y++) {
561 for (int x = 0; x < src.width() && x + xOffset < dst->width() ; x++) {
562 *dst->getAddr32(xOffset + x, yOffset + y) = *src.getAddr32(x, y);
563 }
564 }
565 }
566
567 bool TiledPictureRenderer::nextTile(int &i, int &j) {
568 if (++fCurrentTileOffset < fTileRects.count()) {
569 i = fCurrentTileOffset % fTilesX;
570 j = fCurrentTileOffset / fTilesX;
571 return true;
572 }
573 return false;
574 }
575
576 void TiledPictureRenderer::drawCurrentTile() {
577 SkASSERT(fCurrentTileOffset >= 0 && fCurrentTileOffset < fTileRects.count()) ;
578 draw_tile_to_canvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture);
579 }
580
581 bool TiledPictureRenderer::postRender(SkCanvas* canvas, const SkIRect& tileRect,
582 SkBitmap* tempBM, SkBitmap** out,
583 int tileNumber) {
584 bool success = true;
585
586 if (out) {
587 if (canvas->readPixels(tempBM, 0, 0)) {
588 // Add this tile to the entire bitmap.
589 bitmapCopyAtOffset(*tempBM, *out, tileRect.left(), tileRect.top());
590 } else {
591 success = false;
592 }
593 }
594
595 return success;
596 }
597
598 bool TiledPictureRenderer::render(SkBitmap** out) {
599 SkASSERT(fPicture != nullptr);
600 if (nullptr == fPicture) {
601 return false;
602 }
603
604 SkBitmap bitmap;
605 if (out) {
606 *out = new SkBitmap;
607 setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()),
608 SkScalarCeilToInt(fPicture->cullRect().height()));
609 setup_bitmap(&bitmap, fTileWidth, fTileHeight);
610 }
611 bool success = true;
612
613 if (fUseMultiPictureDraw) {
614 SkMultiPictureDraw mpd;
615 SkTDArray<SkSurface*> surfaces;
616 surfaces.setReserve(fTileRects.count());
617
618 // Create a separate SkSurface/SkCanvas for each tile along with a
619 // translated version of the skp (to mimic Chrome's behavior) and
620 // feed all such pairs to the MultiPictureDraw.
621 for (int i = 0; i < fTileRects.count(); ++i) {
622 SkImageInfo ii = fCanvas->imageInfo().makeWH(fTileRects[i].width(),
623 fTileRects[i].height()) ;
624 *surfaces.append() = fCanvas->newSurface(ii);
625 surfaces[i]->getCanvas()->setMatrix(fCanvas->getTotalMatrix());
626
627 SkPictureRecorder recorder;
628 SkRTreeFactory bbhFactory;
629
630 SkCanvas* c = recorder.beginRecording(SkIntToScalar(fTileRects[i].wi dth()),
631 SkIntToScalar(fTileRects[i].he ight()),
632 &bbhFactory,
633 SkPictureRecorder::kComputeSav eLayerInfo_RecordFlag);
634 c->save();
635 SkMatrix mat;
636 mat.setTranslate(-SkIntToScalar(fTileRects[i].fLeft),
637 -SkIntToScalar(fTileRects[i].fTop));
638 c->setMatrix(mat);
639 c->drawPicture(fPicture);
640 c->restore();
641
642 SkAutoTUnref<SkPicture> xlatedPicture(recorder.endRecording());
643
644 mpd.add(surfaces[i]->getCanvas(), xlatedPicture);
645 }
646
647 // Render all the buffered SkCanvases/SkPictures
648 mpd.draw();
649
650 // Sort out the results and cleanup the allocated surfaces
651 for (int i = 0; i < fTileRects.count(); ++i) {
652 success &= this->postRender(surfaces[i]->getCanvas(), fTileRects[i], &bitmap, out, i);
653 surfaces[i]->unref();
654 }
655 } else {
656 for (int i = 0; i < fTileRects.count(); ++i) {
657 draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture);
658 success &= this->postRender(fCanvas, fTileRects[i], &bitmap, out, i) ;
659 }
660 }
661
662 return success;
663 }
664
665 SkCanvas* TiledPictureRenderer::setupCanvas(int width, int height) {
666 SkCanvas* canvas = this->INHERITED::setupCanvas(width, height);
667 SkASSERT(fPicture);
668 // Clip the tile to an area that is completely inside both the SkPicture and the viewport. This
669 // is mostly important for tiles on the right and bottom edges as they may g o over this area and
670 // the picture may have some commands that draw outside of this area and so should not actually
671 // be written.
672 // Uses a clipRegion so that it will be unaffected by the scale factor, whic h may have been set
673 // by INHERITED::setupCanvas.
674 SkRegion clipRegion;
675 clipRegion.setRect(0, 0, this->getViewWidth(), this->getViewHeight());
676 canvas->clipRegion(clipRegion);
677 return canvas;
678 }
679
680 SkString TiledPictureRenderer::getConfigNameInternal() {
681 SkString name;
682 if (fTileMinPowerOf2Width > 0) {
683 name.append("pow2tile_");
684 name.appendf("%i", fTileMinPowerOf2Width);
685 } else {
686 name.append("tile_");
687 if (fTileWidthPercentage > 0) {
688 name.appendf("%.f%%", fTileWidthPercentage);
689 } else {
690 name.appendf("%i", fTileWidth);
691 }
692 }
693 name.append("x");
694 if (fTileHeightPercentage > 0) {
695 name.appendf("%.f%%", fTileHeightPercentage);
696 } else {
697 name.appendf("%i", fTileHeight);
698 }
699 return name;
700 }
701
702 //////////////////////////////////////////////////////////////////////////////// ///////////////
703
704 void PlaybackCreationRenderer::setup() {
705 SkAutoTDelete<SkBBHFactory> factory(this->getFactory());
706 fRecorder.reset(new SkPictureRecorder);
707 SkCanvas* canvas = fRecorder->beginRecording(SkIntToScalar(this->getViewWidt h()),
708 SkIntToScalar(this->getViewHeig ht()),
709 factory.get(),
710 this->recordFlags());
711 this->scaleToScaleFactor(canvas);
712 canvas->drawPicture(fPicture);
713 }
714
715 bool PlaybackCreationRenderer::render(SkBitmap** out) {
716 fPicture.reset(fRecorder->endRecording());
717 // Since this class does not actually render, return false.
718 return false;
719 }
720
721 SkString PlaybackCreationRenderer::getConfigNameInternal() {
722 return SkString("playback_creation");
723 }
724
725 //////////////////////////////////////////////////////////////////////////////// ///////////////
726 // SkPicture variants for each BBoxHierarchy type
727
728 SkBBHFactory* PictureRenderer::getFactory() {
729 switch (fBBoxHierarchyType) {
730 case kNone_BBoxHierarchyType:
731 return nullptr;
732 case kRTree_BBoxHierarchyType:
733 return new SkRTreeFactory;
734 }
735 SkASSERT(0); // invalid bbhType
736 return nullptr;
737 }
738
739 } // namespace sk_tools
OLDNEW
« no previous file with comments | « tools/PictureRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698