add helper makeShader for the common Clamp case
[platform/upstream/libSkiaSharp.git] / gm / rectangletexture.cpp
1 /*
2  * Copyright 2016 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.h"
11
12 #if SK_SUPPORT_GPU
13
14 #include "GrBackendSurface.h"
15 #include "GrContext.h"
16 #include "GrGpu.h"
17 #include "GrTest.h"
18 #include "gl/GrGLContext.h"
19 #include "SkBitmap.h"
20 #include "SkGradientShader.h"
21 #include "SkImage.h"
22
23 namespace skiagm {
24 class RectangleTexture : public GM {
25 public:
26     RectangleTexture() {
27         this->setBGColor(0xFFFFFFFF);
28     }
29
30 protected:
31     SkString onShortName() override {
32         return SkString("rectangle_texture");
33     }
34
35     SkISize onISize() override {
36         return SkISize::Make(1035, 240);
37     }
38
39     void fillPixels(int width, int height, void *pixels) {
40         SkBitmap bmp;
41         bmp.setInfo(SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType), width * 4);
42         bmp.setPixels(pixels);
43         SkPaint paint;
44         SkCanvas canvas(bmp);
45         SkPoint pts[] = { {0, 0}, {0, SkIntToScalar(height)} };
46         SkColor colors0[] = { 0xFF1060B0 , 0xFF102030 };
47         paint.setShader(SkGradientShader::MakeLinear(pts, colors0, nullptr, 2,
48                                                      SkShader::kClamp_TileMode));
49         canvas.drawPaint(paint);
50
51         SkColor colors1[] = { 0xFFA07010 , 0xFFA02080 };
52         paint.setAntiAlias(true);
53         paint.setShader(SkGradientShader::MakeLinear(pts, colors1, nullptr, 2,
54                                                      SkShader::kClamp_TileMode));
55         canvas.drawCircle(SkIntToScalar(width) / 2, SkIntToScalar(height) / 2,
56                           SkIntToScalar(width + height) / 5, paint);
57     }
58
59     sk_sp<SkImage> createRectangleTextureImg(GrContext* context, int width, int height,
60                                              void* pixels) {
61         if (!context) {
62             return nullptr;
63         }
64         GrGpu* gpu = context->getGpu();
65         if (!gpu) {
66             return nullptr;
67         }
68         const GrGLContext* glCtx = gpu->glContextForTesting();
69         if (!glCtx) {
70             return nullptr;
71         }
72
73         if (!(kGL_GrGLStandard == glCtx->standard() && glCtx->version() >= GR_GL_VER(3, 1)) &&
74             !glCtx->hasExtension("GL_ARB_texture_rectangle")) {
75             return nullptr;
76         }
77
78         // We will always create the GL texture as GL_RGBA, however the pixels uploaded may be
79         // be RGBA or BGRA, depending on how SkPMColor was compiled.
80         GrGLenum format;
81         if (kSkia8888_GrPixelConfig == kBGRA_8888_GrPixelConfig) {
82             format = GR_GL_BGRA;
83         } else {
84             SkASSERT(kSkia8888_GrPixelConfig == kRGBA_8888_GrPixelConfig);
85             format = GR_GL_RGBA;
86         }
87
88         const GrGLInterface* gl = glCtx->interface();
89 // Useful for debugging whether errors result from use of RECTANGLE
90 // #define TARGET GR_GL_TEXTURE_2D
91 #define TARGET GR_GL_TEXTURE_RECTANGLE
92         GrGLuint id = 0;
93         GR_GL_CALL(gl, GenTextures(1, &id));
94         GR_GL_CALL(gl, BindTexture(TARGET, id));
95         GR_GL_CALL(gl, TexParameteri(TARGET, GR_GL_TEXTURE_MAG_FILTER,
96                                      GR_GL_NEAREST));
97         GR_GL_CALL(gl, TexParameteri(TARGET, GR_GL_TEXTURE_MIN_FILTER,
98                                      GR_GL_NEAREST));
99         GR_GL_CALL(gl, TexParameteri(TARGET, GR_GL_TEXTURE_WRAP_S,
100                                      GR_GL_CLAMP_TO_EDGE));
101         GR_GL_CALL(gl, TexParameteri(TARGET, GR_GL_TEXTURE_WRAP_T,
102                                      GR_GL_CLAMP_TO_EDGE));
103         GR_GL_CALL(gl, TexImage2D(TARGET, 0, GR_GL_RGBA, width, height, 0,
104                                   format, GR_GL_UNSIGNED_BYTE, pixels));
105
106
107         context->resetContext();
108         GrGLTextureInfo info;
109         info.fID = id;
110         info.fTarget = TARGET;
111
112         GrBackendTexture rectangleTex(width, height, kRGBA_8888_GrPixelConfig, &info);
113
114         if (sk_sp<SkImage> image = SkImage::MakeFromAdoptedTexture(context, rectangleTex,
115                                                                    kTopLeft_GrSurfaceOrigin)) {
116             return image;
117         }
118         GR_GL_CALL(gl, DeleteTextures(1, &id));
119         return nullptr;
120     }
121
122     void onDraw(SkCanvas* canvas) override {
123         GrContext *context = canvas->getGrContext();
124         if (!context) {
125             skiagm::GM::DrawGpuOnlyMessage(canvas);
126             return;
127         }
128
129         constexpr int kWidth = 50;
130         constexpr int kHeight = 50;
131         constexpr SkScalar kPad = 5.f;
132
133         SkPMColor pixels[kWidth * kHeight];
134         this->fillPixels(kWidth, kHeight, pixels);
135         sk_sp<SkImage> rectImg(this->createRectangleTextureImg(context, kWidth, kHeight, pixels));
136
137         if (!rectImg) {
138             SkPaint paint;
139             paint.setAntiAlias(true);
140             const char* kMsg = "Could not create rectangle texture image.";
141             canvas->drawText(kMsg, strlen(kMsg), 10, 100, paint);
142             return;
143         }
144
145         constexpr SkFilterQuality kQualities[] = {
146             kNone_SkFilterQuality,
147             kLow_SkFilterQuality,
148             kMedium_SkFilterQuality,
149             kHigh_SkFilterQuality,
150         };
151
152         constexpr SkScalar kScales[] = { 1.0f, 1.2f, 0.75f };
153
154         canvas->translate(kPad, kPad);
155         for (auto s : kScales) {
156             canvas->save();
157             canvas->scale(s, s);
158             for (auto q : kQualities) {
159                 SkPaint plainPaint;
160                 plainPaint.setFilterQuality(q);
161                 canvas->drawImage(rectImg.get(), 0, 0, &plainPaint);
162                 canvas->translate(kWidth + kPad, 0);
163
164                 SkPaint clampPaint;
165                 clampPaint.setFilterQuality(q);
166                 clampPaint.setShader(rectImg->makeShader());
167                 canvas->drawRect(SkRect::MakeWH(1.5f * kWidth, 1.5f * kHeight), clampPaint);
168                 canvas->translate(kWidth * 1.5f + kPad, 0);
169
170                 SkPaint repeatPaint;
171                 repeatPaint.setFilterQuality(q);
172                 repeatPaint.setShader(rectImg->makeShader(SkShader::kRepeat_TileMode,
173                                                           SkShader::kMirror_TileMode));
174                 canvas->drawRect(SkRect::MakeWH(1.5f * kWidth, 1.5f * kHeight), repeatPaint);
175                 canvas->translate(1.5f * kWidth + kPad, 0);
176             }
177             canvas->restore();
178             canvas->translate(0, kPad + 1.5f * kHeight * s);
179         }
180     }
181
182 private:
183     typedef GM INHERITED;
184 };
185
186 DEF_GM(return new RectangleTexture;)
187 }
188
189 #endif