diff options
author | Android Chromium Automerger <chromium-automerger@android> | 2014-05-05 23:55:00 +0000 |
---|---|---|
committer | Android Chromium Automerger <chromium-automerger@android> | 2014-05-05 23:55:00 +0000 |
commit | b4711302d408d8eaa5549aeaf35dc809395c6372 (patch) | |
tree | 13109220ebe203b1026d1f499a7eea0df826f830 | |
parent | 1abe0e981de19b02c442866e0ff80cb3d0bcc1da (diff) | |
parent | 49a30064bc69cb8638e7cecf1e9a7d58fc718716 (diff) | |
download | src-b4711302d408d8eaa5549aeaf35dc809395c6372.tar.gz |
Merge third_party/skia/src from https://chromium.googlesource.com/external/skia/src.git at 49a30064bc69cb8638e7cecf1e9a7d58fc718716
This commit was generated by merge_from_chromium.py.
Change-Id: I9f227703eb8587f893f0c5f7683dd790fce58c22
28 files changed, 238 insertions, 293 deletions
diff --git a/core/SkBitmapProcShader.cpp b/core/SkBitmapProcShader.cpp index 46cf7db1..503269ac 100644 --- a/core/SkBitmapProcShader.cpp +++ b/core/SkBitmapProcShader.cpp @@ -97,39 +97,25 @@ static bool valid_for_drawing(const SkBitmap& bm) { return true; } -bool SkBitmapProcShader::validInternal(const ContextRec& rec, SkMatrix* totalInverse, - SkBitmapProcState* state) const { +SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const { if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) { - return false; - } - - // Make sure we can use totalInverse as a cache. - SkMatrix totalInverseLocal; - if (NULL == totalInverse) { - totalInverse = &totalInverseLocal; + return NULL; } - + + SkMatrix totalInverse; // Do this first, so we know the matrix can be inverted. - if (!this->INHERITED::validContext(rec, totalInverse)) { - return false; + if (!this->computeTotalInverse(rec, &totalInverse)) { + return NULL; } + + void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); + SkBitmapProcState* state = SkNEW_PLACEMENT(stateStorage, SkBitmapProcState); SkASSERT(state); state->fTileModeX = fTileModeX; state->fTileModeY = fTileModeY; state->fOrigBitmap = fRawBitmap; - return state->chooseProcs(*totalInverse, *rec.fPaint); -} - -bool SkBitmapProcShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { - SkBitmapProcState state; - return this->validInternal(rec, totalInverse, &state); -} - -SkShader::Context* SkBitmapProcShader::createContext(const ContextRec& rec, void* storage) const { - void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); - SkBitmapProcState* state = SkNEW_PLACEMENT(stateStorage, SkBitmapProcState); - if (!this->validInternal(rec, NULL, state)) { + if (!state->chooseProcs(totalInverse, *rec.fPaint)) { state->~SkBitmapProcState(); return NULL; } diff --git a/core/SkBitmapProcShader.h b/core/SkBitmapProcShader.h index e32d35e2..0a036d31 100644 --- a/core/SkBitmapProcShader.h +++ b/core/SkBitmapProcShader.h @@ -23,8 +23,6 @@ public: virtual bool isOpaque() const SK_OVERRIDE; virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const SK_OVERRIDE; - virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty); @@ -59,13 +57,12 @@ public: protected: SkBitmapProcShader(SkReadBuffer& ); virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; SkBitmap fRawBitmap; // experimental for RLE encoding uint8_t fTileModeX, fTileModeY; private: - bool validInternal(const ContextRec&, SkMatrix* totalInverse, SkBitmapProcState*) const; - typedef SkShader INHERITED; }; diff --git a/core/SkBlitter.cpp b/core/SkBlitter.cpp index 74cd2982..0e12a627 100644 --- a/core/SkBlitter.cpp +++ b/core/SkBlitter.cpp @@ -591,29 +591,14 @@ public: return size; } - virtual bool validContext(const ContextRec& rec, SkMatrix* totalInverse) const SK_OVERRIDE { - if (!this->INHERITED::validContext(rec, totalInverse)) { - return false; - } - if (fProxy) { - return fProxy->validContext(rec); - } - return true; - } - - virtual SkShader::Context* createContext(const ContextRec& rec, void* storage) const SK_OVERRIDE - { - if (!this->validContext(rec, NULL)) { - return NULL; - } - - SkShader::Context* proxyContext; + virtual Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE { + SkShader::Context* proxyContext = NULL; if (fProxy) { char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext); proxyContext = fProxy->createContext(rec, proxyContextStorage); - SkASSERT(proxyContext); - } else { - proxyContext = NULL; + if (!proxyContext) { + return NULL; + } } return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, rec, proxyContext)); } @@ -1016,6 +1001,19 @@ const uint32_t gMask_00FF00FF = 0xFF00FF; /////////////////////////////////////////////////////////////////////////////// +class SkTransparentShaderContext : public SkShader::Context { +public: + SkTransparentShaderContext(const SkShader& shader, const SkShader::ContextRec& rec) + : INHERITED(shader, rec) {} + + virtual void shadeSpan(int x, int y, SkPMColor colors[], int count) SK_OVERRIDE { + sk_bzero(colors, count * sizeof(SkPMColor)); + } + +private: + typedef SkShader::Context INHERITED; +}; + SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint, SkShader::Context* shaderContext) : INHERITED(device) @@ -1035,9 +1033,6 @@ SkShaderBlitter::~SkShaderBlitter() { bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { SkShader::ContextRec rec(device, paint, matrix); - if (!fShader->validContext(rec)) { - return false; - } // Only destroy the old context if we have a new one. We need to ensure to have a // live context in fShaderContext because the storage is owned by an SkSmallAllocator @@ -1045,8 +1040,11 @@ bool SkShaderBlitter::resetShaderContext(const SkBitmap& device, const SkPaint& // The new context will be of the same size as the old one because we use the same // shader to create it. It is therefore safe to re-use the storage. fShaderContext->~Context(); - fShaderContext = fShader->createContext(rec, (void*)fShaderContext); - SkASSERT(fShaderContext); - - return true; + SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext); + if (NULL == ctx) { + // Need a valid context in fShaderContext's storage, so we can later (or our caller) call + // the in-place destructor. + SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec)); + } + return ctx != NULL; } diff --git a/core/SkComposeShader.cpp b/core/SkComposeShader.cpp index df8215c1..7a7dce66 100644 --- a/core/SkComposeShader.cpp +++ b/core/SkComposeShader.cpp @@ -73,55 +73,38 @@ void SkComposeShader::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(fMode); } -/* We call validContext/createContext on our two worker shaders. - However, we always let them see opaque alpha, and if the paint - really is translucent, then we apply that after the fact. - - */ -bool SkComposeShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { - if (!this->INHERITED::validContext(rec, totalInverse)) { - return false; +template <typename T> void safe_call_destructor(T* obj) { + if (obj) { + obj->~T(); } - - // we preconcat our localMatrix (if any) with the device matrix - // before calling our sub-shaders - - SkMatrix tmpM; - tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix()); - - ContextRec newRec(rec); - newRec.fMatrix = &tmpM; - - return fShaderA->validContext(newRec) && fShaderB->validContext(newRec); } -SkShader::Context* SkComposeShader::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - - // TODO : must fix this to not "cheat" and modify fPaint - SkAutoAlphaRestore restore(const_cast<SkPaint*>(rec.fPaint), 0xFF); - +SkShader::Context* SkComposeShader::onCreateContext(const ContextRec& rec, void* storage) const { char* aStorage = (char*) storage + sizeof(ComposeShaderContext); char* bStorage = aStorage + fShaderA->contextSize(); // we preconcat our localMatrix (if any) with the device matrix // before calling our sub-shaders - SkMatrix tmpM; tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix()); + // Our sub-shaders need to see opaque, so by combining them we don't double-alphatize the + // result. ComposeShader itself will respect the alpha, and post-apply it after calling the + // sub-shaders. + SkPaint opaquePaint(*rec.fPaint); + opaquePaint.setAlpha(0xFF); + ContextRec newRec(rec); newRec.fMatrix = &tmpM; + newRec.fPaint = &opaquePaint; SkShader::Context* contextA = fShaderA->createContext(newRec, aStorage); SkShader::Context* contextB = fShaderB->createContext(newRec, bStorage); - - // Both functions must succeed; otherwise validContext should have returned - // false. - SkASSERT(contextA); - SkASSERT(contextB); + if (!contextA || !contextB) { + safe_call_destructor(contextA); + safe_call_destructor(contextB); + return NULL; + } return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, (*this, rec, contextA, contextB)); } @@ -148,6 +131,10 @@ void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode; unsigned scale = SkAlpha255To256(this->getPaintAlpha()); +#ifdef SK_BUILD_FOR_ANDROID + scale = 256; // ugh -- maintain old bug/behavior for now +#endif + SkPMColor tmp[TMP_COLOR_COUNT]; if (NULL == mode) { // implied SRC_OVER @@ -188,7 +175,7 @@ void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re shaderContextB->shadeSpan(x, y, tmp, n); mode->xfer32(result, tmp, n, NULL); - if (256 == scale) { + if (256 != scale) { for (int i = 0; i < n; i++) { result[i] = SkAlphaMulQ(result[i], scale); } diff --git a/core/SkDraw.cpp b/core/SkDraw.cpp index c4f5f74e..a74e3c0f 100644 --- a/core/SkDraw.cpp +++ b/core/SkDraw.cpp @@ -2353,7 +2353,6 @@ class SkTriColorShader : public SkShader { public: SkTriColorShader() {} - virtual SkShader::Context* createContext(const ContextRec&, void*) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class TriColorShaderContext : public SkShader::Context { @@ -2378,18 +2377,14 @@ public: protected: SkTriColorShader(SkReadBuffer& buffer) : SkShader(buffer) {} + virtual Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE { + return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec)); + } + private: typedef SkShader INHERITED; }; -SkShader::Context* SkTriColorShader::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - - return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec)); -} - bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], int index0, int index1, int index2) { diff --git a/core/SkFilterShader.cpp b/core/SkFilterShader.cpp index f1cc68d0..5094706e 100644 --- a/core/SkFilterShader.cpp +++ b/core/SkFilterShader.cpp @@ -55,11 +55,7 @@ uint32_t SkFilterShader::FilterShaderContext::getFlags() const { return shaderF; } -SkShader::Context* SkFilterShader::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec, NULL)) { - return NULL; - } - +SkShader::Context* SkFilterShader::onCreateContext(const ContextRec& rec, void* storage) const { char* shaderContextStorage = (char*)storage + sizeof(FilterShaderContext); SkShader::Context* shaderContext = fShader->createContext(rec, shaderContextStorage); SkASSERT(shaderContext); @@ -71,10 +67,6 @@ size_t SkFilterShader::contextSize() const { return sizeof(FilterShaderContext) + fShader->contextSize(); } -bool SkFilterShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { - return this->INHERITED::validContext(rec, totalInverse) && fShader->validContext(rec); -} - SkFilterShader::FilterShaderContext::FilterShaderContext(const SkFilterShader& filterShader, SkShader::Context* shaderContext, const ContextRec& rec) diff --git a/core/SkFilterShader.h b/core/SkFilterShader.h index 629f3f8c..3f983e26 100644 --- a/core/SkFilterShader.h +++ b/core/SkFilterShader.h @@ -17,8 +17,6 @@ public: SkFilterShader(SkShader* shader, SkColorFilter* filter); virtual ~SkFilterShader(); - virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class FilterShaderContext : public SkShader::Context { @@ -44,6 +42,8 @@ public: protected: SkFilterShader(SkReadBuffer& ); virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; + private: SkShader* fShader; diff --git a/core/SkPaintPriv.cpp b/core/SkPaintPriv.cpp index ce053890..65fd0e75 100644 --- a/core/SkPaintPriv.cpp +++ b/core/SkPaintPriv.cpp @@ -76,3 +76,24 @@ bool isPaintOpaque(const SkPaint* paint, } return false; } + +bool NeedsDeepCopy(const SkPaint& paint) { + /* + * These fields are known to be immutable, and so can be shallow-copied + * + * getTypeface() + * getAnnotation() + * paint.getColorFilter() + * getXfermode() + * getPathEffect() + * getMaskFilter() + */ + + return paint.getShader() || +#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API + paint.getRasterizer() || +#endif + paint.getLooper() || // needs to hide its addLayer... + paint.getImageFilter(); +} + diff --git a/core/SkPaintPriv.h b/core/SkPaintPriv.h index 38c9063e..9668fef1 100644 --- a/core/SkPaintPriv.h +++ b/core/SkPaintPriv.h @@ -22,4 +22,11 @@ class SkPaint; */ bool isPaintOpaque(const SkPaint* paint, const SkBitmap* bmpReplacesShader = NULL); + +/** Returns true if the provided paint has fields which are not + immutable (and will thus require deep copying). + @param paint the paint to be analyzed + @return true if the paint requires a deep copy +*/ +bool NeedsDeepCopy(const SkPaint& paint); #endif diff --git a/core/SkPicture.cpp b/core/SkPicture.cpp index 3b04906e..68434303 100644 --- a/core/SkPicture.cpp +++ b/core/SkPicture.cpp @@ -15,6 +15,7 @@ #include "SkBitmapDevice.h" #include "SkCanvas.h" #include "SkChunkAlloc.h" +#include "SkPaintPriv.h" #include "SkPicture.h" #include "SkRegion.h" #include "SkStream.h" @@ -217,26 +218,6 @@ SkPicture* SkPicture::clone() const { return clonedPicture; } -static bool needs_deep_copy(const SkPaint& paint) { - /* - * These fields are known to be immutable, and so can be shallow-copied - * - * getTypeface() - * getAnnotation() - * paint.getColorFilter() - * getXfermode() - * getPathEffect() - * getMaskFilter() - */ - - return paint.getShader() || -#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API - paint.getRasterizer() || -#endif - paint.getLooper() || // needs to hide its addLayer... - paint.getImageFilter(); -} - void SkPicture::clone(SkPicture* pictures, int count) const { SkPictCopyInfo copyInfo; SkPictInfo info; @@ -282,7 +263,7 @@ void SkPicture::clone(SkPicture* pictures, int count) const { SkDEBUGCODE(int heapSize = SafeCount(fPlayback->fBitmapHeap.get());) for (int i = 0; i < paintCount; i++) { - if (needs_deep_copy(fPlayback->fPaints->at(i))) { + if (NeedsDeepCopy(fPlayback->fPaints->at(i))) { copyInfo.paintData[i] = SkFlatData::Create<SkPaint::FlatteningTraits>(©Info.controller, fPlayback->fPaints->at(i), 0); diff --git a/core/SkPictureShader.cpp b/core/SkPictureShader.cpp index 81f92428..9555624f 100644 --- a/core/SkPictureShader.cpp +++ b/core/SkPictureShader.cpp @@ -110,58 +110,55 @@ SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix) const { return fCachedBitmapShader; } -SkShader* SkPictureShader::validInternal(const ContextRec& rec, SkMatrix* totalInverse) const { - if (!this->INHERITED::validContext(rec, totalInverse)) { - return NULL; - } +size_t SkPictureShader::contextSize() const { + return sizeof(PictureShaderContext); +} +SkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void* storage) const { SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix)); - if (!bitmapShader || !bitmapShader->validContext(rec)) { + if (NULL == bitmapShader.get()) { return NULL; } - - return bitmapShader.detach(); + return PictureShaderContext::Create(storage, *this, rec, bitmapShader.detach()); } -bool SkPictureShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { - SkAutoTUnref<SkShader> shader(this->validInternal(rec, totalInverse)); - return shader != NULL; -} +///////////////////////////////////////////////////////////////////////////////////////// -SkShader::Context* SkPictureShader::createContext(const ContextRec& rec, void* storage) const { - SkAutoTUnref<SkShader> bitmapShader(this->validInternal(rec, NULL)); - if (!bitmapShader) { - return NULL; +SkShader::Context* SkPictureShader::PictureShaderContext::Create(void* storage, + const SkPictureShader& shader, const ContextRec& rec, SkShader* bitmapShader) { + PictureShaderContext* ctx = SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext, + (shader, rec, bitmapShader)); + if (NULL == ctx->fBitmapShaderContext) { + ctx->~PictureShaderContext(); + ctx = NULL; } - - return SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext, (*this, rec, bitmapShader.detach())); -} - -size_t SkPictureShader::contextSize() const { - return sizeof(PictureShaderContext); + return ctx; } SkPictureShader::PictureShaderContext::PictureShaderContext( const SkPictureShader& shader, const ContextRec& rec, SkShader* bitmapShader) : INHERITED(shader, rec) - , fBitmapShader(bitmapShader) + , fBitmapShader(SkRef(bitmapShader)) { - SkASSERT(fBitmapShader); - fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize()); - fBitmapShaderContext = fBitmapShader->createContext(rec, fBitmapShaderContextStorage); - SkASSERT(fBitmapShaderContext); + fBitmapShaderContextStorage = sk_malloc_throw(bitmapShader->contextSize()); + fBitmapShaderContext = bitmapShader->createContext(rec, fBitmapShaderContextStorage); + //if fBitmapShaderContext is null, we are invalid } SkPictureShader::PictureShaderContext::~PictureShaderContext() { - fBitmapShaderContext->~Context(); + if (fBitmapShaderContext) { + fBitmapShaderContext->~Context(); + } sk_free(fBitmapShaderContextStorage); } uint32_t SkPictureShader::PictureShaderContext::getFlags() const { + SkASSERT(fBitmapShaderContext); return fBitmapShaderContext->getFlags(); } SkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc(void** ctx) { + SkASSERT(fBitmapShaderContext); return fBitmapShaderContext->asAShadeProc(ctx); } diff --git a/core/SkPictureShader.h b/core/SkPictureShader.h index 2ef6c1c9..17882055 100644 --- a/core/SkPictureShader.h +++ b/core/SkPictureShader.h @@ -24,29 +24,8 @@ public: static SkPictureShader* Create(SkPicture*, TileMode, TileMode, const SkMatrix* = NULL); virtual ~SkPictureShader(); - virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; - class PictureShaderContext : public SkShader::Context { - public: - PictureShaderContext(const SkPictureShader&, const ContextRec&, SkShader* bitmapShader); - virtual ~PictureShaderContext(); - - virtual uint32_t getFlags() const SK_OVERRIDE; - - virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE; - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; - virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; - - private: - SkAutoTUnref<SkShader> fBitmapShader; - SkShader::Context* fBitmapShaderContext; - void* fBitmapShaderContextStorage; - - typedef SkShader::Context INHERITED; - }; - SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPictureShader) @@ -57,11 +36,11 @@ public: protected: SkPictureShader(SkReadBuffer&); virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; private: SkPictureShader(SkPicture*, TileMode, TileMode, const SkMatrix* = NULL); - SkShader* validInternal(const ContextRec&, SkMatrix* totalInverse) const; SkShader* refBitmapShader(const SkMatrix&) const; SkPicture* fPicture; @@ -72,6 +51,29 @@ private: mutable SkSize fCachedTileScale; mutable SkMatrix fCachedLocalMatrix; + class PictureShaderContext : public SkShader::Context { + public: + static Context* Create(void* storage, const SkPictureShader&, const ContextRec&, + SkShader* bitmapShader); + + virtual ~PictureShaderContext(); + + virtual uint32_t getFlags() const SK_OVERRIDE; + + virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE; + virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; + virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) SK_OVERRIDE; + + private: + PictureShaderContext(const SkPictureShader&, const ContextRec&, SkShader* bitmapShader); + + SkAutoTUnref<SkShader> fBitmapShader; + SkShader::Context* fBitmapShaderContext; + void* fBitmapShaderContextStorage; + + typedef SkShader::Context INHERITED; + }; + typedef SkShader INHERITED; }; diff --git a/core/SkShader.cpp b/core/SkShader.cpp index 67dd5815..8e6112ae 100644 --- a/core/SkShader.cpp +++ b/core/SkShader.cpp @@ -6,6 +6,7 @@ */ #include "SkBitmapProcShader.h" +#include "SkEmptyShader.h" #include "SkReadBuffer.h" #include "SkMallocPixelRef.h" #include "SkPaint.h" @@ -44,23 +45,25 @@ void SkShader::flatten(SkWriteBuffer& buffer) const { } } -bool SkShader::computeTotalInverse(const SkMatrix& matrix, SkMatrix* totalInverse) const { - const SkMatrix* m = &matrix; +bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const { + const SkMatrix* m = rec.fMatrix; SkMatrix total; if (this->hasLocalMatrix()) { - total.setConcat(matrix, this->getLocalMatrix()); + total.setConcat(*m, this->getLocalMatrix()); m = &total; } - return m->invert(totalInverse); } -bool SkShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { - return this->computeTotalInverse(*rec.fMatrix, totalInverse); +SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const { + if (!this->computeTotalInverse(rec, NULL)) { + return NULL; + } + return this->onCreateContext(rec, storage); } -SkShader::Context* SkShader::createContext(const ContextRec&, void* storage) const { +SkShader::Context* SkShader::onCreateContext(const ContextRec&, void*) const { return NULL; } @@ -71,11 +74,9 @@ size_t SkShader::contextSize() const { SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) : fShader(shader) { - SkASSERT(fShader.validContext(rec)); - // Because the context parameters must be valid at this point, we know that the matrix is // invertible. - SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, &fTotalInverse)); + SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse)); fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); fPaintAlpha = rec.fPaint->getAlpha(); @@ -188,6 +189,10 @@ GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const { return NULL; } +SkShader* SkShader::CreateEmptyShader() { + return SkNEW(SkEmptyShader); +} + SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, const SkMatrix* localMatrix) { return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL); @@ -246,11 +251,7 @@ uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const { return SkGetPackedA32(fPMColor); } -SkShader::Context* SkColorShader::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - +SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec)); } diff --git a/effects/SkPerlinNoiseShader.cpp b/effects/SkPerlinNoiseShader.cpp index a4944fb8..c6d61180 100644 --- a/effects/SkPerlinNoiseShader.cpp +++ b/effects/SkPerlinNoiseShader.cpp @@ -425,11 +425,8 @@ SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); } -SkShader::Context* SkPerlinNoiseShader::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - +SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec, + void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, rec)); } diff --git a/effects/SkTransparentShader.cpp b/effects/SkTransparentShader.cpp index 9a390ad6..f290d0dc 100644 --- a/effects/SkTransparentShader.cpp +++ b/effects/SkTransparentShader.cpp @@ -11,11 +11,8 @@ #include "SkColorPriv.h" #include "SkString.h" -SkShader::Context* SkTransparentShader::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - +SkShader::Context* SkTransparentShader::onCreateContext(const ContextRec& rec, + void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, rec)); } diff --git a/effects/gradients/SkLinearGradient.cpp b/effects/gradients/SkLinearGradient.cpp index b9de651f..f37759c1 100644 --- a/effects/gradients/SkLinearGradient.cpp +++ b/effects/gradients/SkLinearGradient.cpp @@ -76,11 +76,7 @@ size_t SkLinearGradient::contextSize() const { return sizeof(LinearGradientContext); } -SkShader::Context* SkLinearGradient::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - +SkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, LinearGradientContext, (*this, rec)); } diff --git a/effects/gradients/SkLinearGradient.h b/effects/gradients/SkLinearGradient.h index d9ffc77c..e892fe33 100644 --- a/effects/gradients/SkLinearGradient.h +++ b/effects/gradients/SkLinearGradient.h @@ -14,7 +14,6 @@ class SkLinearGradient : public SkGradientShaderBase { public: SkLinearGradient(const SkPoint pts[2], const Descriptor&, const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class LinearGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { @@ -39,6 +38,7 @@ public: protected: SkLinearGradient(SkReadBuffer& buffer); virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; private: typedef SkGradientShaderBase INHERITED; diff --git a/effects/gradients/SkRadialGradient.cpp b/effects/gradients/SkRadialGradient.cpp index 07ee680a..e379f36c 100644 --- a/effects/gradients/SkRadialGradient.cpp +++ b/effects/gradients/SkRadialGradient.cpp @@ -161,11 +161,7 @@ size_t SkRadialGradient::contextSize() const { return sizeof(RadialGradientContext); } -SkShader::Context* SkRadialGradient::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - +SkShader::Context* SkRadialGradient::onCreateContext(const ContextRec& rec, void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, RadialGradientContext, (*this, rec)); } diff --git a/effects/gradients/SkRadialGradient.h b/effects/gradients/SkRadialGradient.h index 87302473..2c60ba5e 100644 --- a/effects/gradients/SkRadialGradient.h +++ b/effects/gradients/SkRadialGradient.h @@ -16,7 +16,6 @@ public: SkRadialGradient(const SkPoint& center, SkScalar radius, const Descriptor&, const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class RadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { @@ -42,6 +41,7 @@ public: protected: SkRadialGradient(SkReadBuffer& buffer); virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; private: typedef SkGradientShaderBase INHERITED; diff --git a/effects/gradients/SkSweepGradient.cpp b/effects/gradients/SkSweepGradient.cpp index 0baf5c71..81ebb344 100644 --- a/effects/gradients/SkSweepGradient.cpp +++ b/effects/gradients/SkSweepGradient.cpp @@ -56,11 +56,7 @@ size_t SkSweepGradient::contextSize() const { return sizeof(SweepGradientContext); } -SkShader::Context* SkSweepGradient::createContext(const ContextRec& rec, void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - +SkShader::Context* SkSweepGradient::onCreateContext(const ContextRec& rec, void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, SweepGradientContext, (*this, rec)); } diff --git a/effects/gradients/SkSweepGradient.h b/effects/gradients/SkSweepGradient.h index 9ddd1e25..36cdd638 100644 --- a/effects/gradients/SkSweepGradient.h +++ b/effects/gradients/SkSweepGradient.h @@ -16,7 +16,6 @@ public: SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&, const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class SweepGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { @@ -44,6 +43,7 @@ public: protected: SkSweepGradient(SkReadBuffer& buffer); virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; private: const SkPoint fCenter; diff --git a/effects/gradients/SkTwoPointConicalGradient.cpp b/effects/gradients/SkTwoPointConicalGradient.cpp index e9c2efe3..574df082 100644 --- a/effects/gradients/SkTwoPointConicalGradient.cpp +++ b/effects/gradients/SkTwoPointConicalGradient.cpp @@ -221,12 +221,8 @@ size_t SkTwoPointConicalGradient::contextSize() const { return sizeof(TwoPointConicalGradientContext); } -SkShader::Context* SkTwoPointConicalGradient::createContext(const ContextRec& rec, - void* storage) const { - if (!this->validContext(rec)) { - return NULL; - } - +SkShader::Context* SkTwoPointConicalGradient::onCreateContext(const ContextRec& rec, + void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext, (*this, rec)); } diff --git a/effects/gradients/SkTwoPointConicalGradient.h b/effects/gradients/SkTwoPointConicalGradient.h index 1c5e409a..85e0bc0b 100644 --- a/effects/gradients/SkTwoPointConicalGradient.h +++ b/effects/gradients/SkTwoPointConicalGradient.h @@ -48,7 +48,6 @@ public: const SkMatrix* localMatrix); - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; class TwoPointConicalGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { @@ -83,6 +82,7 @@ public: protected: SkTwoPointConicalGradient(SkReadBuffer& buffer); virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; private: SkPoint fCenter1; diff --git a/effects/gradients/SkTwoPointRadialGradient.cpp b/effects/gradients/SkTwoPointRadialGradient.cpp index f691db29..d85be5d3 100644 --- a/effects/gradients/SkTwoPointRadialGradient.cpp +++ b/effects/gradients/SkTwoPointRadialGradient.cpp @@ -224,21 +224,12 @@ size_t SkTwoPointRadialGradient::contextSize() const { return sizeof(TwoPointRadialGradientContext); } -bool SkTwoPointRadialGradient::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { +SkShader::Context* SkTwoPointRadialGradient::onCreateContext(const ContextRec& rec, + void* storage) const { // For now, we might have divided by zero, so detect that. if (0 == fDiffRadius) { - return false; - } - - return this->INHERITED::validContext(rec, totalInverse); -} - -SkShader::Context* SkTwoPointRadialGradient::createContext(const ContextRec& rec, - void* storage) const { - if (!this->validContext(rec, NULL)) { return NULL; } - return SkNEW_PLACEMENT_ARGS(storage, TwoPointRadialGradientContext, (*this, rec)); } diff --git a/effects/gradients/SkTwoPointRadialGradient.h b/effects/gradients/SkTwoPointRadialGradient.h index de5b5434..6d36fe44 100644 --- a/effects/gradients/SkTwoPointRadialGradient.h +++ b/effects/gradients/SkTwoPointRadialGradient.h @@ -24,8 +24,6 @@ public: virtual GrEffectRef* asNewEffect(GrContext* context, const SkPaint&) const SK_OVERRIDE; virtual size_t contextSize() const SK_OVERRIDE; - virtual bool validContext(const ContextRec&, SkMatrix* totalInverse) const SK_OVERRIDE; - virtual SkShader::Context* createContext(const ContextRec&, void* storage) const SK_OVERRIDE; class TwoPointRadialGradientContext : public SkGradientShaderBase::GradientShaderBaseContext { public: @@ -47,6 +45,7 @@ public: protected: SkTwoPointRadialGradient(SkReadBuffer& buffer); virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; + virtual Context* onCreateContext(const ContextRec&, void* storage) const SK_OVERRIDE; private: const SkPoint fCenter1; diff --git a/gpu/GrPictureUtils.cpp b/gpu/GrPictureUtils.cpp index e8c3b504..d8e4161c 100644 --- a/gpu/GrPictureUtils.cpp +++ b/gpu/GrPictureUtils.cpp @@ -7,6 +7,8 @@ #include "GrPictureUtils.h" #include "SkDevice.h" +#include "SkDraw.h" +#include "SkPaintPriv.h" // The GrGather device performs GPU-backend-specific preprocessing on // a picture. The results are stored in a GPUAccelData. @@ -20,12 +22,17 @@ class GrGatherDevice : public SkBaseDevice { public: SK_DECLARE_INST_COUNT(GrGatherDevice) - GrGatherDevice(int width, int height, SkPicture* picture, GPUAccelData* accelData) { + GrGatherDevice(int width, int height, SkPicture* picture, GPUAccelData* accelData, + int saveLayerDepth) { fPicture = picture; + fSaveLayerDepth = saveLayerDepth; + fInfo.fValid = true; fInfo.fSize.set(width, height); + fInfo.fPaint = NULL; fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID(); fInfo.fRestoreOpID = 0; fInfo.fHasNestedLayers = false; + fInfo.fIsNested = (2 == fSaveLayerDepth); fEmptyBitmap.setConfig(SkImageInfo::Make(fInfo.fSize.fWidth, fInfo.fSize.fHeight, @@ -110,7 +117,8 @@ protected: const SkPaint& paint) SK_OVERRIDE { } virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, int y, - const SkPaint&) SK_OVERRIDE { + const SkPaint& paint) SK_OVERRIDE { + // deviceIn is the one that is being "restored" back to its parent GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn); if (device->fAlreadyDrawn) { @@ -118,6 +126,29 @@ protected: } device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID(); + device->fInfo.fCTM = *draw.fMatrix; + device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX), + SkIntToScalar(-device->getOrigin().fY)); + + // We need the x & y values that will yield 'getOrigin' when transformed + // by 'draw.fMatrix'. + device->fInfo.fOffset.iset(device->getOrigin()); + + SkMatrix invMatrix; + if (draw.fMatrix->invert(&invMatrix)) { + invMatrix.mapPoints(&device->fInfo.fOffset, 1); + } else { + device->fInfo.fValid = false; + } + + if (NeedsDeepCopy(paint)) { + // This NULL acts as a signal that the paint was uncopyable (for now) + device->fInfo.fPaint = NULL; + device->fInfo.fValid = false; + } else { + device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint)); + } + fAccelData->addSaveLayerInfo(device->fInfo); device->fAlreadyDrawn = true; } @@ -158,6 +189,9 @@ private: // The information regarding the saveLayer call this device represents. GPUAccelData::SaveLayerInfo fInfo; + // The depth of this device in the saveLayer stack + int fSaveLayerDepth; + virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE { NotSupported(); } @@ -167,7 +201,8 @@ private: SkASSERT(kSaveLayer_Usage == usage); fInfo.fHasNestedLayers = true; - return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture, fAccelData)); + return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture, + fAccelData, fSaveLayerDepth+1)); } virtual void flush() SK_OVERRIDE {} @@ -239,7 +274,7 @@ void GatherGPUInfo(SkPicture* pict, GPUAccelData* accelData) { return ; } - GrGatherDevice device(pict->width(), pict->height(), pict, accelData); + GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0); GrGatherCanvas canvas(&device, pict); canvas.gather(); diff --git a/gpu/GrPictureUtils.h b/gpu/GrPictureUtils.h index 6b4d901c..5ca41320 100644 --- a/gpu/GrPictureUtils.h +++ b/gpu/GrPictureUtils.h @@ -17,8 +17,21 @@ class GPUAccelData : public SkPicture::AccelData { public: // Information about a given saveLayer in an SkPicture struct SaveLayerInfo { + // True if the SaveLayerInfo is valid. False if either 'fOffset' is + // invalid (due to a non-invertible CTM) or 'fPaint' is NULL (due + // to a non-copyable paint). + bool fValid; // The size of the saveLayer SkISize fSize; + // The CTM in which this layer's draws must occur. It already incorporates + // the translation needed to map the layer's top-left point to the origin. + SkMatrix fCTM; + // The offset that needs to be passed to drawBitmap to correctly + // position the pre-rendered layer. + SkPoint fOffset; + // The paint to use on restore. NULL if the paint was not copyable (and + // thus that this layer should not be pulled forward). + const SkPaint* fPaint; // The ID of this saveLayer in the picture. 0 is an invalid ID. size_t fSaveLayerOpID; // The ID of the matching restore in the picture. 0 is an invalid ID. @@ -26,6 +39,8 @@ public: // True if this saveLayer has at least one other saveLayer nested within it. // False otherwise. bool fHasNestedLayers; + // True if this saveLayer is nested within another. False otherwise. + bool fIsNested; }; GPUAccelData(Key key) : INHERITED(key) { } @@ -43,6 +58,14 @@ public: return fSaveLayerInfo[index]; } + // We may, in the future, need to pass in the GPUDevice in order to + // incorporate the clip and matrix state into the key + static SkPicture::AccelData::Key ComputeAccelDataKey() { + static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain(); + + return gGPUID; + } + protected: SkTDArray<SaveLayerInfo> fSaveLayerInfo; diff --git a/gpu/SkGpuDevice.cpp b/gpu/SkGpuDevice.cpp index 714a6da6..3119a9e7 100644 --- a/gpu/SkGpuDevice.cpp +++ b/gpu/SkGpuDevice.cpp @@ -1910,16 +1910,8 @@ SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info) { return SkSurface::NewRenderTarget(fContext, info, fRenderTarget->numSamples()); } -// In the future this may not be a static method if we need to incorporate the -// clip and matrix state into the key -SkPicture::AccelData::Key SkGpuDevice::ComputeAccelDataKey() { - static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain(); - - return gGPUID; -} - void SkGpuDevice::EXPERIMENTAL_optimize(SkPicture* picture) { - SkPicture::AccelData::Key key = ComputeAccelDataKey(); + SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey(); GPUAccelData* data = SkNEW_ARGS(GPUAccelData, (key)); @@ -1934,7 +1926,7 @@ void SkGpuDevice::EXPERIMENTAL_purge(SkPicture* picture) { bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, SkPicture* picture) { - SkPicture::AccelData::Key key = ComputeAccelDataKey(); + SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey(); const SkPicture::AccelData* data = picture->EXPERIMENTAL_getAccelData(key); if (NULL == data) { @@ -1943,27 +1935,6 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, SkPicture* picture) const GPUAccelData *gpuData = static_cast<const GPUAccelData*>(data); -//#define SK_PRINT_PULL_FORWARD_INFO 1 - -#ifdef SK_PRINT_PULL_FORWARD_INFO - static bool gPrintedAccelData = false; - - if (!gPrintedAccelData) { - for (int i = 0; i < gpuData->numSaveLayers(); ++i) { - const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i); - - SkDebugf("%d: Width: %d Height: %d SL: %d R: %d hasNestedLayers: %s\n", - i, - info.fSize.fWidth, - info.fSize.fHeight, - info.fSaveLayerOpID, - info.fRestoreOpID, - info.fHasNestedLayers ? "T" : "F"); - } - gPrintedAccelData = true; - } -#endif - SkAutoTArray<bool> pullForward(gpuData->numSaveLayers()); for (int i = 0; i < gpuData->numSaveLayers(); ++i) { pullForward[i] = false; @@ -1984,10 +1955,6 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, SkPicture* picture) const SkPicture::OperationList& ops = picture->EXPERIMENTAL_getActiveOps(clip); -#ifdef SK_PRINT_PULL_FORWARD_INFO - SkDebugf("rect: %d %d %d %d\n", clip.fLeft, clip.fTop, clip.fRight, clip.fBottom); -#endif - for (int i = 0; i < ops.numOps(); ++i) { for (int j = 0; j < gpuData->numSaveLayers(); ++j) { const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(j); @@ -1998,17 +1965,5 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* canvas, SkPicture* picture) } } -#ifdef SK_PRINT_PULL_FORWARD_INFO - SkDebugf("Need SaveLayers: "); - for (int i = 0; i < gpuData->numSaveLayers(); ++i) { - if (pullForward[i]) { - const GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture, i); - - SkDebugf("%d (%d), ", i, layer->layerID()); - } - } - SkDebugf("\n"); -#endif - return false; } |