Flutter Engine
The Flutter Engine
yuvtorgbsubset.cpp
Go to the documentation of this file.
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/gm.h"
15#include "include/core/SkRect.h"
18#include "include/core/SkSize.h"
24#include "src/gpu/ganesh/SkGr.h"
25#include "tools/gpu/YUVUtils.h"
26
27#include <memory>
28#include <utility>
29
30class SkCanvas;
31
32namespace skiagm {
33
34//////////////////////////////////////////////////////////////////////////////
35
36// This GM tests subsetting YUV multiplanar images where the U and V
37// planes have different resolution from Y. See skbug:8959
38
39class YUVtoRGBSubsetEffect : public GM {
40public:
42 this->setBGColor(0xFFFFFFFF);
43 }
44
45protected:
46 SkString getName() const override { return SkString("yuv_to_rgb_subset_effect"); }
47
48 SkISize getISize() override { return {1310, 540}; }
49
50 void makePixmaps() {
51 SkYUVAInfo yuvaInfo = SkYUVAInfo({8, 8},
55 SkColorType colorTypes[] = {kAlpha_8_SkColorType,
58 SkYUVAPixmapInfo pmapInfo(yuvaInfo, colorTypes, nullptr);
59 fPixmaps = SkYUVAPixmaps::Allocate(pmapInfo);
60
61 unsigned char innerY[16] = {149, 160, 130, 105,
62 160, 130, 105, 149,
63 130, 105, 149, 160,
64 105, 149, 160, 130};
65 unsigned char innerU[4] = {43, 75, 145, 200};
66 unsigned char innerV[4] = {88, 180, 200, 43};
67 int outerYUV[] = {128, 128, 128};
68 SkBitmap bitmaps[3];
69 for (int i = 0; i < 3; ++i) {
70 bitmaps[i].installPixels(fPixmaps.plane(i));
71 bitmaps[i].eraseColor(SkColorSetARGB(outerYUV[i], 0, 0, 0));
72 }
73 SkPixmap innerYPM(SkImageInfo::MakeA8(4, 4), innerY, 4);
74 SkPixmap innerUPM(SkImageInfo::MakeA8(2, 2), innerU, 2);
75 SkPixmap innerVPM(SkImageInfo::MakeA8(2, 2), innerV, 2);
76 bitmaps[0].writePixels(innerYPM, 2, 2);
77 bitmaps[1].writePixels(innerUPM, 1, 1);
78 bitmaps[2].writePixels(innerVPM, 1, 1);
79 }
80
82 auto context = GrAsDirectContext(canvas->recordingContext());
83 skgpu::graphite::Recorder* recorder = nullptr;
84#if defined(SK_GRAPHITE)
85 recorder = canvas->recorder();
86#endif
87 if (!context && !recorder) {
88 return DrawResult::kSkip;
89 }
90
91 if (!fPixmaps.isValid()) {
92 this->makePixmaps();
93 }
94
95 auto lazyYUV = sk_gpu_test::LazyYUVImage::Make(fPixmaps);
96#if defined(SK_GRAPHITE)
97 if (recorder) {
98 fYUVImage = lazyYUV->refImage(recorder, sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
99 } else
100#endif
101 {
102 fYUVImage = lazyYUV->refImage(context, sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
103 }
104
105 return DrawResult::kOk;
106 }
107
108 void onGpuTeardown() override { fYUVImage.reset(); }
109
111 SkString* errorMsg) override {
112 auto context = GrAsDirectContext(canvas->recordingContext());
113 skgpu::graphite::Recorder* recorder = nullptr;
114#if defined(SK_GRAPHITE)
115 recorder = canvas->recorder();
116#endif
117 if (!context && !recorder) {
119 return DrawResult::kSkip;
120 }
121
122 if (!fYUVImage) {
123 *errorMsg = "No valid YUV image generated -- skipping";
124 return DrawResult::kSkip;
125 }
126
127 static const SkFilterMode kFilters[] = {SkFilterMode::kNearest,
129 static const SkIRect kColorRect = SkIRect::MakeLTRB(2, 2, 6, 6);
130
131 // Outset to visualize wrap modes.
132 SkRect rect = SkRect::Make(fYUVImage->dimensions());
133 rect = rect.makeOutset(fYUVImage->width()/2.f, fYUVImage->height()/2.f);
134
135 SkScalar y = kTestPad;
136 // Rows are filter modes.
137 for (uint32_t i = 0; i < std::size(kFilters); ++i) {
138 SkScalar x = kTestPad;
139 // Columns are non-subsetted followed by subsetted with each TileMode in a row
140 for (uint32_t j = 0; j < kSkTileModeCount + 1; ++j) {
142 ctm.postScale(10.f, 10.f);
143
144 const SkIRect* subset = j > 0 ? &kColorRect : nullptr;
145
146 auto tm = SkTileMode::kClamp;
147 if (j > 0) {
148 tm = static_cast<SkTileMode>(j - 1);
149 }
150
151 canvas->save();
152 canvas->concat(ctm);
153 SkSamplingOptions sampling(kFilters[i]);
155 // Draw black rectangle in background so rendering with Decal tilemode matches
156 // the previously used ClampToBorder wrapmode.
157 paint.setColor(SK_ColorBLACK);
158 canvas->drawRect(rect, paint);
159 if (subset) {
160 sk_sp<SkImage> subsetImg;
161#if defined(SK_GRAPHITE)
162 if (recorder) {
163 subsetImg = fYUVImage->makeSubset(recorder, *subset, {false});
164 } else
165#endif
166 {
167 subsetImg = fYUVImage->makeSubset(context, *subset);
168 }
169 SkASSERT(subsetImg);
170 paint.setShader(subsetImg->makeShader(tm, tm,
172 } else {
173 paint.setShader(fYUVImage->makeShader(tm, tm,
175 }
176 canvas->drawRect(rect, paint);
177 canvas->restore();
178 x += rect.width() + kTestPad;
179 }
180
181 y += rect.height() + kTestPad;
182 }
183
184 return DrawResult::kOk;
185 }
186
187private:
188 SkYUVAPixmaps fPixmaps;
189 sk_sp<SkImage> fYUVImage;
190
191 inline static constexpr SkScalar kTestPad = 10.f;
192
193 using INHERITED = GM;
194};
195
196DEF_GM(return new YUVtoRGBSubsetEffect;)
197} // namespace skiagm
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkColorType
Definition: SkColorType.h:19
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColor.h:49
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
@ kJPEG_Full_SkYUVColorSpace
describes full range
Definition: SkImageInfo.h:69
SkFilterMode
SkTileMode
Definition: SkTileMode.h:13
static constexpr int kSkTileModeCount
Definition: SkTileMode.h:39
bool installPixels(const SkImageInfo &info, void *pixels, size_t rowBytes, void(*releaseProc)(void *addr, void *context), void *context)
Definition: SkBitmap.cpp:323
bool writePixels(const SkPixmap &src, int dstX, int dstY)
Definition: SkBitmap.cpp:501
void eraseColor(SkColor4f) const
Definition: SkBitmap.cpp:442
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void restore()
Definition: SkCanvas.cpp:461
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
virtual skgpu::graphite::Recorder * recorder() const
Definition: SkCanvas.cpp:1641
int save()
Definition: SkCanvas.cpp:447
void concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
SkISize dimensions() const
Definition: SkImage.h:297
int width() const
Definition: SkImage.h:285
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkImage.cpp:179
int height() const
Definition: SkImage.h:291
virtual sk_sp< SkImage > makeSubset(GrDirectContext *direct, const SkIRect &subset) const =0
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:360
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
@ kY_U_V
Plane 0: Y, Plane 1: U, Plane 2: V.
@ k420
1 set of UV values for each 2x2 block of Y values.
const SkPixmap & plane(int i) const
static SkYUVAPixmaps Allocate(const SkYUVAPixmapInfo &yuvaPixmapInfo)
bool isValid() const
static std::unique_ptr< LazyYUVImage > Make(sk_sp< SkData > data, skgpu::Mipmapped=skgpu::Mipmapped::kNo, sk_sp< SkColorSpace >=nullptr)
Definition: YUVUtils.cpp:200
void reset(T *ptr=nullptr)
Definition: SkRefCnt.h:310
Definition: gm.h:110
GM(SkColor backgroundColor=SK_ColorWHITE)
Definition: gm.cpp:81
static constexpr char kErrorMsg_DrawSkippedGpuOnly[]
Definition: gm.h:127
void setBGColor(SkColor)
Definition: gm.cpp:159
DrawResult onGpuSetup(SkCanvas *canvas, SkString *errorMsg, GraphiteTestContext *) override
SkString getName() const override
DrawResult onDraw(SkCanvas *canvas, SkString *errorMsg) override
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
double y
double x
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
SkSamplingOptions sampling
Definition: SkRecords.h:337
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
DrawResult
Definition: gm.h:104
Definition: SkRect.h:32
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition: SkRect.h:91
Definition: SkSize.h:16
static SkImageInfo MakeA8(int width, int height)
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669