LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkBitmapProcShader.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 55 102 53.9 %
Date: 2017-07-14 16:53:18 Functions: 10 20 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "SkBitmapProcShader.h"
       9             : 
      10             : #include "SkArenaAlloc.h"
      11             : #include "SkBitmapProcState.h"
      12             : #include "SkBitmapProvider.h"
      13             : #include "SkXfermodePriv.h"
      14             : 
      15          17 : static bool only_scale_and_translate(const SkMatrix& matrix) {
      16          17 :     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
      17          17 :     return (matrix.getType() & ~mask) == 0;
      18             : }
      19             : 
      20         141 : class BitmapProcInfoContext : public SkShader::Context {
      21             : public:
      22             :     // The info has been allocated elsewhere, but we are responsible for calling its destructor.
      23         141 :     BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& rec,
      24             :                             SkBitmapProcInfo* info)
      25         141 :         : INHERITED(shader, rec)
      26         141 :         , fInfo(info)
      27             :     {
      28         141 :         fFlags = 0;
      29         141 :         if (fInfo->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) {
      30          29 :             fFlags |= SkShader::kOpaqueAlpha_Flag;
      31             :         }
      32             : 
      33         141 :         if (1 == fInfo->fPixmap.height() && only_scale_and_translate(this->getTotalInverse())) {
      34          17 :             fFlags |= SkShader::kConstInY32_Flag;
      35             :         }
      36         141 :     }
      37             : 
      38        2337 :     uint32_t getFlags() const override { return fFlags; }
      39             : 
      40             : private:
      41             :     SkBitmapProcInfo*   fInfo;
      42             :     uint32_t            fFlags;
      43             : 
      44             :     typedef SkShader::Context INHERITED;
      45             : };
      46             : 
      47             : ///////////////////////////////////////////////////////////////////////////////////////////////////
      48             : 
      49         141 : class BitmapProcShaderContext : public BitmapProcInfoContext {
      50             : public:
      51         141 :     BitmapProcShaderContext(const SkShader& shader, const SkShader::ContextRec& rec,
      52             :                             SkBitmapProcState* state)
      53         141 :         : INHERITED(shader, rec, state)
      54         141 :         , fState(state)
      55         141 :     {}
      56             : 
      57        4790 :     void shadeSpan(int x, int y, SkPMColor dstC[], int count) override {
      58        4790 :         const SkBitmapProcState& state = *fState;
      59        4790 :         if (state.getShaderProc32()) {
      60        2936 :             state.getShaderProc32()(&state, x, y, dstC, count);
      61        2936 :             return;
      62             :         }
      63             : 
      64        1854 :         const int BUF_MAX = 128;
      65             :         uint32_t buffer[BUF_MAX];
      66        1854 :         SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
      67        1854 :         SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
      68        1854 :         const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
      69             : 
      70        1854 :         SkASSERT(state.fPixmap.addr());
      71             : 
      72             :         for (;;) {
      73        2070 :             int n = SkTMin(count, max);
      74        2070 :             SkASSERT(n > 0 && n < BUF_MAX*2);
      75        2070 :             mproc(state, buffer, n, x, y);
      76        2070 :             sproc(state, buffer, n, dstC);
      77             : 
      78        2070 :             if ((count -= n) == 0) {
      79        1854 :                 break;
      80             :             }
      81         216 :             SkASSERT(count > 0);
      82         216 :             x += n;
      83         216 :             dstC += n;
      84         216 :         }
      85             :     }
      86             : 
      87          47 :     ShadeProc asAShadeProc(void** ctx) override {
      88          47 :         if (fState->getShaderProc32()) {
      89          47 :             *ctx = fState;
      90          47 :             return (ShadeProc)fState->getShaderProc32();
      91             :         }
      92           0 :         return nullptr;
      93             :     }
      94             : 
      95             : private:
      96             :     SkBitmapProcState*  fState;
      97             : 
      98             :     typedef BitmapProcInfoContext INHERITED;
      99             : };
     100             : 
     101             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     102             : #include "SkLinearBitmapPipeline.h"
     103             : #include "SkPM4f.h"
     104             : 
     105           0 : class LinearPipelineContext : public BitmapProcInfoContext {
     106             : public:
     107           0 :     LinearPipelineContext(const SkShader& shader, const SkShader::ContextRec& rec,
     108             :                           SkBitmapProcInfo* info, SkArenaAlloc* alloc)
     109           0 :         : INHERITED(shader, rec, info), fAllocator{alloc}
     110             :     {
     111             :         // Save things off in case we need to build a blitter pipeline.
     112           0 :         fSrcPixmap = info->fPixmap;
     113           0 :         fAlpha = SkColorGetA(info->fPaintColor) / 255.0f;
     114           0 :         fFilterQuality = info->fFilterQuality;
     115           0 :         fMatrixTypeMask = info->fRealInvMatrix.getType();
     116             : 
     117           0 :         fShaderPipeline = alloc->make<SkLinearBitmapPipeline>(
     118             :             info->fRealInvMatrix, info->fFilterQuality,
     119             :             info->fTileModeX, info->fTileModeY,
     120             :             info->fPaintColor,
     121             :             info->fPixmap,
     122             :             fAllocator);
     123             : 
     124             :         // To implement the old shadeSpan entry-point, we need to efficiently convert our native
     125             :         // floats into SkPMColor. The SkXfermode::D32Procs do exactly that.
     126             :         //
     127           0 :         fSrcModeProc = SkXfermode::GetD32Proc(SkBlendMode::kSrc, 0);
     128           0 :     }
     129             : 
     130           0 :     void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override {
     131           0 :         fShaderPipeline->shadeSpan4f(x, y, dstC, count);
     132           0 :     }
     133             : 
     134           0 :     void shadeSpan(int x, int y, SkPMColor dstC[], int count) override {
     135           0 :         const int N = 128;
     136             :         SkPM4f  tmp[N];
     137             : 
     138           0 :         while (count > 0) {
     139           0 :             const int n = SkTMin(count, N);
     140           0 :             fShaderPipeline->shadeSpan4f(x, y, tmp, n);
     141           0 :             fSrcModeProc(SkBlendMode::kSrc, dstC, tmp, n, nullptr);
     142           0 :             dstC += n;
     143           0 :             x += n;
     144           0 :             count -= n;
     145             :         }
     146           0 :     }
     147             : 
     148           0 :     bool onChooseBlitProcs(const SkImageInfo& dstInfo, BlitState* state) override {
     149           0 :         if ((fBlitterPipeline = SkLinearBitmapPipeline::ClonePipelineForBlitting(
     150           0 :             *fShaderPipeline,
     151             :             fMatrixTypeMask,
     152             :             fFilterQuality, fSrcPixmap,
     153             :             fAlpha, state->fMode, dstInfo, fAllocator)))
     154             :         {
     155           0 :             state->fStorage[0] = fBlitterPipeline;
     156           0 :             state->fBlitBW = &LinearPipelineContext::ForwardToPipeline;
     157             : 
     158           0 :             return true;
     159             :         }
     160             : 
     161           0 :         return false;
     162             :     }
     163             : 
     164           0 :     static void ForwardToPipeline(BlitState* state, int x, int y, const SkPixmap& dst, int count) {
     165           0 :         SkLinearBitmapPipeline* pipeline = static_cast<SkLinearBitmapPipeline*>(state->fStorage[0]);
     166           0 :         void* addr = dst.writable_addr32(x, y);
     167           0 :         pipeline->blitSpan(x, y, addr, count);
     168           0 :     }
     169             : 
     170             : private:
     171             :     // Store the allocator from the context creation incase we are asked to build a blitter.
     172             :     SkArenaAlloc*           fAllocator;
     173             :     SkLinearBitmapPipeline* fShaderPipeline;
     174             :     SkLinearBitmapPipeline* fBlitterPipeline;
     175             :     SkXfermode::D32Proc     fSrcModeProc;
     176             :     SkPixmap                fSrcPixmap;
     177             :     float                   fAlpha;
     178             :     SkMatrix::TypeMask      fMatrixTypeMask;
     179             :     SkFilterQuality         fFilterQuality;
     180             : 
     181             :     typedef BitmapProcInfoContext INHERITED;
     182             : };
     183             : 
     184             : ///////////////////////////////////////////////////////////////////////////////////////////////////
     185             : 
     186         141 : static bool choose_linear_pipeline(const SkShader::ContextRec& rec, const SkImageInfo& srcInfo) {
     187             :     // If we get here, we can reasonably use either context, respect the caller's preference
     188             :     //
     189         141 :     bool needsPremul = srcInfo.alphaType() == kUnpremul_SkAlphaType;
     190         141 :     bool needsSwizzle = srcInfo.bytesPerPixel() == 4 && srcInfo.colorType() != kN32_SkColorType;
     191         141 :     return SkShader::ContextRec::kPM4f_DstType == rec.fPreferredDstType
     192         141 :            || needsPremul || needsSwizzle;
     193             : }
     194             : 
     195           0 : size_t SkBitmapProcLegacyShader::ContextSize(const ContextRec& rec, const SkImageInfo& srcInfo) {
     196           0 :     size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
     197           0 :     size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo);
     198           0 :     size_t s = SkTMax(size0, size1);
     199           0 :     return s;
     200             : }
     201             : 
     202         141 : SkShader::Context* SkBitmapProcLegacyShader::MakeContext(
     203             :     const SkShader& shader, TileMode tmx, TileMode tmy,
     204             :     const SkBitmapProvider& provider, const ContextRec& rec, SkArenaAlloc* alloc)
     205             : {
     206             :     SkMatrix totalInverse;
     207             :     // Do this first, so we know the matrix can be inverted.
     208         141 :     if (!shader.computeTotalInverse(rec, &totalInverse)) {
     209           0 :         return nullptr;
     210             :     }
     211             : 
     212             :     // Decide if we can/want to use the new linear pipeline
     213         141 :     bool useLinearPipeline = choose_linear_pipeline(rec, provider.info());
     214             : 
     215         141 :     if (useLinearPipeline) {
     216           0 :         SkBitmapProcInfo* info = alloc->make<SkBitmapProcInfo>(provider, tmx, tmy);
     217           0 :         if (!info->init(totalInverse, *rec.fPaint)) {
     218           0 :             return nullptr;
     219             :         }
     220             : 
     221           0 :         return alloc->make<LinearPipelineContext>(shader, rec, info, alloc);
     222             :     } else {
     223         141 :         SkBitmapProcState* state = alloc->make<SkBitmapProcState>(provider, tmx, tmy);
     224         141 :         if (!state->setup(totalInverse, *rec.fPaint)) {
     225           0 :             return nullptr;
     226             :         }
     227         141 :         return alloc->make<BitmapProcShaderContext>(shader, rec, state);
     228             :     }
     229             : }

Generated by: LCOV version 1.13