3232#include " tools/Resources.h"
3333#include " tools/gpu/YUVUtils.h"
3434
35- using sk_gpu_test::YUVABackendReleaseContext;
36-
3735class GrRenderTargetContext ;
3836
3937namespace skiagm {
@@ -50,128 +48,90 @@ class ImageFromYUVTextures : public GpuGM {
5048
5149 SkISize onISize () override { return {1420 , 610 }; }
5250
53- static SkBitmap CreateBmpAndPlanes (const char * name, SkBitmap yuvaBmps[ 4 ] ) {
51+ static std::unique_ptr<sk_gpu_test::LazyYUVImage> CreatePlanes (const char * name) {
5452 SkBitmap bmp;
5553 if (!GetResourceAsBitmap (name, &bmp)) {
5654 return {};
5755 }
58- auto ii = SkImageInfo::Make (bmp.dimensions (), kRGBA_8888_SkColorType , kPremul_SkAlphaType );
59-
60- SkBitmap rgbaBmp;
61- rgbaBmp.allocPixels (ii);
62- bmp.readPixels (rgbaBmp.pixmap (), 0 , 0 );
63-
64- SkImageInfo yaInfo = SkImageInfo::Make (rgbaBmp.dimensions (), kAlpha_8_SkColorType ,
65- kUnpremul_SkAlphaType );
66- yuvaBmps[0 ].allocPixels (yaInfo);
67- SkISize uvSize = {rgbaBmp.width ()/2 , rgbaBmp.height ()/2 };
68- SkImageInfo uvInfo = SkImageInfo::Make (uvSize, kAlpha_8_SkColorType , kUnpremul_SkAlphaType );
69- yuvaBmps[1 ].allocPixels (uvInfo);
70- yuvaBmps[2 ].allocPixels (uvInfo);
71- yuvaBmps[3 ].allocPixels (yaInfo);
56+ if (bmp.colorType () != kRGBA_8888_SkColorType ) {
57+ auto info = bmp.info ().makeColorType (kRGBA_8888_SkColorType );
58+ SkBitmap copy;
59+ copy.allocPixels (info);
60+ SkAssertResult (bmp.readPixels (copy.pixmap ()));
61+ bmp = copy;
62+ }
63+ SkYUVAPixmapInfo pixmapInfo ({bmp.dimensions (),
64+ SkYUVAInfo::PlanarConfig::kY_U_V_A_4204 ,
65+ kJPEG_Full_SkYUVColorSpace },
66+ SkYUVAPixmapInfo::DataType::kUnorm8 ,
67+ nullptr );
68+ auto pixmaps = SkYUVAPixmaps::Allocate (pixmapInfo);
7269
7370 unsigned char * yuvPixels[] = {
74- static_cast <unsigned char *>(yuvaBmps [0 ].getPixels ()),
75- static_cast <unsigned char *>(yuvaBmps [1 ].getPixels ()),
76- static_cast <unsigned char *>(yuvaBmps [2 ].getPixels ()),
77- static_cast <unsigned char *>(yuvaBmps [3 ].getPixels ()),
71+ static_cast <unsigned char *>(pixmaps. planes () [0 ].writable_addr ()),
72+ static_cast <unsigned char *>(pixmaps. planes () [1 ].writable_addr ()),
73+ static_cast <unsigned char *>(pixmaps. planes () [2 ].writable_addr ()),
74+ static_cast <unsigned char *>(pixmaps. planes () [3 ].writable_addr ()),
7875 };
7976
8077 float m[20 ];
81- SkColorMatrix_RGB2YUV (kJPEG_SkYUVColorSpace , m);
78+ SkColorMatrix_RGB2YUV (pixmaps. yuvaInfo (). yuvColorSpace () , m);
8279 // Here we encode using the kJPEG_SkYUVColorSpace (i.e., full-swing Rec 601) even though
8380 // we will draw it with all the supported yuv color spaces when converted back to RGB
84- for (int j = 0 ; j < yaInfo .height (); ++j) {
85- for (int i = 0 ; i < yaInfo .width (); ++i) {
86- auto rgba = *rgbaBmp .getAddr32 (i, j);
81+ for (int j = 0 ; j < pixmaps. planes ()[ 0 ] .height (); ++j) {
82+ for (int i = 0 ; i < pixmaps. planes ()[ 0 ] .width (); ++i) {
83+ auto rgba = *bmp .getAddr32 (i, j);
8784 auto r = (rgba & 0x000000ff ) >> 0 ;
8885 auto g = (rgba & 0x0000ff00 ) >> 8 ;
8986 auto b = (rgba & 0x00ff0000 ) >> 16 ;
9087 auto a = (rgba & 0xff000000 ) >> 24 ;
91- yuvPixels[0 ][j*yaInfo .width () + i] = SkToU8 (
88+ yuvPixels[0 ][j*pixmaps. planes ()[ 0 ] .width () + i] = SkToU8 (
9289 sk_float_round2int (m[0 ]*r + m[1 ]*g + m[2 ]*b + m[3 ]*a + 255 *m[4 ]));
93- yuvPixels[3 ][j*yaInfo .width () + i] = SkToU8 (sk_float_round2int (
90+ yuvPixels[3 ][j*pixmaps. planes ()[ 0 ] .width () + i] = SkToU8 (sk_float_round2int (
9491 m[15 ]*r + m[16 ]*g + m[17 ]*b + m[18 ]*a + 255 *m[19 ]));
9592 }
9693 }
97- for (int j = 0 ; j < uvInfo .height (); ++j) {
98- for (int i = 0 ; i < uvInfo .width (); ++i) {
94+ for (int j = 0 ; j < pixmaps. planes ()[ 1 ] .height (); ++j) {
95+ for (int i = 0 ; i < pixmaps. planes ()[ 1 ] .width (); ++i) {
9996 // Average together 4 pixels of RGB.
10097 int rgba[] = {0 , 0 , 0 , 0 };
101- for (int y = 0 ; y < 2 ; ++y) {
102- for (int x = 0 ; x < 2 ; ++x) {
103- auto src = *rgbaBmp.getAddr32 (2 * i + x, 2 * j + y);
98+ int denom = 0 ;
99+ int ylimit = std::min (2 *j + 2 , pixmaps.planes ()[0 ].height ());
100+ int xlimit = std::min (2 *i + 2 , pixmaps.planes ()[0 ].width ());
101+ for (int y = 2 *j; y < ylimit; ++y) {
102+ for (int x = 2 *i; x < xlimit; ++x) {
103+ auto src = *bmp.getAddr32 (x, y);
104104 rgba[0 ] += (src & 0x000000ff ) >> 0 ;
105105 rgba[1 ] += (src & 0x0000ff00 ) >> 8 ;
106106 rgba[2 ] += (src & 0x00ff0000 ) >> 16 ;
107107 rgba[3 ] += (src & 0xff000000 ) >> 24 ;
108+ ++denom;
108109 }
109110 }
110111 for (int c = 0 ; c < 4 ; ++c) {
111- rgba[c] /= 4 ;
112+ rgba[c] /= denom ;
112113 }
113- int uvIndex = j*uvInfo .width () + i;
114+ int uvIndex = j*pixmaps. planes ()[ 1 ] .width () + i;
114115 yuvPixels[1 ][uvIndex] = SkToU8 (sk_float_round2int (
115116 m[5 ]*rgba[0 ] + m[6 ]*rgba[1 ] + m[7 ]*rgba[2 ] + m[8 ]*rgba[3 ] + 255 *m[9 ]));
116117 yuvPixels[2 ][uvIndex] = SkToU8 (sk_float_round2int (
117118 m[10 ]*rgba[0 ] + m[11 ]*rgba[1 ] + m[12 ]*rgba[2 ] + m[13 ]*rgba[3 ] + 255 *m[14 ]));
118119 }
119120 }
120- return rgbaBmp;
121- }
122-
123- static bool CreateYUVBackendTextures (GrDirectContext* context, SkBitmap bmps[4 ],
124- SkYUVAIndex indices[4 ],
125- YUVABackendReleaseContext* beContext) {
126- for (int i = 0 ; i < 4 ; ++i) {
127- GrBackendTexture tmp = context->createBackendTexture (
128- bmps[i].pixmap (), GrRenderable::kNo , GrProtected::kNo ,
129- YUVABackendReleaseContext::CreationCompleteProc (i),
130- beContext);
131- if (!tmp.isValid ()) {
132- return false ;
133- }
134-
135- beContext->set (i, tmp);
136- }
137-
138- for (int i = 0 ; i < 4 ; ++i) {
139- auto chanMask = beContext->beTexture (i).getBackendFormat ().channelMask ();
140- // We expect the single channel bitmaps to produce single channel textures.
141- SkASSERT (chanMask && SkIsPow2 (chanMask));
142- if (chanMask & kGray_SkColorChannelFlag ) {
143- indices[i].fChannel = SkColorChannel::kR ;
144- } else {
145- indices[i].fChannel = static_cast <SkColorChannel>(31 - SkCLZ (chanMask));
146- }
147- indices[i].fIndex = i;
148- }
149-
150- return true ;
121+ return sk_gpu_test::LazyYUVImage::Make (std::move (pixmaps));
151122 }
152123
153124 sk_sp<SkImage> makeYUVAImage (GrDirectContext* context) {
154- auto releaseContext = new YUVABackendReleaseContext (context);
155- SkYUVAIndex indices[ 4 ];
125+ return fLazyYUVImage -> refImage (context, sk_gpu_test::LazyYUVImage::Type:: kFromTextures );
126+ }
156127
157- if (!CreateYUVBackendTextures (context, fYUVABmps , indices, releaseContext)) {
158- YUVABackendReleaseContext::Unwind (context, releaseContext, false );
128+ sk_sp<SkImage> createReferenceImage (GrDirectContext* dContext) {
129+ auto planarImage = this ->makeYUVAImage (dContext);
130+ if (!planarImage) {
159131 return nullptr ;
160132 }
161133
162- return SkImage::MakeFromYUVATextures (context,
163- kJPEG_SkYUVColorSpace ,
164- releaseContext->beTextures (),
165- indices,
166- fRGBABmp .dimensions (),
167- kTopLeft_GrSurfaceOrigin ,
168- nullptr ,
169- YUVABackendReleaseContext::Release,
170- releaseContext);
171- }
172-
173- sk_sp<SkImage> createReferenceImage (GrDirectContext* dContext) {
174- auto resultInfo = SkImageInfo::Make (fRGBABmp .dimensions (),
134+ auto resultInfo = SkImageInfo::Make (fLazyYUVImage ->dimensions (),
175135 kRGBA_8888_SkColorType ,
176136 kPremul_SkAlphaType );
177137 auto resultSurface = SkSurface::MakeRenderTarget (dContext,
@@ -184,27 +144,7 @@ class ImageFromYUVTextures : public GpuGM {
184144 return nullptr ;
185145 }
186146
187- auto planeReleaseContext = new YUVABackendReleaseContext (dContext);
188- SkYUVAIndex indices[4 ];
189-
190- if (!CreateYUVBackendTextures (dContext, fYUVABmps , indices, planeReleaseContext)) {
191- YUVABackendReleaseContext::Unwind (dContext, planeReleaseContext, false );
192- return nullptr ;
193- }
194-
195- auto tmp = SkImage::MakeFromYUVATextures (dContext,
196- kJPEG_SkYUVColorSpace ,
197- planeReleaseContext->beTextures (),
198- indices,
199- fRGBABmp .dimensions (),
200- kTopLeft_GrSurfaceOrigin ,
201- nullptr );
202- if (!tmp) {
203- YUVABackendReleaseContext::Unwind (dContext, planeReleaseContext, false );
204- return nullptr ;
205- }
206- resultSurface->getCanvas ()->drawImage (std::move (tmp), 0 , 0 );
207- YUVABackendReleaseContext::Unwind (dContext, planeReleaseContext, true );
147+ resultSurface->getCanvas ()->drawImage (std::move (planarImage), 0 , 0 );
208148 return resultSurface->makeImageSnapshot ();
209149 }
210150
@@ -213,7 +153,9 @@ class ImageFromYUVTextures : public GpuGM {
213153 return DrawResult::kSkip ;
214154 }
215155
216- fRGBABmp = CreateBmpAndPlanes (" images/mandrill_32.png" , fYUVABmps );
156+ if (!fLazyYUVImage ) {
157+ fLazyYUVImage = CreatePlanes (" images/mandrill_32.png" );
158+ }
217159
218160 // We make a version of this image for each draw because, if any draw flattens it to
219161 // RGBA, then all subsequent draws would use the RGBA texture.
@@ -320,8 +262,7 @@ class ImageFromYUVTextures : public GpuGM {
320262 }
321263
322264private:
323- SkBitmap fRGBABmp ; // TODO: oddly, it looks like this could just be an SkISize
324- SkBitmap fYUVABmps [4 ];
265+ std::unique_ptr<sk_gpu_test::LazyYUVImage> fLazyYUVImage ;
325266
326267 // 3 draws x 3 scales x 4 filter qualities
327268 static constexpr int kNumImages = 3 * 3 * 4 ;
0 commit comments