blob: 9110ac82f9e09884b355cf7a2ba2b0d472fa61d4 [file] [log] [blame]
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrRecordReplaceDraw_DEFINED
#define GrRecordReplaceDraw_DEFINED
#include "SkChecksum.h"
#include "SkDrawPictureCallback.h"
#include "SkImage.h"
#include "SkRect.h"
#include "SkTDynamicHash.h"
class SkBBoxHierarchy;
class SkBitmap;
class SkCanvas;
class SkImage;
class SkMatrix;
class SkPaint;
class SkPicture;
class SkRecord;
// GrReplacements collects op ranges that can be replaced with
// a single drawBitmap call (using a precomputed bitmap).
class GrReplacements {
public:
// All the operations between fStart and fStop (inclusive) will be replaced with
// a single drawBitmap call using fPos, fImage and fPaint.
class ReplacementInfo {
public:
struct Key {
Key(uint32_t pictureID, unsigned int start, const SkMatrix& ctm)
: fPictureID(pictureID)
, fStart(start)
, fCTM(ctm) {
fCTM.getType(); // force initialization of type so hashes match
// Key needs to be tightly packed.
GR_STATIC_ASSERT(sizeof(Key) == sizeof(uint32_t) + // picture ID
sizeof(int) + // start
9 * sizeof(SkScalar) // 3x3 from CTM
+sizeof(uint32_t)); // matrix's type
}
bool operator==(const Key& other) const {
return fPictureID == other.fPictureID &&
fStart == other.fStart &&
fCTM.cheapEqualTo(other.fCTM); // TODO: should be fuzzy
}
uint32_t pictureID() const { return fPictureID; }
unsigned int start() const { return fStart; }
private:
const uint32_t fPictureID;
const unsigned int fStart;
const SkMatrix fCTM;
};
static const Key& GetKey(const ReplacementInfo& layer) { return layer.fKey; }
static uint32_t Hash(const Key& key) {
return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
}
ReplacementInfo(uint32_t pictureID, unsigned int start, const SkMatrix& ctm)
: fKey(pictureID, start, ctm)
, fImage(NULL)
, fPaint(NULL) {
}
~ReplacementInfo() { fImage->unref(); SkDELETE(fPaint); }
unsigned int start() const { return fKey.start(); }
const Key fKey;
unsigned fStop;
SkIPoint fPos;
SkImage* fImage; // Owns a ref
const SkPaint* fPaint; // Owned by this object
SkIRect fSrcRect;
};
~GrReplacements() { this->freeAll(); }
// Add a new replacement range.
ReplacementInfo* newReplacement(uint32_t pictureID, unsigned int start, const SkMatrix& ctm);
// look up a replacement range by its pictureID, start offset and the CTM
// TODO: also need to add clip to lookup
const ReplacementInfo* lookupByStart(uint32_t pictureID, size_t start,
const SkMatrix& ctm) const;
private:
SkTDynamicHash<ReplacementInfo, ReplacementInfo::Key> fReplacementHash;
void freeAll();
};
// Draw an SkPicture into an SkCanvas replacing saveLayer/restore blocks with
// drawBitmap calls. A convenience wrapper around SkRecords::Draw.
// It returns the number of saveLayer/restore blocks replaced with drawBitmap calls.
int GrRecordReplaceDraw(const SkPicture*,
SkCanvas*,
const GrReplacements*,
const SkMatrix& initialMatrix,
SkDrawPictureCallback*);
#endif // GrRecordReplaceDraw_DEFINED