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