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" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 }; | 60 }; |
61 | 61 |
62 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 62 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
63 | 63 |
64 class BitmapProcShaderContext : public BitmapProcInfoContext { | 64 class BitmapProcShaderContext : public BitmapProcInfoContext { |
65 public: | 65 public: |
66 // The context takes ownership of the state. It will call its destructor | 66 // The context takes ownership of the state. It will call its destructor |
67 // but will NOT free the memory. | 67 // but will NOT free the memory. |
68 BitmapProcShaderContext(const SkShader& shader, const SkShader::ContextRec& rec, | 68 BitmapProcShaderContext(const SkShader& shader, const SkShader::ContextRec& rec, |
69 SkBitmapProcState* state) | 69 SkBitmapProcState* state) |
70 : INHERITED(shader, rec, state) | 70 : INHERITED(shader, rec, state) |
71 , fState(state) | 71 , fState(state) |
72 {} | 72 {} |
73 | 73 |
74 void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { | 74 void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { |
75 const SkBitmapProcState& state = *fState; | 75 const SkBitmapProcState& state = *fState; |
76 if (state.getShaderProc32()) { | 76 if (state.getShaderProc32()) { |
77 state.getShaderProc32()(&state, x, y, dstC, count); | 77 state.getShaderProc32()(&state, x, y, dstC, count); |
78 return; | 78 return; |
79 } | 79 } |
80 | 80 |
81 const int BUF_MAX = 128; | 81 const int BUF_MAX = 128; |
(...skipping 27 matching lines...) Expand all Loading... | |
109 return nullptr; | 109 return nullptr; |
110 } | 110 } |
111 | 111 |
112 private: | 112 private: |
113 SkBitmapProcState* fState; | 113 SkBitmapProcState* fState; |
114 | 114 |
115 typedef BitmapProcInfoContext INHERITED; | 115 typedef BitmapProcInfoContext INHERITED; |
116 }; | 116 }; |
117 | 117 |
118 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 118 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
119 #include "SkLinearBitmapPipeline.h" | |
120 #include "SkPM4f.h" | |
121 #include "SkXfermode.h" | |
122 | |
123 class LinearPipelineContext : public BitmapProcInfoContext { | |
124 public: | |
125 // The context takes ownership of the state. It will call its destructor | |
mtklein
2016/03/03 01:30:37
Having read this code, or at least in a while, it'
reed1
2016/03/03 14:05:25
Done.
| |
126 // but will NOT free the memory. | |
127 LinearPipelineContext(const SkShader& shader, const SkShader::ContextRec& re c, | |
128 SkBitmapProcInfo* info) | |
129 : INHERITED(shader, rec, info) | |
130 , fPipeline(info->fInvMatrix, info->fFilterQuality, info->fTileModeX, in fo->fTileModeY, | |
131 info->fPixmap) | |
132 {} | |
133 | |
134 void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override { | |
135 fPipeline.shadeSpan4f(x, y, dstC, count); | |
136 } | |
137 | |
138 void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { | |
139 // we're not necessarily opaque, but we want the proc to treat us as if we are, so we | |
140 // get memcpy performance/semantics | |
mtklein
2016/03/03 01:30:37
remind me (or the reader) why this is okay?
reed1
2016/03/03 14:05:25
Done.
| |
141 auto proc = SkXfermode::GetD32Proc(nullptr, SkXfermode::kSrcIsOpaque_D32 Flag); | |
142 const int N = 128; | |
143 SkPM4f tmp[N]; | |
144 | |
145 while (count > 0) { | |
146 const int n = SkTMin(count, N); | |
147 fPipeline.shadeSpan4f(x, y, tmp, n); | |
148 proc(nullptr, dstC, tmp, n, nullptr); | |
149 dstC += n; | |
150 x += n; | |
151 count -= n; | |
152 } | |
153 } | |
154 | |
155 private: | |
156 SkLinearBitmapPipeline fPipeline; | |
157 | |
158 typedef BitmapProcInfoContext INHERITED; | |
159 }; | |
160 | |
161 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
119 | 162 |
120 size_t SkBitmapProcShader::ContextSize(const ContextRec& rec) { | 163 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 | 164 // These src attributes are not supported in the new 4f context (yet) |
122 // a pointer to it. | 165 // |
123 return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); | 166 if (srcInfo.bytesPerPixel() < 4 || |
167 kRGBA_F16_SkColorType == srcInfo.colorType()) { | |
168 return false; | |
169 } | |
170 | |
171 // These src attributes are only supported in the new 4f context | |
172 // | |
173 if (srcInfo.isSRGB() || | |
174 kUnpremul_SkAlphaType == srcInfo.alphaType() || | |
175 (4 == srcInfo.bytesPerPixel() && kN32_SkColorType != srcInfo.colorType() )) | |
176 { | |
177 return true; | |
178 } | |
179 | |
180 // If we get here, we can reasonably use either context, respect the caller' s preference | |
181 // | |
182 return SkShader::ContextRec::kPM4f_DstType == rec.fPreferredDstType; | |
183 } | |
184 | |
185 size_t SkBitmapProcShader::ContextSize(const ContextRec& rec, const SkImageInfo& srcInfo) { | |
186 size_t size0 = sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState); | |
187 size_t size1 = sizeof(LinearPipelineContext) + sizeof(SkBitmapProcInfo); | |
188 return SkTMax(size0, size1); | |
124 } | 189 } |
125 | 190 |
126 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, | 191 SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader, |
127 TileMode tmx, TileMode tmy, | 192 TileMode tmx, TileMode tmy, |
128 const SkBitmapProvider& provi der, | 193 const SkBitmapProvider& provi der, |
129 const ContextRec& rec, void* storage) { | 194 const ContextRec& rec, void* storage) { |
130 SkMatrix totalInverse; | 195 SkMatrix totalInverse; |
131 // Do this first, so we know the matrix can be inverted. | 196 // Do this first, so we know the matrix can be inverted. |
132 if (!shader.computeTotalInverse(rec, &totalInverse)) { | 197 if (!shader.computeTotalInverse(rec, &totalInverse)) { |
133 return nullptr; | 198 return nullptr; |
134 } | 199 } |
135 | 200 |
136 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); | 201 // Decide if we can/want to use the new linear pipeine |
137 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider, tm x, tmy); | 202 bool useLinearPipeline = choose_linear_pipeline(rec, provider.info()); |
138 | 203 if (SkShader::kMirror_TileMode == tmx || SkShader::kMirror_TileMode == tmy) { |
139 SkASSERT(state); | 204 useLinearPipeline = false; |
140 if (!state->setup(totalInverse, *rec.fPaint)) { | 205 } |
141 state->~SkBitmapProcState(); | 206 if (totalInverse.hasPerspective()) { |
142 return nullptr; | 207 useLinearPipeline = false; |
143 } | 208 } |
144 | 209 |
145 return new (storage) BitmapProcShaderContext(shader, rec, state); | 210 if (useLinearPipeline) { |
211 void* infoStorage = (char*)storage + sizeof(LinearPipelineContext); | |
212 SkBitmapProcInfo* info = new (infoStorage) SkBitmapProcInfo(provider, tm x, tmy); | |
213 if (!info->init(totalInverse, *rec.fPaint)) { | |
214 info->~SkBitmapProcInfo(); | |
215 return nullptr; | |
216 } | |
217 return new (storage) LinearPipelineContext(shader, rec, info); | |
218 } else { | |
219 void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); | |
220 SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider , tmx, tmy); | |
221 if (!state->setup(totalInverse, *rec.fPaint)) { | |
222 state->~SkBitmapProcState(); | |
223 return nullptr; | |
224 } | |
225 return new (storage) BitmapProcShaderContext(shader, rec, state); | |
226 } | |
146 } | 227 } |
147 | 228 |
148 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo id* storage) const { | 229 SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, vo id* storage) const { |
149 return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, | 230 return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, |
150 SkBitmapProvider(fRawBitmap), rec, storage); | 231 SkBitmapProvider(fRawBitmap), rec, storage); |
151 } | 232 } |
152 | 233 |
153 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 234 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
154 | 235 |
155 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMo de tmy, | 236 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)); | 434 inner.reset(GrSimpleTextureEffect::Create(texture, matrix, params)); |
354 } | 435 } |
355 | 436 |
356 if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { | 437 if (kAlpha_8_SkColorType == fRawBitmap.colorType()) { |
357 return GrFragmentProcessor::MulOutputByInputUnpremulColor(inner); | 438 return GrFragmentProcessor::MulOutputByInputUnpremulColor(inner); |
358 } | 439 } |
359 return GrFragmentProcessor::MulOutputByInputAlpha(inner); | 440 return GrFragmentProcessor::MulOutputByInputAlpha(inner); |
360 } | 441 } |
361 | 442 |
362 #endif | 443 #endif |
OLD | NEW |