Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: src/effects/SkBicubicImageFilter.cpp

Issue 23779003: first cut at HQ GPU scaling; refactored existing bicubic scaler (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: final version for trybots Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/core/SkBitmapProcShader.cpp ('k') | src/gpu/effects/GrBicubicEffect.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 The Android Open Source Project 2 * Copyright 2013 The Android Open Source Project
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 "SkBicubicImageFilter.h" 8 #include "SkBicubicImageFilter.h"
9 #include "SkBitmap.h" 9 #include "SkBitmap.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
11 #include "SkFlattenableBuffers.h" 11 #include "SkFlattenableBuffers.h"
12 #include "SkMatrix.h" 12 #include "SkMatrix.h"
13 #include "SkRect.h" 13 #include "SkRect.h"
14 #include "SkUnPreMultiply.h" 14 #include "SkUnPreMultiply.h"
15 15
16 #if SK_SUPPORT_GPU 16 #if SK_SUPPORT_GPU
17 #include "gl/GrGLEffectMatrix.h" 17 #include "effects/GrBicubicEffect.h"
18 #include "effects/GrSingleTextureEffect.h"
19 #include "GrTBackendEffectFactory.h"
20 #include "GrContext.h" 18 #include "GrContext.h"
21 #include "GrTexture.h" 19 #include "GrTexture.h"
22 #include "SkImageFilterUtils.h" 20 #include "SkImageFilterUtils.h"
23 #endif 21 #endif
24 22
23 #define DS(x) SkDoubleToScalar(x)
24
25 static const SkScalar gMitchellCoefficients[16] = {
26 DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0),
27 DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0),
28 DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0),
29 DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0),
30 };
31
25 SkBicubicImageFilter::SkBicubicImageFilter(const SkSize& scale, const SkScalar c oefficients[16], SkImageFilter* input) 32 SkBicubicImageFilter::SkBicubicImageFilter(const SkSize& scale, const SkScalar c oefficients[16], SkImageFilter* input)
26 : INHERITED(input), 33 : INHERITED(input),
27 fScale(scale) { 34 fScale(scale) {
28 memcpy(fCoefficients, coefficients, sizeof(fCoefficients)); 35 memcpy(fCoefficients, coefficients, sizeof(fCoefficients));
29 } 36 }
30 37
31 #define DS(x) SkDoubleToScalar(x)
32
33 SkBicubicImageFilter* SkBicubicImageFilter::CreateMitchell(const SkSize& scale, 38 SkBicubicImageFilter* SkBicubicImageFilter::CreateMitchell(const SkSize& scale,
34 SkImageFilter* input) { 39 SkImageFilter* input) {
35 static const SkScalar coefficients[16] = { 40 return SkNEW_ARGS(SkBicubicImageFilter, (scale, gMitchellCoefficients, input ));
36 DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0),
37 DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0),
38 DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0),
39 DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0),
40 };
41 return SkNEW_ARGS(SkBicubicImageFilter, (scale, coefficients, input));
42 } 41 }
43 42
44 SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : IN HERITED(buffer) { 43 SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : IN HERITED(buffer) {
45 SkDEBUGCODE(uint32_t readSize =) buffer.readScalarArray(fCoefficients); 44 SkDEBUGCODE(uint32_t readSize =) buffer.readScalarArray(fCoefficients);
46 SkASSERT(readSize == 16); 45 SkASSERT(readSize == 16);
47 fScale.fWidth = buffer.readScalar(); 46 fScale.fWidth = buffer.readScalar();
48 fScale.fHeight = buffer.readScalar(); 47 fScale.fHeight = buffer.readScalar();
49 } 48 }
50 49
51 void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 50 void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 SkPMColor s3 = cubicBlend(fCoefficients, fractx, s03, s13, s23, s33) ; 149 SkPMColor s3 = cubicBlend(fCoefficients, fractx, s03, s13, s23, s33) ;
151 *dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3); 150 *dptr++ = cubicBlend(fCoefficients, fracty, s0, s1, s2, s3);
152 } 151 }
153 } 152 }
154 return true; 153 return true;
155 } 154 }
156 155
157 /////////////////////////////////////////////////////////////////////////////// 156 ///////////////////////////////////////////////////////////////////////////////
158 157
159 #if SK_SUPPORT_GPU 158 #if SK_SUPPORT_GPU
160 class GrGLBicubicEffect;
161
162 class GrBicubicEffect : public GrSingleTextureEffect {
163 public:
164 virtual ~GrBicubicEffect();
165
166 static const char* Name() { return "Bicubic"; }
167 const float* coefficients() const { return fCoefficients; }
168
169 typedef GrGLBicubicEffect GLEffect;
170
171 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
172 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE;
173
174 static GrEffectRef* Create(GrTexture* tex, const SkScalar coefficients[16]) {
175 AutoEffectUnref effect(SkNEW_ARGS(GrBicubicEffect, (tex, coefficients))) ;
176 return CreateEffectRef(effect);
177 }
178
179 private:
180 GrBicubicEffect(GrTexture*, const SkScalar coefficients[16]);
181 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
182 float fCoefficients[16];
183
184 GR_DECLARE_EFFECT_TEST;
185
186 typedef GrSingleTextureEffect INHERITED;
187 };
188
189 class GrGLBicubicEffect : public GrGLEffect {
190 public:
191 GrGLBicubicEffect(const GrBackendEffectFactory& factory,
192 const GrDrawEffect&);
193 virtual void emitCode(GrGLShaderBuilder*,
194 const GrDrawEffect&,
195 EffectKey,
196 const char* outputColor,
197 const char* inputColor,
198 const TextureSamplerArray&) SK_OVERRIDE;
199
200 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
201
202 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
203
204 private:
205 typedef GrGLUniformManager::UniformHandle UniformHandle;
206
207 UniformHandle fCoefficientsUni;
208 UniformHandle fImageIncrementUni;
209
210 GrGLEffectMatrix fEffectMatrix;
211
212 typedef GrGLEffect INHERITED;
213 };
214
215 GrGLBicubicEffect::GrGLBicubicEffect(const GrBackendEffectFactory& factory,
216 const GrDrawEffect& drawEffect)
217 : INHERITED(factory)
218 , fEffectMatrix(drawEffect.castEffect<GrBicubicEffect>().coordsType()) {
219 }
220
221 void GrGLBicubicEffect::emitCode(GrGLShaderBuilder* builder,
222 const GrDrawEffect&,
223 EffectKey key,
224 const char* outputColor,
225 const char* inputColor,
226 const TextureSamplerArray& samplers) {
227 SkString coords;
228 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, &coords);
229 fCoefficientsUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibili ty,
230 kMat44f_GrSLType, "Coefficients");
231 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibi lity,
232 kVec2f_GrSLType, "ImageIncrement");
233
234 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
235 const char* coeff = builder->getUniformCStr(fCoefficientsUni);
236
237 SkString cubicBlendName;
238
239 static const GrGLShaderVar gCubicBlendArgs[] = {
240 GrGLShaderVar("coefficients", kMat44f_GrSLType),
241 GrGLShaderVar("t", kFloat_GrSLType),
242 GrGLShaderVar("c0", kVec4f_GrSLType),
243 GrGLShaderVar("c1", kVec4f_GrSLType),
244 GrGLShaderVar("c2", kVec4f_GrSLType),
245 GrGLShaderVar("c3", kVec4f_GrSLType),
246 };
247 builder->fsEmitFunction(kVec4f_GrSLType,
248 "cubicBlend",
249 SK_ARRAY_COUNT(gCubicBlendArgs),
250 gCubicBlendArgs,
251 "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n"
252 "\tvec4 c = coefficients * ts;\n"
253 "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3; \n",
254 &cubicBlendName);
255 builder->fsCodeAppendf("\tvec2 coord = %s - %s * vec2(0.5, 0.5);\n", coords. c_str(), imgInc);
256 builder->fsCodeAppendf("\tvec2 f = fract(coord / %s);\n", imgInc);
257 for (int y = 0; y < 4; ++y) {
258 for (int x = 0; x < 4; ++x) {
259 SkString coord;
260 coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1);
261 builder->fsCodeAppendf("\tvec4 s%d%d = ", x, y);
262 builder->fsAppendTextureLookup(samplers[0], coord.c_str());
263 builder->fsCodeAppend(";\n");
264 }
265 builder->fsCodeAppendf("\tvec4 s%d = %s(%s, f.x, s0%d, s1%d, s2%d, s3%d) ;\n", y, cubicBlendName.c_str(), coeff, y, y, y, y);
266 }
267 builder->fsCodeAppendf("\t%s = %s(%s, f.y, s0, s1, s2, s3);\n", outputColor, cubicBlendName.c_str(), coeff);
268 }
269
270 GrGLEffect::EffectKey GrGLBicubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
271 const GrBicubicEffect& bicubic = drawEffect.castEffect<GrBicubicEffect>();
272 EffectKey matrixKey = GrGLEffectMatrix::GenKey(bicubic.getMatrix(),
273 drawEffect,
274 bicubic.coordsType(),
275 bicubic.texture(0));
276 return matrixKey;
277 }
278
279 void GrGLBicubicEffect::setData(const GrGLUniformManager& uman,
280 const GrDrawEffect& drawEffect) {
281 const GrBicubicEffect& effect = drawEffect.castEffect<GrBicubicEffect>();
282 GrTexture& texture = *effect.texture(0);
283 float imageIncrement[2];
284 imageIncrement[0] = 1.0f / texture.width();
285 imageIncrement[1] = 1.0f / texture.height();
286 uman.set2fv(fImageIncrementUni, 0, 1, imageIncrement);
287 uman.setMatrix4f(fCoefficientsUni, effect.coefficients());
288 fEffectMatrix.setData(uman,
289 effect.getMatrix(),
290 drawEffect,
291 effect.texture(0));
292 }
293
294 GrBicubicEffect::GrBicubicEffect(GrTexture* texture,
295 const SkScalar coefficients[16])
296 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)) {
297 for (int y = 0; y < 4; y++) {
298 for (int x = 0; x < 4; x++) {
299 // Convert from row-major scalars to column-major floats.
300 fCoefficients[x * 4 + y] = SkScalarToFloat(coefficients[y * 4 + x]);
301 }
302 }
303 }
304
305 GrBicubicEffect::~GrBicubicEffect() {
306 }
307
308 const GrBackendEffectFactory& GrBicubicEffect::getFactory() const {
309 return GrTBackendEffectFactory<GrBicubicEffect>::getInstance();
310 }
311
312 bool GrBicubicEffect::onIsEqual(const GrEffect& sBase) const {
313 const GrBicubicEffect& s = CastEffect<GrBicubicEffect>(sBase);
314 return this->texture(0) == s.texture(0) &&
315 !memcmp(fCoefficients, s.coefficients(), 16);
316 }
317
318 void GrBicubicEffect::getConstantColorComponents(GrColor* color, uint32_t* valid Flags) const {
319 // FIXME: Perhaps we can do better.
320 *validFlags = 0;
321 return;
322 }
323
324 GR_DEFINE_EFFECT_TEST(GrBicubicEffect);
325
326 GrEffectRef* GrBicubicEffect::TestCreate(SkMWCRandom* random,
327 GrContext* context,
328 const GrDrawTargetCaps&,
329 GrTexture* textures[]) {
330 int texIdx = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
331 GrEffectUnitTest::kAlphaTextureIdx;
332 SkScalar coefficients[16];
333 for (int i = 0; i < 16; i++) {
334 coefficients[i] = random->nextSScalar1();
335 }
336 return GrBicubicEffect::Create(textures[texIdx], coefficients);
337 }
338 159
339 bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, con st SkMatrix& ctm, 160 bool SkBicubicImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, con st SkMatrix& ctm,
340 SkBitmap* result, SkIPoint* offset) { 161 SkBitmap* result, SkIPoint* offset) {
341 SkBitmap srcBM; 162 SkBitmap srcBM;
342 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &sr cBM, offset)) { 163 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &sr cBM, offset)) {
343 return false; 164 return false;
344 } 165 }
345 GrTexture* srcTexture = srcBM.getTexture(); 166 GrTexture* srcTexture = srcBM.getTexture();
346 GrContext* context = srcTexture->getContext(); 167 GrContext* context = srcTexture->getContext();
347 168
(...skipping 15 matching lines...) Expand all
363 GrPaint paint; 184 GrPaint paint;
364 paint.addColorEffect(GrBicubicEffect::Create(srcTexture, fCoefficients))->un ref(); 185 paint.addColorEffect(GrBicubicEffect::Create(srcTexture, fCoefficients))->un ref();
365 SkRect srcRect; 186 SkRect srcRect;
366 srcBM.getBounds(&srcRect); 187 srcBM.getBounds(&srcRect);
367 context->drawRectToRect(paint, dstRect, srcRect); 188 context->drawRectToRect(paint, dstRect, srcRect);
368 return SkImageFilterUtils::WrapTexture(dst, desc.fWidth, desc.fHeight, resul t); 189 return SkImageFilterUtils::WrapTexture(dst, desc.fWidth, desc.fHeight, resul t);
369 } 190 }
370 #endif 191 #endif
371 192
372 /////////////////////////////////////////////////////////////////////////////// 193 ///////////////////////////////////////////////////////////////////////////////
OLDNEW
« no previous file with comments | « src/core/SkBitmapProcShader.cpp ('k') | src/gpu/effects/GrBicubicEffect.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698