Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Unified Diff: src/core/SkPictureShader.cpp

Issue 207683004: Extract most of the mutable state of SkShader into a separate Context object. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fCachedLocalMatrix Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/core/SkPictureShader.cpp
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index 15df3a37a587f253f0634558517a09e141bce63a..f7c3443f659ebda31558b215d963118339ab9894 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) {
+ SkAutoMutexAcquire ama(fCachedBitmapShaderMutex);
+
+ if (!fCachedBitmapShader || tileScale != fCachedTileScale ||
+ this->getLocalMatrix() != fCachedLocalMatrix) {
SkBitmap bm;
if (!bm.allocN32Pixels(tileSize.width(), tileSize.height())) {
- return false;
+ return NULL;
}
bm.eraseColor(SK_ColorTRANSPARENT);
@@ -96,66 +99,95 @@ 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;
- }
+ fCachedLocalMatrix = this->getLocalMatrix();
- SkMatrix shaderMatrix = this->getLocalMatrix();
- shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
- fCachedShader->setLocalMatrix(shaderMatrix);
+ SkMatrix shaderMatrix = this->getLocalMatrix();
+ shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
+ fCachedBitmapShader->setLocalMatrix(shaderMatrix);
+ }
- return true;
+ // Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
+ // Otherwise, the object pointed to may have already been overwritten on a different thread.
+ fCachedBitmapShader.get()->ref();
+ 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;
}
- if (!this->INHERITED::setContext(device, paint, matrix)) {
- return false;
+ SkShader* bitmapShader = this->buildBitmapShader(matrix);
+ if (!bitmapShader) {
+ return NULL;
}
- SkASSERT(fCachedShader);
- if (!fCachedShader->setContext(device, paint, matrix)) {
- this->INHERITED::endContext();
- return false;
+ if (!bitmapShader->validContext(device, paint, matrix)) {
+ bitmapShader->unref();
+ return NULL;
}
- return true;
+ return bitmapShader;
}
-void SkPictureShader::endContext() {
- SkASSERT(fCachedShader);
- fCachedShader->endContext();
-
- this->INHERITED::endContext();
+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;
}
-uint32_t SkPictureShader::getFlags() {
- if (NULL != fCachedShader) {
- return fCachedShader->getFlags();
+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 0;
+
+ return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext,
+ (*this, device, paint, matrix, bitmapShader));
}
-SkShader::ShadeProc SkPictureShader::asAShadeProc(void** ctx) {
- if (fCachedShader) {
- return fCachedShader->asAShadeProc(ctx);
- }
- return NULL;
+size_t SkPictureShader::contextSize() const {
+ return sizeof(PictureShaderContext);
+}
+
+SkPictureShader::PictureShaderContext::PictureShaderContext(
+ const SkPictureShader& shader, const SkBitmap& device,
+ const SkPaint& paint, const SkMatrix& matrix, SkShader* bitmapShader)
+ : INHERITED(shader, device, paint, matrix)
+ , fBitmapShader(bitmapShader)
+{
+ SkASSERT(fBitmapShader);
+ fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize());
+ fBitmapShaderContext = fBitmapShader->createContext(
+ device, paint, matrix, fBitmapShaderContextStorage);
+ SkASSERT(fBitmapShaderContext);
+}
+
+SkPictureShader::PictureShaderContext::~PictureShaderContext() {
+ fBitmapShaderContext->SkShader::Context::~Context();
+ sk_free(fBitmapShaderContextStorage);
+}
+
+uint32_t SkPictureShader::PictureShaderContext::getFlags() const {
+ return fBitmapShaderContext->getFlags();
+}
+
+SkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc(void** ctx) {
+ return fBitmapShaderContext->asAShadeProc(ctx);
}
-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 +208,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

Powered by Google App Engine
This is Rietveld 408576698