Index: src/core/SkPictureShader.cpp |
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp |
index 15df3a37a587f253f0634558517a09e141bce63a..98669ac4f39734ea6fdc3bd584eaf2633e7ac437 100644 |
--- a/src/core/SkPictureShader.cpp |
+++ b/src/core/SkPictureShader.cpp |
@@ -55,9 +55,9 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const { |
} |
} |
-bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { |
+SkShader* SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { |
if (!fPicture || (0 == fPicture->width() && 0 == fPicture->height())) { |
- return false; |
+ return NULL; |
} |
SkMatrix m; |
@@ -78,17 +78,20 @@ bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { |
SkISize tileSize = scaledSize.toRound(); |
if (tileSize.isEmpty()) { |
- return false; |
+ return NULL; |
} |
// The actual scale, compensating for rounding. |
SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fPicture->width(), |
SkIntToScalar(tileSize.height()) / fPicture->height()); |
- if (!fCachedShader || tileScale != fCachedTileScale) { |
+ SK_DECLARE_STATIC_MUTEX(cachedShaderMutex); |
scroggo
2014/04/11 15:51:45
Why is this static?
Dominik Grewe
2014/04/11 17:08:22
Good point. It should be a regular class member.
|
+ SkAutoMutexAcquire ama(cachedShaderMutex); |
scroggo
2014/04/11 15:51:45
It seems like we're doing an awful lot inside this
Dominik Grewe
2014/04/11 17:08:22
We always have to lock though before we access the
|
+ |
+ if (!fCachedBitmapShader || tileScale != fCachedTileScale) { |
scroggo
2014/04/11 15:51:45
Sort of tied into my last comment, if the cached s
Dominik Grewe
2014/04/11 17:08:22
I didn't even realize the setLocalMatrix below...
scroggo
2014/04/11 17:51:36
Yes. It may make more sense to make that change al
|
SkBitmap bm; |
if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) { |
- return false; |
+ return NULL; |
} |
bm.eraseColor(SK_ColorTRANSPARENT); |
@@ -96,66 +99,100 @@ bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const { |
canvas.scale(tileScale.width(), tileScale.height()); |
canvas.drawPicture(*fPicture); |
- fCachedShader.reset(CreateBitmapShader(bm, fTmx, fTmy)); |
+ fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy)); |
fCachedTileScale = tileScale; |
} |
SkMatrix shaderMatrix = this->getLocalMatrix(); |
shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height()); |
- fCachedShader->setLocalMatrix(shaderMatrix); |
+ fCachedBitmapShader->setLocalMatrix(shaderMatrix); |
- return true; |
+ fCachedBitmapShader.get()->ref(); |
scroggo
2014/04/11 15:51:45
Typically the caller refs the object that gets ret
Dominik Grewe
2014/04/11 17:08:22
Yes, we have to do it inside the mutex cause other
|
+ return fCachedBitmapShader; |
} |
-bool SkPictureShader::setContext(const SkBitmap& device, |
- const SkPaint& paint, |
- const SkMatrix& matrix) { |
- if (!this->buildBitmapShader(matrix)) { |
- return false; |
+SkShader* SkPictureShader::validInternal(const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, SkMatrix* totalInverse) const { |
+ if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { |
+ return NULL; |
+ } |
+ |
+ SkShader* bitmapShader = this->buildBitmapShader(matrix); |
+ if (!bitmapShader) { |
+ return NULL; |
} |
- if (!this->INHERITED::setContext(device, paint, matrix)) { |
- return false; |
+ if (!bitmapShader->validContext(device, paint, matrix)) { |
+ bitmapShader->unref(); |
+ return NULL; |
} |
- SkASSERT(fCachedShader); |
- if (!fCachedShader->setContext(device, paint, matrix)) { |
- this->INHERITED::endContext(); |
- return false; |
+ return bitmapShader; |
+} |
+ |
+bool SkPictureShader::validContext(const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, SkMatrix* totalInverse) const { |
+ SkAutoTUnref<SkShader> shader(this->validInternal(device, paint, matrix, totalInverse)); |
+ return shader != NULL; |
+} |
+ |
+SkShader::Context* SkPictureShader::createContext(const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, void* storage) const { |
+ SkShader* bitmapShader = this->validInternal(device, paint, matrix, NULL); |
+ if (!bitmapShader) { |
+ return NULL; |
} |
- return true; |
+ return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext, |
+ (*this, device, paint, matrix, bitmapShader)); |
+} |
+ |
+size_t SkPictureShader::contextSize() const { |
+ return sizeof(PictureShaderContext); |
} |
-void SkPictureShader::endContext() { |
- SkASSERT(fCachedShader); |
- fCachedShader->endContext(); |
+SkPictureShader::PictureShaderContext::PictureShaderContext( |
+ const SkPictureShader& shader, const SkBitmap& device, |
+ const SkPaint& paint, const SkMatrix& matrix, SkShader* bitmapShader) |
+ : INHERITED(shader, device, paint, matrix) |
+ , fBitmapShader(bitmapShader) |
+{ |
+ // TODO(dominikg): Can we avoid heap alloc here and instead put it in the same |
+ // storage as this? The problem is that SkPicutreShader::contextSize() |
+ // doesn't know the size of the bitmap shader's context. |
Dominik Grewe
2014/04/11 12:39:52
Any ideas?
scroggo
2014/04/11 15:51:45
No. I guess we don't know because we don't what ty
Dominik Grewe
2014/04/11 17:08:22
Yeah, we could hard-code a maximum size, but that'
|
+ fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize()); |
+ fBitmapShaderContext = fBitmapShader->createContext( |
+ device, paint, matrix, fBitmapShaderContextStorage); |
+ SkASSERT(fBitmapShaderContext); |
+} |
- this->INHERITED::endContext(); |
+SkPictureShader::PictureShaderContext::~PictureShaderContext() { |
+ fBitmapShaderContext->SkShader::Context::~Context(); |
+ sk_free(fBitmapShaderContextStorage); |
} |
-uint32_t SkPictureShader::getFlags() { |
- if (NULL != fCachedShader) { |
- return fCachedShader->getFlags(); |
+uint32_t SkPictureShader::PictureShaderContext::getFlags() { |
+ if (fBitmapShaderContext) { |
scroggo
2014/04/11 15:51:45
I don't think this can ever be NULL, since it's cr
Dominik Grewe
2014/04/11 17:08:22
Done.
|
+ return fBitmapShaderContext->getFlags(); |
} |
return 0; |
} |
-SkShader::ShadeProc SkPictureShader::asAShadeProc(void** ctx) { |
- if (fCachedShader) { |
- return fCachedShader->asAShadeProc(ctx); |
+SkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc(void** ctx) { |
+ if (fBitmapShaderContext) { |
scroggo
2014/04/11 15:51:45
This should never be NULL.
Dominik Grewe
2014/04/11 17:08:22
Done.
|
+ return fBitmapShaderContext->asAShadeProc(ctx); |
} |
return NULL; |
} |
-void SkPictureShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { |
- SkASSERT(fCachedShader); |
- fCachedShader->shadeSpan(x, y, dstC, count); |
+void SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { |
+ SkASSERT(fBitmapShaderContext); |
+ fBitmapShaderContext->shadeSpan(x, y, dstC, count); |
} |
-void SkPictureShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) { |
- SkASSERT(fCachedShader); |
- fCachedShader->shadeSpan16(x, y, dstC, count); |
+void SkPictureShader::PictureShaderContext::shadeSpan16(int x, int y, uint16_t dstC[], int count) { |
+ SkASSERT(fBitmapShaderContext); |
+ fBitmapShaderContext->shadeSpan16(x, y, dstC, count); |
} |
#ifndef SK_IGNORE_TO_STRING |
@@ -176,10 +213,10 @@ void SkPictureShader::toString(SkString* str) const { |
#if SK_SUPPORT_GPU |
GrEffectRef* SkPictureShader::asNewEffect(GrContext* context, const SkPaint& paint) const { |
- if (!this->buildBitmapShader(context->getMatrix())) { |
+ SkAutoTUnref<SkShader> bitmapShader(this->buildBitmapShader(context->getMatrix())); |
+ if (!bitmapShader) { |
return NULL; |
} |
- SkASSERT(fCachedShader); |
- return fCachedShader->asNewEffect(context, paint); |
+ return bitmapShader->asNewEffect(context, paint); |
} |
#endif |