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

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: rebase 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
« no previous file with comments | « src/core/SkPictureShader.h ('k') | src/core/SkShader.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkPictureShader.cpp
diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp
index bf312851ab3bb33b81d4a0b116d1549f96eea352..dc5c90b62e8ec7eb14fc31413f2f3d78ec1afabe 100644
--- a/src/core/SkPictureShader.cpp
+++ b/src/core/SkPictureShader.cpp
@@ -49,7 +49,7 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const {
fPicture->flatten(buffer);
}
-bool SkPictureShader::buildBitmapShader(const SkMatrix& matrix) const {
+SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix) const {
SkASSERT(fPicture && fPicture->width() > 0 && fPicture->height() > 0);
SkMatrix m;
@@ -70,17 +70,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);
@@ -88,66 +91,91 @@ 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 pointer may have been overwritten on a different thread before the object's
+ // ref count was incremented.
+ 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;
+ SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(matrix));
+ if (!bitmapShader || !bitmapShader->validContext(device, paint, matrix)) {
+ return NULL;
}
- SkASSERT(fCachedShader);
- if (!fCachedShader->setContext(device, paint, matrix)) {
- this->INHERITED::endContext();
- return false;
+ return bitmapShader.detach();
+}
+
+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 {
+ SkAutoTUnref<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.detach()));
+}
+
+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)
+{
+ SkASSERT(fBitmapShader);
+ fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize());
+ fBitmapShaderContext = fBitmapShader->createContext(
+ device, paint, matrix, fBitmapShaderContextStorage);
+ SkASSERT(fBitmapShaderContext);
+}
- this->INHERITED::endContext();
+SkPictureShader::PictureShaderContext::~PictureShaderContext() {
+ fBitmapShaderContext->~Context();
+ sk_free(fBitmapShaderContextStorage);
}
-uint32_t SkPictureShader::getFlags() {
- if (NULL != fCachedShader) {
- return fCachedShader->getFlags();
- }
- return 0;
+uint32_t SkPictureShader::PictureShaderContext::getFlags() const {
+ return fBitmapShaderContext->getFlags();
}
-SkShader::ShadeProc SkPictureShader::asAShadeProc(void** ctx) {
- if (fCachedShader) {
- return fCachedShader->asAShadeProc(ctx);
- }
- return NULL;
+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
@@ -168,10 +196,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->refBitmapShader(context->getMatrix()));
+ if (!bitmapShader) {
return NULL;
}
- SkASSERT(fCachedShader);
- return fCachedShader->asNewEffect(context, paint);
+ return bitmapShader->asNewEffect(context, paint);
}
#endif
« no previous file with comments | « src/core/SkPictureShader.h ('k') | src/core/SkShader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698