blob: 538661a7b4afad42fd7e14a9dd5d8e3a6c3067f0 [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, const SkMatrix& initialMat,
const int* key, int keySize, bool copyKey = false)
: fKeySize(keySize)
, fFreeKey(copyKey) {
fIDMatrix.fPictureID = pictureID;
fIDMatrix.fInitialMat = initialMat;
fIDMatrix.fInitialMat.getType(); // force initialization of type so hashes match
if (copyKey) {
int* tempKey = SkNEW_ARRAY(int, keySize);
memcpy(tempKey, key, keySize * sizeof(int));
fKey = tempKey;
} else {
fKey = key;
}
// The pictureID/matrix portion needs to be tightly packed.
GR_STATIC_ASSERT(sizeof(IDMatrix) == sizeof(uint32_t)+ // pictureID
9 * sizeof(SkScalar)+sizeof(uint32_t)); // matrix
}
~Key() {
if (fFreeKey) {
SkDELETE_ARRAY(fKey);
}
}
bool operator==(const Key& other) const {
if (fKeySize != other.fKeySize) {
return false;
}
return fIDMatrix.fPictureID == other.fIDMatrix.fPictureID &&
fIDMatrix.fInitialMat.cheapEqualTo(other.fIDMatrix.fInitialMat) &&
!memcmp(fKey, other.fKey, fKeySize * sizeof(int));
}
uint32_t hash() const {
uint32_t hash = SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(fKey),
fKeySize * sizeof(int));
return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&fIDMatrix),
sizeof(IDMatrix), hash);
}
private:
struct IDMatrix {
uint32_t fPictureID;
SkMatrix fInitialMat;
} fIDMatrix;
const int* fKey;
const int fKeySize;
const bool fFreeKey;
};
static const Key& GetKey(const ReplacementInfo& layer) { return layer.fKey; }
static uint32_t Hash(const Key& key) { return key.hash(); }
ReplacementInfo(uint32_t pictureID, const SkMatrix& initialMat,
const int* key, int keySize)
: fKey(pictureID, initialMat, key, keySize, true)
, fImage(NULL)
, fPaint(NULL) {
}
~ReplacementInfo() { fImage->unref(); SkDELETE(fPaint); }
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, const SkMatrix& initialMat,
const int* key, int keySize);
const ReplacementInfo* lookup(uint32_t pictureID, const SkMatrix& initalMat,
const int* key, int keySize) 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