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

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

Issue 2050773002: Refactoring of CPU NormalMap handling out into its own class (Closed) Base URL: https://skia.googlesource.com/skia@dvonbeck-normals-gpu-cl
Patch Set: SkLS Context dependencies now allocated on the heap Created 4 years, 5 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
« no previous file with comments | « src/core/SkNormalSource.h ('k') | src/ports/SkGlobalInitialization_default.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "SkError.h"
9 #include "SkErrorInternals.h"
10 #include "SkLightingShader.h"
11 #include "SkNormalSource.h"
12 #include "SkReadBuffer.h"
13 #include "SkWriteBuffer.h"
14
15 // Genretating vtable
16 SkNormalSource::~SkNormalSource() {}
17
18 ///////////////////////////////////////////////////////////////////////////////
19
20 class NormalMapSourceImpl : public SkNormalSource {
21 public:
22 NormalMapSourceImpl(sk_sp<SkShader> mapShader, const SkVector &normRotation)
23 : fMapShader(std::move(mapShader))
24 , fNormRotation(normRotation) {}
25
26 #if SK_SUPPORT_GPU
27 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*,
28 const SkMatrix& viewM,
29 const SkMatrix* localMatrix,
30 SkFilterQuality,
31 SkSourceGammaTreatment) const override;
32 #endif
33
34 SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec,
35 void* storage) const ov erride;
36
37 size_t providerSize(const SkShader::ContextRec& rec) const override;
38 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(NormalMapSourceImpl)
39
40 protected:
41 void flatten(SkWriteBuffer& buf) const override;
42
43 bool computeNormTotalInverse(const SkShader::ContextRec& rec, SkMatrix* norm TotalInverse) const;
44
45 private:
46 class Provider : public SkNormalSource::Provider {
47 public:
48 Provider(const NormalMapSourceImpl& source, SkShader::Context* fMapConte xt);
49
50 virtual ~Provider() override;
51
52 void fillScanLine(int x, int y, SkPoint3 output[], int count) const over ride;
53 private:
54 const NormalMapSourceImpl& fSource;
55 SkShader::Context* fMapContext;
56
57 typedef SkNormalSource::Provider INHERITED;
58 };
59
60 sk_sp<SkShader> fMapShader;
61 SkVector fNormRotation;
62
63 friend class SkNormalSource;
64
65 typedef SkNormalSource INHERITED;
66 };
67
68 ////////////////////////////////////////////////////////////////////////////
69
70 #if SK_SUPPORT_GPU
71
72 #include "GrCoordTransform.h"
73 #include "GrInvariantOutput.h"
74 #include "GrTextureParams.h"
75 #include "glsl/GrGLSLFragmentProcessor.h"
76 #include "glsl/GrGLSLFragmentShaderBuilder.h"
77 #include "SkGr.h"
78
79 class NormalMapFP : public GrFragmentProcessor {
80 public:
81 NormalMapFP(sk_sp<GrFragmentProcessor> mapFP, const SkVector& normRotation)
82 : fNormRotation(normRotation) {
83 this->registerChildProcessor(mapFP);
84
85 this->initClassID<NormalMapFP>();
86 }
87
88 class GLSLNormalMapFP : public GrGLSLFragmentProcessor {
89 public:
90 GLSLNormalMapFP() {
91 fNormRotation.set(0.0f, 0.0f);
92 }
93
94 void emitCode(EmitArgs& args) override {
95
96 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
97 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
98
99 // add uniform
100 const char* xformUniName = nullptr;
101 fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
102 kVec2f_GrSLType, kDefault_GrS LPrecision,
103 "Xform", &xformUniName);
104
105 SkString dstNormalColorName("dstNormalColor");
106 this->emitChild(0, nullptr, &dstNormalColorName, args);
107 fragBuilder->codeAppendf("vec3 normal = %s.rgb - vec3(0.5);",
108 dstNormalColorName.c_str());
109
110 // TODO: inverse map the light direction vectors in the vertex shade r rather than
111 // transforming all the normals here!
112 fragBuilder->codeAppendf(
113 "mat3 m = mat3(%s.x, -%s.y, 0.0, %s.y, %s.x, 0.0, 0.0, 0.0, 1.0);",
114 xformUniName, xformUniName, xformUniName, xformUniName);
115
116 fragBuilder->codeAppend("normal = normalize(m*normal);");
117 fragBuilder->codeAppendf("%s = vec4(normal, 0);", args.fOutputColor) ;
118 }
119
120 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
121 GrProcessorKeyBuilder* b) {
122 b->add32(0x0);
123 }
124
125 protected:
126 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
127 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>();
128
129 const SkVector& normRotation = normalMapFP.normRotation();
130 if (normRotation != fNormRotation) {
131 pdman.set2fv(fXformUni, 1, &normRotation.fX);
132 fNormRotation = normRotation;
133 }
134 }
135
136 private:
137 SkVector fNormRotation;
138 GrGLSLProgramDataManager::UniformHandle fXformUni;
139 };
140
141 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
142 GLSLNormalMapFP::GenKey(*this, caps, b);
143 }
144
145 const char* name() const override { return "NormalMapFP"; }
146
147 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
148 inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput);
149 }
150
151 const SkVector& normRotation() const { return fNormRotation; }
152
153 private:
154 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalMapFP; }
155
156 bool onIsEqual(const GrFragmentProcessor& proc) const override {
157 const NormalMapFP& normalMapFP = proc.cast<NormalMapFP>();
158 return fNormRotation == normalMapFP.fNormRotation;
159 }
160
161 SkVector fNormRotation;
162 };
163
164 sk_sp<GrFragmentProcessor> NormalMapSourceImpl::asFragmentProcessor(
165 GrContext *context,
166 const SkMatrix &viewM,
167 const SkMatrix *localMatrix ,
168 SkFilterQuality filterQuali ty,
169 SkSourceGammaTreatment gamm aTreatment) const {
170
171 sk_sp<GrFragmentProcessor> mapFP = fMapShader->asFragmentProcessor(context, viewM,
172 localMatrix, filterQuality, gammaTreatment);
173
174 return sk_make_sp<NormalMapFP>(std::move(mapFP), fNormRotation);
175 }
176
177 #endif // SK_SUPPORT_GPU
178
179 ////////////////////////////////////////////////////////////////////////////
180
181 NormalMapSourceImpl::Provider::Provider(const NormalMapSourceImpl& source,
182 SkShader::Context* mapContext)
183 : fSource(source)
184 , fMapContext(mapContext) {
185 }
186
187 NormalMapSourceImpl::Provider::~Provider() {
188 fMapContext->~Context();
189 }
190
191 SkNormalSource::Provider* NormalMapSourceImpl::asProvider(
192 const SkShader::ContextRec &rec, void *storage) const {
193 SkMatrix normTotalInv;
194 if (!this->computeNormTotalInverse(rec, &normTotalInv)) {
195 return nullptr;
196 }
197
198 void* mapContextStorage = (char*)storage + sizeof(Provider);
199 SkShader::Context* context = fMapShader->createContext(rec, mapContextStorag e);
200 if (!context) {
201 return nullptr;
202 }
203
204 return new (storage) Provider(*this, context);
205 }
206
207 size_t NormalMapSourceImpl::providerSize(const SkShader::ContextRec& rec) const {
208 return sizeof(Provider) + fMapShader->contextSize(rec);
209 }
210
211 bool NormalMapSourceImpl::computeNormTotalInverse(const SkShader::ContextRec& re c,
212 SkMatrix* normTotalInverse) co nst {
213 SkMatrix total;
214 total.setConcat(*rec.fMatrix, fMapShader->getLocalMatrix());
215
216 const SkMatrix* m = &total;
217 if (rec.fLocalMatrix) {
218 total.setConcat(*m, *rec.fLocalMatrix);
219 m = &total;
220 }
221 return m->invert(normTotalInverse);
222 }
223
224 #define BUFFER_MAX 16
225 void NormalMapSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[] ,
226 int count) const {
227 SkPMColor tmpNormalColors[BUFFER_MAX];
228
229 do {
230 int n = SkTMin(count, BUFFER_MAX);
231
232 fMapContext->shadeSpan(x, y, tmpNormalColors, n);
233
234 for (int i = 0; i < n; i++) {
235 SkPoint3 tempNorm;
236
237 tempNorm.set(SkIntToScalar(SkGetPackedR32(tmpNormalColors[i])) - 127 .0f,
238 SkIntToScalar(SkGetPackedG32(tmpNormalColors[i])) - 127 .0f,
239 SkIntToScalar(SkGetPackedB32(tmpNormalColors[i])) - 127 .0f);
240 tempNorm.normalize();
241
242 output[i].fX = fSource.fNormRotation.fX * tempNorm.fX +
243 fSource.fNormRotation.fY * tempNorm.fY;
244 output[i].fY = -fSource.fNormRotation.fY * tempNorm.fX +
245 fSource.fNormRotation.fX * tempNorm.fY;
246 output[i].fZ = tempNorm.fZ;
247 }
248
249 output += n;
250 x += n;
251 count -= n;
252 } while (count > 0);
253 }
254
255 ////////////////////////////////////////////////////////////////////////////////
256
257 sk_sp<SkFlattenable> NormalMapSourceImpl::CreateProc(SkReadBuffer& buf) {
258
259 sk_sp<SkShader> mapShader = buf.readFlattenable<SkShader>();
260
261 SkVector normRotation = {1,0};
262 if (!buf.isVersionLT(SkReadBuffer::kLightingShaderWritesInvNormRotation)) {
263 normRotation = buf.readPoint();
264 }
265
266 return sk_make_sp<NormalMapSourceImpl>(std::move(mapShader), normRotation);
267 }
268
269 void NormalMapSourceImpl::flatten(SkWriteBuffer& buf) const {
270 this->INHERITED::flatten(buf);
271
272 buf.writeFlattenable(fMapShader.get());
273 buf.writePoint(fNormRotation);
274 }
275
276 ////////////////////////////////////////////////////////////////////////////
277
278 sk_sp<SkNormalSource> SkNormalSource::MakeFromNormalMap(sk_sp<SkShader> map,
279 const SkVector &normRota tion) {
280 SkASSERT(SkScalarNearlyEqual(normRotation.lengthSqd(), SK_Scalar1));
281 if (!map) {
282 return nullptr;
283 }
284
285 return sk_make_sp<NormalMapSourceImpl>(std::move(map), normRotation);
286 }
287
288 ////////////////////////////////////////////////////////////////////////////
289
290 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkNormalSource)
291 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(NormalMapSourceImpl)
292 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
293
294 ////////////////////////////////////////////////////////////////////////////
OLDNEW
« no previous file with comments | « src/core/SkNormalSource.h ('k') | src/ports/SkGlobalInitialization_default.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698