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

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: rename 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
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) {
robertphillips 2016/01/29 20:33:13 Don't all the 'sizes' need to be the same in this
bsalomon 2016/02/01 20:27:45 Most of these comments are about YUVtoRGBEffect. I
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 {
robertphillips 2016/01/29 20:33:13 1 line ?
bsalomon 2016/02/01 20:27:45 Done.
95 return fColorSpace;
96 }
97
98 class GLSLProcessor : public GrGLSLFragmentProcessor {
99 public:
100 // this class always generates the same code.
101 static void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKey Builder*) {}
102
103 GLSLProcessor(const GrProcessor&) {}
104
robertphillips 2016/01/29 20:33:13 rm virtual ?
bsalomon 2016/02/01 20:27:45 Done.
105 virtual void emitCode(EmitArgs& args) override {
106 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
107
robertphillips 2016/01/29 20:33:13 yuvMatrix -> colorSpaceMat ?
bsalomon 2016/02/01 20:27:45 Done.
108 const char* yuvMatrix = nullptr;
109 fMatrixUni = args.fUniformHandler->addUniform(
110 GrGLSLUniformHandler::k Fragment_Visibility,
111 kMat44f_GrSLType, kDefa ult_GrSLPrecision,
112 "YUVMatrix", &yuvMatrix );
robertphillips 2016/01/29 20:33:13 rm formatting control characters ?
bsalomon 2016/02/01 20:27:45 Done.
113 fragBuilder->codeAppendf("\t%s = vec4(\n\t\t", args.fOutputColor);
114 fragBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0]. c_str(),
115 args.fCoords[0].getType());
116 fragBuilder->codeAppend(".r,\n\t\t");
117 fragBuilder->appendTextureLookup(args.fSamplers[1], args.fCoords[1]. c_str(),
118 args.fCoords[1].getType());
119 fragBuilder->codeAppend(".r,\n\t\t");
120 fragBuilder->appendTextureLookup(args.fSamplers[2], args.fCoords[2]. c_str(),
121 args.fCoords[2].getType());
122 fragBuilder->codeAppendf(".r,\n\t\t1.0) * %s;\n", yuvMatrix);
123 }
124
125 protected:
robertphillips 2016/01/29 20:33:13 rm virtual ?
bsalomon 2016/02/01 20:27:45 Done.
126 virtual void onSetData(const GrGLSLProgramDataManager& pdman,
127 const GrProcessor& processor) override {
128 const YUVtoRGBEffect& yuvEffect = processor.cast<YUVtoRGBEffect>();
129 switch (yuvEffect.getColorSpace()) {
130 case kJPEG_SkYUVColorSpace:
131 pdman.setMatrix4f(fMatrixUni, kJPEGConversionMatrix);
132 break;
133 case kRec601_SkYUVColorSpace:
134 pdman.setMatrix4f(fMatrixUni, kRec601ConversionMatrix);
135 break;
136 case kRec709_SkYUVColorSpace:
137 pdman.setMatrix4f(fMatrixUni, kRec709ConversionMatrix);
138 break;
139 }
140 }
141
142 private:
143 GrGLSLProgramDataManager::UniformHandle fMatrixUni;
144
145 typedef GrGLSLFragmentProcessor INHERITED;
146 };
147
148 private:
149 YUVtoRGBEffect(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture ,
150 const SkMatrix yuvMatrix[3], GrTextureParams::FilterMode uvFi lterMode,
151 SkYUVColorSpace colorSpace)
152 : fYTransform(kLocal_GrCoordSet, yuvMatrix[0], yTexture, GrTextureParams::kN one_FilterMode)
153 , fYAccess(yTexture)
154 , fUTransform(kLocal_GrCoordSet, yuvMatrix[1], uTexture, uvFilterMode)
155 , fUAccess(uTexture, uvFilterMode)
156 , fVTransform(kLocal_GrCoordSet, yuvMatrix[2], vTexture, uvFilterMode)
157 , fVAccess(vTexture, uvFilterMode)
158 , fColorSpace(colorSpace) {
159 this->initClassID<YUVtoRGBEffect>();
160 this->addCoordTransform(&fYTransform);
161 this->addTextureAccess(&fYAccess);
162 this->addCoordTransform(&fUTransform);
163 this->addTextureAccess(&fUAccess);
164 this->addCoordTransform(&fVTransform);
165 this->addTextureAccess(&fVAccess);
166 }
167
168 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
169 return new GLSLProcessor(*this);
170 }
171
robertphillips 2016/01/29 20:33:13 rm virtual ?
bsalomon 2016/02/01 20:27:45 Done.
172 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
173 GrProcessorKeyBuilder* b) const override {
174 GLSLProcessor::GenKey(*this, caps, b);
175 }
176
177 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
178 const YUVtoRGBEffect& s = sBase.cast<YUVtoRGBEffect>();
179 return fColorSpace == s.getColorSpace();
180 }
181
182 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
183 // YUV is opaque
184 inout->setToOther(kA_GrColorComponentFlag, 0xFF << GrColor_SHIFT_A,
185 GrInvariantOutput::kWillNot_ReadInput);
186 }
187
188 GrCoordTransform fYTransform;
189 GrTextureAccess fYAccess;
190 GrCoordTransform fUTransform;
191 GrTextureAccess fUAccess;
192 GrCoordTransform fVTransform;
193 GrTextureAccess fVAccess;
194 SkYUVColorSpace fColorSpace;
195
196 typedef GrFragmentProcessor INHERITED;
197 };
198
199
200 class RGBToYUVEffect : public GrFragmentProcessor {
201 public:
202 enum OutputChannels {
203 // output color r = y, g = u, b = v, a = a
204 kYUV_OutputChannels,
205 // output color rgba = y
206 kY_OutputChannels,
207 // output color r = u, g = v, b = 0, a = a
208 kUV_OutputChannels,
209 // output color rgba = u
210 kU_OutputChannels,
211 // output color rgba = v
212 kV_OutputChannels
213 };
214
215 RGBToYUVEffect(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colorSpace,
216 OutputChannels output)
217 : fColorSpace(colorSpace)
218 , fOutputChannels(output) {
219 this->initClassID<RGBToYUVEffect>();
220 this->registerChildProcessor(rgbFP);
221 }
222
223 const char* name() const override { return "RGBToYUV"; }
224
225 SkYUVColorSpace getColorSpace() const { return fColorSpace; }
226
227 OutputChannels outputChannels() const { return fOutputChannels; }
228
229 class GLSLProcessor : public GrGLSLFragmentProcessor {
230 public:
231 GLSLProcessor(const GrProcessor&) : fLastColorSpace(-1), fLastOutputChan nels(-1) {}
232
robertphillips 2016/01/29 20:33:13 rm virtual ?
bsalomon 2016/02/01 20:27:45 Done.
233 virtual void emitCode(EmitArgs& args) override {
234 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
235 OutputChannels oc = args.fFp.cast<RGBToYUVEffect>().outputChannels() ;
236
237 SkString outputColor("rgbColor");
238 this->emitChild(0, args.fInputColor, &outputColor, args);
239
240 const char* uniName;
241 switch (oc) {
242 case kYUV_OutputChannels:
243 fRGBToYUVUni = args.fUniformHandler->addUniformArray(
244 GrGLSLUniformHandler::kFragment_Visibility,
245 kVec4f_GrSLType, kDefault_GrSLPrecision,
246 "RGBToYUV", 3, &uniName);
247 fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s[0]. rgb) + %s[0].a,"
248 "dot(rgbColor.rgb, %s[1]. rgb) + %s[1].a,"
249 "dot(rgbColor.rgb, %s[2]. rgb) + %s[2].a,"
250 "rgbColor.a);",
251 args.fOutputColor, uniName, uniName , uniName, uniName,
252 uniName, uniName);
253 break;
254 case kUV_OutputChannels:
255 fRGBToYUVUni = args.fUniformHandler->addUniformArray(
256 GrGLSLUniformHandler::kFragment_Visibility,
257 kVec4f_GrSLType, kDefault_GrSLPrecision,
258 "RGBToUV", 2, &uniName);
259 fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s[0]. rgb) + %s[0].a,"
260 "dot(rgbColor.rgb, %s[1]. rgb) + %s[1].a,"
261 "0.0,"
262 "rgbColor.a);",
263 args.fOutputColor, uniName, uniName , uniName, uniName);
264 break;
265 case kY_OutputChannels:
266 case kU_OutputChannels:
267 case kV_OutputChannels:
268 fRGBToYUVUni = args.fUniformHandler->addUniform(
269 GrGLSLUniformHandler::kFragment_Visibility,
270 kVec4f_GrSLType, kDefault_GrSLPrecision,
271 "RGBToYUorV", &uniName);
272 fragBuilder->codeAppendf("%s = vec4(dot(rgbColor.rgb, %s.rgb ) + %s.a);\n",
273 args.fOutputColor, uniName, uniName );
274 break;
275 }
276 }
277
278 private:
279 void onSetData(const GrGLSLProgramDataManager& pdman,
280 const GrProcessor& processor) override {
281 const RGBToYUVEffect& effect = processor.cast<RGBToYUVEffect>();
282 OutputChannels oc = effect.outputChannels();
283 if (effect.getColorSpace() != fLastColorSpace || oc != fLastOutputCh annels) {
284
285 const float* matrix = nullptr;
286 switch (effect.getColorSpace()) {
287 case kJPEG_SkYUVColorSpace:
288 matrix = kJPEGInverseConversionMatrix;
289 break;
290 case kRec601_SkYUVColorSpace:
291 matrix = kRec601InverseConversionMatrix;
292 break;
293 case kRec709_SkYUVColorSpace:
294 matrix = kRec709InverseConversionMatrix;
295 break;
296 }
297 switch (oc) {
298 case kYUV_OutputChannels:
299 pdman.set4fv(fRGBToYUVUni, 3, matrix);
300 break;
301 case kUV_OutputChannels:
302 pdman.set4fv(fRGBToYUVUni, 2, matrix + 4);
303 break;
304 case kY_OutputChannels:
305 pdman.set4fv(fRGBToYUVUni, 1, matrix);
306 break;
307 case kU_OutputChannels:
308 pdman.set4fv(fRGBToYUVUni, 1, matrix + 4);
309 break;
310 case kV_OutputChannels:
311 pdman.set4fv(fRGBToYUVUni, 1, matrix + 8);
312 break;
313 }
314 fLastColorSpace = effect.getColorSpace();
315 }
316 }
317 GrGLSLProgramDataManager::UniformHandle fRGBToYUVUni;
318 int fLastColorSpace;
319 int fLastOutputChannels;
320
321 typedef GrGLSLFragmentProcessor INHERITED;
322 };
323
324 private:
325 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
326 return new GLSLProcessor(*this);
327 }
328
329 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
330 // kY, kU, and kV all generate the same code, just upload different coef ficients.
331 if (kU_OutputChannels == fOutputChannels || kV_OutputChannels == fOutput Channels) {
332 b->add32(kY_OutputChannels);
333 } else {
334 b->add32(fOutputChannels);
335 }
336 }
337
338 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
339 const RGBToYUVEffect& s = sBase.cast<RGBToYUVEffect>();
340 return fColorSpace == s.getColorSpace() && fOutputChannels == s.outputCh annels();
341 }
342
343 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
344 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
345 }
346
347 GrCoordTransform fTransform;
348 GrTextureAccess fAccess;
349 SkYUVColorSpace fColorSpace;
350 OutputChannels fOutputChannels;
351
352 typedef GrFragmentProcessor INHERITED;
353 };
354
355 }
356
357 //////////////////////////////////////////////////////////////////////////////
358
359 const GrFragmentProcessor*
360 GrYUVEffect::CreateYUVToRGB(GrTexture* yTexture, GrTexture* uTexture, GrTexture* vTexture,
361 const SkISize sizes[3], SkYUVColorSpace colorSpace) {
362 SkASSERT(yTexture && uTexture && vTexture && sizes);
363 return YUVtoRGBEffect::Create(yTexture, uTexture, vTexture, sizes, colorSpac e);
364 }
365
366 const GrFragmentProcessor*
367 GrYUVEffect::CreateRGBToYUV(const GrFragmentProcessor* rgbFP, SkYUVColorSpace co lorSpace) {
368 SkASSERT(rgbFP);
369 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kYUV_OutputChan nels);
370 }
371
372 const GrFragmentProcessor*
373 GrYUVEffect::CreateRGBToY(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colo rSpace) {
374 SkASSERT(rgbFP);
375 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kY_OutputChanne ls);
376 }
377
378 const GrFragmentProcessor*
379 GrYUVEffect::CreateRGBToUV(const GrFragmentProcessor* rgbFP, SkYUVColorSpace col orSpace) {
380 SkASSERT(rgbFP);
381 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kUV_OutputChann els);
382 }
383
384 const GrFragmentProcessor*
385 GrYUVEffect::CreateRGBToU(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colo rSpace) {
386 SkASSERT(rgbFP);
387 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kU_OutputChanne ls);
388 }
389
390 const GrFragmentProcessor*
391 GrYUVEffect::CreateRGBToV(const GrFragmentProcessor* rgbFP, SkYUVColorSpace colo rSpace) {
392 SkASSERT(rgbFP);
393 return new RGBToYUVEffect(rgbFP, colorSpace, RGBToYUVEffect::kV_OutputChanne ls);
394 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698