Skip to content

Commit 3fcf83a

Browse files
bsalomonSkia Commit-Bot
authored andcommitted
Fix GrTextureEffect with kRepeat/kRepeat/kBilerp.
Use absolute error value when doing shader-based interp between all four subset corner texels. Add 2x2 image to rectangle_texture GM and draw with all combos of tile modes. Change-Id: Ia5856d592b1c9ab8b588301e7b659b05a7439396 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272920 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
1 parent 03b8ab2 commit 3fcf83a

File tree

2 files changed

+116
-64
lines changed

2 files changed

+116
-64
lines changed

gm/rectangletexture.cpp

Lines changed: 114 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,49 @@ class RectangleTexture : public GpuGM {
5151
this->setBGColor(0xFFFFFFFF);
5252
}
5353

54-
protected:
54+
private:
55+
enum class ImageType {
56+
kGradientCircle,
57+
k2x2
58+
};
59+
5560
SkString onShortName() override {
5661
return SkString("rectangle_texture");
5762
}
5863

59-
SkISize onISize() override { return SkISize::Make(1200, 500); }
60-
61-
void fillPixels(int width, int height, void *pixels) {
62-
SkBitmap bmp;
63-
bmp.setInfo(SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
64-
bmp.setPixels(pixels);
65-
SkPaint paint;
66-
SkCanvas canvas(bmp);
67-
SkPoint pts[] = { {0, 0}, {0, SkIntToScalar(height)} };
68-
SkColor colors0[] = { 0xFF1060B0 , 0xFF102030 };
69-
paint.setShader(SkGradientShader::MakeLinear(pts, colors0, nullptr, 2, SkTileMode::kClamp));
70-
canvas.drawPaint(paint);
71-
72-
SkColor colors1[] = {0xFFA07010, 0xFFA02080};
73-
paint.setAntiAlias(true);
74-
paint.setShader(SkGradientShader::MakeLinear(pts, colors1, nullptr, 2, SkTileMode::kClamp));
75-
canvas.drawCircle(SkIntToScalar(width) / 2, SkIntToScalar(height) / 2,
76-
SkIntToScalar(width + height) / 5, paint);
64+
SkISize onISize() override { return SkISize::Make(1180, 710); }
65+
66+
SkBitmap makeImagePixels(int size, ImageType type) {
67+
auto ii = SkImageInfo::Make(size, size, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
68+
switch (type) {
69+
case ImageType::kGradientCircle: {
70+
SkBitmap bmp;
71+
bmp.allocPixels(ii);
72+
SkPaint paint;
73+
SkCanvas canvas(bmp);
74+
SkPoint pts[] = {{0, 0}, {0, SkIntToScalar(size)}};
75+
SkColor colors0[] = {0xFF1060B0, 0xFF102030};
76+
paint.setShader(
77+
SkGradientShader::MakeLinear(pts, colors0, nullptr, 2, SkTileMode::kClamp));
78+
canvas.drawPaint(paint);
79+
SkColor colors1[] = {0xFFA07010, 0xFFA02080};
80+
paint.setAntiAlias(true);
81+
paint.setShader(
82+
SkGradientShader::MakeLinear(pts, colors1, nullptr, 2, SkTileMode::kClamp));
83+
canvas.drawCircle(size/2.f, size/2.f, 2.f*size/5, paint);
84+
return bmp;
85+
}
86+
case ImageType::k2x2: {
87+
SkBitmap bmp;
88+
bmp.allocPixels(ii);
89+
*bmp.getAddr32(0, 0) = 0xFF0000FF;
90+
*bmp.getAddr32(1, 0) = 0xFF00FF00;
91+
*bmp.getAddr32(0, 1) = 0xFFFF0000;
92+
*bmp.getAddr32(1, 1) = 0xFFFFFFFF;
93+
return bmp;
94+
}
95+
}
96+
SkUNREACHABLE;
7797
}
7898

7999
static const GrGLContext* GetGLContextIfSupported(GrContext* context) {
@@ -87,8 +107,10 @@ class RectangleTexture : public GpuGM {
87107
return context->priv().getGpu()->glContextForTesting();
88108
}
89109

90-
sk_sp<SkImage> createRectangleTextureImg(GrContext* context, GrSurfaceOrigin origin, int width,
91-
int height, const uint32_t* pixels) {
110+
sk_sp<SkImage> createRectangleTextureImg(GrContext* context, GrSurfaceOrigin origin,
111+
const SkBitmap content) {
112+
SkASSERT(content.colorType() == kRGBA_8888_SkColorType);
113+
92114
const GrGLContext* glCtx = GetGLContextIfSupported(context);
93115
if (!glCtx) {
94116
return nullptr;
@@ -106,26 +128,29 @@ class RectangleTexture : public GpuGM {
106128
GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
107129
GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
108130
std::unique_ptr<uint32_t[]> tempPixels;
131+
auto src = content.getAddr32(0, 0);
132+
int h = content.height();
133+
int w = content.width();
109134
if (origin == kBottomLeft_GrSurfaceOrigin) {
110-
tempPixels.reset(new uint32_t[width * height]);
111-
for (int y = 0; y < height; ++y) {
112-
std::copy_n(pixels + width * (height - y - 1), width, tempPixels.get() + width * y);
135+
tempPixels.reset(new uint32_t[w * h]);
136+
for (int y = 0; y < h; ++y) {
137+
std::copy_n(src + w*(h - y - 1), w, tempPixels.get() + w*y);
113138
}
114-
pixels = tempPixels.get();
139+
src = tempPixels.get();
115140
}
116-
GR_GL_CALL(gl, TexImage2D(kTarget, 0, GR_GL_RGBA, width, height, 0, GR_GL_RGBA,
117-
GR_GL_UNSIGNED_BYTE, pixels));
141+
GR_GL_CALL(gl, TexImage2D(kTarget, 0, GR_GL_RGBA, w, h, 0, GR_GL_RGBA, GR_GL_UNSIGNED_BYTE,
142+
src));
118143

119144
context->resetContext();
120145
GrGLTextureInfo info;
121146
info.fID = id;
122147
info.fTarget = kTarget;
123148
info.fFormat = GR_GL_RGBA8;
124149

125-
GrBackendTexture rectangleTex(width, height, GrMipMapped::kNo, info);
150+
GrBackendTexture rectangleTex(w, h, GrMipMapped::kNo, info);
126151

127-
if (sk_sp<SkImage> image = SkImage::MakeFromAdoptedTexture(context, rectangleTex, origin,
128-
kRGBA_8888_SkColorType)) {
152+
if (sk_sp<SkImage> image = SkImage::MakeFromAdoptedTexture(
153+
context, rectangleTex, origin, content.colorType(), content.alphaType())) {
129154
return image;
130155
}
131156
GR_GL_CALL(gl, DeleteTextures(1, &id));
@@ -135,25 +160,19 @@ class RectangleTexture : public GpuGM {
135160
DrawResult onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas,
136161
SkString* errorMsg) override {
137162
if (!GetGLContextIfSupported(context)) {
138-
*errorMsg = "this GM requires an OpenGL 3.1+ context";
163+
*errorMsg = "This GM requires an OpenGL context that supports texture rectangles.";
139164
return DrawResult::kSkip;
140165
}
141166

142-
constexpr int kWidth = 50;
143-
constexpr int kHeight = 50;
144-
constexpr SkScalar kPad = 5.f;
167+
auto gradCircle = this->makeImagePixels(50, ImageType::kGradientCircle);
168+
static constexpr SkScalar kPad = 5.f;
145169

146-
SkPMColor pixels[kWidth * kHeight];
147-
this->fillPixels(kWidth, kHeight, pixels);
148-
149-
sk_sp<SkImage> rectImgs[] = {
150-
this->createRectangleTextureImg(context, kTopLeft_GrSurfaceOrigin, kWidth, kHeight,
151-
pixels),
152-
this->createRectangleTextureImg(context, kBottomLeft_GrSurfaceOrigin, kWidth,
153-
kHeight, pixels),
170+
sk_sp<SkImage> gradImgs[] = {
171+
this->createRectangleTextureImg(context, kTopLeft_GrSurfaceOrigin, gradCircle),
172+
this->createRectangleTextureImg(context, kBottomLeft_GrSurfaceOrigin, gradCircle),
154173
};
155-
SkASSERT(SkToBool(rectImgs[0]) == SkToBool(rectImgs[1]));
156-
if (!rectImgs[0]) {
174+
SkASSERT(SkToBool(gradImgs[0]) == SkToBool(gradImgs[1]));
175+
if (!gradImgs[0]) {
157176
*errorMsg = "Could not create rectangle texture image.";
158177
return DrawResult::kFail;
159178
}
@@ -168,48 +187,80 @@ class RectangleTexture : public GpuGM {
168187
constexpr SkScalar kScales[] = {1.0f, 1.2f, 0.75f};
169188

170189
canvas->translate(kPad, kPad);
171-
for (size_t i = 0; i < SK_ARRAY_COUNT(rectImgs); ++i) {
190+
for (size_t i = 0; i < SK_ARRAY_COUNT(gradImgs); ++i) {
191+
auto img = gradImgs[i];
192+
int w = img->width();
193+
int h = img->height();
172194
for (auto s : kScales) {
173195
canvas->save();
174196
canvas->scale(s, s);
175197
for (auto q : kQualities) {
176198
// drawImage
177199
SkPaint plainPaint;
178200
plainPaint.setFilterQuality(q);
179-
canvas->drawImage(rectImgs[i], 0, 0, &plainPaint);
180-
canvas->translate(kWidth + kPad, 0);
201+
canvas->drawImage(img, 0, 0, &plainPaint);
202+
canvas->translate(w + kPad, 0);
181203

182204
// clamp/clamp shader
183205
SkPaint clampPaint;
184206
clampPaint.setFilterQuality(q);
185-
clampPaint.setShader(rectImgs[i]->makeShader());
186-
canvas->drawRect(SkRect::MakeWH(1.5f * kWidth, 1.5f * kHeight), clampPaint);
187-
canvas->translate(kWidth * 1.5f + kPad, 0);
207+
clampPaint.setShader(gradImgs[i]->makeShader());
208+
canvas->drawRect(SkRect::MakeWH(1.5f*w, 1.5f*h), clampPaint);
209+
canvas->translate(1.5f*w + kPad, 0);
188210

189211
// repeat/mirror shader
190212
SkPaint repeatPaint;
191213
repeatPaint.setFilterQuality(q);
192-
repeatPaint.setShader(rectImgs[i]->makeShader(SkTileMode::kRepeat,
214+
repeatPaint.setShader(gradImgs[i]->makeShader(SkTileMode::kRepeat,
193215
SkTileMode::kMirror));
194-
canvas->drawRect(SkRect::MakeWH(1.5f * kWidth, 1.5f * kHeight), repeatPaint);
195-
canvas->translate(1.5f * kWidth + kPad, 0);
216+
canvas->drawRect(SkRect::MakeWH(1.5f*w, 1.5f*h), repeatPaint);
217+
canvas->translate(1.5f*w + kPad, 0);
196218

197219
// drawImageRect with kStrict
198-
auto srcRect = SkRect::MakeXYWH(.25f * rectImgs[i]->width(),
199-
.25f * rectImgs[i]->height(),
200-
.50f * rectImgs[i]->width(),
201-
.50f * rectImgs[i]->height());
202-
auto dstRect = SkRect::MakeXYWH(0, 0,
203-
.50f * rectImgs[i]->width(),
204-
.50f * rectImgs[i]->height());
205-
canvas->drawImageRect(rectImgs[i], srcRect, dstRect, &plainPaint,
220+
auto srcRect = SkRect::MakeXYWH(.25f*w, .25f*h, .50f*w, .50f*h);
221+
auto dstRect = SkRect::MakeXYWH( 0, 0, .50f*w, .50f*h);
222+
canvas->drawImageRect(gradImgs[i], srcRect, dstRect, &plainPaint,
206223
SkCanvas::kStrict_SrcRectConstraint);
207-
canvas->translate(kWidth * .5f + kPad, 0);
224+
canvas->translate(.5f*w + kPad, 0);
208225
}
209226
canvas->restore();
210-
canvas->translate(0, kPad + 1.5f * kHeight * s);
227+
canvas->translate(0, kPad + 1.5f*h*s);
211228
}
212229
}
230+
231+
auto smallImg = this->createRectangleTextureImg(context, kTopLeft_GrSurfaceOrigin,
232+
this->makeImagePixels(2, ImageType::k2x2));
233+
static constexpr SkScalar kOutset = 25.f;
234+
canvas->translate(kOutset, kOutset);
235+
auto dstRect = SkRect::Make(smallImg->dimensions()).makeOutset(kOutset, kOutset);
236+
237+
for (int fq = kNone_SkFilterQuality; fq <= kLast_SkFilterQuality; ++fq) {
238+
if (fq == kMedium_SkFilterQuality) {
239+
// Medium is the same as Low for upscaling.
240+
continue;
241+
}
242+
canvas->save();
243+
for (int ty = 0; ty < kSkTileModeCount; ++ty) {
244+
canvas->save();
245+
for (int tx = 0; tx < kSkTileModeCount; ++tx) {
246+
SkMatrix lm;
247+
lm.setRotate(45.f, 1, 1);
248+
lm.postScale(6.5f, 6.5f);
249+
auto shader = smallImg->makeShader(static_cast<SkTileMode>(tx),
250+
static_cast<SkTileMode>(ty), &lm);
251+
SkPaint paint;
252+
paint.setShader(std::move(shader));
253+
paint.setFilterQuality(static_cast<SkFilterQuality>(fq));
254+
canvas->drawRect(dstRect, paint);
255+
canvas->translate(dstRect.width() + kPad, 0);
256+
}
257+
canvas->restore();
258+
canvas->translate(0, dstRect.height() + kPad);
259+
}
260+
canvas->restore();
261+
canvas->translate((dstRect.width() + kPad)*kSkTileModeCount, 0);
262+
}
263+
213264
return DrawResult::kOk;
214265
}
215266

src/gpu/effects/GrTextureEffect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,10 @@ GrGLSLFragmentProcessor* GrTextureEffect::onCreateGLSLInstance() const {
472472
auto repeatBilerpReadXY = read("float2(repeatCoordX, repeatCoordY)");
473473
fb->codeAppendf(
474474
"if (errX != 0 && errY != 0) {"
475+
" errX = abs(errX);"
475476
" textureColor = mix(mix(textureColor, %s, errX),"
476477
" mix(%s, %s, errX),"
477-
" errY);"
478+
" abs(errY));"
478479
"}",
479480
repeatBilerpReadX.c_str(), repeatBilerpReadY.c_str(),
480481
repeatBilerpReadXY.c_str());

0 commit comments

Comments
 (0)