blob: d33518e172d7e0e9beae27eec60a26bb74e41b19 [file] [log] [blame] [edit]
/*
* Copyright 2025 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/ContextOptions.h"
#include "include/gpu/graphite/GraphiteTypes.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "include/gpu/graphite/mtl/MtlBackendContext.h"
#include "include/gpu/graphite/mtl/MtlGraphiteUtils.h"
#include "graphite_metal_context_helper.h"
#define WIDTH 200
#define HEIGHT 400
int main(int argc, char *argv[]) {
/* SET UP CONTEXT AND RECORDERS FOR DRAWING AND CAPTURE */
skgpu::graphite::MtlBackendContext backendContext = GetMetalContext();
skgpu::graphite::ContextOptions options;
options.fEnableCapture = true;
std::unique_ptr<skgpu::graphite::Context> context =
skgpu::graphite::ContextFactory::MakeMetal(backendContext, options);
if (!context) {
printf("Could not make Graphite Native Metal context\n");
return 1;
}
printf("Context made, now to make the surface\n");
SkImageInfo imageInfo =
SkImageInfo::Make(WIDTH, HEIGHT, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
std::unique_ptr<skgpu::graphite::Recorder> recorder = context->makeRecorder();
if (!recorder) {
printf("Could not make recorder\n");
return 1;
}
sk_sp<SkSurface> surface =
SkSurfaces::RenderTarget(recorder.get(), imageInfo);
if (!surface) {
printf("Could not make surface from Metal Recorder\n");
return 1;
}
sk_sp<SkSurface> surfaceB =
SkSurfaces::RenderTarget(recorder.get(), imageInfo);
if (!surfaceB) {
printf("Could not make second surface from Metal Recorder\n");
return 1;
}
/* DRAWING */
context->startCapture();
printf("Capture started, now to draw\n");
SkCanvas* canvas = surface->getCanvas();
SkCanvas* canvasB = surfaceB->getCanvas();
// Canvas A
canvas->clear(SK_ColorCYAN);
SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeLTRB(10, 20, 50, 70), 10, 10);
SkPaint paint;
paint.setColor(SK_ColorYELLOW);
paint.setAntiAlias(true);
canvas->drawRRect(rrect, paint);
// Canvas B
// TODO (b/412351769): take image snapshot from canvas A and draw into B
canvasB->clear(SK_ColorMAGENTA);
paint.setColor(SK_ColorBLACK);
canvasB->drawCircle(10, 10, 5, paint);
printf("ready to snap the GPU calls\n");
// Now to send the draws to the GPU
std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
if (!recording) {
printf("Could not create a recording\n");
return 1;
}
skgpu::graphite::InsertRecordingInfo info;
info.fRecording = recording.get();
if (!context->insertRecording(info)) {
printf("Context::insertRecording failed\n");
return 1;
}
sk_sp<SkImage> img;
auto callback = [](SkImage::ReadPixelsContext ctx,
std::unique_ptr<const SkImage::AsyncReadResult> result) {
if (result->count() != 1) {
printf("Didn't load exactly one plane\n");
return;
}
auto ii = SkImageInfo::Make(WIDTH, HEIGHT, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
sk_sp<SkImage>* output = reinterpret_cast<sk_sp<SkImage>*>(ctx);
SkPixmap pm(ii, result->data(0), result->rowBytes(0));
*output = SkImages::RasterFromPixmapCopy(pm);
};
printf("GPU operations modifying surface have been inserted in the command buffer,"
"scheduling pixel readback\n");
context->asyncRescaleAndReadPixels(surface.get(), imageInfo, SkIRect::MakeSize({WIDTH, HEIGHT}),
SkImage::RescaleGamma::kSrc,
SkImage::RescaleMode::kRepeatedCubic,
callback, &img);
printf("Submitting work to GPU and waiting for it to be done\n");
// Note this doesn't work on all backend types, e.g. Dawn.
context->submit(skgpu::graphite::SyncToCpu::kYes);
if (context->hasUnfinishedGpuWork()) {
printf("Sync with GPU completion failed\n");
return 1;
}
// TODO (b/412351769): inspect CaptureManager / output capture
context->endCapture();
printf("done\n");
return 0;
}