3232#include " tools/Resources.h"
3333#include " tools/gpu/YUVUtils.h"
3434
35+ using sk_gpu_test::YUVABackendReleaseContext;
36+
3537class GrRenderTargetContext ;
3638
3739namespace skiagm {
@@ -48,90 +50,128 @@ class ImageFromYUVTextures : public GpuGM {
4850
4951 SkISize onISize () override { return {1420 , 610 }; }
5052
51- static std::unique_ptr<sk_gpu_test::LazyYUVImage> CreatePlanes (const char * name) {
53+ static SkBitmap CreateBmpAndPlanes (const char * name, SkBitmap yuvaBmps[ 4 ] ) {
5254 SkBitmap bmp;
5355 if (!GetResourceAsBitmap (name, &bmp)) {
5456 return {};
5557 }
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);
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);
6972
7073 unsigned char * yuvPixels[] = {
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 ()),
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 ()),
7578 };
7679
7780 float m[20 ];
78- SkColorMatrix_RGB2YUV (pixmaps. yuvaInfo (). yuvColorSpace () , m);
81+ SkColorMatrix_RGB2YUV (kJPEG_SkYUVColorSpace , m);
7982 // Here we encode using the kJPEG_SkYUVColorSpace (i.e., full-swing Rec 601) even though
8083 // we will draw it with all the supported yuv color spaces when converted back to RGB
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);
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);
8487 auto r = (rgba & 0x000000ff ) >> 0 ;
8588 auto g = (rgba & 0x0000ff00 ) >> 8 ;
8689 auto b = (rgba & 0x00ff0000 ) >> 16 ;
8790 auto a = (rgba & 0xff000000 ) >> 24 ;
88- yuvPixels[0 ][j*pixmaps. planes ()[ 0 ] .width () + i] = SkToU8 (
91+ yuvPixels[0 ][j*yaInfo .width () + i] = SkToU8 (
8992 sk_float_round2int (m[0 ]*r + m[1 ]*g + m[2 ]*b + m[3 ]*a + 255 *m[4 ]));
90- yuvPixels[3 ][j*pixmaps. planes ()[ 0 ] .width () + i] = SkToU8 (sk_float_round2int (
93+ yuvPixels[3 ][j*yaInfo .width () + i] = SkToU8 (sk_float_round2int (
9194 m[15 ]*r + m[16 ]*g + m[17 ]*b + m[18 ]*a + 255 *m[19 ]));
9295 }
9396 }
94- for (int j = 0 ; j < pixmaps. planes ()[ 1 ] .height (); ++j) {
95- for (int i = 0 ; i < pixmaps. planes ()[ 1 ] .width (); ++i) {
97+ for (int j = 0 ; j < uvInfo .height (); ++j) {
98+ for (int i = 0 ; i < uvInfo .width (); ++i) {
9699 // Average together 4 pixels of RGB.
97100 int rgba[] = {0 , 0 , 0 , 0 };
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);
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);
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;
109108 }
110109 }
111110 for (int c = 0 ; c < 4 ; ++c) {
112- rgba[c] /= denom ;
111+ rgba[c] /= 4 ;
113112 }
114- int uvIndex = j*pixmaps. planes ()[ 1 ] .width () + i;
113+ int uvIndex = j*uvInfo .width () + i;
115114 yuvPixels[1 ][uvIndex] = SkToU8 (sk_float_round2int (
116115 m[5 ]*rgba[0 ] + m[6 ]*rgba[1 ] + m[7 ]*rgba[2 ] + m[8 ]*rgba[3 ] + 255 *m[9 ]));
117116 yuvPixels[2 ][uvIndex] = SkToU8 (sk_float_round2int (
118117 m[10 ]*rgba[0 ] + m[11 ]*rgba[1 ] + m[12 ]*rgba[2 ] + m[13 ]*rgba[3 ] + 255 *m[14 ]));
119118 }
120119 }
121- return sk_gpu_test::LazyYUVImage::Make ( std::move (pixmaps)) ;
120+ return rgbaBmp ;
122121 }
123122
124- sk_sp<SkImage> makeYUVAImage (GrDirectContext* context) {
125- return fLazyYUVImage ->refImage (context, sk_gpu_test::LazyYUVImage::Type::kFromTextures );
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 ;
126151 }
127152
128- sk_sp<SkImage> createReferenceImage (GrDirectContext* dContext) {
129- auto planarImage = this ->makeYUVAImage (dContext);
130- if (!planarImage) {
153+ sk_sp<SkImage> makeYUVAImage (GrDirectContext* context) {
154+ auto releaseContext = new YUVABackendReleaseContext (context);
155+ SkYUVAIndex indices[4 ];
156+
157+ if (!CreateYUVBackendTextures (context, fYUVABmps , indices, releaseContext)) {
158+ YUVABackendReleaseContext::Unwind (context, releaseContext, false );
131159 return nullptr ;
132160 }
133161
134- auto resultInfo = SkImageInfo::Make (fLazyYUVImage ->dimensions (),
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 (),
135175 kRGBA_8888_SkColorType ,
136176 kPremul_SkAlphaType );
137177 auto resultSurface = SkSurface::MakeRenderTarget (dContext,
@@ -144,7 +184,27 @@ class ImageFromYUVTextures : public GpuGM {
144184 return nullptr ;
145185 }
146186
147- resultSurface->getCanvas ()->drawImage (std::move (planarImage), 0 , 0 );
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 );
148208 return resultSurface->makeImageSnapshot ();
149209 }
150210
@@ -153,9 +213,7 @@ class ImageFromYUVTextures : public GpuGM {
153213 return DrawResult::kSkip ;
154214 }
155215
156- if (!fLazyYUVImage ) {
157- fLazyYUVImage = CreatePlanes (" images/mandrill_32.png" );
158- }
216+ fRGBABmp = CreateBmpAndPlanes (" images/mandrill_32.png" , fYUVABmps );
159217
160218 // We make a version of this image for each draw because, if any draw flattens it to
161219 // RGBA, then all subsequent draws would use the RGBA texture.
@@ -262,7 +320,8 @@ class ImageFromYUVTextures : public GpuGM {
262320 }
263321
264322private:
265- std::unique_ptr<sk_gpu_test::LazyYUVImage> fLazyYUVImage ;
323+ SkBitmap fRGBABmp ; // TODO: oddly, it looks like this could just be an SkISize
324+ SkBitmap fYUVABmps [4 ];
266325
267326 // 3 draws x 3 scales x 4 filter qualities
268327 static constexpr int kNumImages = 3 * 3 * 4 ;
0 commit comments