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 size_t SkBitmapProcShader::ContextSize() { | 23 static bool only_scale_and_translate(const SkMatrix& matrix) { |
| 24 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; |
| 25 return (matrix.getType() & ~mask) == 0; |
| 26 } |
| 27 |
| 28 class BitmapProcInfoContext : public SkShader::Context { |
| 29 public: |
| 30 // The context takes ownership of the info. It will call its destructor |
| 31 // but will NOT free the memory. |
| 32 BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& re
c, |
| 33 SkBitmapProcInfo* info) |
| 34 : INHERITED(shader, rec) |
| 35 , fInfo(info) |
| 36 { |
| 37 fFlags = 0; |
| 38 if (fInfo->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) { |
| 39 fFlags |= SkShader::kOpaqueAlpha_Flag; |
| 40 } |
| 41 |
| 42 if (1 == fInfo->fPixmap.height() && only_scale_and_translate(this->getTo
talInverse())) { |
| 43 fFlags |= SkShader::kConstInY32_Flag; |
| 44 } |
| 45 } |
| 46 |
| 47 ~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(); |
| 51 } |
| 52 |
| 53 uint32_t getFlags() const override { return fFlags; } |
| 54 |
| 55 private: |
| 56 SkBitmapProcInfo* fInfo; |
| 57 uint32_t fFlags; |
| 58 |
| 59 typedef SkShader::Context INHERITED; |
| 60 }; |
| 61 |
| 62 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 63 |
| 64 class BitmapProcShaderContext : public BitmapProcInfoContext { |
| 65 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, |
| 69 SkBitmapProcState* state) |
| 70 : INHERITED(shader, rec, state) |
| 71 , fState(state) |
| 72 {} |
| 73 |
| 74 void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { |
| 75 const SkBitmapProcState& state = *fState; |
| 76 if (state.getShaderProc32()) { |
| 77 state.getShaderProc32()(&state, x, y, dstC, count); |
| 78 return; |
| 79 } |
| 80 |
| 81 const int BUF_MAX = 128; |
| 82 uint32_t buffer[BUF_MAX]; |
| 83 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); |
| 84 SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32(); |
| 85 const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX)
; |
| 86 |
| 87 SkASSERT(state.fPixmap.addr()); |
| 88 |
| 89 for (;;) { |
| 90 int n = SkTMin(count, max); |
| 91 SkASSERT(n > 0 && n < BUF_MAX*2); |
| 92 mproc(state, buffer, n, x, y); |
| 93 sproc(state, buffer, n, dstC); |
| 94 |
| 95 if ((count -= n) == 0) { |
| 96 break; |
| 97 } |
| 98 SkASSERT(count > 0); |
| 99 x += n; |
| 100 dstC += n; |
| 101 } |
| 102 } |
| 103 |
| 104 ShadeProc asAShadeProc(void** ctx) override { |
| 105 if (fState->getShaderProc32()) { |
| 106 *ctx = fState; |
| 107 return (ShadeProc)fState->getShaderProc32(); |
| 108 } |
| 109 return nullptr; |
| 110 } |
| 111 |
| 112 private: |
| 113 SkBitmapProcState* fState; |
| 114 |
| 115 typedef BitmapProcInfoContext INHERITED; |
| 116 }; |
| 117 |
| 118 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 119 |
| 120 size_t SkBitmapProcShader::ContextSize(const ContextRec& rec) { |
24 // The SkBitmapProcState is stored outside of the context object, with the c
ontext holding | 121 // The SkBitmapProcState is stored outside of the context object, with the c
ontext holding |
25 // a pointer to it. | 122 // a pointer to it. |
26 return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); | 123 return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); |
27 } | 124 } |
28 | 125 |
29 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMo
de tmy, | |
30 const SkMatrix* localMatrix) | |
31 : INHERITED(localMatrix) { | |
32 fRawBitmap = src; | |
33 fTileModeX = (uint8_t)tmx; | |
34 fTileModeY = (uint8_t)tmy; | |
35 } | |
36 | |
37 bool SkBitmapProcShader::onIsABitmap(SkBitmap* texture, SkMatrix* texM, TileMode
xy[]) const { | |
38 if (texture) { | |
39 *texture = fRawBitmap; | |
40 } | |
41 if (texM) { | |
42 texM->reset(); | |
43 } | |
44 if (xy) { | |
45 xy[0] = (TileMode)fTileModeX; | |
46 xy[1] = (TileMode)fTileModeY; | |
47 } | |
48 return true; | |
49 } | |
50 | |
51 SkFlattenable* SkBitmapProcShader::CreateProc(SkReadBuffer& buffer) { | |
52 SkMatrix lm; | |
53 buffer.readMatrix(&lm); | |
54 SkBitmap bm; | |
55 if (!buffer.readBitmap(&bm)) { | |
56 return nullptr; | |
57 } | |
58 bm.setImmutable(); | |
59 TileMode mx = (TileMode)buffer.readUInt(); | |
60 TileMode my = (TileMode)buffer.readUInt(); | |
61 return SkShader::CreateBitmapShader(bm, mx, my, &lm); | |
62 } | |
63 | |
64 void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const { | |
65 buffer.writeMatrix(this->getLocalMatrix()); | |
66 buffer.writeBitmap(fRawBitmap); | |
67 buffer.writeUInt(fTileModeX); | |
68 buffer.writeUInt(fTileModeY); | |
69 } | |
70 | |
71 bool SkBitmapProcShader::isOpaque() const { | |
72 return fRawBitmap.isOpaque(); | |
73 } | |
74 | |
75 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, | 126 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, |
76 TileMode tmx, TileMode tmy, | 127 TileMode tmx, TileMode tmy, |
77 const SkBitmapProvider& provi
der, | 128 const SkBitmapProvider& provi
der, |
78 const ContextRec& rec, void*
storage) { | 129 const ContextRec& rec, void*
storage) { |
79 SkMatrix totalInverse; | 130 SkMatrix totalInverse; |
80 // Do this first, so we know the matrix can be inverted. | 131 // Do this first, so we know the matrix can be inverted. |
81 if (!shader.computeTotalInverse(rec, &totalInverse)) { | 132 if (!shader.computeTotalInverse(rec, &totalInverse)) { |
82 return nullptr; | 133 return nullptr; |
83 } | 134 } |
84 | 135 |
85 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); | 136 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); |
86 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider, tm
x, tmy); | 137 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider, tm
x, tmy); |
87 | 138 |
88 SkASSERT(state); | 139 SkASSERT(state); |
89 if (!state->chooseProcs(totalInverse, *rec.fPaint)) { | 140 if (!state->setup(totalInverse, *rec.fPaint)) { |
90 state->~SkBitmapProcState(); | 141 state->~SkBitmapProcState(); |
91 return nullptr; | 142 return nullptr; |
92 } | 143 } |
93 | 144 |
94 return new (storage) BitmapProcShaderContext(shader, rec, state); | 145 return new (storage) BitmapProcShaderContext(shader, rec, state); |
95 } | 146 } |
96 | 147 |
97 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo
id* storage) const { | 148 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo
id* storage) const { |
98 return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, | 149 return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, |
99 SkBitmapProvider(fRawBitmap), rec, storage); | 150 SkBitmapProvider(fRawBitmap), rec, storage); |
100 } | 151 } |
101 | 152 |
102 static bool only_scale_and_translate(const SkMatrix& matrix) { | 153 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
103 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; | 154 |
104 return (matrix.getType() & ~mask) == 0; | 155 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMo
de tmy, |
| 156 const SkMatrix* localMatrix) |
| 157 : INHERITED(localMatrix) { |
| 158 fRawBitmap = src; |
| 159 fTileModeX = (uint8_t)tmx; |
| 160 fTileModeY = (uint8_t)tmy; |
105 } | 161 } |
106 | 162 |
107 SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(const SkSha
der& shader, | 163 bool SkBitmapProcShader::onIsABitmap(SkBitmap* texture, SkMatrix* texM, TileMode
xy[]) const { |
108 const Conte
xtRec& rec, | 164 if (texture) { |
109 SkBitmapPro
cState* state) | 165 *texture = fRawBitmap; |
110 : INHERITED(shader, rec) | |
111 , fState(state) | |
112 { | |
113 fFlags = 0; | |
114 if (fState->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) { | |
115 fFlags |= kOpaqueAlpha_Flag; | |
116 } | 166 } |
117 | 167 if (texM) { |
118 if (1 == fState->fPixmap.height() && only_scale_and_translate(this->getTotal
Inverse())) { | 168 texM->reset(); |
119 fFlags |= kConstInY32_Flag; | |
120 } | 169 } |
| 170 if (xy) { |
| 171 xy[0] = (TileMode)fTileModeX; |
| 172 xy[1] = (TileMode)fTileModeY; |
| 173 } |
| 174 return true; |
121 } | 175 } |
122 | 176 |
123 SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() { | 177 SkFlattenable* SkBitmapProcShader::CreateProc(SkReadBuffer& buffer) { |
124 // The bitmap proc state has been created outside of the context on memory t
hat will be freed | 178 SkMatrix lm; |
125 // elsewhere. Only call the destructor but leave the freeing of the memory t
o the caller. | 179 buffer.readMatrix(&lm); |
126 fState->~SkBitmapProcState(); | 180 SkBitmap bm; |
| 181 if (!buffer.readBitmap(&bm)) { |
| 182 return nullptr; |
| 183 } |
| 184 bm.setImmutable(); |
| 185 TileMode mx = (TileMode)buffer.readUInt(); |
| 186 TileMode my = (TileMode)buffer.readUInt(); |
| 187 return SkShader::CreateBitmapShader(bm, mx, my, &lm); |
127 } | 188 } |
128 | 189 |
129 #define BUF_MAX 128 | 190 void SkBitmapProcShader::flatten(SkWriteBuffer& buffer) const { |
130 | 191 buffer.writeMatrix(this->getLocalMatrix()); |
131 #define TEST_BUFFER_OVERRITEx | 192 buffer.writeBitmap(fRawBitmap); |
132 | 193 buffer.writeUInt(fTileModeX); |
133 #ifdef TEST_BUFFER_OVERRITE | 194 buffer.writeUInt(fTileModeY); |
134 #define TEST_BUFFER_EXTRA 32 | |
135 #define TEST_PATTERN 0x88888888 | |
136 #else | |
137 #define TEST_BUFFER_EXTRA 0 | |
138 #endif | |
139 | |
140 void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMCo
lor dstC[], | |
141 int count) { | |
142 const SkBitmapProcState& state = *fState; | |
143 if (state.getShaderProc32()) { | |
144 state.getShaderProc32()(&state, x, y, dstC, count); | |
145 return; | |
146 } | |
147 | |
148 uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA]; | |
149 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); | |
150 SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32(); | |
151 int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX); | |
152 | |
153 SkASSERT(state.fPixmap.addr()); | |
154 | |
155 for (;;) { | |
156 int n = count; | |
157 if (n > max) { | |
158 n = max; | |
159 } | |
160 SkASSERT(n > 0 && n < BUF_MAX*2); | |
161 #ifdef TEST_BUFFER_OVERRITE | |
162 for (int i = 0; i < TEST_BUFFER_EXTRA; i++) { | |
163 buffer[BUF_MAX + i] = TEST_PATTERN; | |
164 } | |
165 #endif | |
166 mproc(state, buffer, n, x, y); | |
167 #ifdef TEST_BUFFER_OVERRITE | |
168 for (int j = 0; j < TEST_BUFFER_EXTRA; j++) { | |
169 SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN); | |
170 } | |
171 #endif | |
172 sproc(state, buffer, n, dstC); | |
173 | |
174 if ((count -= n) == 0) { | |
175 break; | |
176 } | |
177 SkASSERT(count > 0); | |
178 x += n; | |
179 dstC += n; | |
180 } | |
181 } | 195 } |
182 | 196 |
183 SkShader::Context::ShadeProc SkBitmapProcShader::BitmapProcShaderContext::asASha
deProc(void** ctx) { | 197 bool SkBitmapProcShader::isOpaque() const { |
184 if (fState->getShaderProc32()) { | 198 return fRawBitmap.isOpaque(); |
185 *ctx = fState; | |
186 return (ShadeProc)fState->getShaderProc32(); | |
187 } | |
188 return nullptr; | |
189 } | 199 } |
190 | 200 |
191 /////////////////////////////////////////////////////////////////////////////// | 201 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
192 | 202 |
193 #include "SkUnPreMultiply.h" | 203 #include "SkUnPreMultiply.h" |
194 #include "SkColorShader.h" | 204 #include "SkColorShader.h" |
195 #include "SkEmptyShader.h" | 205 #include "SkEmptyShader.h" |
196 | 206 |
197 // returns true and set color if the bitmap can be drawn as a single color | 207 // returns true and set color if the bitmap can be drawn as a single color |
198 // (for efficiency) | 208 // (for efficiency) |
199 static bool can_use_color_shader(const SkBitmap& bm, SkColor* color) { | 209 static bool can_use_color_shader(const SkBitmap& bm, SkColor* color) { |
200 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK | 210 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK |
201 // HWUI does not support color shaders (see b/22390304) | 211 // HWUI does not support color shaders (see b/22390304) |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 inner.reset(GrSimpleTextureEffect::Create(texture, matrix, params)); | 353 inner.reset(GrSimpleTextureEffect::Create(texture, matrix, params)); |
344 } | 354 } |
345 | 355 |
346 if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { | 356 if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { |
347 return GrFragmentProcessor::MulOutputByInputUnpremulColor(inner); | 357 return GrFragmentProcessor::MulOutputByInputUnpremulColor(inner); |
348 } | 358 } |
349 return GrFragmentProcessor::MulOutputByInputAlpha(inner); | 359 return GrFragmentProcessor::MulOutputByInputAlpha(inner); |
350 } | 360 } |
351 | 361 |
352 #endif | 362 #endif |
OLD | NEW |