Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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,
171 sampling, SkMatrix::Translate(2, 2)));
172 } else {
173 paint.setShader(fYUVImage->makeShader(tm, tm,
174 sampling, SkMatrix::I()));
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)
void restore()
Definition SkCanvas.cpp:465
virtual GrRecordingContext * recordingContext() const
virtual skgpu::graphite::Recorder * recorder() const
int save()
Definition SkCanvas.cpp:451
void concat(const SkMatrix &matrix)
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()
@ 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
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
float SkScalar
Definition extension.cpp:12
#define DEF_GM(CODE)
Definition gm.h:40
double y
double x
DrawResult
Definition gm.h:104
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition SkRect.h:91
static SkImageInfo MakeA8(int width, int height)
static SkRect Make(const SkISize &size)
Definition SkRect.h:669