55b6d8be99
Add a unique ID to SkImageFilter, and use it as part of a persistent cache of image-filtered results. This is used for caching frame-to-frame coherent filters. We also keep track of which filter subtrees do not reference the src input, and use a GenID of zero for the src input in that case. That way, subtrees which are not dependent on the filter input can be cached independently of it. This gives approximately a 4X speedup on letmespellitoutforyou.com/samples/svg/filter_terrain.svg on Z620 and Nexus10. The cache key consists of the uniqueID of the filter, the clip bounds, the CTM and the genID of the input bitmap. Since this does not yet handle the case where the input primitives (and part of the resulting filter tree) are unchanged, we have to keep around the external cache for that painting case. When the work to cache unchanging input primitives is done, the old cache can be removed, and the new UniqueIDCache will be renamed to Cache. R=bsalomon@google.com, mtklein@google.com Author: senorblanco@chromium.org Review URL: https://codereview.chromium.org/414483003
234 lines
7.7 KiB
C++
234 lines
7.7 KiB
C++
/*
|
|
* Copyright 2011 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef SkReadBuffer_DEFINED
|
|
#define SkReadBuffer_DEFINED
|
|
|
|
#include "SkBitmapHeap.h"
|
|
#include "SkColorFilter.h"
|
|
#include "SkData.h"
|
|
#include "SkDrawLooper.h"
|
|
#include "SkImageFilter.h"
|
|
#include "SkMaskFilter.h"
|
|
#include "SkPath.h"
|
|
#include "SkPathEffect.h"
|
|
#include "SkPicture.h"
|
|
#include "SkRasterizer.h"
|
|
#include "SkReadBuffer.h"
|
|
#include "SkReader32.h"
|
|
#include "SkRefCnt.h"
|
|
#include "SkShader.h"
|
|
#include "SkWriteBuffer.h"
|
|
#include "SkXfermode.h"
|
|
|
|
class SkBitmap;
|
|
|
|
#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_MAC)
|
|
#define DEBUG_NON_DETERMINISTIC_ASSERT
|
|
#endif
|
|
|
|
class SkReadBuffer {
|
|
public:
|
|
SkReadBuffer();
|
|
SkReadBuffer(const void* data, size_t size);
|
|
SkReadBuffer(SkStream* stream);
|
|
virtual ~SkReadBuffer();
|
|
|
|
enum Version {
|
|
kFilterLevelIsEnum_Version = 23,
|
|
kGradientFlippedFlag_Version = 24,
|
|
kDashWritesPhaseIntervals_Version = 25,
|
|
kColorShaderNoBool_Version = 26,
|
|
kNoUnitMappers_Version = 27,
|
|
kNoMoreBitmapFlatten_Version = 28,
|
|
kSimplifyLocalMatrix_Version = 30,
|
|
kImageFilterUniqueID_Version = 31,
|
|
};
|
|
|
|
/**
|
|
* Returns true IFF the version is older than the specified version.
|
|
*/
|
|
bool isVersionLT(Version targetVersion) const {
|
|
SkASSERT(targetVersion > 0);
|
|
return fVersion > 0 && fVersion < targetVersion;
|
|
}
|
|
|
|
/** This may be called at most once; most clients of SkReadBuffer should not mess with it. */
|
|
void setVersion(int version) {
|
|
SkASSERT(0 == fVersion || version == fVersion);
|
|
fVersion = version;
|
|
}
|
|
|
|
enum Flags {
|
|
kCrossProcess_Flag = 1 << 0,
|
|
kScalarIsFloat_Flag = 1 << 1,
|
|
kPtrIs64Bit_Flag = 1 << 2,
|
|
kValidation_Flag = 1 << 3,
|
|
};
|
|
|
|
void setFlags(uint32_t flags) { fFlags = flags; }
|
|
uint32_t getFlags() const { return fFlags; }
|
|
|
|
bool isCrossProcess() const {
|
|
return this->isValidating() || SkToBool(fFlags & kCrossProcess_Flag);
|
|
}
|
|
bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
|
|
bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
|
|
bool isValidating() const { return SkToBool(fFlags & kValidation_Flag); }
|
|
|
|
SkReader32* getReader32() { return &fReader; }
|
|
|
|
size_t size() { return fReader.size(); }
|
|
size_t offset() { return fReader.offset(); }
|
|
bool eof() { return fReader.eof(); }
|
|
virtual const void* skip(size_t size) { return fReader.skip(size); }
|
|
void* readFunctionPtr() { return fReader.readPtr(); }
|
|
|
|
// primitives
|
|
virtual bool readBool();
|
|
virtual SkColor readColor();
|
|
virtual SkFixed readFixed();
|
|
virtual int32_t readInt();
|
|
virtual SkScalar readScalar();
|
|
virtual uint32_t readUInt();
|
|
virtual int32_t read32();
|
|
|
|
// strings -- the caller is responsible for freeing the string contents
|
|
virtual void readString(SkString* string);
|
|
virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding);
|
|
|
|
// common data structures
|
|
virtual void readPoint(SkPoint* point);
|
|
SkPoint readPoint() { SkPoint p; this->readPoint(&p); return p; }
|
|
virtual void readMatrix(SkMatrix* matrix);
|
|
virtual void readIRect(SkIRect* rect);
|
|
virtual void readRect(SkRect* rect);
|
|
virtual void readRegion(SkRegion* region);
|
|
virtual void readPath(SkPath* path);
|
|
void readPaint(SkPaint* paint) { paint->unflatten(*this); }
|
|
|
|
virtual SkFlattenable* readFlattenable(SkFlattenable::Type);
|
|
template <typename T> T* readFlattenable() {
|
|
return (T*) this->readFlattenable(T::GetFlattenableType());
|
|
}
|
|
SkColorFilter* readColorFilter() { return this->readFlattenable<SkColorFilter>(); }
|
|
SkDrawLooper* readDrawLooper() { return this->readFlattenable<SkDrawLooper>(); }
|
|
SkImageFilter* readImageFilter() { return this->readFlattenable<SkImageFilter>(); }
|
|
SkMaskFilter* readMaskFilter() { return this->readFlattenable<SkMaskFilter>(); }
|
|
SkPathEffect* readPathEffect() { return this->readFlattenable<SkPathEffect>(); }
|
|
SkRasterizer* readRasterizer() { return this->readFlattenable<SkRasterizer>(); }
|
|
SkShader* readShader() { return this->readFlattenable<SkShader>(); }
|
|
SkXfermode* readXfermode() { return this->readFlattenable<SkXfermode>(); }
|
|
|
|
/**
|
|
* Like readFlattenable() but explicitly just skips the data that was written for the
|
|
* flattenable (or the sentinel that there wasn't one).
|
|
*/
|
|
virtual void skipFlattenable();
|
|
|
|
// binary data and arrays
|
|
virtual bool readByteArray(void* value, size_t size);
|
|
virtual bool readColorArray(SkColor* colors, size_t size);
|
|
virtual bool readIntArray(int32_t* values, size_t size);
|
|
virtual bool readPointArray(SkPoint* points, size_t size);
|
|
virtual bool readScalarArray(SkScalar* values, size_t size);
|
|
|
|
SkData* readByteArrayAsData() {
|
|
size_t len = this->getArrayCount();
|
|
if (!this->validateAvailable(len)) {
|
|
return SkData::NewEmpty();
|
|
}
|
|
void* buffer = sk_malloc_throw(len);
|
|
this->readByteArray(buffer, len);
|
|
return SkData::NewFromMalloc(buffer, len);
|
|
}
|
|
|
|
// helpers to get info about arrays and binary data
|
|
virtual uint32_t getArrayCount();
|
|
|
|
/**
|
|
* Returns false if the bitmap could not be completely read. In that case, it will be set
|
|
* to have width/height, but no pixels.
|
|
*/
|
|
bool readBitmap(SkBitmap* bitmap);
|
|
|
|
virtual SkTypeface* readTypeface();
|
|
|
|
void setBitmapStorage(SkBitmapHeapReader* bitmapStorage) {
|
|
SkRefCnt_SafeAssign(fBitmapStorage, bitmapStorage);
|
|
}
|
|
|
|
void setTypefaceArray(SkTypeface* array[], int count) {
|
|
fTFArray = array;
|
|
fTFCount = count;
|
|
}
|
|
|
|
/**
|
|
* Call this with a pre-loaded array of Factories, in the same order as
|
|
* were created/written by the writer. SkPicture uses this.
|
|
*/
|
|
void setFactoryPlayback(SkFlattenable::Factory array[], int count) {
|
|
fFactoryTDArray = NULL;
|
|
fFactoryArray = array;
|
|
fFactoryCount = count;
|
|
}
|
|
|
|
/**
|
|
* Call this with an initially empty array, so the reader can cache each
|
|
* factory it sees by name. Used by the pipe code in conjunction with
|
|
* SkWriteBuffer::setNamedFactoryRecorder.
|
|
*/
|
|
void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
|
|
fFactoryTDArray = array;
|
|
fFactoryArray = NULL;
|
|
fFactoryCount = 0;
|
|
}
|
|
|
|
/**
|
|
* Provide a function to decode an SkBitmap from encoded data. Only used if the writer
|
|
* encoded the SkBitmap. If the proper decoder cannot be used, a red bitmap with the
|
|
* appropriate size will be used.
|
|
*/
|
|
void setBitmapDecoder(SkPicture::InstallPixelRefProc bitmapDecoder) {
|
|
fBitmapDecoder = bitmapDecoder;
|
|
}
|
|
|
|
// Default impelementations don't check anything.
|
|
virtual bool validate(bool isValid) { return true; }
|
|
virtual bool isValid() const { return true; }
|
|
virtual bool validateAvailable(size_t size) { return true; }
|
|
|
|
protected:
|
|
SkReader32 fReader;
|
|
|
|
private:
|
|
bool readArray(void* value, size_t size, size_t elementSize);
|
|
|
|
uint32_t fFlags;
|
|
int fVersion;
|
|
|
|
void* fMemoryPtr;
|
|
|
|
SkBitmapHeapReader* fBitmapStorage;
|
|
SkTypeface** fTFArray;
|
|
int fTFCount;
|
|
|
|
SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
|
|
SkFlattenable::Factory* fFactoryArray;
|
|
int fFactoryCount;
|
|
|
|
SkPicture::InstallPixelRefProc fBitmapDecoder;
|
|
|
|
#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
|
|
// Debugging counter to keep track of how many bitmaps we
|
|
// have decoded.
|
|
int fDecodedBitmapIndex;
|
|
#endif // DEBUG_NON_DETERMINISTIC_ASSERT
|
|
};
|
|
|
|
#endif // SkReadBuffer_DEFINED
|