1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2014 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBigPicture.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkData.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDrawable.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMiniRecorder.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPictureRecorder.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRecord.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRecordDraw.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRecordOpts.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRecordedDrawable.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRecorder.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypes.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkPictureRecorder::SkPictureRecorder() { 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fActivelyRecording = false; 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMiniRecorder.reset(new SkMiniRecorder); 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRecorder.reset(new SkRecorder(nullptr, SkRect::MakeEmpty(), fMiniRecorder.get())); 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkPictureRecorder::~SkPictureRecorder() {} 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkCanvas* SkPictureRecorder::beginRecording(const SkRect& userCullRect, 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBBHFactory* bbhFactory /* = nullptr */, 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t recordFlags /* = 0 */) { 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect cullRect = userCullRect.isEmpty() ? SkRect::MakeEmpty() : userCullRect; 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCullRect = cullRect; 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFlags = recordFlags; 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (bbhFactory) { 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBBH.reset((*bbhFactory)(cullRect)); 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fBBH.get()); 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fRecord) { 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRecord.reset(new SkRecord); 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRecorder::DrawPictureMode dpm = (recordFlags & kPlaybackDrawPicture_RecordFlag) 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? SkRecorder::Playback_DrawPictureMode 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : SkRecorder::Record_DrawPictureMode; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRecorder->reset(fRecord.get(), cullRect, dpm, fMiniRecorder.get()); 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fActivelyRecording = true; 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->getRecordingCanvas(); 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkCanvas* SkPictureRecorder::getRecordingCanvas() { 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fActivelyRecording ? fRecorder.get() : nullptr; 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkPicture> SkPictureRecorder::finishRecordingAsPicture(uint32_t finishFlags) { 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fActivelyRecording = false; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRecorder->restoreToCount(1); // If we were missing any restores, add them now. 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRecord->count() == 0) { 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto pic = fMiniRecorder->detachAsPicture(fBBH ? nullptr : &fCullRect); 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBBH.reset(nullptr); 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return pic; 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: delay as much of this work until just before first playback? 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRecordOptimize(fRecord.get()); 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDrawableList* drawableList = fRecorder->getDrawableList(); 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBigPicture::SnapshotArray* pictList = 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawableList ? drawableList->newDrawableSnapshot() : nullptr; 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fBBH.get()) { 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoTMalloc<SkRect> bounds(fRecord->count()); 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRecordFillBounds(fCullRect, *fRecord, bounds); 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBBH->insert(bounds, fRecord->count()); 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now that we've calculated content bounds, we can update fCullRect, often trimming it. 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: get updated fCullRect from bounds instead of forcing the BBH to return it? 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect bbhBound = fBBH->getRootBound(); 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT((bbhBound.isEmpty() || fCullRect.contains(bbhBound)) 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot || (bbhBound.isEmpty() && fCullRect.isEmpty())); 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCullRect = bbhBound; 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t subPictureBytes = fRecorder->approxBytesUsedBySubPictures(); 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; pictList && i < pictList->count(); i++) { 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot subPictureBytes += pictList->begin()[i]->approximateBytesUsed(); 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_make_sp<SkBigPicture>(fCullRect, fRecord.release(), pictList, fBBH.release(), 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot subPictureBytes); 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkPicture> SkPictureRecorder::finishRecordingAsPictureWithCull(const SkRect& cullRect, 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t finishFlags) { 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCullRect = cullRect; 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return this->finishRecordingAsPicture(finishFlags); 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkPictureRecorder::partialReplay(SkCanvas* canvas) const { 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == canvas) { 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int drawableCount = 0; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDrawable* const* drawables = nullptr; 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDrawableList* drawableList = fRecorder->getDrawableList(); 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (drawableList) { 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawableCount = drawableList->count(); 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot drawables = drawableList->begin(); 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRecordDraw(*fRecord, canvas, nullptr, drawables, drawableCount, nullptr/*bbh*/, nullptr/*callback*/); 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<SkDrawable> SkPictureRecorder::finishRecordingAsDrawable(uint32_t finishFlags) { 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fActivelyRecording = false; 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRecorder->flushMiniRecorder(); 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRecorder->restoreToCount(1); // If we were missing any restores, add them now. 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRecordOptimize(fRecord.get()); 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fBBH.get()) { 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoTMalloc<SkRect> bounds(fRecord->count()); 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRecordFillBounds(fCullRect, *fRecord, bounds); 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBBH->insert(bounds, fRecord->count()); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_sp<SkDrawable> drawable = 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_make_sp<SkRecordedDrawable>(std::move(fRecord), std::move(fBBH), 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRecorder->detachDrawableList(), fCullRect); 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return drawable; 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 135