blob: 9e45bb7b5eac5192516f4ab4a5deff7780c68cb7 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
bungemanf3c15b72015-08-19 11:56:48 -07007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/shaders/SkBitmapProcShader.h"
Herb Derby83e939b2017-02-07 14:25:11 -05009
Ben Wagner729a23f2019-05-17 16:29:34 -040010#include "src/core/SkArenaAlloc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/core/SkBitmapProcState.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/core/SkXfermodePriv.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013
Mike Kleinfaa844b2020-08-26 14:32:45 -050014class BitmapProcShaderContext : public SkShaderBase::Context {
reed05a56472016-03-02 09:49:02 -080015public:
Mike Kleinfaa844b2020-08-26 14:32:45 -050016 BitmapProcShaderContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec,
17 SkBitmapProcState* state)
reed05a56472016-03-02 09:49:02 -080018 : INHERITED(shader, rec)
Mike Kleinfaa844b2020-08-26 14:32:45 -050019 , fState(state)
20 , fFlags(0)
reed05a56472016-03-02 09:49:02 -080021 {
Mike Kleinfaa844b2020-08-26 14:32:45 -050022 if (fState->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) {
Florin Malita4aed1382017-05-25 10:38:07 -040023 fFlags |= SkShaderBase::kOpaqueAlpha_Flag;
reed05a56472016-03-02 09:49:02 -080024 }
25
Mike Kleinfaa844b2020-08-26 14:32:45 -050026 auto only_scale_and_translate = [](const SkMatrix& matrix) {
27 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
28 return (matrix.getType() & ~mask) == 0;
29 };
30
31 if (1 == fState->fPixmap.height() && only_scale_and_translate(this->getTotalInverse())) {
Florin Malita4aed1382017-05-25 10:38:07 -040032 fFlags |= SkShaderBase::kConstInY32_Flag;
reed05a56472016-03-02 09:49:02 -080033 }
34 }
35
reed05a56472016-03-02 09:49:02 -080036 uint32_t getFlags() const override { return fFlags; }
37
reed05a56472016-03-02 09:49:02 -080038 void shadeSpan(int x, int y, SkPMColor dstC[], int count) override {
39 const SkBitmapProcState& state = *fState;
40 if (state.getShaderProc32()) {
41 state.getShaderProc32()(&state, x, y, dstC, count);
42 return;
43 }
44
45 const int BUF_MAX = 128;
46 uint32_t buffer[BUF_MAX];
47 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc();
48 SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
49 const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
50
51 SkASSERT(state.fPixmap.addr());
52
53 for (;;) {
Brian Osman788b9162020-02-07 10:36:46 -050054 int n = std::min(count, max);
reed05a56472016-03-02 09:49:02 -080055 SkASSERT(n > 0 && n < BUF_MAX*2);
56 mproc(state, buffer, n, x, y);
57 sproc(state, buffer, n, dstC);
58
59 if ((count -= n) == 0) {
60 break;
61 }
62 SkASSERT(count > 0);
63 x += n;
64 dstC += n;
65 }
66 }
67
reed05a56472016-03-02 09:49:02 -080068private:
69 SkBitmapProcState* fState;
Mike Kleinfaa844b2020-08-26 14:32:45 -050070 uint32_t fFlags;
reed05a56472016-03-02 09:49:02 -080071
John Stiles7571f9e2020-09-02 22:42:33 -040072 using INHERITED = SkShaderBase::Context;
reed05a56472016-03-02 09:49:02 -080073};
74
75///////////////////////////////////////////////////////////////////////////////////////////////////
reed7a4d8472015-09-15 13:33:58 -070076
Florin Malita4aed1382017-05-25 10:38:07 -040077SkShaderBase::Context* SkBitmapProcLegacyShader::MakeContext(
Mike Reedfae8fce2019-04-03 10:27:45 -040078 const SkShaderBase& shader, SkTileMode tmx, SkTileMode tmy,
Mike Reed64acf4f2019-08-01 15:35:20 -040079 const SkImage_Base* image, const ContextRec& rec, SkArenaAlloc* alloc)
Herb Derby83e939b2017-02-07 14:25:11 -050080{
reed05a56472016-03-02 09:49:02 -080081 SkMatrix totalInverse;
82 // Do this first, so we know the matrix can be inverted.
Florin Malita26368c32017-05-08 13:03:24 -040083 if (!shader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &totalInverse)) {
reed05a56472016-03-02 09:49:02 -080084 return nullptr;
85 }
86
Mike Reed64acf4f2019-08-01 15:35:20 -040087 SkBitmapProcState* state = alloc->make<SkBitmapProcState>(image, tmx, tmy);
Mike Klein0fddb2d2017-07-20 08:59:19 -040088 if (!state->setup(totalInverse, *rec.fPaint)) {
89 return nullptr;
Mike Reedfb499092017-06-26 13:53:32 +000090 }
Mike Klein0fddb2d2017-07-20 08:59:19 -040091 return alloc->make<BitmapProcShaderContext>(shader, rec, state);
reed05a56472016-03-02 09:49:02 -080092}