14a8126e7f81384526629b1e21bf89b632ea13cd9reed/* 24a8126e7f81384526629b1e21bf89b632ea13cd9reed * Copyright 2014 Google Inc. 34a8126e7f81384526629b1e21bf89b632ea13cd9reed * 44a8126e7f81384526629b1e21bf89b632ea13cd9reed * Use of this source code is governed by a BSD-style license that can be 54a8126e7f81384526629b1e21bf89b632ea13cd9reed * found in the LICENSE file. 64a8126e7f81384526629b1e21bf89b632ea13cd9reed */ 74a8126e7f81384526629b1e21bf89b632ea13cd9reed 84a8126e7f81384526629b1e21bf89b632ea13cd9reed#include "gm.h" 933d2055e594177b27360f84e0631b26d74a55a9bMike Klein#include "sk_tool_utils.h" 104a8126e7f81384526629b1e21bf89b632ea13cd9reed#include "SkGradientShader.h" 114a8126e7f81384526629b1e21bf89b632ea13cd9reed#include "SkSurface.h" 124a8126e7f81384526629b1e21bf89b632ea13cd9reed#include "SkSurfaceProps.h" 134a8126e7f81384526629b1e21bf89b632ea13cd9reed 144a8126e7f81384526629b1e21bf89b632ea13cd9reed#define W 200 154a8126e7f81384526629b1e21bf89b632ea13cd9reed#define H 100 164a8126e7f81384526629b1e21bf89b632ea13cd9reed 171a9b9640843a64af8d9d90337ec3b3fea663196areedstatic sk_sp<SkShader> make_shader() { 184a8126e7f81384526629b1e21bf89b632ea13cd9reed int a = 0x99; 194a8126e7f81384526629b1e21bf89b632ea13cd9reed int b = 0xBB; 204a8126e7f81384526629b1e21bf89b632ea13cd9reed SkPoint pts[] = { { 0, 0 }, { W, H } }; 214a8126e7f81384526629b1e21bf89b632ea13cd9reed SkColor colors[] = { SkColorSetRGB(a, a, a), SkColorSetRGB(b, b, b) }; 221a9b9640843a64af8d9d90337ec3b3fea663196areed return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::kClamp_TileMode); 234a8126e7f81384526629b1e21bf89b632ea13cd9reed} 244a8126e7f81384526629b1e21bf89b632ea13cd9reed 257c1235457f7ef69d3bde48306e9be528718da7e6reedstatic sk_sp<SkSurface> make_surface(GrContext* ctx, const SkImageInfo& info, SkPixelGeometry geo) { 267c1235457f7ef69d3bde48306e9be528718da7e6reed SkSurfaceProps props(0, geo); 274a8126e7f81384526629b1e21bf89b632ea13cd9reed if (ctx) { 28e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info, 0, &props); 294a8126e7f81384526629b1e21bf89b632ea13cd9reed } else { 30e8f3062a36d3682f4019309a32b5b84dc9eddf8creed return SkSurface::MakeRaster(info, &props); 314a8126e7f81384526629b1e21bf89b632ea13cd9reed } 324a8126e7f81384526629b1e21bf89b632ea13cd9reed} 334a8126e7f81384526629b1e21bf89b632ea13cd9reed 344a8126e7f81384526629b1e21bf89b632ea13cd9reedstatic void test_draw(SkCanvas* canvas, const char label[]) { 354a8126e7f81384526629b1e21bf89b632ea13cd9reed SkPaint paint; 364a8126e7f81384526629b1e21bf89b632ea13cd9reed 374a8126e7f81384526629b1e21bf89b632ea13cd9reed paint.setAntiAlias(true); 384a8126e7f81384526629b1e21bf89b632ea13cd9reed paint.setLCDRenderText(true); 394a8126e7f81384526629b1e21bf89b632ea13cd9reed paint.setDither(true); 404a8126e7f81384526629b1e21bf89b632ea13cd9reed 411a9b9640843a64af8d9d90337ec3b3fea663196areed paint.setShader(make_shader()); 424a8126e7f81384526629b1e21bf89b632ea13cd9reed canvas->drawRect(SkRect::MakeWH(W, H), paint); 4396fcdcc219d2a0d3579719b84b28bede76efba64halcanary paint.setShader(nullptr); 444a8126e7f81384526629b1e21bf89b632ea13cd9reed 454a8126e7f81384526629b1e21bf89b632ea13cd9reed paint.setColor(SK_ColorWHITE); 464a8126e7f81384526629b1e21bf89b632ea13cd9reed paint.setTextSize(32); 474a8126e7f81384526629b1e21bf89b632ea13cd9reed paint.setTextAlign(SkPaint::kCenter_Align); 48f597c42c50718d5c39769077040de1768c89bbd3caryclark sk_tool_utils::set_portable_typeface(&paint); 492a475eae622adc1e8fa29206be1eaf862c23548eCary Clark canvas->drawString(label, W / 2, H * 3 / 4, paint); 504a8126e7f81384526629b1e21bf89b632ea13cd9reed} 514a8126e7f81384526629b1e21bf89b632ea13cd9reed 524a8126e7f81384526629b1e21bf89b632ea13cd9reedclass SurfacePropsGM : public skiagm::GM { 534a8126e7f81384526629b1e21bf89b632ea13cd9reedpublic: 544a8126e7f81384526629b1e21bf89b632ea13cd9reed SurfacePropsGM() {} 554a8126e7f81384526629b1e21bf89b632ea13cd9reed 564a8126e7f81384526629b1e21bf89b632ea13cd9reedprotected: 5736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkString onShortName() override { 584a8126e7f81384526629b1e21bf89b632ea13cd9reed return SkString("surfaceprops"); 594a8126e7f81384526629b1e21bf89b632ea13cd9reed } 604a8126e7f81384526629b1e21bf89b632ea13cd9reed 6136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkISize onISize() override { 627c1235457f7ef69d3bde48306e9be528718da7e6reed return SkISize::Make(W, H * 5); 634a8126e7f81384526629b1e21bf89b632ea13cd9reed } 644a8126e7f81384526629b1e21bf89b632ea13cd9reed 6536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onDraw(SkCanvas* canvas) override { 664a8126e7f81384526629b1e21bf89b632ea13cd9reed GrContext* ctx = canvas->getGrContext(); 674a8126e7f81384526629b1e21bf89b632ea13cd9reed 684a8126e7f81384526629b1e21bf89b632ea13cd9reed // must be opaque to have a hope of testing LCD text 690e22eb8e6efc7d7ab7a601ba555947916d139906brianosman const SkImageInfo info = SkImageInfo::MakeN32(W, H, kOpaque_SkAlphaType); 704a8126e7f81384526629b1e21bf89b632ea13cd9reed 714a8126e7f81384526629b1e21bf89b632ea13cd9reed const struct { 724a8126e7f81384526629b1e21bf89b632ea13cd9reed SkPixelGeometry fGeo; 734a8126e7f81384526629b1e21bf89b632ea13cd9reed const char* fLabel; 74e6cad6b370d781c0e8345b5be74b83c2c328074cscroggo } recs[] = { 754a8126e7f81384526629b1e21bf89b632ea13cd9reed { kUnknown_SkPixelGeometry, "Unknown" }, 764a8126e7f81384526629b1e21bf89b632ea13cd9reed { kRGB_H_SkPixelGeometry, "RGB_H" }, 774a8126e7f81384526629b1e21bf89b632ea13cd9reed { kBGR_H_SkPixelGeometry, "BGR_H" }, 784a8126e7f81384526629b1e21bf89b632ea13cd9reed { kRGB_V_SkPixelGeometry, "RGB_V" }, 794a8126e7f81384526629b1e21bf89b632ea13cd9reed { kBGR_V_SkPixelGeometry, "BGR_V" }, 804a8126e7f81384526629b1e21bf89b632ea13cd9reed }; 819d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 824a8126e7f81384526629b1e21bf89b632ea13cd9reed SkScalar x = 0; 837c1235457f7ef69d3bde48306e9be528718da7e6reed SkScalar y = 0; 847c1235457f7ef69d3bde48306e9be528718da7e6reed for (const auto& rec : recs) { 857c1235457f7ef69d3bde48306e9be528718da7e6reed auto surface(make_surface(ctx, info, rec.fGeo)); 867c1235457f7ef69d3bde48306e9be528718da7e6reed if (!surface) { 877c1235457f7ef69d3bde48306e9be528718da7e6reed SkDebugf("failed to create surface! label: %s", rec.fLabel); 887c1235457f7ef69d3bde48306e9be528718da7e6reed continue; 894a8126e7f81384526629b1e21bf89b632ea13cd9reed } 907c1235457f7ef69d3bde48306e9be528718da7e6reed test_draw(surface->getCanvas(), rec.fLabel); 917c1235457f7ef69d3bde48306e9be528718da7e6reed surface->draw(canvas, x, y, nullptr); 927c1235457f7ef69d3bde48306e9be528718da7e6reed y += H; 934a8126e7f81384526629b1e21bf89b632ea13cd9reed } 944a8126e7f81384526629b1e21bf89b632ea13cd9reed } 954a8126e7f81384526629b1e21bf89b632ea13cd9reed 964a8126e7f81384526629b1e21bf89b632ea13cd9reedprivate: 974a8126e7f81384526629b1e21bf89b632ea13cd9reed typedef GM INHERITED; 984a8126e7f81384526629b1e21bf89b632ea13cd9reed}; 994a8126e7f81384526629b1e21bf89b632ea13cd9reedDEF_GM( return new SurfacePropsGM ) 1004af267b11964d4a8acdb232ac46094c84d890e88reed 1014af267b11964d4a8acdb232ac46094c84d890e88reed#ifdef SK_DEBUG 1024af267b11964d4a8acdb232ac46094c84d890e88reedstatic bool equal(const SkSurfaceProps& a, const SkSurfaceProps& b) { 1034af267b11964d4a8acdb232ac46094c84d890e88reed return a.flags() == b.flags() && a.pixelGeometry() == b.pixelGeometry(); 1044af267b11964d4a8acdb232ac46094c84d890e88reed} 1054af267b11964d4a8acdb232ac46094c84d890e88reed#endif 1064af267b11964d4a8acdb232ac46094c84d890e88reed 1074af267b11964d4a8acdb232ac46094c84d890e88reedclass NewSurfaceGM : public skiagm::GM { 1084af267b11964d4a8acdb232ac46094c84d890e88reedpublic: 1094af267b11964d4a8acdb232ac46094c84d890e88reed NewSurfaceGM() {} 1104af267b11964d4a8acdb232ac46094c84d890e88reed 1114af267b11964d4a8acdb232ac46094c84d890e88reedprotected: 11236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkString onShortName() override { 1134af267b11964d4a8acdb232ac46094c84d890e88reed return SkString("surfacenew"); 1144af267b11964d4a8acdb232ac46094c84d890e88reed } 1154af267b11964d4a8acdb232ac46094c84d890e88reed 11636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein SkISize onISize() override { 1174af267b11964d4a8acdb232ac46094c84d890e88reed return SkISize::Make(300, 140); 1184af267b11964d4a8acdb232ac46094c84d890e88reed } 1194af267b11964d4a8acdb232ac46094c84d890e88reed 1204af267b11964d4a8acdb232ac46094c84d890e88reed static void drawInto(SkCanvas* canvas) { 1214af267b11964d4a8acdb232ac46094c84d890e88reed canvas->drawColor(SK_ColorRED); 1224af267b11964d4a8acdb232ac46094c84d890e88reed } 1234af267b11964d4a8acdb232ac46094c84d890e88reed 12436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void onDraw(SkCanvas* canvas) override { 1254af267b11964d4a8acdb232ac46094c84d890e88reed SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100); 1264af267b11964d4a8acdb232ac46094c84d890e88reed 12746596ae50559e89a0a2462573ac9448cf309cf56Mike Reed auto surf(sk_tool_utils::makeSurface(canvas, info, nullptr)); 1284af267b11964d4a8acdb232ac46094c84d890e88reed drawInto(surf->getCanvas()); 1294af267b11964d4a8acdb232ac46094c84d890e88reed 1309ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image(surf->makeImageSnapshot()); 13196fcdcc219d2a0d3579719b84b28bede76efba64halcanary canvas->drawImage(image, 10, 10, nullptr); 1324af267b11964d4a8acdb232ac46094c84d890e88reed 133e8f3062a36d3682f4019309a32b5b84dc9eddf8creed auto surf2(surf->makeSurface(info)); 1344af267b11964d4a8acdb232ac46094c84d890e88reed drawInto(surf2->getCanvas()); 1354af267b11964d4a8acdb232ac46094c84d890e88reed 1364af267b11964d4a8acdb232ac46094c84d890e88reed // Assert that the props were communicated transitively through the first image 1374af267b11964d4a8acdb232ac46094c84d890e88reed SkASSERT(equal(surf->props(), surf2->props())); 1384af267b11964d4a8acdb232ac46094c84d890e88reed 1399ce9d6772df650ceb0511f275e1a83dffa78ff72reed sk_sp<SkImage> image2(surf2->makeImageSnapshot()); 1409ce9d6772df650ceb0511f275e1a83dffa78ff72reed canvas->drawImage(image2.get(), 10 + SkIntToScalar(image->width()) + 10, 10, nullptr); 1414af267b11964d4a8acdb232ac46094c84d890e88reed } 1424af267b11964d4a8acdb232ac46094c84d890e88reed 1434af267b11964d4a8acdb232ac46094c84d890e88reedprivate: 1444af267b11964d4a8acdb232ac46094c84d890e88reed typedef GM INHERITED; 1454af267b11964d4a8acdb232ac46094c84d890e88reed}; 1464af267b11964d4a8acdb232ac46094c84d890e88reedDEF_GM( return new NewSurfaceGM ) 147d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed 148d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed/////////////////////////////////////////////////////////////////////////////////////////////////// 149d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed 150d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike ReedDEF_SIMPLE_GM(copy_on_write_retain, canvas, 256, 256) { 151d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256); 15246596ae50559e89a0a2462573ac9448cf309cf56Mike Reed sk_sp<SkSurface> surf = sk_tool_utils::makeSurface(canvas, info); 153d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed 154d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed surf->getCanvas()->clear(SK_ColorRED); 155d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed // its important that image survives longer than the next draw, so the surface will see 156d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed // an outstanding image, and have to decide if it should retain or discard those pixels 157d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed sk_sp<SkImage> image = surf->makeImageSnapshot(); 158d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed 159d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed // normally a clear+opaque should trigger the discard optimization, but since we have a clip 160d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed // it should not (we need the previous red pixels). 161d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed surf->getCanvas()->clipRect(SkRect::MakeWH(128, 256)); 162d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed surf->getCanvas()->clear(SK_ColorBLUE); 163d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed 164d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed // expect to see two rects: blue | red 165d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed canvas->drawImage(surf->makeImageSnapshot(), 0, 0, nullptr); 166d94abc5330a9332ca7bdb98f20d3d3b085bf623bMike Reed} 167a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed 168a1361364e64138adda3dc5f71d50d7503838bb6dMike ReedDEF_SIMPLE_GM(copy_on_write_savelayer, canvas, 256, 256) { 169a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256); 17046596ae50559e89a0a2462573ac9448cf309cf56Mike Reed sk_sp<SkSurface> surf = sk_tool_utils::makeSurface(canvas, info); 171a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed surf->getCanvas()->clear(SK_ColorRED); 172a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // its important that image survives longer than the next draw, so the surface will see 173a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // an outstanding image, and have to decide if it should retain or discard those pixels 174a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed sk_sp<SkImage> image = surf->makeImageSnapshot(); 175a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed 176a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // now draw into a full-screen layer. This should (a) trigger a copy-on-write, but it should 177a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // not trigger discard, even tho its alpha (SK_ColorBLUE) is opaque, since it is in a layer 178a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // with a non-opaque paint. 179a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed SkPaint paint; 180a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed paint.setAlpha(0x40); 181a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed surf->getCanvas()->saveLayer({0, 0, 256, 256}, &paint); 182a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed surf->getCanvas()->clear(SK_ColorBLUE); 183a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed surf->getCanvas()->restore(); 184a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed 185a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed // expect to see two rects: blue blended on red 186a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed canvas->drawImage(surf->makeImageSnapshot(), 0, 0, nullptr); 187a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed} 188