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

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

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

Powered by Google App Engine
This is Rietveld 408576698