specialize drawAtlas for raster backend

2x faster than calling drawVertices as the impl.

Lots more to do in future CLs
- much of the time is spent in malloc, as we cons-up private shaders.
  we *could* create a private shader and wack its data for each draw
  (breaking the immutable contract, but that may be ok for a raster-only
  internal-use shader...)
- also spend time building the pipeline for each draw, even though
  all that has changed is a color payload (and the ctm). A custome
  stage(s) that exposed its private data could be reused with new
  data...

Bug: skia:
Change-Id: I0ff15155e37c0af7931abd34c0883701a47a048a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/203168
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2019-08-05 13:04:18 -04:00 committed by Skia Commit-Bot
parent ea6bb447a2
commit 560e9178bd
6 changed files with 67 additions and 2 deletions

View File

@ -139,7 +139,7 @@ protected:
for (int i = 0; i < N; ++i) {
fRects[i] = SkRect::MakeXYWH(rand.nextF() * (imageW - 8),
rand.nextF() * (imageH - 8), 8, 8);
fColors[i] = rand.nextU();
fColors[i] = rand.nextU() | 0xFF000000;
fXforms[i] = SkRSXform::Make(1, 0, rand.nextF() * W, rand.nextF() * H);
}
}
@ -155,7 +155,7 @@ protected:
atlas = fAtlas.get();
}
for (int i = 0; i < loops; i++) {
canvas->drawAtlas(atlas, fXforms, fRects, colors, N, SkBlendMode::kSrcOver,
canvas->drawAtlas(atlas, fXforms, fRects, colors, N, SkBlendMode::kModulate,
cullRect, paintPtr);
}
}

View File

@ -177,6 +177,7 @@ skia_core_sources = [
"$_src/core/SkDistanceFieldGen.h",
"$_src/core/SkDocument.cpp",
"$_src/core/SkDraw.cpp",
"$_src/core/SkDraw_atlas.cpp",
"$_src/core/SkDraw_text.cpp",
"$_src/core/SkDraw_vertices.cpp",
"$_src/core/SkDraw.h",

View File

@ -575,6 +575,17 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain
}
}
void SkBitmapDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
const SkRect tex[], const SkColor colors[], int count,
SkBlendMode mode, const SkPaint& paint) {
// set this to true for performance comparisons with the old drawVertices way
if (false) {
this->INHERITED::drawAtlas(atlas, xform, tex, colors, count, mode, paint);
return;
}
BDDraw(this).drawAtlas(atlas, xform, tex, colors, count, mode, paint);
}
///////////////////////////////////////////////////////////////////////////////
namespace {

View File

@ -101,6 +101,8 @@ protected:
void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override;
void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount, SkBlendMode,
const SkPaint& paint) override;
void drawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int count,
SkBlendMode, const SkPaint&) override;
void drawDevice(SkBaseDevice*, int x, int y, const SkPaint&) override;
///////////////////////////////////////////////////////////////////////////

View File

@ -68,6 +68,8 @@ public:
const SkVertices::BoneWeights boneWeights[], SkBlendMode bmode,
const uint16_t indices[], int ptCount,
const SkPaint& paint, const SkVertices::Bone bones[], int boneCount) const;
void drawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int count,
SkBlendMode, const SkPaint&);
/**
* Overwrite the target with the path's coverage (i.e. its mask).

49
src/core/SkDraw_atlas.cpp Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkColorFilter.h"
#include "include/core/SkRSXform.h"
#include "src/core/SkDraw.h"
#include "src/core/SkScan.h"
#include "src/shaders/SkShaderBase.h"
void SkDraw::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect textures[],
const SkColor colors[], int count, SkBlendMode bmode, const SkPaint& paint) {
SkDraw draw(*this);
SkPaint p(paint);
p.setAntiAlias(false); // we never respect this for drawAtlas(or drawVertices)
p.setStyle(SkPaint::kFill_Style);
p.setShader(nullptr);
p.setMaskFilter(nullptr);
sk_sp<SkShader> atlasShader;
if (atlas) {
atlasShader = atlas->makeShader();
}
SkMatrix xf;
for (int i = 0; i < count; ++i) {
if (colors) {
if (atlasShader) {
p.setShader(SkShaders::Blend(bmode,
SkShaders::Color(colors[i]),
atlasShader));
p.setColor4f(paint.getColor4f(), nullptr);
} else {
p.setColor(colors[i]); // modulate with paint.getAlpha()?
}
} else {
p.setShader(atlasShader);
}
xf.setRSXform(xform[i]);
xf.preTranslate(-textures[i].fLeft, -textures[i].fTop);
xf.postConcat(*fMatrix);
draw.fMatrix = &xf;
draw.drawRect(textures[i], p);
}
}