use SkBitmapProvider for shader-context
authorreed <reed@google.com>
Tue, 15 Sep 2015 20:33:58 +0000 (13:33 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 15 Sep 2015 20:33:58 +0000 (13:33 -0700)
BUG=skia:

Review URL: https://codereview.chromium.org/1343123005

include/core/SkShader.h
src/core/SkBitmapController.h
src/core/SkBitmapProcShader.cpp
src/core/SkBitmapProcShader.h
src/core/SkBitmapProcState.cpp
src/core/SkBitmapProcState.h
src/core/SkLightingShader.cpp

index 47934dd9ad9579b4cdd8b0209039e4e90f3f5035..a95e7e713e4dedb79c8ea865e217c070f200bca8 100644 (file)
@@ -439,6 +439,7 @@ private:
 
     // So the SkLocalMatrixShader can whack fLocalMatrix in its SkReadBuffer constructor.
     friend class SkLocalMatrixShader;
+    friend class SkBitmapProcShader;    // for computeTotalInverse()
 
     typedef SkFlattenable INHERITED;
 };
index 435d9e72aff83456f76e6d7511ed0462cb3124c3..e6c4443872eaf0faddee6f8b8e1a9f0d206bb3bc 100644 (file)
 
 class SkBitmapProvider {
 public:
-    SkBitmapProvider(const SkBitmap& bm) : fBitmap(bm) {}
-    SkBitmapProvider(const SkImage* img) : fImage(SkRef(img)) {}
+    explicit SkBitmapProvider(const SkBitmap& bm) : fBitmap(bm) {}
+    explicit SkBitmapProvider(const SkImage* img) : fImage(SkSafeRef(img)) {}
+    SkBitmapProvider(const SkBitmapProvider& other)
+        : fBitmap(other.fBitmap)
+        , fImage(SkSafeRef(other.fImage.get()))
+    {}
 
     int width() const;
     int height() const;
index 97abbf96759ff7e7e9e029493791e99f718fcb71..36bfb1e7d6e153de446c4e06744a755bef19749c 100644 (file)
 #include "effects/GrSimpleTextureEffect.h"
 #endif
 
+size_t SkBitmapProcShader::ContextSize() {
+    // The SkBitmapProcState is stored outside of the context object, with the context holding
+    // a pointer to it.
+    return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
+}
+
 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
                                        const SkMatrix* localMatrix)
         : INHERITED(localMatrix) {
@@ -70,36 +76,36 @@ bool SkBitmapProcShader::isOpaque() const {
     return fRawBitmap.isOpaque();
 }
 
-SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
+SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader,
+                                                   TileMode tmx, TileMode tmy,
+                                                   const SkBitmap& bitmap,
+                                                   const ContextRec& rec, void* storage) {
     SkMatrix totalInverse;
     // Do this first, so we know the matrix can be inverted.
-    if (!this->computeTotalInverse(rec, &totalInverse)) {
+    if (!shader.computeTotalInverse(rec, &totalInverse)) {
         return nullptr;
     }
 
     void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext);
-    SkBitmapProcState* state = new (stateStorage) SkBitmapProcState;
+    SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(SkBitmapProvider(bitmap),
+                                                                    tmx, tmy);
 
     SkASSERT(state);
-    state->fTileModeX = fTileModeX;
-    state->fTileModeY = fTileModeY;
-    state->fOrigBitmap = fRawBitmap;
     if (!state->chooseProcs(totalInverse, *rec.fPaint)) {
         state->~SkBitmapProcState();
         return nullptr;
     }
 
-    return new (storage) BitmapProcShaderContext(*this, rec, state);
+    return new (storage) BitmapProcShaderContext(shader, rec, state);
 }
 
-size_t SkBitmapProcShader::contextSize() const {
-    // The SkBitmapProcState is stored outside of the context object, with the context holding
-    // a pointer to it.
-    return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
+SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
+    return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, fRawBitmap, rec, storage);
 }
 
-SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(
-        const SkBitmapProcShader& shader, const ContextRec& rec, SkBitmapProcState* state)
+SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(const SkShader& shader,
+                                                                     const ContextRec& rec,
+                                                                     SkBitmapProcState* state)
     : INHERITED(shader, rec)
     , fState(state)
 {
index 63985c06c514472a2194ef498ed86c728c9ff1a7..9e90f9faace7b4a861cf2c1c98ed5ef9d058442a 100644 (file)
@@ -22,7 +22,7 @@ public:
 
     bool isOpaque() const override;
 
-    size_t contextSize() const override;
+    size_t contextSize() const override { return ContextSize(); }
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBitmapProcShader)
@@ -33,11 +33,12 @@ public:
                                                    GrProcessorDataManager*) const override;
 #endif
 
+protected:
     class BitmapProcShaderContext : public SkShader::Context {
     public:
         // The context takes ownership of the state. It will call its destructor
         // but will NOT free the memory.
-        BitmapProcShaderContext(const SkBitmapProcShader&, const ContextRec&, SkBitmapProcState*);
+        BitmapProcShaderContext(const SkShader&, const ContextRec&, SkBitmapProcState*);
         ~BitmapProcShaderContext() override;
 
         void shadeSpan(int x, int y, SkPMColor dstC[], int count) override;
@@ -52,8 +53,7 @@ public:
 
         typedef SkShader::Context INHERITED;
     };
-
-protected:
+    
     void flatten(SkWriteBuffer&) const override;
     Context* onCreateContext(const ContextRec&, void* storage) const override;
     bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode*) const override;
@@ -62,6 +62,12 @@ protected:
     uint8_t     fTileModeX, fTileModeY;
 
 private:
+    friend class SkImageShader;
+
+    static size_t ContextSize();
+    static Context* MakeContext(const SkShader&, TileMode tmx, TileMode tmy, const SkBitmap&,
+                                const ContextRec&, void* storage);
+
     typedef SkShader INHERITED;
 };
 
@@ -70,7 +76,7 @@ private:
 // an Sk3DBlitter in SkDraw.cpp
 // Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not
 // yet found a situation where the size below isn't big enough.
-typedef SkSmallAllocator<3, 1152> SkTBlitterAllocator;
+typedef SkSmallAllocator<3, 1160> SkTBlitterAllocator;
 
 // If alloc is non-nullptr, it will be used to allocate the returned SkShader, and MUST outlive
 // the SkShader.
index 31109aaee972df057efae1e8bb000a77ab1b977f..5ec6721436ec72cec91f6e3a9c9f1160d35ac016 100644 (file)
@@ -37,7 +37,23 @@ extern void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const SkBitmapProcState&
 #include "SkBitmapProcState_filter.h"
 #include "SkBitmapProcState_procs.h"
 
-SkBitmapProcState::SkBitmapProcState() : fBMState(nullptr) {}
+SkBitmapProcState::SkBitmapProcState(const SkBitmapProvider& provider,
+                                     SkShader::TileMode tmx, SkShader::TileMode tmy)
+    : fProvider(provider)
+    , fBMState(nullptr)
+{
+    fTileModeX = tmx;
+    fTileModeY = tmy;
+}
+
+SkBitmapProcState::SkBitmapProcState(const SkBitmap& bm,
+                                     SkShader::TileMode tmx, SkShader::TileMode tmy)
+    : fProvider(SkBitmapProvider(bm))
+    , fBMState(nullptr)
+{
+    fTileModeX = tmx;
+    fTileModeY = tmy;
+}
 
 SkBitmapProcState::~SkBitmapProcState() {
     SkInPlaceDeleteCheck(fBMState, fBMStateStorage.get());
@@ -119,7 +135,7 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
     fFilterLevel = paint.getFilterQuality();
 
     SkDefaultBitmapController controller;
-    fBMState = controller.requestBitmap(fOrigBitmap, inv, paint.getFilterQuality(),
+    fBMState = controller.requestBitmap(fProvider, inv, paint.getFilterQuality(),
                                         fBMStateStorage.get(), fBMStateStorage.size());
     // Note : we allow the controller to return an empty (zero-dimension) result. Should we?
     if (nullptr == fBMState || fBMState->pixmap().info().isEmpty()) {
index 814c79a92cdb68a01f5a1c39bac8b0ff05030434..b66299cbff469159987f55e061d7e6e0e66544aa 100644 (file)
@@ -25,7 +25,8 @@ typedef SkFixed3232    SkFractionalInt;
 class SkPaint;
 
 struct SkBitmapProcState {
-    SkBitmapProcState();
+    SkBitmapProcState(const SkBitmapProvider&, SkShader::TileMode tmx, SkShader::TileMode tmy);
+    SkBitmapProcState(const SkBitmap&, SkShader::TileMode tmx, SkShader::TileMode tmy);
     ~SkBitmapProcState();
 
     typedef void (*ShaderProc32)(const SkBitmapProcState&, int x, int y,
@@ -128,7 +129,7 @@ private:
     SampleProc32        fSampleProc32;      // chooseProcs
     SampleProc16        fSampleProc16;      // chooseProcs
 
-    SkBitmap            fOrigBitmap;        // CONSTRUCTOR
+    const SkBitmapProvider fProvider;
 
     enum {
         kBMStateSize = 136  // found by inspection. if too small, we will call new/delete
index 4ab233a82890c37ace8e9362a0976443a772d19d..2907dba7d57f816f273c9cc8fd2694805c14aeba 100644 (file)
@@ -664,24 +664,18 @@ SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec,
     }
 
     void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext);
-    SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcState;
+    SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcState(fDiffuseMap,
+                                              SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
     SkASSERT(diffuseState);
-
-    diffuseState->fTileModeX = SkShader::kClamp_TileMode;
-    diffuseState->fTileModeY = SkShader::kClamp_TileMode;
-    diffuseState->fOrigBitmap = fDiffuseMap;
     if (!diffuseState->chooseProcs(diffTotalInv, *rec.fPaint)) {
         diffuseState->~SkBitmapProcState();
         return nullptr;
     }
 
     void* normalStateStorage = (char*)storage + sizeof(LightingShaderContext) + sizeof(SkBitmapProcState);
-    SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState;
+    SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState(fNormalMap,
+                                            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
     SkASSERT(normalState);
-
-    normalState->fTileModeX = SkShader::kClamp_TileMode;
-    normalState->fTileModeY = SkShader::kClamp_TileMode;
-    normalState->fOrigBitmap = fNormalMap;
     if (!normalState->chooseProcs(normTotalInv, *rec.fPaint)) {
         diffuseState->~SkBitmapProcState();
         normalState->~SkBitmapProcState();