Plumb dst color space in many places, rather than "mode"
[platform/upstream/libSkiaSharp.git] / gm / yuvtorgbeffect.cpp
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 #if SK_SUPPORT_GPU
13
14 #include "GrContext.h"
15 #include "GrRenderTargetContextPriv.h"
16 #include "SkBitmap.h"
17 #include "SkGr.h"
18 #include "SkGradientShader.h"
19 #include "batches/GrDrawOp.h"
20 #include "batches/GrRectBatchFactory.h"
21 #include "effects/GrYUVEffect.h"
22
23 #define YSIZE 8
24 #define USIZE 4
25 #define VSIZE 4
26
27 namespace skiagm {
28 /**
29  * This GM directly exercises GrYUVtoRGBEffect.
30  */
31 class YUVtoRGBEffect : public GM {
32 public:
33     YUVtoRGBEffect() {
34         this->setBGColor(0xFFFFFFFF);
35     }
36
37 protected:
38     SkString onShortName() override {
39         return SkString("yuv_to_rgb_effect");
40     }
41
42     SkISize onISize() override {
43         return SkISize::Make(238, 120);
44     }
45
46     void onOnceBeforeDraw() override {
47         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
48         fBmp[0].allocPixels(yinfo);
49         SkImageInfo uinfo = SkImageInfo::MakeA8(USIZE, USIZE);
50         fBmp[1].allocPixels(uinfo);
51         SkImageInfo vinfo = SkImageInfo::MakeA8(VSIZE, VSIZE);
52         fBmp[2].allocPixels(vinfo);
53         unsigned char* pixels[3];
54         for (int i = 0; i < 3; ++i) {
55             pixels[i] = (unsigned char*)fBmp[i].getPixels();
56         }
57         int color[] = {0, 85, 170};
58         const int limit[] = {255, 0, 255};
59         const int invl[]  = {0, 255, 0};
60         const int inc[]   = {1, -1, 1};
61         for (int i = 0; i < 3; ++i) {
62             const size_t nbBytes = fBmp[i].rowBytes() * fBmp[i].height();
63             for (size_t j = 0; j < nbBytes; ++j) {
64                 pixels[i][j] = (unsigned char)color[i];
65                 color[i] = (color[i] == limit[i]) ? invl[i] : color[i] + inc[i];
66             }
67         }
68     }
69
70     void onDraw(SkCanvas* canvas) override {
71         GrRenderTargetContext* renderTargetContext =
72             canvas->internal_private_accessTopLayerRenderTargetContext();
73         if (!renderTargetContext) {
74             skiagm::GM::DrawGpuOnlyMessage(canvas);
75             return;        
76         }
77
78         GrContext* context = canvas->getGrContext();
79         if (!context) {
80             return;
81         }
82
83         sk_sp<GrTexture> texture[3];
84         texture[0].reset(
85             GrRefCachedBitmapTexture(context, fBmp[0], GrSamplerParams::ClampBilerp()));
86         texture[1].reset(
87             GrRefCachedBitmapTexture(context, fBmp[1], GrSamplerParams::ClampBilerp()));
88         texture[2].reset(
89             GrRefCachedBitmapTexture(context, fBmp[2], GrSamplerParams::ClampBilerp()));
90
91         if (!texture[0] || !texture[1] || !texture[2]) {
92             return;
93         }
94
95         constexpr SkScalar kDrawPad = 10.f;
96         constexpr SkScalar kTestPad = 10.f;
97         constexpr SkScalar kColorSpaceOffset = 36.f;
98         SkISize sizes[3] = {{YSIZE, YSIZE}, {USIZE, USIZE}, {VSIZE, VSIZE}};
99
100         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace;
101              ++space) {
102             SkRect renderRect = SkRect::MakeWH(SkIntToScalar(fBmp[0].width()),
103                                                SkIntToScalar(fBmp[0].height()));
104             renderRect.outset(kDrawPad, kDrawPad);
105
106             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
107             SkScalar x = kDrawPad + kTestPad;
108
109             const int indices[6][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
110                                        {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};
111
112             for (int i = 0; i < 6; ++i) {
113                 GrPaint grPaint;
114                 grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
115                 sk_sp<GrFragmentProcessor> fp(
116                         GrYUVEffect::MakeYUVToRGB(texture[indices[i][0]].get(),
117                                                   texture[indices[i][1]].get(),
118                                                   texture[indices[i][2]].get(),
119                                                   sizes,
120                                                   static_cast<SkYUVColorSpace>(space),
121                                                   false));
122                 if (fp) {
123                     SkMatrix viewMatrix;
124                     viewMatrix.setTranslate(x, y);
125                     grPaint.addColorFragmentProcessor(std::move(fp));
126                     sk_sp<GrDrawOp> batch(
127                             GrRectBatchFactory::CreateNonAAFill(GrColor_WHITE, viewMatrix,
128                                                                 renderRect, nullptr, nullptr));
129                     renderTargetContext->priv().testingOnly_drawBatch(grPaint, batch.get());
130                 }
131                 x += renderRect.width() + kTestPad;
132             }
133         }
134      }
135
136 private:
137     SkBitmap fBmp[3];
138
139     typedef GM INHERITED;
140 };
141
142 DEF_GM(return new YUVtoRGBEffect;)
143
144 //////////////////////////////////////////////////////////////////////////////
145
146 class YUVNV12toRGBEffect : public GM {
147 public:
148     YUVNV12toRGBEffect() {
149         this->setBGColor(0xFFFFFFFF);
150     }
151
152 protected:
153     SkString onShortName() override {
154         return SkString("yuv_nv12_to_rgb_effect");
155     }
156
157     SkISize onISize() override {
158         return SkISize::Make(48, 120);
159     }
160
161     void onOnceBeforeDraw() override {
162         SkImageInfo yinfo = SkImageInfo::MakeA8(YSIZE, YSIZE);
163         fBmp[0].allocPixels(yinfo);
164         SkImageInfo uvinfo = SkImageInfo::MakeN32Premul(USIZE, USIZE);
165         fBmp[1].allocPixels(uvinfo);
166         int color[] = {0, 85, 170};
167         const int limit[] = {255, 0, 255};
168         const int invl[] = {0, 255, 0};
169         const int inc[] = {1, -1, 1};
170
171         {
172             unsigned char* pixels = (unsigned char*)fBmp[0].getPixels();
173             const size_t nbBytes = fBmp[0].rowBytes() * fBmp[0].height();
174             for (size_t j = 0; j < nbBytes; ++j) {
175                 pixels[j] = (unsigned char)color[0];
176                 color[0] = (color[0] == limit[0]) ? invl[0] : color[0] + inc[0];
177             }
178         }
179
180         {
181             for (int y = 0; y < fBmp[1].height(); ++y) {
182                 uint32_t* pixels = fBmp[1].getAddr32(0, y);
183                 for (int j = 0; j < fBmp[1].width(); ++j) {
184                     pixels[j] = SkColorSetARGB(0, color[1], color[2], 0);
185                     color[1] = (color[1] == limit[1]) ? invl[1] : color[1] + inc[1];
186                     color[2] = (color[2] == limit[2]) ? invl[2] : color[2] + inc[2];
187                 }
188             }
189         }
190     }
191
192     void onDraw(SkCanvas* canvas) override {
193         GrRenderTargetContext* renderTargetContext =
194             canvas->internal_private_accessTopLayerRenderTargetContext();
195         if (!renderTargetContext) {
196             skiagm::GM::DrawGpuOnlyMessage(canvas);
197             return;
198         }
199
200         GrContext* context = canvas->getGrContext();
201         if (!context) {
202             return;
203         }
204
205         sk_sp<GrTexture> texture[3];
206         texture[0].reset(
207             GrRefCachedBitmapTexture(context, fBmp[0], GrSamplerParams::ClampBilerp()));
208         texture[1].reset(
209             GrRefCachedBitmapTexture(context, fBmp[1], GrSamplerParams::ClampBilerp()));
210         texture[2].reset(
211             GrRefCachedBitmapTexture(context, fBmp[1], GrSamplerParams::ClampBilerp()));
212
213         if (!texture[0] || !texture[1] || !texture[2]) {
214             return;
215         }
216
217         constexpr SkScalar kDrawPad = 10.f;
218         constexpr SkScalar kTestPad = 10.f;
219         constexpr SkScalar kColorSpaceOffset = 36.f;
220         SkISize sizes[3] = {{YSIZE, YSIZE}, {USIZE, USIZE}, {VSIZE, VSIZE}};
221
222         for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
223             SkRect renderRect =
224                 SkRect::MakeWH(SkIntToScalar(fBmp[0].width()), SkIntToScalar(fBmp[0].height()));
225             renderRect.outset(kDrawPad, kDrawPad);
226
227             SkScalar y = kDrawPad + kTestPad + space * kColorSpaceOffset;
228             SkScalar x = kDrawPad + kTestPad;
229
230             GrPaint grPaint;
231             grPaint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
232             sk_sp<GrFragmentProcessor> fp(
233                 GrYUVEffect::MakeYUVToRGB(texture[0].get(), texture[1].get(), texture[2].get(),
234                                           sizes, static_cast<SkYUVColorSpace>(space), true));
235             if (fp) {
236                 SkMatrix viewMatrix;
237                 viewMatrix.setTranslate(x, y);
238                 grPaint.addColorFragmentProcessor(fp);
239                 sk_sp<GrDrawOp> batch(GrRectBatchFactory::CreateNonAAFill(
240                     GrColor_WHITE, viewMatrix, renderRect, nullptr, nullptr));
241                 renderTargetContext->priv().testingOnly_drawBatch(grPaint, batch.get());
242             }
243         }
244     }
245
246 private:
247     SkBitmap fBmp[2];
248
249     typedef GM INHERITED;
250 };
251
252 DEF_GM(return new YUVNV12toRGBEffect;)
253 }
254
255 #endif