revert 6798 (assert in GM)

git-svn-id: http://skia.googlecode.com/svn/trunk@6802 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-12-13 21:53:41 +00:00
parent 2a3f08b0a7
commit 135e16cd8e
13 changed files with 115 additions and 136 deletions

View File

@ -34,10 +34,11 @@ public:
SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode = NULL); SkComposeShader(SkShader* sA, SkShader* sB, SkXfermode* mode = NULL);
virtual ~SkComposeShader(); virtual ~SkComposeShader();
virtual bool setContext(const SkBitmap&, const SkPaint&, // override
const SkMatrix&) SK_OVERRIDE; virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix);
virtual void endContext() SK_OVERRIDE; virtual void shadeSpan(int x, int y, SkPMColor result[], int count);
virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; virtual void beginSession();
virtual void endSession();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeShader)

View File

@ -139,28 +139,11 @@ public:
/** /**
* Called once before drawing, with the current paint and device matrix. * Called once before drawing, with the current paint and device matrix.
* Return true if your shader supports these parameters, or false if not. * Return true if your shader supports these parameters, or false if not.
* If false is returned, nothing will be drawn. If true is returned, then * If false is returned, nothing will be drawn.
* a balancing call to endContext() will be made before the next call to
* setContext.
*
* Subclasses should be sure to call their INHERITED::setContext() if they
* override this method.
*/ */
virtual bool setContext(const SkBitmap& device, const SkPaint& paint, virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
const SkMatrix& matrix); const SkMatrix& matrix);
/**
* Assuming setContext returned true, endContext() will be called when
* the draw using the shader has completed. It is an error for setContext
* to be called twice w/o an intervening call to endContext().
*
* Subclasses should be sure to call their INHERITED::endContext() if they
* override this method.
*/
virtual void endContext();
SkDEBUGCODE(bool setContextHasBeenCalled() const { return fInSetContext; })
/** /**
* Called for each span of the object being drawn. Your subclass should * Called for each span of the object being drawn. Your subclass should
* set the appropriate colors (with premultiplied alpha) that correspond * set the appropriate colors (with premultiplied alpha) that correspond
@ -199,6 +182,14 @@ public:
return (flags & kHasSpan16_Flag) != 0; return (flags & kHasSpan16_Flag) != 0;
} }
/**
* Called before a session using the shader begins. Some shaders override
* this to defer some of their work (like calling bitmap.lockPixels()).
* Must be balanced by a call to endSession.
*/
virtual void beginSession();
virtual void endSession();
/** /**
Gives method bitmap should be read to implement a shader. Gives method bitmap should be read to implement a shader.
Also determines number and interpretation of "extra" parameters returned Also determines number and interpretation of "extra" parameters returned
@ -364,7 +355,7 @@ private:
uint8_t fPaintAlpha; uint8_t fPaintAlpha;
uint8_t fDeviceConfig; uint8_t fDeviceConfig;
uint8_t fTotalInverseClass; uint8_t fTotalInverseClass;
SkDEBUGCODE(SkBool8 fInSetContext;) SkDEBUGCODE(SkBool8 fInSession;)
static SkShader* CreateBitmapShader(const SkBitmap& src, static SkShader* CreateBitmapShader(const SkBitmap& src,
TileMode, TileMode, TileMode, TileMode,

View File

@ -41,6 +41,18 @@ SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
fFlags = 0; // computed in setContext fFlags = 0; // computed in setContext
} }
void SkBitmapProcShader::beginSession() {
this->INHERITED::beginSession();
fRawBitmap.lockPixels();
}
void SkBitmapProcShader::endSession() {
fRawBitmap.unlockPixels();
this->INHERITED::endSession();
}
SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture, SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
SkMatrix* texM, SkMatrix* texM,
TileMode xy[]) const { TileMode xy[]) const {
@ -90,7 +102,6 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
} }
if (!fState.chooseProcs(this->getTotalInverse(), paint)) { if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
fState.fOrigBitmap.unlockPixels();
return false; return false;
} }
@ -138,11 +149,6 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
return true; return true;
} }
void SkBitmapProcShader::endContext() {
fState.fOrigBitmap.unlockPixels();
this->INHERITED::endContext();
}
#define BUF_MAX 128 #define BUF_MAX 128
#define TEST_BUFFER_OVERRITEx #define TEST_BUFFER_OVERRITEx

View File

@ -20,11 +20,12 @@ public:
// overrides from SkShader // overrides from SkShader
virtual bool isOpaque() const SK_OVERRIDE; virtual bool isOpaque() const SK_OVERRIDE;
virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&); virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
virtual void endContext();
virtual uint32_t getFlags() { return fFlags; } virtual uint32_t getFlags() { return fFlags; }
virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count); virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE; virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE;
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count); virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
virtual void beginSession();
virtual void endSession();
virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const; virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const;
static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty); static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty);

View File

@ -572,30 +572,16 @@ public:
void setMask(const SkMask* mask) { fMask = mask; } void setMask(const SkMask* mask) { fMask = mask; }
virtual bool setContext(const SkBitmap& device, const SkPaint& paint, virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
const SkMatrix& matrix) SK_OVERRIDE { const SkMatrix& matrix) {
if (!this->INHERITED::setContext(device, paint, matrix)) {
return false;
}
if (fProxy) { if (fProxy) {
if (!fProxy->setContext(device, paint, matrix)) { return fProxy->setContext(device, paint, matrix);
// must keep our set/end context calls balanced
this->INHERITED::endContext();
return false;
}
} else { } else {
fPMColor = SkPreMultiplyColor(paint.getColor()); fPMColor = SkPreMultiplyColor(paint.getColor());
return this->INHERITED::setContext(device, paint, matrix);
} }
return true;
}
virtual void endContext() SK_OVERRIDE {
if (fProxy) {
fProxy->endContext();
}
this->INHERITED::endContext();
} }
virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { virtual void shadeSpan(int x, int y, SkPMColor span[], int count) {
if (fProxy) { if (fProxy) {
fProxy->shadeSpan(x, y, span, count); fProxy->shadeSpan(x, y, span, count);
} }
@ -659,6 +645,20 @@ public:
} }
} }
virtual void beginSession() {
this->INHERITED::beginSession();
if (fProxy) {
fProxy->beginSession();
}
}
virtual void endSession() {
if (fProxy) {
fProxy->endSession();
}
this->INHERITED::endSession();
}
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
protected: protected:
@ -907,17 +907,8 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
// if there is one, the shader will take care of it. // if there is one, the shader will take care of it.
} }
/*
* We need to have balanced calls to the shader:
* setContext
* endContext
* We make the first call here, in case it fails we can abort the draw.
* The endContext() call is made by the blitter (assuming setContext did
* not fail) in its destructor.
*/
if (shader && !shader->setContext(device, *paint, matrix)) { if (shader && !shader->setContext(device, *paint, matrix)) {
SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); return SkNEW(SkNullBlitter);
return blitter;
} }
switch (device.getConfig()) { switch (device.getConfig()) {
@ -987,15 +978,14 @@ SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
: INHERITED(device) { : INHERITED(device) {
fShader = paint.getShader(); fShader = paint.getShader();
SkASSERT(fShader); SkASSERT(fShader);
SkASSERT(fShader->setContextHasBeenCalled());
fShader->ref(); fShader->ref();
fShader->beginSession();
fShaderFlags = fShader->getFlags(); fShaderFlags = fShader->getFlags();
} }
SkShaderBlitter::~SkShaderBlitter() { SkShaderBlitter::~SkShaderBlitter() {
SkASSERT(fShader->setContextHasBeenCalled()); fShader->endSession();
fShader->endContext();
fShader->unref(); fShader->unref();
} }

View File

@ -62,6 +62,16 @@ SkFilterShader::~SkFilterShader() {
fShader->unref(); fShader->unref();
} }
void SkFilterShader::beginSession() {
this->INHERITED::beginSession();
fShader->beginSession();
}
void SkFilterShader::endSession() {
fShader->endSession();
this->INHERITED::endSession();
}
void SkFilterShader::flatten(SkFlattenableWriteBuffer& buffer) const { void SkFilterShader::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer); this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fShader); buffer.writeFlattenable(fShader);
@ -86,22 +96,8 @@ uint32_t SkFilterShader::getFlags() {
bool SkFilterShader::setContext(const SkBitmap& device, bool SkFilterShader::setContext(const SkBitmap& device,
const SkPaint& paint, const SkPaint& paint,
const SkMatrix& matrix) { const SkMatrix& matrix) {
// we need to keep the setContext/endContext calls balanced. If we return return this->INHERITED::setContext(device, paint, matrix) &&
// false, our endContext() will not be called. fShader->setContext(device, paint, matrix);
if (!this->INHERITED::setContext(device, paint, matrix)) {
return false;
}
if (!fShader->setContext(device, paint, matrix)) {
this->INHERITED::endContext();
return false;
}
return true;
}
void SkFilterShader::endContext() {
fShader->endContext();
this->INHERITED::endContext();
} }
void SkFilterShader::shadeSpan(int x, int y, SkPMColor result[], int count) { void SkFilterShader::shadeSpan(int x, int y, SkPMColor result[], int count) {

View File

@ -43,6 +43,18 @@ SkComposeShader::~SkComposeShader() {
fShaderA->unref(); fShaderA->unref();
} }
void SkComposeShader::beginSession() {
this->INHERITED::beginSession();
fShaderA->beginSession();
fShaderB->beginSession();
}
void SkComposeShader::endSession() {
fShaderA->endSession();
fShaderB->endSession();
this->INHERITED::endSession();
}
class SkAutoAlphaRestore { class SkAutoAlphaRestore {
public: public:
SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) {
@ -69,10 +81,7 @@ void SkComposeShader::flatten(SkFlattenableWriteBuffer& buffer) const {
/* We call setContext on our two worker shaders. However, we /* We call setContext on our two worker shaders. However, we
always let them see opaque alpha, and if the paint really always let them see opaque alpha, and if the paint really
is translucent, then we apply that after the fact. is translucent, then we apply that after the fact.
*/
We need to keep the calls to setContext/endContext balanced, since if we
return false, our endContext() will not be called.
*/
bool SkComposeShader::setContext(const SkBitmap& device, bool SkComposeShader::setContext(const SkBitmap& device,
const SkPaint& paint, const SkPaint& paint,
const SkMatrix& matrix) { const SkMatrix& matrix) {
@ -89,25 +98,8 @@ bool SkComposeShader::setContext(const SkBitmap& device,
SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF);
bool setContextA = fShaderA->setContext(device, paint, tmpM); return fShaderA->setContext(device, paint, tmpM) &&
bool setContextB = fShaderB->setContext(device, paint, tmpM); fShaderB->setContext(device, paint, tmpM);
if (!setContextA || !setContextB) {
if (setContextB) {
fShaderB->endContext();
}
else if (setContextA) {
fShaderA->endContext();
}
this->INHERITED::endContext();
return false;
}
return true;
}
void SkComposeShader::endContext() {
fShaderB->endContext();
fShaderA->endContext();
this->INHERITED::endContext();
} }
// larger is better (fewer times we have to loop), but we shouldn't // larger is better (fewer times we have to loop), but we shouldn't

View File

@ -1228,6 +1228,13 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
} }
} }
// only lock the pixels if we passed the clip and bounder tests
SkAutoLockPixels alp(bitmap);
// after the lock, check if we are valid
if (!bitmap.readyToDraw()) {
return;
}
if (bitmap.getConfig() != SkBitmap::kA8_Config && if (bitmap.getConfig() != SkBitmap::kA8_Config &&
just_translate(matrix, bitmap)) { just_translate(matrix, bitmap)) {
int ix = SkScalarRound(matrix.getTranslateX()); int ix = SkScalarRound(matrix.getTranslateX());
@ -2272,7 +2279,7 @@ public:
bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
@ -2399,7 +2406,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
if (NULL != colors) { if (NULL != colors) {
if (NULL == textures) { if (NULL == textures) {
// just colors (no texture) // just colors (no texture)
shader = p.setShader(&triShader); p.setShader(&triShader);
} else { } else {
// colors * texture // colors * texture
SkASSERT(shader); SkASSERT(shader);
@ -2414,7 +2421,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
if (releaseMode) { if (releaseMode) {
xmode->unref(); xmode->unref();
} }
shader = compose;
} }
} }
@ -2430,17 +2436,10 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
savedLocalM = shader->getLocalMatrix(); savedLocalM = shader->getLocalMatrix();
} }
// do we need this? triShader should have been installed in p, either
// directly or indirectly (using compose shader), so its setContext
// should have already been called.
if (NULL != colors) { if (NULL != colors) {
SkASSERT(triShader.setContextHasBeenCalled());
#if 0
if (!triShader.setContext(*fBitmap, p, *fMatrix)) { if (!triShader.setContext(*fBitmap, p, *fMatrix)) {
colors = NULL; colors = NULL;
} }
#endif
} }
while (vertProc(&state)) { while (vertProc(&state)) {
@ -2449,7 +2448,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
tempM.postConcat(savedLocalM); tempM.postConcat(savedLocalM);
shader->setLocalMatrix(tempM); shader->setLocalMatrix(tempM);
// need to recal setContext since we changed the local matrix // need to recal setContext since we changed the local matrix
shader->endContext();
if (!shader->setContext(*fBitmap, p, *fMatrix)) { if (!shader->setContext(*fBitmap, p, *fMatrix)) {
continue; continue;
} }

View File

@ -17,12 +17,14 @@ public:
SkFilterShader(SkShader* shader, SkColorFilter* filter); SkFilterShader(SkShader* shader, SkColorFilter* filter);
virtual ~SkFilterShader(); virtual ~SkFilterShader();
virtual uint32_t getFlags() SK_OVERRIDE; // override
virtual bool setContext(const SkBitmap&, const SkPaint&, virtual uint32_t getFlags();
const SkMatrix&) SK_OVERRIDE; virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
virtual void endContext() SK_OVERRIDE; const SkMatrix& matrix);
virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE; virtual void shadeSpan(int x, int y, SkPMColor result[], int count);
virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE; virtual void shadeSpan16(int x, int y, uint16_t result[], int count);
virtual void beginSession();
virtual void endSession();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkFilterShader) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkFilterShader)

View File

@ -17,7 +17,7 @@ SK_DEFINE_INST_COUNT(SkShader)
SkShader::SkShader() { SkShader::SkShader() {
fLocalMatrix.reset(); fLocalMatrix.reset();
SkDEBUGCODE(fInSetContext = false;) SkDEBUGCODE(fInSession = false;)
} }
SkShader::SkShader(SkFlattenableReadBuffer& buffer) SkShader::SkShader(SkFlattenableReadBuffer& buffer)
@ -28,11 +28,21 @@ SkShader::SkShader(SkFlattenableReadBuffer& buffer)
fLocalMatrix.reset(); fLocalMatrix.reset();
} }
SkDEBUGCODE(fInSetContext = false;) SkDEBUGCODE(fInSession = false;)
} }
SkShader::~SkShader() { SkShader::~SkShader() {
SkASSERT(!fInSetContext); SkASSERT(!fInSession);
}
void SkShader::beginSession() {
SkASSERT(!fInSession);
SkDEBUGCODE(fInSession = true;)
}
void SkShader::endSession() {
SkASSERT(fInSession);
SkDEBUGCODE(fInSession = false;)
} }
void SkShader::flatten(SkFlattenableWriteBuffer& buffer) const { void SkShader::flatten(SkFlattenableWriteBuffer& buffer) const {
@ -47,8 +57,6 @@ void SkShader::flatten(SkFlattenableWriteBuffer& buffer) const {
bool SkShader::setContext(const SkBitmap& device, bool SkShader::setContext(const SkBitmap& device,
const SkPaint& paint, const SkPaint& paint,
const SkMatrix& matrix) { const SkMatrix& matrix) {
SkASSERT(!this->setContextHasBeenCalled());
const SkMatrix* m = &matrix; const SkMatrix* m = &matrix;
SkMatrix total; SkMatrix total;
@ -60,17 +68,11 @@ bool SkShader::setContext(const SkBitmap& device,
} }
if (m->invert(&fTotalInverse)) { if (m->invert(&fTotalInverse)) {
fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
SkDEBUGCODE(fInSetContext = true;)
return true; return true;
} }
return false; return false;
} }
void SkShader::endContext() {
SkASSERT(fInSetContext);
SkDEBUGCODE(fInSetContext = false;)
}
SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) { SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) {
return NULL; return NULL;
} }

View File

@ -213,8 +213,6 @@ bool SkGradientShaderBase::setContext(const SkBitmap& device,
const SkMatrix& inverse = this->getTotalInverse(); const SkMatrix& inverse = this->getTotalInverse();
if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) { if (!fDstToIndex.setConcat(fPtsToUnit, inverse)) {
// need to keep our set/end context calls balanced.
this->INHERITED::endContext();
return false; return false;
} }

View File

@ -91,6 +91,7 @@ public:
int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper); int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper);
virtual ~SkGradientShaderBase(); virtual ~SkGradientShaderBase();
// overrides
virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE; virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; } virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
virtual bool isOpaque() const SK_OVERRIDE; virtual bool isOpaque() const SK_OVERRIDE;

View File

@ -292,15 +292,16 @@ void SkTwoPointRadialGradient::shadeSpan(int x, int y, SkPMColor* dstCParam,
} }
} }
bool SkTwoPointRadialGradient::setContext( const SkBitmap& device, bool SkTwoPointRadialGradient::setContext(
const SkPaint& paint, const SkBitmap& device,
const SkMatrix& matrix){ const SkPaint& paint,
// For now, we might have divided by zero, so detect that const SkMatrix& matrix){
if (0 == fDiffRadius) { if (!this->INHERITED::setContext(device, paint, matrix)) {
return false; return false;
} }
if (!this->INHERITED::setContext(device, paint, matrix)) { // For now, we might have divided by zero, so detect that
if (0 == fDiffRadius) {
return false; return false;
} }