Make an embeddable container to hold linear pipelines.
authorherb <herb@google.com>
Thu, 19 May 2016 21:19:23 +0000 (14:19 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 19 May 2016 21:19:23 +0000 (14:19 -0700)
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1998793002

Review-Url: https://codereview.chromium.org/1998793002

src/core/SkBitmapProcShader.cpp
src/core/SkLinearBitmapPipeline.cpp
src/core/SkLinearBitmapPipeline.h

index ae973a2a5902c31d7aa06158be1edb7652e8cc3c..a372b5199041d9c608d608ecac302ae8f24aced6 100644 (file)
@@ -129,12 +129,11 @@ public:
         fFilterQuality = info->fFilterQuality;
         fMatrixTypeMask = info->fRealInvMatrix.getType();
 
-        // Need to ensure that our pipeline is created at a 16byte aligned address
-        fShaderPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fShaderStorage);
-        new (fShaderPipeline) SkLinearBitmapPipeline(info->fRealInvMatrix, info->fFilterQuality,
-                                                     info->fTileModeX, info->fTileModeY,
-                                                     info->fPaintColor,
-                                                     info->fPixmap);
+        fShaderPipeline.init(
+            info->fRealInvMatrix, info->fFilterQuality,
+            info->fTileModeX, info->fTileModeY,
+            info->fPaintColor,
+            info->fPixmap);
 
         // To implement the old shadeSpan entry-point, we need to efficiently convert our native
         // floats into SkPMColor. The SkXfermode::D32Procs do exactly that.
@@ -143,14 +142,6 @@ public:
         fXferProc = SkXfermode::GetD32Proc(xfer.get(), 0);
     }
 
-    ~LinearPipelineContext() override {
-        // since we did a manual new, we need to manually destroy as well.
-        fShaderPipeline->~SkLinearBitmapPipeline();
-        if (fBlitterPipeline != nullptr) {
-            fBlitterPipeline->~SkLinearBitmapPipeline();
-        }
-    }
-
     void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override {
         fShaderPipeline->shadeSpan4f(x, y, dstC, count);
     }
@@ -173,23 +164,19 @@ public:
         SkXfermode::Mode mode;
         if (!SkXfermode::AsMode(state->fXfer, &mode)) { return false; }
 
-        // Need to ensure that our pipeline is created at a 16byte aligned address
-        fBlitterPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fBlitterStorage);
         if (SkLinearBitmapPipeline::ClonePipelineForBlitting(
-            fBlitterPipeline, *fShaderPipeline,
+            &fBlitterPipeline, *fShaderPipeline,
             fMatrixTypeMask,
             fXMode, fYMode,
             fFilterQuality, fSrcPixmap,
             fAlpha, mode, dstInfo))
         {
-            state->fStorage[0] = fBlitterPipeline;
+            state->fStorage[0] = fBlitterPipeline.get();
             state->fBlitBW = &LinearPipelineContext::ForwardToPipeline;
 
             return true;
         }
 
-        // Did not successfully create a pipeline so don't destruct it.
-        fBlitterPipeline = nullptr;
         return false;
     }
 
@@ -199,23 +186,16 @@ public:
         pipeline->blitSpan(x, y, addr, count);
     }
 
-
 private:
-    enum {
-        kActualSize = sizeof(SkLinearBitmapPipeline),
-        kPaddedSize = SkAlignPtr(kActualSize + 12),
-    };
-    void* fShaderStorage[kPaddedSize / sizeof(void*)];
-    SkLinearBitmapPipeline* fShaderPipeline;
-    void* fBlitterStorage[kPaddedSize / sizeof(void*)];
-    SkLinearBitmapPipeline* fBlitterPipeline{nullptr};
-    SkXfermode::D32Proc     fXferProc;
-    SkPixmap                fSrcPixmap;
-    float                   fAlpha;
-    SkShader::TileMode      fXMode;
-    SkShader::TileMode      fYMode;
-    SkMatrix::TypeMask      fMatrixTypeMask;
-    SkFilterQuality         fFilterQuality;
+    SkEmbeddableLinearPipeline fShaderPipeline;
+    SkEmbeddableLinearPipeline fBlitterPipeline;
+    SkXfermode::D32Proc        fXferProc;
+    SkPixmap                   fSrcPixmap;
+    float                      fAlpha;
+    SkShader::TileMode         fXMode;
+    SkShader::TileMode         fYMode;
+    SkMatrix::TypeMask         fMatrixTypeMask;
+    SkFilterQuality            fFilterQuality;
 
     typedef BitmapProcInfoContext INHERITED;
 };
index dfc9aa83762f926d802cfd5744d035f39c508906..7cdeaac5ffa4babfdbb71b27da536b08ca069670 100644 (file)
@@ -891,7 +891,7 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline(
 }
 
 bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
-    void* blitterStorage,
+    SkEmbeddableLinearPipeline* pipelineStorage,
     const SkLinearBitmapPipeline& pipeline,
     SkMatrix::TypeMask matrixMask,
     SkShader::TileMode xTileMode,
@@ -920,7 +920,7 @@ bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
         return false;
     }
 
-    new (blitterStorage) SkLinearBitmapPipeline(pipeline, srcPixmap, xferMode, dstInfo);
+    pipelineStorage->init(pipeline, srcPixmap, xferMode, dstInfo);
 
     return true;
 }
index 853e56fd1b2f9b4d4439085eaa36fad01d4f7774..dce537aa6e6aa90f27f52667e468ee27a712a91a 100644 (file)
 #include "SkMatrix.h"
 #include "SkShader.h"
 
+class SkEmbeddableLinearPipeline;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// SkLinearBitmapPipeline - encapsulates all the machinery for doing floating point pixel
+// processing in a linear color space.
+// Note: this class has unusual alignment requirements due to its use of SIMD instructions. The
+// class SkEmbeddableLinearPipeline below manages these requirements.
 class SkLinearBitmapPipeline {
 public:
     SkLinearBitmapPipeline(
@@ -22,10 +29,14 @@ public:
         SkColor paintColor,
         const SkPixmap& srcPixmap);
 
-
+    SkLinearBitmapPipeline(
+        const SkLinearBitmapPipeline& pipeline,
+        const SkPixmap& srcPixmap,
+        SkXfermode::Mode xferMode,
+        const SkImageInfo& dstInfo);
 
     static bool ClonePipelineForBlitting(
-        void* blitterStorage,
+        SkEmbeddableLinearPipeline* pipelineStorage,
         const SkLinearBitmapPipeline& pipeline,
         SkMatrix::TypeMask matrixMask,
         SkShader::TileMode xTileMode,
@@ -87,12 +98,6 @@ public:
     using BlenderStage = Stage<BlendProcessorInterface,   40>;
 
 private:
-    SkLinearBitmapPipeline(
-        const SkLinearBitmapPipeline& pipeline,
-        const SkPixmap& srcPixmap,
-        SkXfermode::Mode xferMode,
-        const SkImageInfo& dstInfo);
-
     PointProcessorInterface* fFirstStage;
     MatrixStage              fMatrixStage;
     TileStage                fTileStage;
@@ -101,4 +106,35 @@ private:
     DestinationInterface*    fLastStage;
 };
 
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// SkEmbeddableLinearPipeline - manage stricter alignment needs for SkLinearBitmapPipeline.
+class SkEmbeddableLinearPipeline {
+public:
+    SkEmbeddableLinearPipeline() { }
+    ~SkEmbeddableLinearPipeline() {
+        if (get() != nullptr) {
+            get()->~SkLinearBitmapPipeline();
+        }
+    }
+
+    template <typename... Args>
+    void init(Args&&... args) {
+        // Ensure that our pipeline is created at a 16 byte aligned address.
+        fPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fPipelineStorage);
+        new (fPipeline) SkLinearBitmapPipeline{std::forward<Args>(args)...};
+    }
+
+    SkLinearBitmapPipeline* get()        const { return fPipeline;    }
+    SkLinearBitmapPipeline& operator*()  const { return *this->get(); }
+    SkLinearBitmapPipeline* operator->() const { return  this->get(); }
+
+private:
+    enum {
+        kActualSize = sizeof(SkLinearBitmapPipeline),
+        kPaddedSize = SkAlignPtr(kActualSize + 12),
+    };
+    void* fPipelineStorage[kPaddedSize / sizeof(void*)];
+    SkLinearBitmapPipeline* fPipeline{nullptr};
+};
+
 #endif  // SkLinearBitmapPipeline_DEFINED