| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  * Copyright 2011 Google Inc. |    2  * Copyright 2011 Google Inc. | 
|    3  * |    3  * | 
|    4  * Use of this source code is governed by a BSD-style license that can be |    4  * Use of this source code is governed by a BSD-style license that can be | 
|    5  * found in the LICENSE file. |    5  * found in the LICENSE file. | 
|    6  */ |    6  */ | 
|    7  |    7  | 
|    8 #include "SkBitmapProcShader.h" |    8 #include "SkBitmapProcShader.h" | 
|    9 #include "SkBitmapProcState.h" |    9 #include "SkBitmapProcState.h" | 
|   10 #include "SkBitmapProvider.h" |   10 #include "SkBitmapProvider.h" | 
|   11 #include "SkColorPriv.h" |   11 #include "SkColorPriv.h" | 
|   12 #include "SkErrorInternals.h" |   12 #include "SkErrorInternals.h" | 
|   13 #include "SkPixelRef.h" |   13 #include "SkPixelRef.h" | 
|   14 #include "SkReadBuffer.h" |   14 #include "SkReadBuffer.h" | 
|   15 #include "SkWriteBuffer.h" |   15 #include "SkWriteBuffer.h" | 
|   16  |   16  | 
|   17 #if SK_SUPPORT_GPU |   17 #if SK_SUPPORT_GPU | 
|   18 #include "SkGrPriv.h" |   18 #include "SkGrPriv.h" | 
|   19 #include "effects/GrBicubicEffect.h" |   19 #include "effects/GrBicubicEffect.h" | 
|   20 #include "effects/GrSimpleTextureEffect.h" |   20 #include "effects/GrSimpleTextureEffect.h" | 
|   21 #endif |   21 #endif | 
|   22  |   22  | 
|   23 static bool only_scale_and_translate(const SkMatrix& matrix) { |   23 static bool only_scale_and_translate(const SkMatrix& matrix) { | 
|   24     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; |   24     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; | 
|   25     return (matrix.getType() & ~mask) == 0; |   25     return (matrix.getType() & ~mask) == 0; | 
|   26 } |   26 } | 
|   27  |   27  | 
|   28 class BitmapProcInfoContext : public SkShader::Context { |   28 class BitmapProcInfoContext : public SkShader::Context { | 
|   29 public: |   29 public: | 
|   30     // The context takes ownership of the info. It will call its destructor |   30     // The info has been allocated elsewhere, but we are responsible for calling
      its destructor. | 
|   31     // but will NOT free the memory. |  | 
|   32     BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& re
     c, |   31     BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& re
     c, | 
|   33                             SkBitmapProcInfo* info) |   32                             SkBitmapProcInfo* info) | 
|   34         : INHERITED(shader, rec) |   33         : INHERITED(shader, rec) | 
|   35         , fInfo(info) |   34         , fInfo(info) | 
|   36     { |   35     { | 
|   37         fFlags = 0; |   36         fFlags = 0; | 
|   38         if (fInfo->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) { |   37         if (fInfo->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) { | 
|   39             fFlags |= SkShader::kOpaqueAlpha_Flag; |   38             fFlags |= SkShader::kOpaqueAlpha_Flag; | 
|   40         } |   39         } | 
|   41  |   40  | 
|   42         if (1 == fInfo->fPixmap.height() && only_scale_and_translate(this->getTo
     talInverse())) { |   41         if (1 == fInfo->fPixmap.height() && only_scale_and_translate(this->getTo
     talInverse())) { | 
|   43             fFlags |= SkShader::kConstInY32_Flag; |   42             fFlags |= SkShader::kConstInY32_Flag; | 
|   44         } |   43         } | 
|   45     } |   44     } | 
|   46  |   45  | 
|   47     ~BitmapProcInfoContext() override { |   46     ~BitmapProcInfoContext() override { | 
|   48         // The bitmap proc state has been created outside of the context on memo
     ry that will be freed |  | 
|   49         // elsewhere. Only call the destructor but leave the freeing of the memo
     ry to the caller. |  | 
|   50         fInfo->~SkBitmapProcInfo(); |   47         fInfo->~SkBitmapProcInfo(); | 
|   51     } |   48     } | 
|   52      |   49      | 
|   53     uint32_t getFlags() const override { return fFlags; } |   50     uint32_t getFlags() const override { return fFlags; } | 
|   54  |   51  | 
|   55 private: |   52 private: | 
|   56     SkBitmapProcInfo*   fInfo; |   53     SkBitmapProcInfo*   fInfo; | 
|   57     uint32_t            fFlags; |   54     uint32_t            fFlags; | 
|   58  |   55  | 
|   59     typedef SkShader::Context INHERITED; |   56     typedef SkShader::Context INHERITED; | 
|   60 }; |   57 }; | 
|   61  |   58  | 
|   62 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// |   59 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// | 
|   63  |   60  | 
|   64 class BitmapProcShaderContext : public BitmapProcInfoContext { |   61 class BitmapProcShaderContext : public BitmapProcInfoContext { | 
|   65 public: |   62 public: | 
|   66     // The context takes ownership of the state. It will call its destructor |  | 
|   67     // but will NOT free the memory. |  | 
|   68     BitmapProcShaderContext(const SkShader& shader, const SkShader::ContextRec& 
     rec, |   63     BitmapProcShaderContext(const SkShader& shader, const SkShader::ContextRec& 
     rec, | 
|   69                             SkBitmapProcState* state) |   64                             SkBitmapProcState* state) | 
|   70         : INHERITED(shader, rec, state) |   65         : INHERITED(shader, rec, state) | 
|   71         , fState(state) |   66         , fState(state) | 
|   72     {} |   67     {} | 
|   73  |   68  | 
|   74     void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { |   69     void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { | 
|   75         const SkBitmapProcState& state = *fState; |   70         const SkBitmapProcState& state = *fState; | 
|   76         if (state.getShaderProc32()) { |   71         if (state.getShaderProc32()) { | 
|   77             state.getShaderProc32()(&state, x, y, dstC, count); |   72             state.getShaderProc32()(&state, x, y, dstC, count); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  109         return nullptr; |  104         return nullptr; | 
|  110     } |  105     } | 
|  111  |  106  | 
|  112 private: |  107 private: | 
|  113     SkBitmapProcState*  fState; |  108     SkBitmapProcState*  fState; | 
|  114  |  109  | 
|  115     typedef BitmapProcInfoContext INHERITED; |  110     typedef BitmapProcInfoContext INHERITED; | 
|  116 }; |  111 }; | 
|  117  |  112  | 
|  118 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// |  113 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// | 
 |  114 #include "SkLinearBitmapPipeline.h" | 
 |  115 #include "SkPM4f.h" | 
 |  116 #include "SkXfermode.h" | 
 |  117  | 
 |  118 class LinearPipelineContext : public BitmapProcInfoContext { | 
 |  119 public: | 
 |  120     LinearPipelineContext(const SkShader& shader, const SkShader::ContextRec& re
     c, | 
 |  121                           SkBitmapProcInfo* info) | 
 |  122         : INHERITED(shader, rec, info) | 
 |  123     { | 
 |  124         // Need to ensure that our pipeline is created at a 16byte aligned addre
     ss | 
 |  125         fPipeline = (SkLinearBitmapPipeline*)SkAlign16((intptr_t)fStorage); | 
 |  126         new (fPipeline) SkLinearBitmapPipeline(info->fInvMatrix, info->fFilterQu
     ality, | 
 |  127                                                info->fTileModeX, info->fTileMode
     Y, | 
 |  128                                                info->fPixmap); | 
 |  129  | 
 |  130         // To implement the old shadeSpan entry-point, we need to efficiently co
     nvert our native | 
 |  131         // floats into SkPMColor. The SkXfermode::D32Procs do exactly that. | 
 |  132         // | 
 |  133         sk_sp<SkXfermode> xfer(SkXfermode::Create(SkXfermode::kSrc_Mode)); | 
 |  134         fXferProc = SkXfermode::GetD32Proc(xfer.get(), 0); | 
 |  135     } | 
 |  136  | 
 |  137     ~LinearPipelineContext() override { | 
 |  138         // since we did a manual new, we need to manually destroy as well. | 
 |  139         fPipeline->~SkLinearBitmapPipeline(); | 
 |  140     } | 
 |  141  | 
 |  142     void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override { | 
 |  143         fPipeline->shadeSpan4f(x, y, dstC, count); | 
 |  144     } | 
 |  145  | 
 |  146     void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { | 
 |  147         const int N = 128; | 
 |  148         SkPM4f  tmp[N]; | 
 |  149  | 
 |  150         while (count > 0) { | 
 |  151             const int n = SkTMin(count, N); | 
 |  152             fPipeline->shadeSpan4f(x, y, tmp, n); | 
 |  153             fXferProc(nullptr, dstC, tmp, n, nullptr); | 
 |  154             dstC += n; | 
 |  155             x += n; | 
 |  156             count -= n; | 
 |  157         } | 
 |  158     } | 
 |  159  | 
 |  160 private: | 
 |  161     enum { | 
 |  162         kActualSize = sizeof(SkLinearBitmapPipeline), | 
 |  163         kPaddedSize = SkAlignPtr(kActualSize + 12), | 
 |  164     }; | 
 |  165     void* fStorage[kPaddedSize / sizeof(void*)]; | 
 |  166     SkLinearBitmapPipeline* fPipeline; | 
 |  167     SkXfermode::D32Proc     fXferProc; | 
 |  168  | 
 |  169     typedef BitmapProcInfoContext INHERITED; | 
 |  170 }; | 
 |  171  | 
 |  172 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// | 
|  119  |  173  | 
|  120 size_t SkBitmapProcShader::ContextSize(const ContextRec& rec) { |  174 static bool choose_linear_pipeline(const SkShader::ContextRec& rec, const SkImag
     eInfo& srcInfo) { | 
|  121     // The SkBitmapProcState is stored outside of the context object, with the c
     ontext holding |  175     // These src attributes are not supported in the new 4f context (yet) | 
|  122     // a pointer to it. |  176     // | 
|  123     return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); |  177     if (srcInfo.bytesPerPixel() < 4 || | 
 |  178         kRGBA_F16_SkColorType == srcInfo.colorType()) { | 
 |  179         return false; | 
 |  180     } | 
 |  181  | 
 |  182 #if 0   // later we may opt-in to the new code even if the client hasn't request
     ed it... | 
 |  183     // These src attributes are only supported in the new 4f context | 
 |  184     // | 
 |  185     if (srcInfo.isSRGB() || | 
 |  186         kUnpremul_SkAlphaType == srcInfo.alphaType() || | 
 |  187         (4 == srcInfo.bytesPerPixel() && kN32_SkColorType != srcInfo.colorType()
     )) | 
 |  188     { | 
 |  189         return true; | 
 |  190     } | 
 |  191 #endif | 
 |  192  | 
 |  193     // If we get here, we can reasonably use either context, respect the caller'
     s preference | 
 |  194     // | 
 |  195     return SkShader::ContextRec::kPM4f_DstType == rec.fPreferredDstType; | 
 |  196 } | 
 |  197  | 
 |  198 size_t SkBitmapProcShader::ContextSize(const ContextRec& rec, const SkImageInfo&
      srcInfo) { | 
 |  199     size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); | 
 |  200     size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo); | 
 |  201     return SkTMax(size0, size1); | 
|  124 } |  202 } | 
|  125  |  203  | 
|  126 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, |  204 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, | 
|  127                                                    TileMode tmx, TileMode tmy, |  205                                                    TileMode tmx, TileMode tmy, | 
|  128                                                    const SkBitmapProvider& provi
     der, |  206                                                    const SkBitmapProvider& provi
     der, | 
|  129                                                    const ContextRec& rec, void* 
     storage) { |  207                                                    const ContextRec& rec, void* 
     storage) { | 
|  130     SkMatrix totalInverse; |  208     SkMatrix totalInverse; | 
|  131     // Do this first, so we know the matrix can be inverted. |  209     // Do this first, so we know the matrix can be inverted. | 
|  132     if (!shader.computeTotalInverse(rec, &totalInverse)) { |  210     if (!shader.computeTotalInverse(rec, &totalInverse)) { | 
|  133         return nullptr; |  211         return nullptr; | 
|  134     } |  212     } | 
|  135  |  213  | 
|  136     void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); |  214     // Decide if we can/want to use the new linear pipeine | 
|  137     SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider, tm
     x, tmy); |  215     bool useLinearPipeline = choose_linear_pipeline(rec, provider.info()); | 
|  138  |  216  | 
|  139     SkASSERT(state); |  217     // New code doesn't support Mirror (YET), so we detect that here. | 
|  140     if (!state->setup(totalInverse, *rec.fPaint)) { |  218     // | 
|  141         state->~SkBitmapProcState(); |  219     if (SkShader::kMirror_TileMode == tmx || SkShader::kMirror_TileMode == tmy) 
     { | 
|  142         return nullptr; |  220         useLinearPipeline = false; | 
|  143     } |  221     } | 
|  144  |  222  | 
|  145     return new (storage) BitmapProcShaderContext(shader, rec, state); |  223     // New code doesn't support Mirror (YET), so we detect that here. | 
 |  224     // | 
 |  225     if (totalInverse.hasPerspective()) { | 
 |  226         useLinearPipeline = false; | 
 |  227     } | 
 |  228  | 
 |  229     if (useLinearPipeline) { | 
 |  230         void* infoStorage = (char*)storage + sizeof(LinearPipelineContext); | 
 |  231         SkBitmapProcInfo* info = new (infoStorage) SkBitmapProcInfo(provider, tm
     x, tmy); | 
 |  232         if (!info->init(totalInverse, *rec.fPaint)) { | 
 |  233             info->~SkBitmapProcInfo(); | 
 |  234             return nullptr; | 
 |  235         } | 
 |  236         return new (storage) LinearPipelineContext(shader, rec, info); | 
 |  237     } else { | 
 |  238         void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); | 
 |  239         SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider
     , tmx, tmy); | 
 |  240         if (!state->setup(totalInverse, *rec.fPaint)) { | 
 |  241             state->~SkBitmapProcState(); | 
 |  242             return nullptr; | 
 |  243         } | 
 |  244         return new (storage) BitmapProcShaderContext(shader, rec, state); | 
 |  245     } | 
|  146 } |  246 } | 
|  147  |  247  | 
|  148 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo
     id* storage) const { |  248 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo
     id* storage) const { | 
|  149     return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, |  249     return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, | 
|  150                        SkBitmapProvider(fRawBitmap), rec, storage); |  250                        SkBitmapProvider(fRawBitmap), rec, storage); | 
|  151 } |  251 } | 
|  152  |  252  | 
|  153 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// |  253 ////////////////////////////////////////////////////////////////////////////////
     /////////////////// | 
|  154  |  254  | 
|  155 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMo
     de tmy, |  255 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMo
     de tmy, | 
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  353         inner.reset(GrSimpleTextureEffect::Create(texture, matrix, params)); |  453         inner.reset(GrSimpleTextureEffect::Create(texture, matrix, params)); | 
|  354     } |  454     } | 
|  355  |  455  | 
|  356     if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { |  456     if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { | 
|  357         return GrFragmentProcessor::MulOutputByInputUnpremulColor(inner); |  457         return GrFragmentProcessor::MulOutputByInputUnpremulColor(inner); | 
|  358     } |  458     } | 
|  359     return GrFragmentProcessor::MulOutputByInputAlpha(inner); |  459     return GrFragmentProcessor::MulOutputByInputAlpha(inner); | 
|  360 } |  460 } | 
|  361  |  461  | 
|  362 #endif |  462 #endif | 
| OLD | NEW |