1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h" 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "tools/DecodeUtils.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h" 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE) 18*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recording.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/TextureInfo.h" 22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RecorderPriv.h" 23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Surface_Graphite.h" 24*c8dee2aaSAndroid Build Coastguard Worker #include "tools/graphite/GraphiteToolUtils.h" 25*c8dee2aaSAndroid Build Coastguard Worker #endif 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm { 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker class GraphiteReplayGM : public GM { 30*c8dee2aaSAndroid Build Coastguard Worker public: 31*c8dee2aaSAndroid Build Coastguard Worker GraphiteReplayGM() = default; 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker protected: onOnceBeforeDraw()34*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { 35*c8dee2aaSAndroid Build Coastguard Worker this->setBGColor(SK_ColorBLACK); 36*c8dee2aaSAndroid Build Coastguard Worker fImage = ToolUtils::GetResourceAsImage("images/mandrill_128.png"); 37*c8dee2aaSAndroid Build Coastguard Worker } 38*c8dee2aaSAndroid Build Coastguard Worker getName() const39*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("graphite-replay"); } 40*c8dee2aaSAndroid Build Coastguard Worker getISize()41*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(kTileWidth * 3, kTileHeight * 2); } 42*c8dee2aaSAndroid Build Coastguard Worker onAnimate(double nanos)43*c8dee2aaSAndroid Build Coastguard Worker bool onAnimate(double nanos) override { 44*c8dee2aaSAndroid Build Coastguard Worker fStartX = kTileWidth * (1.0f + sinf(nanos * 1e-9)) * 0.5f; 45*c8dee2aaSAndroid Build Coastguard Worker return true; 46*c8dee2aaSAndroid Build Coastguard Worker } 47*c8dee2aaSAndroid Build Coastguard Worker onDraw(SkCanvas * canvas,SkString * errorMsg)48*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 49*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE) 50*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::Recorder* recorder = canvas->recorder(); 51*c8dee2aaSAndroid Build Coastguard Worker if (recorder) { 52*c8dee2aaSAndroid Build Coastguard Worker this->drawGraphite(canvas, recorder); 53*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk; 54*c8dee2aaSAndroid Build Coastguard Worker } 55*c8dee2aaSAndroid Build Coastguard Worker #endif 56*c8dee2aaSAndroid Build Coastguard Worker return this->drawNonGraphite(canvas, errorMsg); 57*c8dee2aaSAndroid Build Coastguard Worker } 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker private: 60*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kImageSize = 128; 61*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kPadding = 2; 62*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kPaddedImageSize = kImageSize + kPadding * 2; 63*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kTileWidth = kPaddedImageSize * 2; 64*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kTileHeight = kPaddedImageSize * 2; 65*c8dee2aaSAndroid Build Coastguard Worker 66*c8dee2aaSAndroid Build Coastguard Worker float fStartX = 0.0f; 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fImage; 69*c8dee2aaSAndroid Build Coastguard Worker drawContent(SkCanvas * canvas,int y)70*c8dee2aaSAndroid Build Coastguard Worker void drawContent(SkCanvas* canvas, int y) { 71*c8dee2aaSAndroid Build Coastguard Worker SkPaint gradientPaint; 72*c8dee2aaSAndroid Build Coastguard Worker constexpr SkPoint points[2] = {{0.0f, 0.0f}, {kImageSize, kImageSize}}; 73*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor colors[4] = {SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED}; 74*c8dee2aaSAndroid Build Coastguard Worker gradientPaint.setShader(SkGradientShader::MakeLinear( 75*c8dee2aaSAndroid Build Coastguard Worker points, colors, nullptr, std::size(colors), SkTileMode::kClamp)); 76*c8dee2aaSAndroid Build Coastguard Worker 77*c8dee2aaSAndroid Build Coastguard Worker // Draw image. 78*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fImage, kPadding, kPadding + y); 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker // Draw gradient. 81*c8dee2aaSAndroid Build Coastguard Worker canvas->save(); 82*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(kPaddedImageSize + kPadding, kPadding + y); 83*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeXYWH(0, 0, kImageSize, kImageSize), gradientPaint); 84*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 85*c8dee2aaSAndroid Build Coastguard Worker } 86*c8dee2aaSAndroid Build Coastguard Worker drawTile(SkCanvas * canvas)87*c8dee2aaSAndroid Build Coastguard Worker void drawTile(SkCanvas* canvas) { 88*c8dee2aaSAndroid Build Coastguard Worker // Clip off the right 1/4 of the tile, after clearing. 89*c8dee2aaSAndroid Build Coastguard Worker canvas->clear(SkColors::kRed); 90*c8dee2aaSAndroid Build Coastguard Worker canvas->clipIRect(SkIRect::MakeWH(3 * kTileWidth / 4, kTileHeight)); 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker // Draw content directly. 93*c8dee2aaSAndroid Build Coastguard Worker drawContent(canvas, 0); 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker // Draw content to a saved layer. 96*c8dee2aaSAndroid Build Coastguard Worker SkPaint pAlpha; 97*c8dee2aaSAndroid Build Coastguard Worker pAlpha.setAlphaf(0.5f); 98*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(nullptr, &pAlpha); 99*c8dee2aaSAndroid Build Coastguard Worker drawContent(canvas, kPaddedImageSize); 100*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 101*c8dee2aaSAndroid Build Coastguard Worker } 102*c8dee2aaSAndroid Build Coastguard Worker 103*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE) drawGraphite(SkCanvas * canvas,skgpu::graphite::Recorder * canvasRecorder)104*c8dee2aaSAndroid Build Coastguard Worker void drawGraphite(SkCanvas* canvas, skgpu::graphite::Recorder* canvasRecorder) { 105*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo tileImageInfo = 106*c8dee2aaSAndroid Build Coastguard Worker canvas->imageInfo().makeDimensions(SkISize::Make(kTileWidth, kTileHeight)); 107*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::TextureInfo textureInfo = 108*c8dee2aaSAndroid Build Coastguard Worker static_cast<skgpu::graphite::Surface*>(canvas->getSurface()) 109*c8dee2aaSAndroid Build Coastguard Worker ->backingTextureProxy() 110*c8dee2aaSAndroid Build Coastguard Worker ->textureInfo(); 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::Context* context = canvasRecorder->priv().context(); 113*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<skgpu::graphite::Recorder> recorder = 114*c8dee2aaSAndroid Build Coastguard Worker context->makeRecorder(ToolUtils::CreateTestingRecorderOptions()); 115*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* recordingCanvas = recorder->makeDeferredCanvas(tileImageInfo, textureInfo); 116*c8dee2aaSAndroid Build Coastguard Worker this->drawTile(recordingCanvas); 117*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap(); 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard Worker // Flush the initial clear added by MakeGraphite. 120*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<skgpu::graphite::Recording> canvasRecording = canvasRecorder->snap(); 121*c8dee2aaSAndroid Build Coastguard Worker context->insertRecording({canvasRecording.get()}); 122*c8dee2aaSAndroid Build Coastguard Worker 123*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < 2; ++y) { 124*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < 2; ++x) { 125*c8dee2aaSAndroid Build Coastguard Worker context->insertRecording( 126*c8dee2aaSAndroid Build Coastguard Worker {recording.get(), 127*c8dee2aaSAndroid Build Coastguard Worker canvas->getSurface(), 128*c8dee2aaSAndroid Build Coastguard Worker {x * kTileWidth + SkScalarRoundToInt(fStartX), y * kTileHeight}}); 129*c8dee2aaSAndroid Build Coastguard Worker } 130*c8dee2aaSAndroid Build Coastguard Worker } 131*c8dee2aaSAndroid Build Coastguard Worker } 132*c8dee2aaSAndroid Build Coastguard Worker #endif 133*c8dee2aaSAndroid Build Coastguard Worker drawNonGraphite(SkCanvas * canvas,SkString * errorMsg)134*c8dee2aaSAndroid Build Coastguard Worker DrawResult drawNonGraphite(SkCanvas* canvas, SkString* errorMsg) { 135*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo tileImageInfo = 136*c8dee2aaSAndroid Build Coastguard Worker canvas->imageInfo().makeDimensions(SkISize::Make(kTileWidth, kTileHeight)); 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> imageSurface = canvas->makeSurface(tileImageInfo); 139*c8dee2aaSAndroid Build Coastguard Worker if (!imageSurface) { 140*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "Cannot create new SkSurface."; 141*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip; 142*c8dee2aaSAndroid Build Coastguard Worker } 143*c8dee2aaSAndroid Build Coastguard Worker 144*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* imageCanvas = imageSurface->getCanvas(); 145*c8dee2aaSAndroid Build Coastguard Worker this->drawTile(imageCanvas); 146*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> image = imageSurface->makeImageSnapshot(); 147*c8dee2aaSAndroid Build Coastguard Worker 148*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < 2; ++y) { 149*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < 2; ++x) { 150*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(image, x * kTileWidth + fStartX, y * kTileHeight); 151*c8dee2aaSAndroid Build Coastguard Worker } 152*c8dee2aaSAndroid Build Coastguard Worker } 153*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk; 154*c8dee2aaSAndroid Build Coastguard Worker } 155*c8dee2aaSAndroid Build Coastguard Worker }; 156*c8dee2aaSAndroid Build Coastguard Worker 157*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new GraphiteReplayGM;) 158*c8dee2aaSAndroid Build Coastguard Worker 159*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm 160