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