• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "GrBackendSurface.h"
13 #include "GrContext.h"
14 #include "GrContextPriv.h"
15 #include "GrGpu.h"
16 #include "gl/GrGLContext.h"
17 #include "SkBitmap.h"
18 #include "SkGradientShader.h"
19 #include "SkImage.h"
20 
21 namespace skiagm {
22 class RectangleTexture : public GpuGM {
23 public:
RectangleTexture()24     RectangleTexture() {
25         this->setBGColor(0xFFFFFFFF);
26     }
27 
28 protected:
onShortName()29     SkString onShortName() override {
30         return SkString("rectangle_texture");
31     }
32 
onISize()33     SkISize onISize() override { return SkISize::Make(1200, 500); }
34 
fillPixels(int width,int height,void * pixels)35     void fillPixels(int width, int height, void *pixels) {
36         SkBitmap bmp;
37         bmp.setInfo(SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType), width * 4);
38         bmp.setPixels(pixels);
39         SkPaint paint;
40         SkCanvas canvas(bmp);
41         SkPoint pts[] = { {0, 0}, {0, SkIntToScalar(height)} };
42         SkColor colors0[] = { 0xFF1060B0 , 0xFF102030 };
43         paint.setShader(SkGradientShader::MakeLinear(pts, colors0, nullptr, 2,
44                                                      SkShader::kClamp_TileMode));
45         canvas.drawPaint(paint);
46 
47         SkColor colors1[] = {0xFFA07010, 0xFFA02080};
48         paint.setAntiAlias(true);
49         paint.setShader(SkGradientShader::MakeLinear(pts, colors1, nullptr, 2,
50                                                      SkShader::kClamp_TileMode));
51         canvas.drawCircle(SkIntToScalar(width) / 2, SkIntToScalar(height) / 2,
52                           SkIntToScalar(width + height) / 5, paint);
53     }
54 
createRectangleTextureImg(GrContext * context,GrSurfaceOrigin origin,int width,int height,const uint32_t * pixels)55     sk_sp<SkImage> createRectangleTextureImg(GrContext* context, GrSurfaceOrigin origin, int width,
56                                              int height, const uint32_t* pixels) {
57         GrGpu* gpu = context->priv().getGpu();
58         if (!gpu) {
59             return nullptr;
60         }
61         const GrGLContext* glCtx = gpu->glContextForTesting();
62         if (!glCtx) {
63             return nullptr;
64         }
65 
66         if (!(kGL_GrGLStandard == glCtx->standard() && glCtx->version() >= GR_GL_VER(3, 1)) &&
67             !(glCtx->hasExtension("GL_ARB_texture_rectangle") ||
68               glCtx->hasExtension("GL_ANGLE_texture_rectangle"))) {
69             return nullptr;
70         }
71 
72         // We will always create the GL texture as GL_RGBA, however the pixels uploaded may be
73         // be RGBA or BGRA, depending on how SkPMColor was compiled.
74         GrGLenum format;
75         if (kSkia8888_GrPixelConfig == kBGRA_8888_GrPixelConfig) {
76             format = GR_GL_BGRA;
77         } else {
78             SkASSERT(kSkia8888_GrPixelConfig == kRGBA_8888_GrPixelConfig);
79             format = GR_GL_RGBA;
80         }
81 
82         const GrGLInterface* gl = glCtx->interface();
83         // Useful for debugging whether errors result from use of RECTANGLE
84         // static constexpr GrGLenum kTarget = GR_GL_TEXTURE_2D;
85         static constexpr GrGLenum kTarget = GR_GL_TEXTURE_RECTANGLE;
86         GrGLuint id = 0;
87         GR_GL_CALL(gl, GenTextures(1, &id));
88         GR_GL_CALL(gl, BindTexture(kTarget, id));
89         GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
90         GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
91         GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
92         GR_GL_CALL(gl, TexParameteri(kTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
93         std::unique_ptr<uint32_t[]> tempPixels;
94         if (origin == kBottomLeft_GrSurfaceOrigin) {
95             tempPixels.reset(new uint32_t[width * height]);
96             for (int y = 0; y < height; ++y) {
97                 std::copy_n(pixels + width * (height - y - 1), width, tempPixels.get() + width * y);
98             }
99             pixels = tempPixels.get();
100         }
101         GR_GL_CALL(gl, TexImage2D(kTarget, 0, GR_GL_RGBA, width, height, 0, format,
102                                   GR_GL_UNSIGNED_BYTE, pixels));
103 
104         context->resetContext();
105         GrGLTextureInfo info;
106         info.fID = id;
107         info.fTarget = kTarget;
108         info.fFormat = GR_GL_RGBA8;
109 
110         GrBackendTexture rectangleTex(width, height, GrMipMapped::kNo, info);
111 
112         if (sk_sp<SkImage> image = SkImage::MakeFromAdoptedTexture(context, rectangleTex, origin,
113                                                                    kRGBA_8888_SkColorType)) {
114             return image;
115         }
116         GR_GL_CALL(gl, DeleteTextures(1, &id));
117         return nullptr;
118     }
119 
onDraw(GrContext * context,GrRenderTargetContext *,SkCanvas * canvas,SkString * errorMsg)120     DrawResult onDraw(GrContext* context, GrRenderTargetContext*, SkCanvas* canvas,
121                       SkString* errorMsg) override {
122         constexpr int kWidth = 50;
123         constexpr int kHeight = 50;
124         constexpr SkScalar kPad = 5.f;
125 
126         SkPMColor pixels[kWidth * kHeight];
127         this->fillPixels(kWidth, kHeight, pixels);
128 
129         sk_sp<SkImage> rectImgs[] = {
130                 this->createRectangleTextureImg(context, kTopLeft_GrSurfaceOrigin, kWidth, kHeight,
131                                                 pixels),
132                 this->createRectangleTextureImg(context, kBottomLeft_GrSurfaceOrigin, kWidth,
133                                                 kHeight, pixels),
134         };
135         SkASSERT(SkToBool(rectImgs[0]) == SkToBool(rectImgs[1]));
136         if (!rectImgs[0]) {
137             *errorMsg = "Could not create rectangle texture image.";
138             return DrawResult::kFail;
139         }
140 
141         constexpr SkFilterQuality kQualities[] = {
142                 kNone_SkFilterQuality,
143                 kLow_SkFilterQuality,
144                 kMedium_SkFilterQuality,
145                 kHigh_SkFilterQuality,
146         };
147 
148         constexpr SkScalar kScales[] = {1.0f, 1.2f, 0.75f};
149 
150         canvas->translate(kPad, kPad);
151         for (size_t i = 0; i < SK_ARRAY_COUNT(rectImgs); ++i) {
152             for (auto s : kScales) {
153                 canvas->save();
154                 canvas->scale(s, s);
155                 for (auto q : kQualities) {
156                     // drawImage
157                     SkPaint plainPaint;
158                     plainPaint.setFilterQuality(q);
159                     canvas->drawImage(rectImgs[i], 0, 0, &plainPaint);
160                     canvas->translate(kWidth + kPad, 0);
161 
162                     // clamp/clamp shader
163                     SkPaint clampPaint;
164                     clampPaint.setFilterQuality(q);
165                     clampPaint.setShader(rectImgs[i]->makeShader());
166                     canvas->drawRect(SkRect::MakeWH(1.5f * kWidth, 1.5f * kHeight), clampPaint);
167                     canvas->translate(kWidth * 1.5f + kPad, 0);
168 
169                     // repeat/mirror shader
170                     SkPaint repeatPaint;
171                     repeatPaint.setFilterQuality(q);
172                     repeatPaint.setShader(rectImgs[i]->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                     // drawImageRect with kStrict
178                     auto srcRect = SkRect::MakeXYWH(.25f * rectImgs[i]->width(),
179                                                     .25f * rectImgs[i]->height(),
180                                                     .50f * rectImgs[i]->width(),
181                                                     .50f * rectImgs[i]->height());
182                     auto dstRect = SkRect::MakeXYWH(0, 0,
183                                                     .50f * rectImgs[i]->width(),
184                                                     .50f * rectImgs[i]->height());
185                     canvas->drawImageRect(rectImgs[i], srcRect, dstRect, &plainPaint,
186                                           SkCanvas::kStrict_SrcRectConstraint);
187                     canvas->translate(kWidth * .5f + kPad, 0);
188                 }
189                 canvas->restore();
190                 canvas->translate(0, kPad + 1.5f * kHeight * s);
191             }
192         }
193         return DrawResult::kOk;
194     }
195 
196 private:
197     typedef GM INHERITED;
198 };
199 
200 DEF_GM(return new RectangleTexture;)
201 }
202