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

Side by Side Diff: src/core/SkLightingShader_NormalSource.cpp

Issue 2043393002: Refactoring of GPU NormalMap handling out into its own class (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Refactoring, style fixes Created 4 years, 6 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 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 */
7
8 #include "SkBitmapProcShader.h"
9 #include "SkError.h"
10 #include "SkErrorInternals.h"
11 #include "SkLightingShader.h"
12 #include "SkReadBuffer.h"
13 #include "SkWriteBuffer.h"
14
15 SkLightingShader::NormalSource::~NormalSource(){}
16
17 ///////////////////////////////////////////////////////////////////////////////
18
19 class SK_API NormalMapSourceImpl : public SkLightingShader::NormalSource {
20 public:
21 NormalMapSourceImpl(const SkBitmap &normal, const SkVector &invNormRotation,
22 const SkMatrix *normLocalM)
23 : fNormalMap(normal)
24 , fInvNormRotation(invNormRotation) {
25
26 if (normLocalM) {
27 fNormLocalMatrix = *normLocalM;
28 } else {
29 fNormLocalMatrix.reset();
30 }
31 // Pre-cache so future calls to fNormLocalMatrix.getType() are threadsaf e.
32 (void)fNormLocalMatrix.getType();
33 }
34
35 #if SK_SUPPORT_GPU
36 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*,
37 const SkMatrix& viewM,
38 const SkMatrix* localMatrix,
39 SkFilterQuality,
40 SkSourceGammaTreatment) const override;
41 #endif
42
43 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(NormalMapSourceImpl)
dvonbeck 2016/06/10 18:31:22 FLATTENABLE: Macro
44
45 protected:
46 void flatten(SkWriteBuffer& buf) const override;
47
48 private:
49 SkBitmap fNormalMap;
50 SkMatrix fNormLocalMatrix;
51 SkVector fInvNormRotation;
52
53 friend class SkLightingShader::NormalMapSource;
54
55 typedef SkLightingShader::NormalSource INHERITED;
56 };
57
58 ////////////////////////////////////////////////////////////////////////////
59
60 #if SK_SUPPORT_GPU
61
62 #include "GrCoordTransform.h"
63 #include "GrInvariantOutput.h"
64 #include "GrTextureParams.h"
65 #include "glsl/GrGLSLFragmentProcessor.h"
66 #include "glsl/GrGLSLFragmentShaderBuilder.h"
67 #include "SkGr.h"
68
69 class NormalMapFP : public GrFragmentProcessor {
70 public:
71 NormalMapFP(GrTexture* normal, const SkMatrix& normMatrix, const GrTexturePa rams& normParams,
72 const SkVector& invNormRotation)
73 : fNormDeviceTransform(kLocal_GrCoordSet, normMatrix, normal, normParams .filterMode())
74 , fNormalTextureAccess(normal, normParams)
75 , fInvNormRotation(invNormRotation) {
76 this->addCoordTransform(&fNormDeviceTransform);
77 this->addTextureAccess(&fNormalTextureAccess);
78
79 this->initClassID<NormalMapFP>();
80 }
81
82 class GLSLNormalMapFP : public GrGLSLFragmentProcessor {
83 public:
84 GLSLNormalMapFP() {
85 fInvNormRotation.set(0.0f, 0.0f);
86 }
87
88 void emitCode(EmitArgs& args) override {
89
90 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
91 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
92
93 // add uniform
94 const char* xformUniName = nullptr;
95 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
96 kVec2f_GrSLType, kDefault_GrS LPrecision,
97 "Xform", &xformUniName);
98
99 fragBuilder->codeAppend("vec4 normalColor = ");
100 fragBuilder->appendTextureLookup(args.fTexSamplers[0],
101 args.fCoords[0].c_str(),
102 args.fCoords[0].getType());
103 fragBuilder->codeAppend(";");
104
105 fragBuilder->codeAppend("vec3 normal = normalColor.rgb - vec3(0.5);" );
106
107 // TODO: inverse map the light direction vectors in the vertex shade r rather than
108 // transforming all the normals here!
109 fragBuilder->codeAppendf(
110 "mat3 m = mat3(%s.x, -%s.y, 0.0, %s.y, %s.x, 0.0, 0.0, 0.0, 1.0);",
111 xformUniName, xformUniName, xformUniName, xformUniName);
112
113 fragBuilder->codeAppend("normal = normalize(m*normal);");
114 fragBuilder->codeAppendf("%s = vec4(normal, 0);", args.fOutputColor) ;
115 }
116
117 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
118 GrProcessorKeyBuilder* b) {
119 b->add32(0x0);
120 }
121
122 protected:
123 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
124 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>();
125
126 const SkVector& invNormRotation = normalMapFP.invNormRotation();
127 if (invNormRotation != fInvNormRotation) {
128 pdman.set2fv(fXformUni, 1, &invNormRotation.fX);
129 fInvNormRotation = invNormRotation;
130 }
131 }
132
133 private:
134 SkVector fInvNormRotation;
135 GrGLSLProgramDataManager::UniformHandle fXformUni;
136 };
137
138 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
139 GLSLNormalMapFP::GenKey(*this, caps, b);
140 }
141
142 const char* name() const override { return "NormalMapFP"; }
143
144 // TODO what is this? keep? delete?
145 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
146 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput);
147 }
148
149 const SkVector& invNormRotation() const { return fInvNormRotation; }
150
151 private:
152 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalMapFP; }
153
154 bool onIsEqual(const GrFragmentProcessor& proc) const override {
155 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>();
156 return fNormDeviceTransform == normalMapFP.fNormDeviceTransform &&
157 fNormalTextureAccess == normalMapFP.fNormalTextureAccess &&
158 fInvNormRotation == normalMapFP.fInvNormRotation;
159 }
160
161 GrCoordTransform fNormDeviceTransform;
162 GrTextureAccess fNormalTextureAccess;
163
164 SkVector fInvNormRotation;
165 };
166
167 // TODO same code at SkLightingShader.cpp. Refactor to common source!
168 static bool make_mat(const SkBitmap& bm,
169 const SkMatrix& localMatrix1,
170 const SkMatrix* localMatrix2,
171 SkMatrix* result) {
172
173 result->setIDiv(bm.width(), bm.height());
174
175 SkMatrix lmInverse;
176 if (!localMatrix1.invert(&lmInverse)) {
177 return false;
178 }
179 if (localMatrix2) {
180 SkMatrix inv;
181 if (!localMatrix2->invert(&inv)) {
182 return false;
183 }
184 lmInverse.postConcat(inv);
185 }
186 result->preConcat(lmInverse);
187
188 return true;
189 }
190
191 sk_sp<GrFragmentProcessor> NormalMapSourceImpl::asFragmentProcessor(
192 GrContext *context,
193 const SkMatrix &viewM,
194 const SkMatrix *localMatrix ,
195 SkFilterQuality filterQuali ty,
196 SkSourceGammaTreatment gamm aTreatment) const {
197
198 // TODO Here, the old code was checking that diffuse map and normal map are same size, that
199 // will be addressed when diffuse maps are factored out of SkLightingSh ader in a future CL
200
201 SkMatrix normM;
202 if (!make_mat(fNormalMap, fNormLocalMatrix, localMatrix, &normM)) {
203 return nullptr;
204 }
205
206 bool doBicubic;
207 GrTextureParams::FilterMode normFilterMode = GrSkFilterQualityToGrFilterMode (
208 SkTMin(filterQuality, kMedium_SkFilterQuality),
209 viewM,
210 fNormLocalMatrix,
211 &doBicubic);
212 SkASSERT(!doBicubic);
213
214 // TODO: support other tile modes
215 GrTextureParams normParams(SkShader::kClamp_TileMode, normFilterMode);
216 SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context,
217 fNormalMap,
218 normParams,
219 gammaTreatmen t));
220 if (!normalTexture) {
221 SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bit map to texture.");
222 return nullptr;
223 }
224
225 return sk_make_sp<NormalMapFP>(normalTexture, normM, normParams, fInvNormRot ation);
226 }
227
228 #endif // SK_SUPPORT_GPU
229
230 ////////////////////////////////////////////////////////////////////////////
231
232 sk_sp<SkFlattenable> NormalMapSourceImpl::CreateProc(SkReadBuffer& buf) {
dvonbeck 2016/06/10 18:31:21 FLATTENABLE: Reading NormalMapSourceImpl from buff
233
234 SkMatrix normLocalM;
235 bool hasNormLocalM = buf.readBool();
236 if (hasNormLocalM) {
237 buf.readMatrix(&normLocalM);
238 } else {
239 normLocalM.reset();
240 }
241
242 SkBitmap normal;
243 if (!buf.readBitmap(&normal)) {
244 return nullptr;
245 }
246 normal.setImmutable();
247
248 SkVector invNormRotation = {1,0};
249 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) {
250 invNormRotation = buf.readPoint();
251 }
252
253 return sk_make_sp<NormalMapSourceImpl>(normal, invNormRotation, &normLocalM) ;
254 }
255
256 void NormalMapSourceImpl::flatten(SkWriteBuffer& buf) const {
dvonbeck 2016/06/10 18:31:22 FLATTENABLE: Flattening NormalMapSourceImpl
257 this->INHERITED::flatten(buf);
258
259 bool hasNormLocalM = !fNormLocalMatrix.isIdentity();
260 buf.writeBool(hasNormLocalM);
261 if (hasNormLocalM) {
262 buf.writeMatrix(fNormLocalMatrix);
263 }
264
265 buf.writeBitmap(fNormalMap);
266 buf.writePoint(fInvNormRotation);
267 }
268
269 ////////////////////////////////////////////////////////////////////////////
270
271 sk_sp<SkLightingShader::NormalSource> SkLightingShader::NormalMapSource::Make(
272 const SkBitmap &normal, const SkVector &invNormRotation, const SkMatrix *normLocalM) {
273
274 // TODO not checking normal and diffuse maps to be same size, will be addres sed when diffuse
275 // maps are factored out of SkLightingShader in a future CL
276 if (normal.isNull() || SkBitmapProcShader::bitmapIsTooBig(normal)) {
277 return nullptr;
278 }
279
280 SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1));
281
282 return sk_make_sp<NormalMapSourceImpl>(normal, invNormRotation, normLocalM);
283 }
284
285 ////////////////////////////////////////////////////////////////////////////
286
287 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader::NormalMapSource)
288 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(NormalMapSourceImpl)
289 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
290
291 ////////////////////////////////////////////////////////////////////////////
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698