xref: /aosp_15_r20/external/skia/src/shaders/SkBitmapProcShader.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkBitmapProcShader.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBitmapProcState.h"
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
18*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
19*c8dee2aaSAndroid Build Coastguard Worker 
20*c8dee2aaSAndroid Build Coastguard Worker enum class SkTileMode;
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker class BitmapProcShaderContext : public SkShaderBase::Context {
23*c8dee2aaSAndroid Build Coastguard Worker public:
BitmapProcShaderContext(const SkShaderBase & shader,const SkShaderBase::ContextRec & rec,SkBitmapProcState * state)24*c8dee2aaSAndroid Build Coastguard Worker     BitmapProcShaderContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec,
25*c8dee2aaSAndroid Build Coastguard Worker                             SkBitmapProcState* state)
26*c8dee2aaSAndroid Build Coastguard Worker         : INHERITED(shader, rec)
27*c8dee2aaSAndroid Build Coastguard Worker         , fState(state)
28*c8dee2aaSAndroid Build Coastguard Worker         , fFlags(0)
29*c8dee2aaSAndroid Build Coastguard Worker     {
30*c8dee2aaSAndroid Build Coastguard Worker         if (fState->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) {
31*c8dee2aaSAndroid Build Coastguard Worker             fFlags |= SkShaderBase::kOpaqueAlpha_Flag;
32*c8dee2aaSAndroid Build Coastguard Worker         }
33*c8dee2aaSAndroid Build Coastguard Worker     }
34*c8dee2aaSAndroid Build Coastguard Worker 
getFlags() const35*c8dee2aaSAndroid Build Coastguard Worker     uint32_t getFlags() const override { return fFlags; }
36*c8dee2aaSAndroid Build Coastguard Worker 
shadeSpan(int x,int y,SkPMColor dstC[],int count)37*c8dee2aaSAndroid Build Coastguard Worker     void shadeSpan(int x, int y, SkPMColor dstC[], int count) override {
38*c8dee2aaSAndroid Build Coastguard Worker         const SkBitmapProcState& state = *fState;
39*c8dee2aaSAndroid Build Coastguard Worker         if (state.getShaderProc32()) {
40*c8dee2aaSAndroid Build Coastguard Worker             state.getShaderProc32()(&state, x, y, dstC, count);
41*c8dee2aaSAndroid Build Coastguard Worker             return;
42*c8dee2aaSAndroid Build Coastguard Worker         }
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker         const int BUF_MAX = 128;
45*c8dee2aaSAndroid Build Coastguard Worker         uint32_t buffer[BUF_MAX];
46*c8dee2aaSAndroid Build Coastguard Worker         SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
47*c8dee2aaSAndroid Build Coastguard Worker         SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
48*c8dee2aaSAndroid Build Coastguard Worker         const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(state.fPixmap.addr());
51*c8dee2aaSAndroid Build Coastguard Worker 
52*c8dee2aaSAndroid Build Coastguard Worker         for (;;) {
53*c8dee2aaSAndroid Build Coastguard Worker             int n = std::min(count, max);
54*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(n > 0 && n < BUF_MAX*2);
55*c8dee2aaSAndroid Build Coastguard Worker             mproc(state, buffer, n, x, y);
56*c8dee2aaSAndroid Build Coastguard Worker             sproc(state, buffer, n, dstC);
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker             if ((count -= n) == 0) {
59*c8dee2aaSAndroid Build Coastguard Worker                 break;
60*c8dee2aaSAndroid Build Coastguard Worker             }
61*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(count > 0);
62*c8dee2aaSAndroid Build Coastguard Worker             x += n;
63*c8dee2aaSAndroid Build Coastguard Worker             dstC += n;
64*c8dee2aaSAndroid Build Coastguard Worker         }
65*c8dee2aaSAndroid Build Coastguard Worker     }
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker private:
68*c8dee2aaSAndroid Build Coastguard Worker     SkBitmapProcState*  fState;
69*c8dee2aaSAndroid Build Coastguard Worker     uint32_t            fFlags;
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = SkShaderBase::Context;
72*c8dee2aaSAndroid Build Coastguard Worker };
73*c8dee2aaSAndroid Build Coastguard Worker 
74*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
75*c8dee2aaSAndroid Build Coastguard Worker 
MakeContext(const SkShaderBase & shader,SkTileMode tmx,SkTileMode tmy,const SkSamplingOptions & sampling,const SkImage_Base * image,const ContextRec & rec,SkArenaAlloc * alloc)76*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::Context* SkBitmapProcLegacyShader::MakeContext(
77*c8dee2aaSAndroid Build Coastguard Worker     const SkShaderBase& shader, SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling,
78*c8dee2aaSAndroid Build Coastguard Worker     const SkImage_Base* image, const ContextRec& rec, SkArenaAlloc* alloc)
79*c8dee2aaSAndroid Build Coastguard Worker {
80*c8dee2aaSAndroid Build Coastguard Worker     SkMatrix totalInverse;
81*c8dee2aaSAndroid Build Coastguard Worker     // Do this first, so we know the matrix can be inverted.
82*c8dee2aaSAndroid Build Coastguard Worker     if (!rec.fMatrixRec.totalInverse(&totalInverse)) {
83*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
84*c8dee2aaSAndroid Build Coastguard Worker     }
85*c8dee2aaSAndroid Build Coastguard Worker 
86*c8dee2aaSAndroid Build Coastguard Worker     SkBitmapProcState* state = alloc->make<SkBitmapProcState>(image, tmx, tmy);
87*c8dee2aaSAndroid Build Coastguard Worker     if (!state->setup(totalInverse, rec.fPaintAlpha, sampling)) {
88*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
89*c8dee2aaSAndroid Build Coastguard Worker     }
90*c8dee2aaSAndroid Build Coastguard Worker     return alloc->make<BitmapProcShaderContext>(shader, rec, state);
91*c8dee2aaSAndroid Build Coastguard Worker }
92