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

Side by Side Diff: src/gpu/GrTextureToYUVPlanes.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 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 "GrTextureToYUVPlanes.h"
9 #include "effects/GrSimpleTextureEffect.h"
10 #include "effects/GrYUVEffect.h"
11 #include "GrClip.h"
12 #include "GrContext.h"
13 #include "GrDrawContext.h"
14 #include "GrPaint.h"
15 #include "GrTextureProvider.h"
16
17 namespace {
18 using CreateFPProc = const GrFragmentProcessor* (*)(const GrFragmentProcesso r*,
19 SkYUVColorSpace colorSpa ce);
20 };
21
22 static bool convert_texture(GrTexture* src, GrDrawContext* dst, int dstW, int ds tH,
23 SkYUVColorSpace colorSpace, CreateFPProc proc) {
24
25 SkScalar xScale = SkIntToScalar(src->width()) / dstW / src->width();
26 SkScalar yScale = SkIntToScalar(src->height()) / dstH / src->height();
27 GrTextureParams::FilterMode filter;
28 if (dstW == src->width() && dstW == src->height()) {
29 filter = GrTextureParams::kNone_FilterMode;
30 } else {
31 filter = GrTextureParams::kBilerp_FilterMode;
32 }
33
34 SkAutoTUnref<const GrFragmentProcessor> fp(
35 GrSimpleTextureEffect::Create(src, SkMatrix::MakeScale(xScale, yScal e), filter));
36 if (!fp) {
37 return false;
38 }
39 fp.reset(proc(fp, colorSpace));
40 if (!fp) {
41 return false;
42 }
43 GrPaint paint;
44 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
45 paint.addColorFragmentProcessor(fp);
46 dst->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), SkRect::MakeIWH(dstW , dstH));
47 return true;
48 }
49
50 bool GrTextureToYUVPlanes(GrTexture* texture, const SkISize sizes[3], void* cons t planes[3],
51 const size_t rowBytes[3], SkYUVColorSpace colorSpace) {
52 if (GrContext* context = texture->getContext()) {
53 // Depending on the relative sizes of the y, u, and v planes we may do 1 to 3 draws/
54 // readbacks.
55 SkAutoTUnref<GrTexture> yuvTex;
56 SkAutoTUnref<GrTexture> yTex;
57 SkAutoTUnref<GrTexture> uvTex;
58 SkAutoTUnref<GrTexture> uTex;
59 SkAutoTUnref<GrTexture> vTex;
60
61 GrPixelConfig singleChannelPixelConfig;
62 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
63 singleChannelPixelConfig = kAlpha_8_GrPixelConfig;
64 } else {
65 singleChannelPixelConfig = kRGBA_8888_GrPixelConfig;
66 }
67
68 if (sizes[0] == sizes[1] && sizes[1] == sizes[2]) {
robertphillips 2016/01/29 20:33:13 // YUV444 - only 1 draw/readback ?
bsalomon 2016/02/01 20:27:45 I put a comment above the first if about the three
69 GrSurfaceDesc yuvDesc;
70 yuvDesc.fConfig = kRGBA_8888_GrPixelConfig;
71 yuvDesc.fFlags = kRenderTarget_GrSurfaceFlag;
72 yuvDesc.fWidth = sizes[0].fWidth;
73 yuvDesc.fHeight = sizes[0].fHeight;
74 yuvTex.reset(context->textureProvider()->createApproxTexture(yuvDesc ));
75 if (!yuvTex) {
76 return false;
77 }
78 } else {
79 GrSurfaceDesc yDesc;
80 yDesc.fConfig = singleChannelPixelConfig;
81 yDesc.fFlags = kRenderTarget_GrSurfaceFlag;
82 yDesc.fWidth = sizes[0].fWidth;
83 yDesc.fHeight = sizes[0].fHeight;
84 yTex.reset(context->textureProvider()->createApproxTexture(yDesc));
85 if (!yTex) {
86 return false;
87 }
88 if (sizes[1] == sizes[2]) {
robertphillips 2016/01/29 20:33:13 // Something like 422 or 411 - only 2 draws/readba
89 GrSurfaceDesc uvDesc;
90 // TODO: Add support for GL_RG when available.
91 uvDesc.fConfig = kRGBA_8888_GrPixelConfig;
92 uvDesc.fFlags = kRenderTarget_GrSurfaceFlag;
93 uvDesc.fWidth = sizes[1].fWidth;
94 uvDesc.fHeight = sizes[1].fHeight;
95 uvTex.reset(context->textureProvider()->createApproxTexture(uvDe sc));
96 if (!uvTex) {
97 return false;
98 }
99 } else {
robertphillips 2016/01/29 20:33:13 // Each channel is different sized - 3 draws/readb
100 GrSurfaceDesc uvDesc;
101 uvDesc.fConfig = singleChannelPixelConfig;
102 uvDesc.fFlags = kRenderTarget_GrSurfaceFlag;
103 uvDesc.fWidth = sizes[1].fWidth;
104 uvDesc.fHeight = sizes[1].fHeight;
105 uTex.reset(context->textureProvider()->createApproxTexture(uvDes c));
106 uvDesc.fWidth = sizes[2].fWidth;
107 uvDesc.fHeight = sizes[2].fHeight;
108 vTex.reset(context->textureProvider()->createApproxTexture(uvDes c));
109 if (!uTex || !vTex) {
110 return false;
111 }
112 }
113 }
114
115 // Do all the draws before any readback.
116 if (yuvTex) {
117 SkAutoTUnref<GrDrawContext> dc(context->drawContext(yuvTex->asRender Target()));
118 if (!dc) {
119 return false;
120 }
121 if (!convert_texture(texture, dc, sizes[0].fWidth, sizes[0].fHeight, colorSpace,
122 GrYUVEffect::CreateRGBToYUV)) {
123 return false;
124 }
125
126 } else {
127 SkASSERT(yTex);
128 SkAutoTUnref<GrDrawContext> dc(context->drawContext(yTex->asRenderTa rget()));
129 if (!dc) {
130 return false;
131 }
132 if (!convert_texture(texture, dc, sizes[0].fWidth, sizes[0].fHeight, colorSpace,
133 GrYUVEffect::CreateRGBToY)) {
134 return false;
135 }
136 if (uvTex) {
137 dc.reset(context->drawContext(uvTex->asRenderTarget()));
138 if (!dc) {
139 return false;
140 }
141 if (!convert_texture(texture, dc, sizes[1].fWidth, sizes[1].fHei ght,
142 colorSpace, GrYUVEffect::CreateRGBToUV)) {
143 return false;
144 }
145 } else {
146 SkASSERT(uTex && vTex);
147 dc.reset(context->drawContext(uTex->asRenderTarget()));
148 if (!dc) {
149 return false;
150 }
151 if (!convert_texture(texture, dc, sizes[1].fWidth, sizes[1].fHei ght,
152 colorSpace, GrYUVEffect::CreateRGBToU)) {
153 return false;
154 }
155 dc.reset(context->drawContext(vTex->asRenderTarget()));
156 if (!dc) {
157 return false;
158 }
159 if (!convert_texture(texture, dc, sizes[2].fWidth, sizes[2].fHei ght,
160 colorSpace, GrYUVEffect::CreateRGBToV)) {
161 return false;
162 }
163 }
164 }
165
166 if (yuvTex) {
robertphillips 2016/01/29 20:33:13 The use of sizes[0], [1] & [2] mildly bothers me h
bsalomon 2016/02/01 20:27:45 Compromise - assert and then use another scoped va
167 // We have no kRGB_888 pixel format, so readback rgba and then copy three channels.
168 SkAutoSTMalloc<128 * 128, uint32_t> tempYUV(sizes[0].fWidth * sizes[ 0].fHeight);
169 if (!yuvTex->readPixels(0, 0, sizes[0].fWidth, sizes[0].fHeight,
170 kRGBA_8888_GrPixelConfig, tempYUV.get(), 0)) {
171 return false;
172 }
173 size_t yRowBytes = rowBytes[0] ? rowBytes[0] : sizes[0].fWidth;
174 size_t uRowBytes = rowBytes[1] ? rowBytes[1] : sizes[1].fWidth;
175 size_t vRowBytes = rowBytes[2] ? rowBytes[2] : sizes[2].fWidth;
176 for (int j = 0; j < sizes[1].fHeight; ++j) {
177 for (int i = 0; i < sizes[1].fWidth; ++i) {
178 // These writes could surely be made more efficient.
179 uint32_t y = GrColorUnpackR(tempYUV.get()[j * sizes[1].fWidt h + i]);
180 uint32_t u = GrColorUnpackG(tempYUV.get()[j * sizes[1].fWidt h + i]);
181 uint32_t v = GrColorUnpackB(tempYUV.get()[j * sizes[1].fWidt h + i]);
182 uint8_t* yLoc = ((uint8_t*)planes[0]) + j * yRowBytes + i;
183 uint8_t* uLoc = ((uint8_t*)planes[1]) + j * uRowBytes + i;
184 uint8_t* vLoc = ((uint8_t*)planes[2]) + j * vRowBytes + i;
185 *yLoc = y;
186 *uLoc = u;
187 *vLoc = v;
188 }
189 }
190 return true;
191 } else {
192 SkASSERT(yTex);
193 if (!yTex->readPixels(0, 0, sizes[0].fWidth, sizes[0].fHeight,
194 kAlpha_8_GrPixelConfig, planes[0], rowBytes[0] )) {
195 return false;
196 }
197 if (uvTex) {
198 // We have no kRG_88 pixel format, so readback rgba and then cop y two channels.
199 SkAutoSTMalloc<128 * 128, uint32_t> tempUV(sizes[1].fWidth * siz es[1].fHeight);
200 if (!uvTex->readPixels(0, 0, sizes[1].fWidth, sizes[1].fHeight,
201 kRGBA_8888_GrPixelConfig, tempUV.get(), 0 )) {
202 return false;
203 }
robertphillips 2016/01/29 20:33:13 SkASSERT(sizes[1].fWidth == sizes[2].fWidth); ?
bsalomon 2016/02/01 20:27:45 Done.
204 size_t uRowBytes = rowBytes[1] ? rowBytes[1] : sizes[1].fWidth;
205 size_t vRowBytes = rowBytes[2] ? rowBytes[2] : sizes[2].fWidth;
206 for (int j = 0; j < sizes[1].fHeight; ++j) {
207 for (int i = 0; i < sizes[1].fWidth; ++i) {
208 // These writes could surely be made more efficient.
209 uint32_t u = GrColorUnpackR(tempUV.get()[j * sizes[1].fW idth + i]);
210 uint32_t v = GrColorUnpackG(tempUV.get()[j * sizes[1].fW idth + i]);
211 uint8_t* uLoc = ((uint8_t*)planes[1]) + j * uRowBytes + i;
212 uint8_t* vLoc = ((uint8_t*)planes[2]) + j * vRowBytes + i;
213 *uLoc = u;
214 *vLoc = v;
215 }
216 }
217 return true;
218 } else {
219 SkASSERT(uTex && vTex);
220 if (!uTex->readPixels(0, 0, sizes[1].fWidth, sizes[1].fHeight,
221 kAlpha_8_GrPixelConfig, planes[1], rowByte s[1])) {
222 return false;
223 }
224 if (!vTex->readPixels(0, 0, sizes[2].fWidth, sizes[2].fHeight,
225 kAlpha_8_GrPixelConfig, planes[2], rowByte s[2])) {
226 return false;
227 }
228 return true;
229 }
230 }
231 }
232 return false;
233 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698