123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "tools/skiaserve/Request.h"
- #include "include/core/SkPictureRecorder.h"
- #include "src/utils/SkJSONWriter.h"
- #include "tools/ToolUtils.h"
- using namespace sk_gpu_test;
- static int kDefaultWidth = 1920;
- static int kDefaultHeight = 1080;
- static int kMaxWidth = 8192;
- static int kMaxHeight = 8192;
- Request::Request(SkString rootUrl)
- : fUploadContext(nullptr)
- , fUrlDataManager(rootUrl)
- , fGPUEnabled(false)
- , fOverdraw(false)
- , fColorMode(0) {
- // create surface
- GrContextOptions grContextOpts;
- fContextFactory = new GrContextFactory(grContextOpts);
- }
- Request::~Request() {
- if (fContextFactory) {
- delete fContextFactory;
- }
- }
- sk_sp<SkData> Request::writeCanvasToPng(SkCanvas* canvas) {
- // capture pixels
- SkBitmap bmp;
- bmp.allocPixels(canvas->imageInfo());
- SkAssertResult(canvas->readPixels(bmp, 0, 0));
- // write to an opaque png (black background)
- SkDynamicMemoryWStream buffer;
- DrawCommand::WritePNG(bmp, buffer);
- return buffer.detachAsData();
- }
- SkCanvas* Request::getCanvas() {
- GrContextFactory* factory = fContextFactory;
- GLTestContext* gl = factory->getContextInfo(GrContextFactory::kGL_ContextType,
- GrContextFactory::ContextOverrides::kNone).glContext();
- if (!gl) {
- gl = factory->getContextInfo(GrContextFactory::kGLES_ContextType,
- GrContextFactory::ContextOverrides::kNone).glContext();
- }
- if (gl) {
- gl->makeCurrent();
- }
- SkASSERT(fDebugCanvas);
- // create the appropriate surface if necessary
- if (!fSurface) {
- this->enableGPU(fGPUEnabled);
- }
- SkCanvas* target = fSurface->getCanvas();
- return target;
- }
- sk_sp<SkData> Request::drawToPng(int n, int m) {
- //fDebugCanvas->setOverdrawViz(true);
- fDebugCanvas->drawTo(this->getCanvas(), n, m);
- //fDebugCanvas->setOverdrawViz(false);
- return writeCanvasToPng(this->getCanvas());
- }
- sk_sp<SkData> Request::writeOutSkp() {
- // Playback into picture recorder
- SkIRect bounds = this->getBounds();
- SkPictureRecorder recorder;
- SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(bounds.width()),
- SkIntToScalar(bounds.height()));
- fDebugCanvas->draw(canvas);
- return recorder.finishRecordingAsPicture()->serialize();
- }
- GrContext* Request::getContext() {
- GrContext* result = fContextFactory->get(GrContextFactory::kGL_ContextType,
- GrContextFactory::ContextOverrides::kNone);
- if (!result) {
- result = fContextFactory->get(GrContextFactory::kGLES_ContextType,
- GrContextFactory::ContextOverrides::kNone);
- }
- return result;
- }
- SkIRect Request::getBounds() {
- SkIRect bounds;
- if (fPicture) {
- bounds = fPicture->cullRect().roundOut();
- if (fGPUEnabled) {
- int maxRTSize = this->getContext()->maxRenderTargetSize();
- bounds = SkIRect::MakeWH(SkTMin(bounds.width(), maxRTSize),
- SkTMin(bounds.height(), maxRTSize));
- }
- } else {
- bounds = SkIRect::MakeWH(kDefaultWidth, kDefaultHeight);
- }
- // We clip to kMaxWidth / kMaxHeight for performance reasons.
- // TODO make this configurable
- bounds = SkIRect::MakeWH(SkTMin(bounds.width(), kMaxWidth),
- SkTMin(bounds.height(), kMaxHeight));
- return bounds;
- }
- namespace {
- struct ColorAndProfile {
- SkColorType fColorType;
- bool fSRGB;
- };
- ColorAndProfile ColorModes[] = {
- { kN32_SkColorType, false },
- { kN32_SkColorType, true },
- { kRGBA_F16_SkColorType, true },
- };
- }
- SkSurface* Request::createCPUSurface() {
- SkIRect bounds = this->getBounds();
- ColorAndProfile cap = ColorModes[fColorMode];
- auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
- ? SkColorSpace::MakeSRGBLinear()
- : SkColorSpace::MakeSRGB();
- SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
- kPremul_SkAlphaType, cap.fSRGB ? colorSpace : nullptr);
- return SkSurface::MakeRaster(info).release();
- }
- SkSurface* Request::createGPUSurface() {
- GrContext* context = this->getContext();
- SkIRect bounds = this->getBounds();
- ColorAndProfile cap = ColorModes[fColorMode];
- auto colorSpace = kRGBA_F16_SkColorType == cap.fColorType
- ? SkColorSpace::MakeSRGBLinear()
- : SkColorSpace::MakeSRGB();
- SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), cap.fColorType,
- kPremul_SkAlphaType, cap.fSRGB ? colorSpace: nullptr);
- SkSurface* surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info).release();
- return surface;
- }
- bool Request::setOverdraw(bool enable) {
- fOverdraw = enable;
- return true;
- }
- bool Request::setColorMode(int mode) {
- fColorMode = mode;
- return enableGPU(fGPUEnabled);
- }
- bool Request::enableGPU(bool enable) {
- if (enable) {
- SkSurface* surface = this->createGPUSurface();
- if (surface) {
- fSurface.reset(surface);
- fGPUEnabled = true;
- // When we switch to GPU, there seems to be some mystery draws in the canvas. So we
- // draw once to flush the pipe
- // TODO understand what is actually happening here
- if (fDebugCanvas) {
- fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
- this->getCanvas()->flush();
- }
- return true;
- }
- return false;
- }
- fSurface.reset(this->createCPUSurface());
- fGPUEnabled = false;
- return true;
- }
- bool Request::initPictureFromStream(SkStream* stream) {
- // parse picture from stream
- fPicture = SkPicture::MakeFromStream(stream);
- if (!fPicture) {
- fprintf(stderr, "Could not create picture from stream.\n");
- return false;
- }
- // reinitialize canvas with the new picture dimensions
- this->enableGPU(fGPUEnabled);
- // pour picture into debug canvas
- SkIRect bounds = this->getBounds();
- fDebugCanvas.reset(new DebugCanvas(bounds.width(), bounds.height()));
- fDebugCanvas->drawPicture(fPicture);
- // for some reason we need to 'flush' the debug canvas by drawing all of the ops
- fDebugCanvas->drawTo(this->getCanvas(), this->getLastOp());
- this->getCanvas()->flush();
- return true;
- }
- sk_sp<SkData> Request::getJsonOps(int n) {
- SkCanvas* canvas = this->getCanvas();
- SkDynamicMemoryWStream stream;
- SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
- writer.beginObject(); // root
- writer.appendString("mode", fGPUEnabled ? "gpu" : "cpu");
- writer.appendBool("drawGpuOpBounds", fDebugCanvas->getDrawGpuOpBounds());
- writer.appendS32("colorMode", fColorMode);
- fDebugCanvas->toJSON(writer, fUrlDataManager, n, canvas);
- writer.endObject(); // root
- writer.flush();
- return stream.detachAsData();
- }
- sk_sp<SkData> Request::getJsonOpList(int n) {
- SkCanvas* canvas = this->getCanvas();
- SkASSERT(fGPUEnabled);
- SkDynamicMemoryWStream stream;
- SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
- fDebugCanvas->toJSONOpList(writer, n, canvas);
- writer.flush();
- return stream.detachAsData();
- }
- sk_sp<SkData> Request::getJsonInfo(int n) {
- // drawTo
- sk_sp<SkSurface> surface(this->createCPUSurface());
- SkCanvas* canvas = surface->getCanvas();
- // TODO this is really slow and we should cache the matrix and clip
- fDebugCanvas->drawTo(canvas, n);
- // make some json
- SkDynamicMemoryWStream stream;
- SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
- SkMatrix vm = fDebugCanvas->getCurrentMatrix();
- SkIRect clip = fDebugCanvas->getCurrentClip();
- writer.beginObject(); // root
- writer.appendName("ViewMatrix");
- DrawCommand::MakeJsonMatrix(writer, vm);
- writer.appendName("ClipRect");
- DrawCommand::MakeJsonIRect(writer, clip);
- writer.endObject(); // root
- // TODO: Old code explicitly avoided the null terminator in the returned data. Important?
- writer.flush();
- return stream.detachAsData();
- }
- SkColor Request::getPixel(int x, int y) {
- SkBitmap bmp;
- bmp.allocPixels(this->getCanvas()->imageInfo().makeWH(1, 1));
- SkAssertResult(this->getCanvas()->readPixels(bmp, x, y));
- return bmp.getColor(0, 0);
- }
|