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