• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // This test only works with the GPU backend.
9 
10 #include "gm.h"
11 
12 #include "GrContext.h"
13 #include "GrContextPriv.h"
14 #include "GrProxyProvider.h"
15 #include "GrRenderTargetContextPriv.h"
16 #include "GrTextureProxy.h"
17 #include "SkBitmap.h"
18 #include "SkGr.h"
19 #include "SkGradientShader.h"
20 #include "effects/GrYUVtoRGBEffect.h"
21 #include "ops/GrDrawOp.h"
22 #include "ops/GrFillRectOp.h"
23 
24 #define YSIZE 8
25 #define USIZE 4
26 #define VSIZE 4
27 
28 namespace skiagm {
29 /**
30  * This GM directly exercises GrYUVtoRGBEffect.
31  */
32 class YUVtoRGBEffect : public GM {
33 public:
YUVtoRGBEffect()34     YUVtoRGBEffect() {
35         this->setBGColor(0xFFFFFFFF);
36     }
37 
38 protected:
onShortName()39     SkString onShortName() override {
40         return SkString("yuv_to_rgb_effect");
41     }
42 
onISize()43     SkISize onISize() override {
44         return SkISize::Make(238, 120);
45     }
46 
onOnceBeforeDraw()47     void onOnceBeforeDraw() override {
48         SkBitmap bmp[3];
49         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
50         bmp[0].allocPixels(yinfo);
51         SkImageInfo uinfo = SkImageInfo::MakeA8(USIZE, USIZE);
52         bmp[1].allocPixels(uinfo);
53         SkImageInfo vinfo = SkImageInfo::MakeA8(VSIZE, VSIZE);
54         bmp[2].allocPixels(vinfo);
55         unsigned char* pixels[3];
56         for (int i = 0; i < 3; ++i) {
57             pixels[i] = (unsigned char*)bmp[i].getPixels();
58         }
59         int color[] = {0, 85, 170};
60         const int limit[] = {255, 0, 255};
61         const int invl[]  = {0, 255, 0};
62         const int inc[]   = {1, -1, 1};
63         for (int i = 0; i < 3; ++i) {
64             const size_t nbBytes = bmp[i].rowBytes() * bmp[i].height();
65             for (size_t j = 0; j < nbBytes; ++j) {
66                 pixels[i][j] = (unsigned char)color[i];
67                 color[i] = (color[i] == limit[i]) ? invl[i] : color[i] + inc[i];
68             }
69         }
70         for (int i = 0; i < 3; ++i) {
71             fImage[i] = SkImage::MakeFromBitmap(bmp[i]);
72         }
73     }
74 
onDraw(SkCanvas * canvas)75     void onDraw(SkCanvas* canvas) override {
76         GrRenderTargetContext* renderTargetContext =
77             canvas->internal_private_accessTopLayerRenderTargetContext();
78         if (!renderTargetContext) {
79             skiagm::GM::DrawGpuOnlyMessage(canvas);
80             return;
81         }
82 
83         GrContext* context = canvas->getGrContext();
84         if (!context) {
85             return;
86         }
87 
88         GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
89         sk_sp<GrTextureProxy> proxies[3];
90 
91         for (int i = 0; i < 3; ++i) {
92             proxies[i] = proxyProvider->createTextureProxy(fImage[i], kNone_GrSurfaceFlags, 1,
93                                                            SkBudgeted::kYes, SkBackingFit::kExact);
94             if (!proxies[i]) {
95                 return;
96             }
97         }
98 
99         constexpr SkScalar kDrawPad = 10.f;
100         constexpr SkScalar kTestPad = 10.f;
101         constexpr SkScalar kColorSpaceOffset = 36.f;
102 
103         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
104             SkRect renderRect = SkRect::MakeWH(SkIntToScalar(fImage[0]->width()),
105                                                SkIntToScalar(fImage[0]->height()));
106             renderRect.outset(kDrawPad, kDrawPad);
107 
108             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
109             SkScalar x = kDrawPad + kTestPad;
110 
111             const int indices[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
112                                        {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};
113 
114             for (int i = 0; i < 6; ++i) {
115                 SkYUVAIndex yuvaIndices[4] = {
116                     { indices[i][0], SkColorChannel::kR },
117                     { indices[i][1], SkColorChannel::kR },
118                     { indices[i][2], SkColorChannel::kR },
119                     { -1, SkColorChannel::kA }
120                 };
121 
122                 std::unique_ptr<GrFragmentProcessor> fp(
123                         GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
124                                                static_cast<SkYUVColorSpace>(space),
125                                                GrSamplerState::Filter::kNearest));
126                 if (fp) {
127                     GrPaint grPaint;
128                     grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
129                     grPaint.addColorFragmentProcessor(std::move(fp));
130                     SkMatrix viewMatrix;
131                     viewMatrix.setTranslate(x, y);
132                     renderTargetContext->priv().testingOnly_addDrawOp(
133                             GrFillRectOp::Make(context, std::move(grPaint), GrAAType::kNone,
134                                                viewMatrix, renderRect));
135                 }
136                 x += renderRect.width() + kTestPad;
137             }
138         }
139      }
140 
141 private:
142     sk_sp<SkImage> fImage[3];
143 
144     typedef GM INHERITED;
145 };
146 
147 DEF_GM(return new YUVtoRGBEffect;)
148 
149 //////////////////////////////////////////////////////////////////////////////
150 
151 class YUVNV12toRGBEffect : public GM {
152 public:
YUVNV12toRGBEffect()153     YUVNV12toRGBEffect() {
154         this->setBGColor(0xFFFFFFFF);
155     }
156 
157 protected:
onShortName()158     SkString onShortName() override {
159         return SkString("yuv_nv12_to_rgb_effect");
160     }
161 
onISize()162     SkISize onISize() override {
163         return SkISize::Make(48, 120);
164     }
165 
onOnceBeforeDraw()166     void onOnceBeforeDraw() override {
167         SkBitmap bmp[2];
168         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
169         bmp[0].allocPixels(yinfo);
170         SkImageInfo uvinfo = SkImageInfo::MakeN32Premul(USIZE, USIZE);
171         bmp[1].allocPixels(uvinfo);
172         int color[] = {0, 85, 170};
173         const int limit[] = {255, 0, 255};
174         const int invl[] = {0, 255, 0};
175         const int inc[] = {1, -1, 1};
176 
177         {
178             unsigned char* pixels = (unsigned char*)bmp[0].getPixels();
179             const size_t nbBytes = bmp[0].rowBytes() * bmp[0].height();
180             for (size_t j = 0; j < nbBytes; ++j) {
181                 pixels[j] = (unsigned char)color[0];
182                 color[0] = (color[0] == limit[0]) ? invl[0] : color[0] + inc[0];
183             }
184         }
185 
186         {
187             for (int y = 0; y < bmp[1].height(); ++y) {
188                 uint32_t* pixels = bmp[1].getAddr32(0, y);
189                 for (int j = 0; j < bmp[1].width(); ++j) {
190                     pixels[j] = SkColorSetARGB(0, color[1], color[2], 0);
191                     color[1] = (color[1] == limit[1]) ? invl[1] : color[1] + inc[1];
192                     color[2] = (color[2] == limit[2]) ? invl[2] : color[2] + inc[2];
193                 }
194             }
195         }
196 
197         for (int i = 0; i < 2; ++i) {
198             fImage[i] = SkImage::MakeFromBitmap(bmp[i]);
199         }
200     }
201 
onDraw(SkCanvas * canvas)202     void onDraw(SkCanvas* canvas) override {
203         GrRenderTargetContext* renderTargetContext =
204             canvas->internal_private_accessTopLayerRenderTargetContext();
205         if (!renderTargetContext) {
206             skiagm::GM::DrawGpuOnlyMessage(canvas);
207             return;
208         }
209 
210         GrContext* context = canvas->getGrContext();
211         if (!context) {
212             return;
213         }
214 
215         GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
216         sk_sp<GrTextureProxy> proxies[2];
217 
218         for (int i = 0; i < 2; ++i) {
219             proxies[i] = proxyProvider->createTextureProxy(fImage[i], kNone_GrSurfaceFlags, 1,
220                                                            SkBudgeted::kYes, SkBackingFit::kExact);
221             if (!proxies[i]) {
222                 return;
223             }
224         }
225 
226         SkYUVAIndex yuvaIndices[4] = {
227             {  0, SkColorChannel::kR },
228             {  1, SkColorChannel::kR },
229             {  1, SkColorChannel::kG },
230             { -1, SkColorChannel::kA }
231         };
232 
233         constexpr SkScalar kDrawPad = 10.f;
234         constexpr SkScalar kTestPad = 10.f;
235         constexpr SkScalar kColorSpaceOffset = 36.f;
236 
237         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
238             SkRect renderRect = SkRect::MakeWH(SkIntToScalar(fImage[0]->width()),
239                                                SkIntToScalar(fImage[0]->height()));
240             renderRect.outset(kDrawPad, kDrawPad);
241 
242             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
243             SkScalar x = kDrawPad + kTestPad;
244 
245             GrPaint grPaint;
246             grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
247             auto fp = GrYUVtoRGBEffect::Make(proxies, yuvaIndices,
248                                              static_cast<SkYUVColorSpace>(space),
249                                              GrSamplerState::Filter::kNearest);
250             if (fp) {
251                 SkMatrix viewMatrix;
252                 viewMatrix.setTranslate(x, y);
253                 grPaint.addColorFragmentProcessor(std::move(fp));
254                 std::unique_ptr<GrDrawOp> op(GrFillRectOp::Make(context, std::move(grPaint),
255                         GrAAType::kNone, viewMatrix, renderRect));
256                 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
257             }
258         }
259     }
260 
261 private:
262     sk_sp<SkImage> fImage[2];
263 
264     typedef GM INHERITED;
265 };
266 
267 DEF_GM(return new YUVNV12toRGBEffect;)
268 }
269