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