Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit db0288d

Browse files
bsalomonSkia Commit-Bot
authored andcommitted
Move all YUVA image creation in GMs into sk_gpu_test::LazyYUVImage.
LazyYUVImage now supports making images from a generator and from textures. It uses ManagedBackendTexture to manage texture plane lifetime via ref-counting. Adds some supporting utility functions to SkYUVAInfo and SkYUVAPixmaps. Eases transition of forthcoming MakeFromYUVATextures API change. Bug: skia:10632 Change-Id: I8cfd747c27076d1627da6ea8a169e554a96049e0 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326720 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
1 parent 1131b65 commit db0288d

14 files changed

+557
-864
lines changed

gm/asyncrescaleandread.cpp

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
#include "include/core/SkPaint.h"
1212
#include "include/core/SkRect.h"
1313
#include "include/core/SkSurface.h"
14-
#include "include/core/SkYUVAIndex.h"
14+
#include "include/core/SkYUVAInfo.h"
15+
#include "include/core/SkYUVAPixmaps.h"
1516
#include "include/gpu/GrDirectContext.h"
1617
#include "include/gpu/GrRecordingContext.h"
1718
#include "src/core/SkAutoPixmapStorage.h"
18-
#include "src/core/SkConvertPixels.h"
1919
#include "src/core/SkScopeExit.h"
2020
#include "tools/Resources.h"
2121
#include "tools/ToolUtils.h"
22+
#include "tools/gpu/YUVUtils.h"
2223

2324
namespace {
2425
struct AsyncContext {
@@ -93,33 +94,17 @@ static sk_sp<SkImage> do_read_and_scale_yuv(Src* src,
9394
if (!asyncContext.fResult) {
9495
return nullptr;
9596
}
96-
GrBackendTexture backendTextures[3];
97-
98-
SkPixmap yPM(yII, asyncContext.fResult->data(0), asyncContext.fResult->rowBytes(0));
99-
SkPixmap uPM(uvII, asyncContext.fResult->data(1), asyncContext.fResult->rowBytes(1));
100-
SkPixmap vPM(uvII, asyncContext.fResult->data(2), asyncContext.fResult->rowBytes(2));
101-
102-
backendTextures[0] = direct->createBackendTexture(yPM, GrRenderable::kNo, GrProtected::kNo);
103-
backendTextures[1] = direct->createBackendTexture(uPM, GrRenderable::kNo, GrProtected::kNo);
104-
backendTextures[2] = direct->createBackendTexture(vPM, GrRenderable::kNo, GrProtected::kNo);
105-
106-
SkYUVAIndex indices[4] = {
107-
{ 0, SkColorChannel::kR},
108-
{ 1, SkColorChannel::kR},
109-
{ 2, SkColorChannel::kR},
110-
{-1, SkColorChannel::kR}
97+
SkYUVAInfo yuvaInfo(size, SkYUVAInfo::PlanarConfig::kY_U_V_420, yuvCS);
98+
SkPixmap yuvPMs[] = {
99+
{yII, asyncContext.fResult->data(0), asyncContext.fResult->rowBytes(0)},
100+
{uvII, asyncContext.fResult->data(1), asyncContext.fResult->rowBytes(1)},
101+
{uvII, asyncContext.fResult->data(2), asyncContext.fResult->rowBytes(2)}
111102
};
112-
113-
*cleanup = {[direct, backendTextures] {
114-
direct->flush();
115-
direct->submit(true);
116-
direct->deleteBackendTexture(backendTextures[0]);
117-
direct->deleteBackendTexture(backendTextures[1]);
118-
direct->deleteBackendTexture(backendTextures[2]);
119-
}};
120-
121-
return SkImage::MakeFromYUVATextures(direct, yuvCS, backendTextures, indices, size,
122-
kTopLeft_GrSurfaceOrigin, SkColorSpace::MakeSRGB());
103+
auto pixmaps = SkYUVAPixmaps::FromExternalPixmaps(yuvaInfo, yuvPMs);
104+
SkASSERT(pixmaps.isValid());
105+
auto lazyYUVImage = sk_gpu_test::LazyYUVImage::Make(pixmaps);
106+
SkASSERT(lazyYUVImage);
107+
return lazyYUVImage->refImage(direct, sk_gpu_test::LazyYUVImage::Type::kFromTextures);
123108
}
124109

125110
// Draws a grid of rescales. The columns are none, low, and high filter quality. The rows are

gm/compositor_quads.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,8 @@ class YUVTextureSetRenderer : public ClipTileRenderer {
897897
int drawTiles(SkCanvas* canvas) override {
898898
// Refresh the SkImage at the start, so that it's not attempted for every set entry
899899
if (fYUVData) {
900-
fImage = fYUVData->refImage(canvas->recordingContext());
900+
fImage = fYUVData->refImage(canvas->recordingContext(),
901+
sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
901902
if (!fImage) {
902903
return 0;
903904
}

gm/ducky_yuv_blend.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ DEF_SIMPLE_GM_CAN_FAIL(ducky_yuv_blend, canvas, errorMsg, 560, 1130) {
3333
auto lazyYUV = sk_gpu_test::LazyYUVImage::Make(GetResourceAsData("images/ducky.jpg"),
3434
GrMipmapped::kYes);
3535
if (lazyYUV) {
36-
duckyFG[1] = lazyYUV->refImage(rContext);
36+
duckyFG[1] = lazyYUV->refImage(rContext, sk_gpu_test::LazyYUVImage::Type::kFromPixmaps);
3737
}
3838
if (!duckyFG[1]) {
3939
return skiagm::DrawResult::kFail;

gm/imagefromyuvtextures.cpp

Lines changed: 47 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
#include "tools/Resources.h"
3333
#include "tools/gpu/YUVUtils.h"
3434

35-
using sk_gpu_test::YUVABackendReleaseContext;
36-
3735
class GrRenderTargetContext;
3836

3937
namespace 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

322264
private:
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

Comments
 (0)