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

Side by Side Diff: src/gpu/effects/GrYUVEffect.cpp

Issue 1513393002: Add ability to extract YUV planes from SkImage (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: gm cleanup Created 4 years, 10 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/gpu/effects/GrYUVEffect.h ('k') | src/gpu/effects/GrYUVtoRGBEffect.h » ('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 2014 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 "GrYUVEffect.h"
9
10 #include "GrCoordTransform.h"
11 #include "GrFragmentProcessor.h"
12 #include "GrInvariantOutput.h"
13 #include "GrProcessor.h"
14 #include "glsl/GrGLSLFragmentProcessor.h"
15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
16 #include "glsl/GrGLSLProgramDataManager.h"
17 #include "glsl/GrGLSLUniformHandler.h"
18
19 namespace {
20
21 static const float kJPEGConversionMatrix[16] = {
22 1.0f, 0.0f, 1.402f, -0.701f,
23 1.0f, -0.34414f, -0.71414f, 0.529f,
24 1.0f, 1.772f, 0.0f, -0.886f,
25 0.0f, 0.0f, 0.0f, 1.0
26 };
27
28 static const float kRec601ConversionMatrix[16] = {
29 1.164f, 0.0f, 1.596f, -0.87075f,
30 1.164f, -0.391f, -0.813f, 0.52925f,
31 1.164f, 2.018f, 0.0f, -1.08175f,
32 0.0f, 0.0f, 0.0f, 1.0}
33 ;
34
35 static const float kRec709ConversionMatrix[16] = {
36 1.164f, 0.0f, 1.793f, -0.96925f,
37 1.164f, -0.213f, -0.533f, 0.30025f,
38 1.164f, 2.112f, 0.0f, -1.12875f,
39 0.0f, 0.0f, 0.0f, 1.0f}
40 ;
41
42 static const float kJPEGInverseConversionMatrix[16] = {
43 0.299001f, 0.586998f, 0.114001f, 0.0000821798f,
44 -0.168736f, -0.331263f, 0.499999f, 0.499954f,
45 0.499999f, -0.418686f, -0.0813131f, 0.499941f,
46 0.f, 0.f, 0.f, 1.f
47 };
48
49 static const float kRec601InverseConversionMatrix[16] = {
50 0.256951f, 0.504421f, 0.0977346f, 0.0625f,
51 -0.148212f, -0.290954f, 0.439166f, 0.5f,
52 0.439166f, -0.367886f, -0.0712802f, 0.5f,
53 0.f, 0.f, 0.f, 1.f
54 };
55
56 static const float kRec709InverseConversionMatrix[16] = {
57 0.182663f, 0.614473f, 0.061971f, 0.0625f,
58 -0.100672f, -0.338658f, 0.43933f, 0.5f,
59 0.439142f, -0.39891f, -0.040231f, 0.5f,
60 0.f, 0.f, 0.f, 1.
61 };
62
63 class YUVtoRGBEffect : public GrFragmentProcessor {
64 public:
65 static GrFragmentProcessor* Create(GrTexture* yTexture, GrTexture* uTexture,
66 GrTexture* vTexture, const SkISize sizes[ 3],
67 SkYUVColorSpace colorSpace) {
68 SkScalar w[3], h[3];
69 w[0] = SkIntToScalar(sizes[0].fWidth) / SkIntToScalar(yTexture->width() );
70 h[0] = SkIntToScalar(sizes[0].fHeight) / SkIntToScalar(yTexture->height( ));
71 w[1] = SkIntToScalar(sizes[1].fWidth) / SkIntToScalar(uTexture->width() );
72 h[1] = SkIntToScalar(sizes[1].fHeight) / SkIntToScalar(uTexture->height( ));
73 w[2] = SkIntToScalar(sizes[2].fWidth) / SkIntToScalar(vTexture->width() );
74 h[2] = SkIntToScalar(sizes[2].fHeight) / SkIntToScalar(vTexture->height( ));
75 SkMatrix yuvMatrix[3];
76 yuvMatrix[0] = GrCoordTransform::MakeDivByTextureWHMatrix(yTexture);
77 yuvMatrix[1] = yuvMatrix[0];
78 yuvMatrix[1].preScale(w[1] / w[0], h[1] / h[0]);
79 yuvMatrix[2] = yuvMatrix[0];
80 yuvMatrix[2].preScale(w[2] / w[0], h[2] / h[0]);
81 GrTextureParams::FilterMode uvFilterMode =
82 ((sizes[1].fWidth != sizes[0].fWidth) ||
83 (sizes[1].fHeight != sizes[0].fHeight) ||
84 (sizes[2].fWidth != sizes[0].fWidth) ||
85 (sizes[2].fHeight != sizes[0].fHeight)) ?
86 GrTextureParams::kBilerp_FilterMode :
87 GrTextureParams::kNone_FilterMode;
88 return new YUVtoRGBEffect(yTexture, uTexture, vTexture, yuvMatrix, uvFil terMode,
89 colorSpace);
90 }
91
92 const char* name() const override { return "YUV to RGB"; }
93
94 SkYUVColorSpace getColorSpace() const { return fColorSpace; }
95
96 class GLSLProcessor : public GrGLSLFragmentProcessor {
97 public:
98 // this class always generates the same code.
99 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKey Builder*) {}
100
101 GLSLProcessor(const GrProcessor&) {}
102
103 void emitCode(EmitArgs& args) override {
104 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
105
106 const char* colorSpaceMatrix = nullptr;
107 fMatrixUni = args.fUniformHandler->addUniform(
108 GrGLSLUniformHandler::k Fragment_Visibility,
109 kMat44f_GrSLType, kDefa ult_GrSLPrecision,
110 "ColorSpaceMatrix", &co lorSpaceMatrix);
111 fragBuilder->codeAppendf("%s = vec4(", args.fOutputColor);
112 fragBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0]. c_str(),
113 args.fCoords[0].getType());
114 fragBuilder->codeAppend(".r,");
115 fragBuilder->appendTextureLookup(args.fSamplers[1], args.fCoords[1]. c_str(),
116 args.fCoords[1].getType());
117 fragBuilder->codeAppend(".r,");
118 fragBuilder->appendTextureLookup(args.fSamplers[2], args.fCoords[2]. c_str(),
119 args.fCoords[2].getType());
120 fragBuilder->codeAppendf(".r, 1.0) * %s;", colorSpaceMatrix);
121 }
122
123 protected:
124 void onSetData(const GrGLSLProgramDataManager& pdman,
125 const GrProcessor& processor) override {
126 const YUVtoRGBEffect& yuvEffect = processor.cast<YUVtoRGBEffect>();
127 switch (yuvEffect.getColorSpace()) {
128 case kJPEG_SkYUVColorSpace:
129 pdman.setMatrix4f(fMatrixUni, kJPEGConversionMatrix);
130 break;
131 case kRec601_SkYUVColorSpace:
132 pdman.setMatrix4f(fMatrixUni, kRec601ConversionMatrix);
133 break;
134 case kRec709_SkYUVColorSpace:
135 pdman.setMatrix4f(fMatrixUni, kRec709ConversionMatrix);
136 break;
137 }
138 }
139
140 private:
141 GrGLSLProgramDataManager::UniformHandle fMatrixUni;
142
143 typedef GrGLSLFragmentProcessor INHERITED;
144 };
145
146 private:
147 YUVtoRGBEffect(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture ,
148 const SkMatrix yuvMatrix[3], GrTextureParams::FilterMode uvFi lterMode,
149 SkYUVColorSpace colorSpace)
150 : fYTransform(kLocal_GrCoordSet, yuvMatrix[0], yTexture, GrTextureParams::kN one_FilterMode)
151 , fYAccess(yTexture)
152 , fUTransform(kLocal_GrCoordSet, yuvMatrix[1], uTexture, uvFilterMode)
153 , fUAccess(uTexture, uvFilterMode)
154 , fVTransform(kLocal_GrCoordSet, yuvMatrix[2], vTexture, uvFilterMode)
155 , fVAccess(vTexture, uvFilterMode)
156 , fColorSpace(colorSpace) {
157 this->initClassID<YUVtoRGBEffect>();
158 this->addCoordTransform(&fYTransform);
159 this->addTextureAccess(&fYAccess);
160 this->addCoordTransform(&fUTransform);
161 this->addTextureAccess(&fUAccess);
162 this->addCoordTransform(&fVTransform);
163 this->addTextureAccess(&fVAccess);
164 }
165
166 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
167 return new GLSLProcessor(*this);
168 }
169
170 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
171 GLSLProcessor::GenKey(*this, caps, b);
172 }
173
174 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
175 const YUVtoRGBEffect& s = sBase.cast<YUVtoRGBEffect>();
176 return fColorSpace == s.getColorSpace();
177 }
178
179 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
180 // YUV is opaque
181 inout->setToOther(kA_GrColorComponentFlag, 0xFF << GrColor_SHIFT_A,
182 GrInvariantOutput::kWillNot_ReadInput);
183 }
184
185 GrCoordTransform fYTransform;
186 GrTextureAccess fYAccess;
187 GrCoordTransform fUTransform;
188 GrTextureAccess fUAccess;
189 GrCoordTransform fVTransform;
190 GrTextureAccess fVAccess;
191 SkYUVColorSpace fColorSpace;
192
193 typedef GrFragmentProcessor INHERITED;
194 };
195
196
197 class RGBToYUVEffect : public GrFragmentProcessor {
198 public:
199 enum OutputChannels {
200 // output color r = y, g = u, b = v, a = a
201 kYUV_OutputChannels,
202 // output color rgba = y
203 kY_OutputChannels,
204 // output color r = u, g = v, b = 0, a = a
205 kUV_OutputChannels,
206 // output color rgba = u
207 kU_OutputChannels,
208 // output color rgba = v
209 kV_OutputChannels
210 };
211
212 RGBToYUVEffect(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colorSpace,
213 OutputChannels output)
214 : fColorSpace(colorSpace)
215 , fOutputChannels(output) {
216 this->initClassID<RGBToYUVEffect>();
217 this->registerChildProcessor(rgbFP);
218 }
219
220 const char* name() const override { return "RGBToYUV"; }
221
222 SkYUVColorSpace getColorSpace() const { return fColorSpace; }
223
224 OutputChannels outputChannels() const { return fOutputChannels; }
225
226 class GLSLProcessor : public GrGLSLFragmentProcessor {
227 public:
228 GLSLProcessor(const GrProcessor&) : fLastColorSpace(-1), fLastOutputChan nels(-1) {}
229
230 void emitCode(EmitArgs& args) override {
231 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
232 OutputChannels oc = args.fFp.cast<RGBToYUVEffect>().outputChannels() ;
233
234 SkString outputColor("rgbColor");
235 this->emitChild(0, args.fInputColor, &outputColor, args);
236
237 const char* uniName;
238 switch (oc) {
239 case kYUV_OutputChannels:
240 fRGBToYUVUni = args.fUniformHandler->addUniformArray(
241 GrGLSLUniformHandler::kFragment_Visibility,
242 kVec4f_GrSLType, kDefault_GrSLPrecision,
243 "RGBToYUV", 3, &uniName);
244 fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s[0]. rgb) + %s[0].a,"
245 "dot(rgbColor.rgb, %s[1]. rgb) + %s[1].a,"
246 "dot(rgbColor.rgb, %s[2]. rgb) + %s[2].a,"
247 "rgbColor.a);",
248 args.fOutputColor, uniName, uniName , uniName, uniName,
249 uniName, uniName);
250 break;
251 case kUV_OutputChannels:
252 fRGBToYUVUni = args.fUniformHandler->addUniformArray(
253 GrGLSLUniformHandler::kFragment_Visibility,
254 kVec4f_GrSLType, kDefault_GrSLPrecision,
255 "RGBToUV", 2, &uniName);
256 fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s[0]. rgb) + %s[0].a,"
257 "dot(rgbColor.rgb, %s[1]. rgb) + %s[1].a,"
258 "0.0,"
259 "rgbColor.a);",
260 args.fOutputColor, uniName, uniName , uniName, uniName);
261 break;
262 case kY_OutputChannels:
263 case kU_OutputChannels:
264 case kV_OutputChannels:
265 fRGBToYUVUni = args.fUniformHandler->addUniform(
266 GrGLSLUniformHandler::kFragment_Visibility,
267 kVec4f_GrSLType, kDefault_GrSLPrecision,
268 "RGBToYUorV", &uniName);
269 fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s.rgb ) + %s.a);\n",
270 args.fOutputColor, uniName, uniName );
271 break;
272 }
273 }
274
275 private:
276 void onSetData(const GrGLSLProgramDataManager& pdman,
277 const GrProcessor& processor) override {
278 const RGBToYUVEffect& effect = processor.cast<RGBToYUVEffect>();
279 OutputChannels oc = effect.outputChannels();
280 if (effect.getColorSpace() != fLastColorSpace || oc != fLastOutputCh annels) {
281
282 const float* matrix = nullptr;
283 switch (effect.getColorSpace()) {
284 case kJPEG_SkYUVColorSpace:
285 matrix = kJPEGInverseConversionMatrix;
286 break;
287 case kRec601_SkYUVColorSpace:
288 matrix = kRec601InverseConversionMatrix;
289 break;
290 case kRec709_SkYUVColorSpace:
291 matrix = kRec709InverseConversionMatrix;
292 break;
293 }
294 switch (oc) {
295 case kYUV_OutputChannels:
296 pdman.set4fv(fRGBToYUVUni, 3, matrix);
297 break;
298 case kUV_OutputChannels:
299 pdman.set4fv(fRGBToYUVUni, 2, matrix + 4);
300 break;
301 case kY_OutputChannels:
302 pdman.set4fv(fRGBToYUVUni, 1, matrix);
303 break;
304 case kU_OutputChannels:
305 pdman.set4fv(fRGBToYUVUni, 1, matrix + 4);
306 break;
307 case kV_OutputChannels:
308 pdman.set4fv(fRGBToYUVUni, 1, matrix + 8);
309 break;
310 }
311 fLastColorSpace = effect.getColorSpace();
312 }
313 }
314 GrGLSLProgramDataManager::UniformHandle fRGBToYUVUni;
315 int fLastColorSpace;
316 int fLastOutputChannels;
317
318 typedef GrGLSLFragmentProcessor INHERITED;
319 };
320
321 private:
322 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
323 return new GLSLProcessor(*this);
324 }
325
326 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
327 // kY, kU, and kV all generate the same code, just upload different coef ficients.
328 if (kU_OutputChannels == fOutputChannels || kV_OutputChannels == fOutput Channels) {
329 b->add32(kY_OutputChannels);
330 } else {
331 b->add32(fOutputChannels);
332 }
333 }
334
335 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
336 const RGBToYUVEffect& s = sBase.cast<RGBToYUVEffect>();
337 return fColorSpace == s.getColorSpace() && fOutputChannels == s.outputCh annels();
338 }
339
340 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
341 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
342 }
343
344 GrCoordTransform fTransform;
345 GrTextureAccess fAccess;
346 SkYUVColorSpace fColorSpace;
347 OutputChannels fOutputChannels;
348
349 typedef GrFragmentProcessor INHERITED;
350 };
351
352 }
353
354 //////////////////////////////////////////////////////////////////////////////
355
356 const GrFragmentProcessor*
357 GrYUVEffect::CreateYUVToRGB(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
358 const SkISize sizes[3], SkYUVColorSpace colorSpace) {
359 SkASSERT(yTexture && uTexture && vTexture && sizes);
360 return YUVtoRGBEffect::Create(yTexture, uTexture, vTexture, sizes, colorSpac e);
361 }
362
363 const GrFragmentProcessor*
364 GrYUVEffect::CreateRGBToYUV(const GrFragmentProcessor* rgbFP, SkYUVColorSpace co lorSpace) {
365 SkASSERT(rgbFP);
366 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kYUV_OutputChan nels);
367 }
368
369 const GrFragmentProcessor*
370 GrYUVEffect::CreateRGBToY(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colo rSpace) {
371 SkASSERT(rgbFP);
372 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kY_OutputChanne ls);
373 }
374
375 const GrFragmentProcessor*
376 GrYUVEffect::CreateRGBToUV(const GrFragmentProcessor* rgbFP, SkYUVColorSpace col orSpace) {
377 SkASSERT(rgbFP);
378 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kUV_OutputChann els);
379 }
380
381 const GrFragmentProcessor*
382 GrYUVEffect::CreateRGBToU(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colo rSpace) {
383 SkASSERT(rgbFP);
384 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kU_OutputChanne ls);
385 }
386
387 const GrFragmentProcessor*
388 GrYUVEffect::CreateRGBToV(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colo rSpace) {
389 SkASSERT(rgbFP);
390 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kV_OutputChanne ls);
391 }
OLDNEW
« no previous file with comments | « src/gpu/effects/GrYUVEffect.h ('k') | src/gpu/effects/GrYUVtoRGBEffect.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698