added skeletal animation support to GPU backend
added caching of SkVertices Docs-Preview: https://skia.org/?cl=138596 Bug: skia: Change-Id: Ia750f55f5f6d0de250d9e9c5619f4d1ac856f9f5 Reviewed-on: https://skia-review.googlesource.com/138596 Reviewed-by: Brian Osman <brianosman@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Ruiqi Mao <ruiqimao@google.com>
This commit is contained in:
parent
b7b73f5bbe
commit
b6307340e8
@ -5772,6 +5772,7 @@ contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
|
||||
The first element of bones should be an object to world space transformation matrix that
|
||||
will be applied before performing mesh deformations. If no such transformation is needed,
|
||||
it should be the identity matrix.
|
||||
boneCount must be at most 100, and thus the size of bones should be at most 100.
|
||||
|
||||
#Param vertices triangle mesh to draw ##
|
||||
#Param bones bone matrix data ##
|
||||
@ -5821,6 +5822,7 @@ contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
|
||||
The first element of bones should be an object to world space transformation matrix that
|
||||
will be applied before performing mesh deformations. If no such transformation is needed,
|
||||
it should be the identity matrix.
|
||||
boneCount must be at most 100, and thus the size of bones should be at most 100.
|
||||
|
||||
#Param vertices triangle mesh to draw ##
|
||||
#Param bones bone matrix data ##
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/* Generated by tools/bookmaker from include/core/SkCanvas.h and docs/SkCanvas_Reference.bmh
|
||||
on 2018-07-02 10:27:08. Additional documentation and examples can be found at:
|
||||
on 2018-07-03 11:34:22. Additional documentation and examples can be found at:
|
||||
https://skia.org/user/api/SkCanvas_Reference
|
||||
|
||||
You may edit either file directly. Structural changes to public interfaces require
|
||||
@ -2156,6 +2156,7 @@ public:
|
||||
The first element of bones should be an object to world space transformation matrix that
|
||||
will be applied before performing mesh deformations. If no such transformation is needed,
|
||||
it should be the identity matrix.
|
||||
boneCount must be at most 100, and thus the size of bones should be at most 100.
|
||||
|
||||
@param vertices triangle mesh to draw
|
||||
@param bones bone matrix data
|
||||
@ -2173,6 +2174,7 @@ public:
|
||||
The first element of bones should be an object to world space transformation matrix that
|
||||
will be applied before performing mesh deformations. If no such transformation is needed,
|
||||
it should be the identity matrix.
|
||||
boneCount must be at most 100, and thus the size of bones should be at most 100.
|
||||
|
||||
@param vertices triangle mesh to draw
|
||||
@param bones bone matrix data
|
||||
|
@ -55,14 +55,16 @@ public:
|
||||
const BoneIndices boneIndices[],
|
||||
const BoneWeights boneWeights[],
|
||||
int indexCount,
|
||||
const uint16_t indices[]);
|
||||
const uint16_t indices[],
|
||||
bool isVolatile = true);
|
||||
|
||||
static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
|
||||
const SkPoint positions[],
|
||||
const SkPoint texs[],
|
||||
const SkColor colors[],
|
||||
const BoneIndices boneIndices[],
|
||||
const BoneWeights boneWeights[]) {
|
||||
const BoneWeights boneWeights[],
|
||||
bool isVolatile = true) {
|
||||
return MakeCopy(mode,
|
||||
vertexCount,
|
||||
positions,
|
||||
@ -71,7 +73,8 @@ public:
|
||||
boneIndices,
|
||||
boneWeights,
|
||||
0,
|
||||
nullptr);
|
||||
nullptr,
|
||||
isVolatile);
|
||||
}
|
||||
|
||||
static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
|
||||
@ -79,7 +82,8 @@ public:
|
||||
const SkPoint texs[],
|
||||
const SkColor colors[],
|
||||
int indexCount,
|
||||
const uint16_t indices[]) {
|
||||
const uint16_t indices[],
|
||||
bool isVolatile = true) {
|
||||
return MakeCopy(mode,
|
||||
vertexCount,
|
||||
positions,
|
||||
@ -88,14 +92,16 @@ public:
|
||||
nullptr,
|
||||
nullptr,
|
||||
indexCount,
|
||||
indices);
|
||||
indices,
|
||||
isVolatile);
|
||||
}
|
||||
|
||||
static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,
|
||||
const SkPoint positions[],
|
||||
const SkPoint texs[],
|
||||
const SkColor colors[]) {
|
||||
return MakeCopy(mode, vertexCount, positions, texs, colors, nullptr, nullptr);
|
||||
const SkColor colors[],
|
||||
bool isVolatile = true) {
|
||||
return MakeCopy(mode, vertexCount, positions, texs, colors, nullptr, nullptr, isVolatile);
|
||||
}
|
||||
|
||||
struct Sizes;
|
||||
@ -104,6 +110,7 @@ public:
|
||||
kHasTexCoords_BuilderFlag = 1 << 0,
|
||||
kHasColors_BuilderFlag = 1 << 1,
|
||||
kHasBones_BuilderFlag = 1 << 2,
|
||||
kIsVolatile_BuilderFlag = 1 << 3,
|
||||
};
|
||||
class Builder {
|
||||
public:
|
||||
@ -114,6 +121,7 @@ public:
|
||||
// if the builder is invalid, these will return 0
|
||||
int vertexCount() const;
|
||||
int indexCount() const;
|
||||
bool isVolatile() const;
|
||||
SkPoint* positions();
|
||||
SkPoint* texCoords(); // returns null if there are no texCoords
|
||||
SkColor* colors(); // returns null if there are no colors
|
||||
@ -125,9 +133,9 @@ public:
|
||||
sk_sp<SkVertices> detach();
|
||||
|
||||
private:
|
||||
Builder(VertexMode mode, int vertexCount, int indexCount, const Sizes&);
|
||||
Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
|
||||
|
||||
void init(VertexMode mode, int vertexCount, int indexCount, const Sizes&);
|
||||
void init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile, const Sizes&);
|
||||
|
||||
// holds a partially complete object. only completed in detach()
|
||||
sk_sp<SkVertices> fVertices;
|
||||
@ -158,6 +166,8 @@ public:
|
||||
int indexCount() const { return fIndexCnt; }
|
||||
const uint16_t* indices() const { return fIndices; }
|
||||
|
||||
bool isVolatile() const { return fIsVolatile; }
|
||||
|
||||
// returns approximate byte size of the vertices object
|
||||
size_t approximateSize() const;
|
||||
|
||||
@ -199,6 +209,8 @@ private:
|
||||
int fVertexCnt;
|
||||
int fIndexCnt;
|
||||
|
||||
bool fIsVolatile;
|
||||
|
||||
VertexMode fMode;
|
||||
// below here is where the actual array data is stored.
|
||||
};
|
||||
|
@ -2684,7 +2684,7 @@ the result with <a href='#Matrix'>Matrix</a>.
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="53c212c4f2449df0b0eedbc6227b6ab7"><div><a href='#SkCanvas_scale'>scale</a> followed by <a href='#SkCanvas_translate'>translate</a> produces different results from <a href='#SkCanvas_translate'>translate</a> followed
|
||||
<div><fiddle-embed name="eb93d5fa66a5f7a10f4f9210494d7222"><div><a href='#SkCanvas_scale'>scale</a> followed by <a href='#SkCanvas_translate'>translate</a> produces different results from <a href='#SkCanvas_translate'>translate</a> followed
|
||||
by <a href='#SkCanvas_scale'>scale</a>.
|
||||
|
||||
The blue stroke follows translate of (50, 50); a black
|
||||
@ -4662,7 +4662,7 @@ and so on; or nullptr</td>
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="185746dc0faa6f1df30c4afe098646ff"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="ac93f30dff13f8a8bb31398de370863b"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
@ -6412,7 +6412,7 @@ void <a href='#SkCanvas_drawPicture'>drawPicture</a>(const <a href='SkPicture_Re
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="9adda80b2dd1b08ec5ccf66da7c8bd91"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="759e4e5bac680838added8f70884dcdc"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
@ -6537,6 +6537,7 @@ contains <a href='undocumented#Shader'>Shader</a>, <a href='SkBlendMode_Referenc
|
||||
The first element of <a href='#SkCanvas_drawVertices_3_bones'>bones</a> should be an object to world space transformation matrix that
|
||||
will be applied before performing mesh deformations. If no such transformation is needed,
|
||||
it should be the identity matrix.
|
||||
<a href='#SkCanvas_drawVertices_3_boneCount'>boneCount</a> must be at most 100, and thus the size of <a href='#SkCanvas_drawVertices_3_bones'>bones</a> should be at most 100.
|
||||
|
||||
### Parameters
|
||||
|
||||
@ -6581,6 +6582,7 @@ contains <a href='undocumented#Shader'>Shader</a>, <a href='SkBlendMode_Referenc
|
||||
The first element of <a href='#SkCanvas_drawVertices_4_bones'>bones</a> should be an object to world space transformation matrix that
|
||||
will be applied before performing mesh deformations. If no such transformation is needed,
|
||||
it should be the identity matrix.
|
||||
<a href='#SkCanvas_drawVertices_4_boneCount'>boneCount</a> must be at most 100, and thus the size of <a href='#SkCanvas_drawVertices_4_bones'>bones</a> should be at most 100.
|
||||
|
||||
### Parameters
|
||||
|
||||
@ -6773,7 +6775,7 @@ If <a href='#SkCanvas_drawAtlas_cullRect'>cullRect</a> is outside of <a href='#C
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="fe79a9c1ec350264eb9c7b2509dd3638"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="1df575f9b8132306ce0552a2554ed132"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
|
@ -1504,7 +1504,7 @@ If <a href='#SkIRect_makeInset_dy'>dy</a> is positive, <a href='#IRect'>IRect</a
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="a7958a4e0668f5cf805a8e78eb57f51d">
|
||||
<div><fiddle-embed name="1db94b2c76e0a7a71856532335fa56b6">
|
||||
|
||||
#### Example Output
|
||||
|
||||
@ -2277,7 +2277,7 @@ true if <a href='#SkIRect_intersectNoEmptyCheck_a'>a</a> and <a href='#SkIRect_i
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="a98993a66616ae406d8bdc54adfb1411">
|
||||
<div><fiddle-embed name="d35fbc9fdea71df8b8a12fd3da50d11c">
|
||||
|
||||
#### Example Output
|
||||
|
||||
|
@ -2035,7 +2035,7 @@ integral rectangle from origin to <a href='#SkImageInfo_width'>width</a> and <a
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="a818be8945cd0c18f99ffe53e90afa48"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="3ce3db36235d80dbac4d39504cf756da"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
|
@ -2300,7 +2300,7 @@ partial or full <a href='#Image'>Image</a>, or nullptr
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="4eb2d95c9e9a66f05296e345bb68bd51"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="93669037c9eb9d142e7776b9f936fa96"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
|
@ -3203,7 +3203,7 @@ Matrix * S(sx, sy) = | D E F | | 0 sy 0 | = | D*sx E*sy F |
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="27a0ab44659201f1aa2ac7fea73368c2"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="3edbdea8e43d06086abf33ec4a9b415b"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
|
@ -2609,7 +2609,7 @@ Sets <a href='SkColor_Reference#Alpha'>Alpha</a> and RGB used when stroking and
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="9adda80b2dd1b08ec5ccf66da7c8bd91">
|
||||
<div><fiddle-embed name="6e70f18300bd676a3c056ceb6b62f8df">
|
||||
|
||||
#### Example Output
|
||||
|
||||
@ -4477,7 +4477,7 @@ typographic height of text
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="29b98ebf58aa9fd1edfaabf9f4490b3a"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="983e2a71ba72d4ba8c945420040b8f1c"></fiddle-embed></div>
|
||||
|
||||
---
|
||||
|
||||
|
@ -5570,7 +5570,7 @@ The format used for <a href='#Path'>Path</a> in memory is not guaranteed.
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="882e8e0103048009a25cfc20400492f7">
|
||||
<div><fiddle-embed name="2c6aff73608cd198659db6d1eeaaae4f">
|
||||
|
||||
#### Example Output
|
||||
|
||||
@ -5753,7 +5753,7 @@ degenerate data.
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="882e8e0103048009a25cfc20400492f7"><div>Ignoring the actual <a href='#Verb'>Verbs</a> and replacing them with <a href='#Quad'>Quads</a> rounds the
|
||||
<div><fiddle-embed name="2f53df9201769ab7e7c0e164a1334309"><div>Ignoring the actual <a href='#Verb'>Verbs</a> and replacing them with <a href='#Quad'>Quads</a> rounds the
|
||||
path of the glyph.
|
||||
</div></fiddle-embed></div>
|
||||
|
||||
|
@ -492,7 +492,7 @@ reference to ImageInfo
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="ab9b3aef7896aee80b780789848fbba4">
|
||||
<div><fiddle-embed name="6e0f558bf7fabc655041116288559134">
|
||||
|
||||
#### Example Output
|
||||
|
||||
@ -1109,7 +1109,7 @@ readable unsigned 8-bit pointer to pixels
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="2bffb6384cc20077e632e7d01da045ca">
|
||||
<div><fiddle-embed name="9adda80b2dd1b08ec5ccf66da7c8bd91">
|
||||
|
||||
#### Example Output
|
||||
|
||||
|
@ -1207,7 +1207,7 @@ Returns <a href='#Point'>Point</a> multiplied by scale.
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="2bffb6384cc20077e632e7d01da045ca"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="35b3bc675779de043706ae4817ee950c"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
|
@ -626,7 +626,7 @@ true if has identical geometry to <a href='undocumented#Oval'>Oval</a>
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="6ac569e40fb68c758319e85428b9ae95"><div>The first radii are scaled down proportionately until both x-axis and y-axis fit
|
||||
<div><fiddle-embed name="ab9b3aef7896aee80b780789848fbba4"><div>The first radii are scaled down proportionately until both x-axis and y-axis fit
|
||||
within the bounds. After scaling, x-axis radius is smaller than half the width;
|
||||
left round rect is not an oval. The second radii are equal to half the
|
||||
dimensions; right round rect is an oval.
|
||||
@ -1042,7 +1042,7 @@ Otherwise, sets to <a href='#SkRRect_kSimple_Type'>kSimple Type</a>.
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="a7958a4e0668f5cf805a8e78eb57f51d"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="6ac569e40fb68c758319e85428b9ae95"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
@ -1292,7 +1292,7 @@ bounding box
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="a7958a4e0668f5cf805a8e78eb57f51d"></fiddle-embed></div>
|
||||
<div><fiddle-embed name="4577e2dcb086b241bb43d8b89ee0b0dd"></fiddle-embed></div>
|
||||
|
||||
### See Also
|
||||
|
||||
|
@ -1171,7 +1171,7 @@ and <a href='#SkRect_sort'>sort</a> to reverse <a href='#SkRect_fTop'>fTop</a> a
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="795061764b10c9e05efb466c9cb60644">
|
||||
<div><fiddle-embed name="a98993a66616ae406d8bdc54adfb1411">
|
||||
|
||||
#### Example Output
|
||||
|
||||
|
@ -1014,7 +1014,7 @@ has no effect. Calling <a href='#SkSurface_makeImageSnapshot'>makeImageSnapshot<
|
||||
|
||||
### Example
|
||||
|
||||
<div><fiddle-embed name="8b8a4cd8a29d22bb9c5e63b70357bd65">
|
||||
<div><fiddle-embed name="99a54b814ccab7d2b1143c88581649ff">
|
||||
|
||||
#### Example Output
|
||||
|
||||
|
@ -4765,7 +4765,7 @@
|
||||
"code": "void draw(SkCanvas* canvas) {\n // sk_sp<SkImage> image;\n SkImage* imagePtr = image.get();\n canvas->drawImage(imagePtr, 0, 0);\n SkPaint paint;\n canvas->drawImage(imagePtr, 80, 0, &paint);\n paint.setAlpha(0x80);\n canvas->drawImage(imagePtr, 160, 0, &paint);\n}\n",
|
||||
"width": 256,
|
||||
"height": 64,
|
||||
"hash": "185746dc0faa6f1df30c4afe098646ff",
|
||||
"hash": "ac93f30dff13f8a8bb31398de370863b",
|
||||
"file": "SkCanvas_Reference",
|
||||
"name": "SkCanvas::drawImage"
|
||||
},
|
||||
@ -5469,7 +5469,7 @@
|
||||
"code": "void draw(SkCanvas* canvas) {\n canvas->scale(.5f, .5f);\n SkImageInfo imageInfo = source.info();\n SkIRect bounds = imageInfo.bounds();\n for (int x : { 0, bounds.width() } ) {\n for (int y : { 0, bounds.height() } ) {\n canvas->drawBitmap(source, x, y);\n }\n }\n}",
|
||||
"width": 256,
|
||||
"height": 64,
|
||||
"hash": "a818be8945cd0c18f99ffe53e90afa48",
|
||||
"hash": "3ce3db36235d80dbac4d39504cf756da",
|
||||
"file": "SkImageInfo_Reference",
|
||||
"name": "SkImageInfo::bounds()"
|
||||
},
|
||||
|
@ -874,7 +874,8 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
|
||||
}
|
||||
|
||||
paint.addCoverageFragmentProcessor(std::move(fp));
|
||||
renderTargetContext->drawVertices(clip, std::move(paint), viewMatrix, std::move(vertices));
|
||||
renderTargetContext->drawVertices(clip, std::move(paint), viewMatrix, std::move(vertices),
|
||||
nullptr, 0);
|
||||
} else {
|
||||
SkMatrix inverse;
|
||||
if (!viewMatrix.invert(&inverse)) {
|
||||
|
@ -1715,6 +1715,7 @@ void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, const SkMatrix* b
|
||||
SkBlendMode mode, const SkPaint& paint) {
|
||||
TRACE_EVENT0("skia", TRACE_FUNC);
|
||||
RETURN_ON_NULL(vertices);
|
||||
SkASSERT(boneCount <= 100);
|
||||
this->onDrawVerticesObject(vertices.get(), bones, boneCount, mode, paint);
|
||||
}
|
||||
|
||||
@ -1722,6 +1723,7 @@ void SkCanvas::drawVertices(const SkVertices* vertices, const SkMatrix* bones, i
|
||||
SkBlendMode mode, const SkPaint& paint) {
|
||||
TRACE_EVENT0("skia", TRACE_FUNC);
|
||||
RETURN_ON_NULL(vertices);
|
||||
SkASSERT(boneCount <= 100);
|
||||
this->onDrawVerticesObject(vertices, bones, boneCount, mode, paint);
|
||||
}
|
||||
|
||||
|
@ -95,16 +95,17 @@ SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
|
||||
bool hasTexs = SkToBool(builderFlags & SkVertices::kHasTexCoords_BuilderFlag);
|
||||
bool hasColors = SkToBool(builderFlags & SkVertices::kHasColors_BuilderFlag);
|
||||
bool hasBones = SkToBool(builderFlags & SkVertices::kHasBones_BuilderFlag);
|
||||
this->init(mode, vertexCount, indexCount,
|
||||
bool isVolatile = SkToBool(builderFlags & SkVertices::kIsVolatile_BuilderFlag);
|
||||
this->init(mode, vertexCount, indexCount, isVolatile,
|
||||
SkVertices::Sizes(mode, vertexCount, indexCount, hasTexs, hasColors, hasBones));
|
||||
}
|
||||
|
||||
SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount,
|
||||
SkVertices::Builder::Builder(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
|
||||
const SkVertices::Sizes& sizes) {
|
||||
this->init(mode, vertexCount, indexCount, sizes);
|
||||
this->init(mode, vertexCount, indexCount, isVolatile, sizes);
|
||||
}
|
||||
|
||||
void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount,
|
||||
void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount, bool isVolatile,
|
||||
const SkVertices::Sizes& sizes) {
|
||||
if (!sizes.isValid()) {
|
||||
return; // fVertices will already be null
|
||||
@ -128,6 +129,7 @@ void SkVertices::Builder::init(VertexMode mode, int vertexCount, int indexCount,
|
||||
fVertices->fIndices = sizes.fISize ? (uint16_t*)ptr : nullptr;
|
||||
fVertices->fVertexCnt = vertexCount;
|
||||
fVertices->fIndexCnt = indexCount;
|
||||
fVertices->fIsVolatile = isVolatile;
|
||||
fVertices->fMode = mode;
|
||||
|
||||
// We defer assigning fBounds and fUniqueID until detach() is called
|
||||
@ -171,6 +173,10 @@ int SkVertices::Builder::indexCount() const {
|
||||
return fVertices ? fVertices->indexCount() : 0;
|
||||
}
|
||||
|
||||
bool SkVertices::Builder::isVolatile() const {
|
||||
return fVertices ? fVertices->isVolatile() : false;
|
||||
}
|
||||
|
||||
SkPoint* SkVertices::Builder::positions() {
|
||||
return fVertices ? const_cast<SkPoint*>(fVertices->positions()) : nullptr;
|
||||
}
|
||||
@ -208,7 +214,8 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
|
||||
const SkColor colors[],
|
||||
const BoneIndices boneIndices[],
|
||||
const BoneWeights boneWeights[],
|
||||
int indexCount, const uint16_t indices[]) {
|
||||
int indexCount, const uint16_t indices[],
|
||||
bool isVolatile) {
|
||||
SkASSERT((!boneIndices && !boneWeights) || (boneIndices && boneWeights));
|
||||
Sizes sizes(mode,
|
||||
vertexCount,
|
||||
@ -220,7 +227,7 @@ sk_sp<SkVertices> SkVertices::MakeCopy(VertexMode mode, int vertexCount,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Builder builder(mode, vertexCount, indexCount, sizes);
|
||||
Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
|
||||
SkASSERT(builder.isValid());
|
||||
|
||||
sk_careful_memcpy(builder.positions(), pos, sizes.fVSize);
|
||||
@ -247,15 +254,15 @@ size_t SkVertices::approximateSize() const {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// storage = packed | vertex_count | index_count | pos[] | texs[] | colors[] | boneIndices[] |
|
||||
// boneWeights[] | indices[]
|
||||
// storage = packed | vertex_count | index_count | is_volatile | pos[] | texs[] | colors[] |
|
||||
// boneIndices[] | boneWeights[] | indices[]
|
||||
// = header + arrays
|
||||
|
||||
#define kMode_Mask 0x0FF
|
||||
#define kHasTexs_Mask 0x100
|
||||
#define kHasColors_Mask 0x200
|
||||
#define kHasBones_Mask 0x400
|
||||
#define kHeaderSize (3 * sizeof(uint32_t))
|
||||
#define kHeaderSize (4 * sizeof(uint32_t))
|
||||
|
||||
sk_sp<SkData> SkVertices::encode() const {
|
||||
// packed has room for addtional flags in the future (e.g. versioning)
|
||||
@ -288,6 +295,7 @@ sk_sp<SkData> SkVertices::encode() const {
|
||||
writer.write32(packed);
|
||||
writer.write32(fVertexCnt);
|
||||
writer.write32(fIndexCnt);
|
||||
writer.writeBool(fIsVolatile);
|
||||
writer.write(fPositions, sizes.fVSize);
|
||||
writer.write(fTexs, sizes.fTSize);
|
||||
writer.write(fColors, sizes.fCSize);
|
||||
@ -310,6 +318,7 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
|
||||
const uint32_t packed = reader.readInt();
|
||||
const int vertexCount = safe.checkGE(reader.readInt(), 0);
|
||||
const int indexCount = safe.checkGE(reader.readInt(), 0);
|
||||
const bool isVolatile = reader.readBool();
|
||||
const VertexMode mode = safe.checkLE<VertexMode>(packed & kMode_Mask,
|
||||
SkVertices::kLast_VertexMode);
|
||||
if (!safe) {
|
||||
@ -327,7 +336,7 @@ sk_sp<SkVertices> SkVertices::Decode(const void* data, size_t length) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Builder builder(mode, vertexCount, indexCount, sizes);
|
||||
Builder builder(mode, vertexCount, indexCount, isVolatile, sizes);
|
||||
|
||||
reader.read(builder.positions(), sizes.fVSize);
|
||||
reader.read(builder.texCoords(), sizes.fTSize);
|
||||
|
@ -27,8 +27,13 @@ enum GPFlag {
|
||||
kColorAttributeIsSkColor_GPFlag = 0x2,
|
||||
kLocalCoordAttribute_GPFlag = 0x4,
|
||||
kCoverageAttribute_GPFlag = 0x8,
|
||||
kBonesAttribute_GPFlag = 0x10,
|
||||
};
|
||||
|
||||
static constexpr int kNumFloatsPerSkMatrix = 9;
|
||||
static constexpr int kMaxBones = 100; // Due to GPU memory limitations, only up to 100 bone
|
||||
// matrices are accepted.
|
||||
|
||||
class DefaultGeoProc : public GrGeometryProcessor {
|
||||
public:
|
||||
static sk_sp<GrGeometryProcessor> Make(uint32_t gpTypeFlags,
|
||||
@ -37,10 +42,12 @@ public:
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkMatrix& localMatrix,
|
||||
bool localCoordsWillBeRead,
|
||||
uint8_t coverage) {
|
||||
uint8_t coverage,
|
||||
const SkMatrix bones[],
|
||||
int boneCount) {
|
||||
return sk_sp<GrGeometryProcessor>(new DefaultGeoProc(
|
||||
gpTypeFlags, color, std::move(colorSpaceXform), viewMatrix, localMatrix, coverage,
|
||||
localCoordsWillBeRead));
|
||||
localCoordsWillBeRead, bones, boneCount));
|
||||
}
|
||||
|
||||
const char* name() const override { return "DefaultGeometryProcessor"; }
|
||||
@ -52,6 +59,9 @@ public:
|
||||
bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; }
|
||||
uint8_t coverage() const { return fCoverage; }
|
||||
bool hasVertexCoverage() const { return fInCoverage.isInitialized(); }
|
||||
const float* bones() const { return fBones.data(); }
|
||||
int boneCount() const { return fBones.size() / kNumFloatsPerSkMatrix; }
|
||||
bool hasBones() const { return fBones.size() > 0; }
|
||||
|
||||
class GLSLProcessor : public GrGLSLGeometryProcessor {
|
||||
public:
|
||||
@ -99,11 +109,37 @@ public:
|
||||
&fColorUniform);
|
||||
}
|
||||
|
||||
// Setup bone transforms
|
||||
const char* transformedPositionName = gp.fInPosition.name();
|
||||
if (gp.hasBones()) {
|
||||
const char* vertBonesUniformName;
|
||||
fBonesUniform = uniformHandler->addUniformArray(kVertex_GrShaderFlag,
|
||||
kFloat3x3_GrSLType,
|
||||
"Bones",
|
||||
kMaxBones,
|
||||
&vertBonesUniformName);
|
||||
vertBuilder->codeAppendf(
|
||||
"float2 transformedPosition = (%s[0] * float3(%s, 1)).xy;"
|
||||
"float3x3 influence = float3x3(0);"
|
||||
"for (int i = 0; i < 4; i++) {"
|
||||
" int index = %s[i];"
|
||||
" float weight = %s[i];"
|
||||
" influence += %s[index] * weight;"
|
||||
"}"
|
||||
"transformedPosition = (influence * float3(transformedPosition, 1)).xy;",
|
||||
vertBonesUniformName,
|
||||
gp.fInPosition.name(),
|
||||
gp.fInBoneIndices.name(),
|
||||
gp.fInBoneWeights.name(),
|
||||
vertBonesUniformName);
|
||||
transformedPositionName = "transformedPosition";
|
||||
}
|
||||
|
||||
// Setup position
|
||||
this->writeOutputPosition(vertBuilder,
|
||||
uniformHandler,
|
||||
gpArgs,
|
||||
gp.fInPosition.name(),
|
||||
transformedPositionName,
|
||||
gp.viewMatrix(),
|
||||
&fViewMatrixUniform);
|
||||
|
||||
@ -147,8 +183,8 @@ public:
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
|
||||
uint32_t key = def.fFlags;
|
||||
key |= (def.coverage() == 0xff) ? 0x10 : 0;
|
||||
key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x20 : 0x0;
|
||||
key |= (def.coverage() == 0xff) ? 0x20 : 0;
|
||||
key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x40 : 0x0;
|
||||
key |= ComputePosKey(def.viewMatrix()) << 20;
|
||||
b->add32(key);
|
||||
b->add32(GrColorSpaceXform::XformKey(def.fColorSpaceXform.get()));
|
||||
@ -180,6 +216,10 @@ public:
|
||||
this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter);
|
||||
|
||||
fColorSpaceHelper.setData(pdman, dgp.fColorSpaceXform.get());
|
||||
|
||||
if (dgp.hasBones()) {
|
||||
pdman.setMatrix3fv(fBonesUniform, dgp.boneCount(), dgp.bones());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@ -189,6 +229,7 @@ public:
|
||||
UniformHandle fViewMatrixUniform;
|
||||
UniformHandle fColorUniform;
|
||||
UniformHandle fCoverageUniform;
|
||||
UniformHandle fBonesUniform;
|
||||
GrGLSLColorSpaceXformHelper fColorSpaceHelper;
|
||||
|
||||
typedef GrGLSLGeometryProcessor INHERITED;
|
||||
@ -209,7 +250,9 @@ private:
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkMatrix& localMatrix,
|
||||
uint8_t coverage,
|
||||
bool localCoordsWillBeRead)
|
||||
bool localCoordsWillBeRead,
|
||||
const SkMatrix* bones,
|
||||
int boneCount)
|
||||
: INHERITED(kDefaultGeoProc_ClassID)
|
||||
, fColor(color)
|
||||
, fViewMatrix(viewMatrix)
|
||||
@ -217,7 +260,8 @@ private:
|
||||
, fCoverage(coverage)
|
||||
, fFlags(gpTypeFlags)
|
||||
, fLocalCoordsWillBeRead(localCoordsWillBeRead)
|
||||
, fColorSpaceXform(std::move(colorSpaceXform)) {
|
||||
, fColorSpaceXform(std::move(colorSpaceXform))
|
||||
, fBones() {
|
||||
fInPosition = {"inPosition", kFloat2_GrVertexAttribType};
|
||||
int cnt = 1;
|
||||
if (fFlags & kColorAttribute_GPFlag) {
|
||||
@ -232,17 +276,49 @@ private:
|
||||
fInCoverage = {"inCoverage", kHalf_GrVertexAttribType};
|
||||
++cnt;
|
||||
}
|
||||
if (fFlags & kBonesAttribute_GPFlag) {
|
||||
SkASSERT(bones && (boneCount > 0));
|
||||
fInBoneIndices = {"inBoneIndices", kInt4_GrVertexAttribType};
|
||||
++cnt;
|
||||
fInBoneWeights = {"inBoneWeights", kFloat4_GrVertexAttribType};
|
||||
++cnt;
|
||||
}
|
||||
this->setVertexAttributeCnt(cnt);
|
||||
|
||||
// Set bone data
|
||||
if (bones) {
|
||||
fBones.reserve(boneCount * kNumFloatsPerSkMatrix);
|
||||
for (int i = 0; i < boneCount; i ++) {
|
||||
const SkMatrix& matrix = bones[i];
|
||||
fBones.push_back(matrix.get(SkMatrix::kMScaleX));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMSkewY));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMPersp0));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMSkewX));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMScaleY));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMPersp1));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMTransX));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMTransY));
|
||||
fBones.push_back(matrix.get(SkMatrix::kMPersp2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Attribute& onVertexAttribute(int i) const override {
|
||||
return IthInitializedAttribute(i, fInPosition, fInColor, fInLocalCoords, fInCoverage);
|
||||
return IthInitializedAttribute(i,
|
||||
fInPosition,
|
||||
fInColor,
|
||||
fInLocalCoords,
|
||||
fInCoverage,
|
||||
fInBoneIndices,
|
||||
fInBoneWeights);
|
||||
}
|
||||
|
||||
Attribute fInPosition;
|
||||
Attribute fInColor;
|
||||
Attribute fInLocalCoords;
|
||||
Attribute fInCoverage;
|
||||
Attribute fInBoneIndices;
|
||||
Attribute fInBoneWeights;
|
||||
GrColor fColor;
|
||||
SkMatrix fViewMatrix;
|
||||
SkMatrix fLocalMatrix;
|
||||
@ -250,6 +326,7 @@ private:
|
||||
uint32_t fFlags;
|
||||
bool fLocalCoordsWillBeRead;
|
||||
sk_sp<GrColorSpaceXform> fColorSpaceXform;
|
||||
std::vector<float> fBones;
|
||||
|
||||
GR_DECLARE_GEOMETRY_PROCESSOR_TEST
|
||||
|
||||
@ -273,6 +350,17 @@ sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
|
||||
if (d->fRandom->nextBool()) {
|
||||
flags |= kLocalCoordAttribute_GPFlag;
|
||||
}
|
||||
if (d->fRandom->nextBool()) {
|
||||
flags |= kBonesAttribute_GPFlag;
|
||||
}
|
||||
|
||||
int numBones = d->fRandom->nextRangeU(0, kMaxBones);
|
||||
std::vector<SkMatrix> bones(numBones);
|
||||
for (int i = 0; i < numBones; i++) {
|
||||
for (int j = 0; j < kNumFloatsPerSkMatrix; j++) {
|
||||
bones[i][j] = d->fRandom->nextF();
|
||||
}
|
||||
}
|
||||
|
||||
return DefaultGeoProc::Make(flags,
|
||||
GrRandomColor(d->fRandom),
|
||||
@ -280,7 +368,9 @@ sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
|
||||
GrTest::TestMatrix(d->fRandom),
|
||||
GrTest::TestMatrix(d->fRandom),
|
||||
d->fRandom->nextBool(),
|
||||
GrRandomCoverage(d->fRandom));
|
||||
GrRandomCoverage(d->fRandom),
|
||||
bones.data(),
|
||||
numBones);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -307,7 +397,9 @@ sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const Color& color,
|
||||
viewMatrix,
|
||||
localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
|
||||
localCoordsWillBeRead,
|
||||
inCoverage);
|
||||
inCoverage,
|
||||
nullptr,
|
||||
0);
|
||||
}
|
||||
|
||||
sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace(
|
||||
@ -330,3 +422,33 @@ sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace(
|
||||
LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
|
||||
return Make(color, coverage, inverted, SkMatrix::I());
|
||||
}
|
||||
|
||||
sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeWithBones(const Color& color,
|
||||
const Coverage& coverage,
|
||||
const LocalCoords& localCoords,
|
||||
const Bones& bones,
|
||||
const SkMatrix& viewMatrix) {
|
||||
uint32_t flags = 0;
|
||||
if (Color::kPremulGrColorAttribute_Type == color.fType) {
|
||||
flags |= kColorAttribute_GPFlag;
|
||||
} else if (Color::kUnpremulSkColorAttribute_Type == color.fType) {
|
||||
flags |= kColorAttribute_GPFlag | kColorAttributeIsSkColor_GPFlag;
|
||||
}
|
||||
flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverageAttribute_GPFlag : 0;
|
||||
flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0;
|
||||
flags |= kBonesAttribute_GPFlag;
|
||||
|
||||
uint8_t inCoverage = coverage.fCoverage;
|
||||
bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type;
|
||||
|
||||
GrColor inColor = color.fColor;
|
||||
return DefaultGeoProc::Make(flags,
|
||||
inColor,
|
||||
color.fColorSpaceXform,
|
||||
viewMatrix,
|
||||
localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
|
||||
localCoordsWillBeRead,
|
||||
inCoverage,
|
||||
bones.fBones,
|
||||
bones.fBoneCount);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ namespace GrDefaultGeoProcFactory {
|
||||
SkPoint fLocalCoord;
|
||||
};
|
||||
|
||||
struct PositionColorLocalCoordCoverage {
|
||||
struct PositionColorLocalCoordCoverageAttr {
|
||||
SkPoint fPosition;
|
||||
GrColor fColor;
|
||||
SkPoint fLocalCoord;
|
||||
@ -118,6 +118,15 @@ namespace GrDefaultGeoProcFactory {
|
||||
const SkMatrix* fMatrix;
|
||||
};
|
||||
|
||||
struct Bones {
|
||||
Bones(const SkMatrix bones[], int boneCount)
|
||||
: fBones(bones)
|
||||
, fBoneCount(boneCount) {}
|
||||
|
||||
const SkMatrix* fBones;
|
||||
int fBoneCount;
|
||||
};
|
||||
|
||||
sk_sp<GrGeometryProcessor> Make(const Color&,
|
||||
const Coverage&,
|
||||
const LocalCoords&,
|
||||
@ -132,6 +141,17 @@ namespace GrDefaultGeoProcFactory {
|
||||
const Coverage&,
|
||||
const LocalCoords&,
|
||||
const SkMatrix& viewMatrix);
|
||||
|
||||
/*
|
||||
* Use this factory to create a GrGeometryProcessor that supports skeletal animation through
|
||||
* deformation of vertices using matrices that are passed in. This should only be called from
|
||||
* GrDrawVerticesOp.
|
||||
*/
|
||||
sk_sp<GrGeometryProcessor> MakeWithBones(const Color&,
|
||||
const Coverage&,
|
||||
const LocalCoords&,
|
||||
const Bones&,
|
||||
const SkMatrix& viewMatrix);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -844,6 +844,8 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip,
|
||||
GrPaint&& paint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<SkVertices> vertices,
|
||||
const SkMatrix bones[],
|
||||
int boneCount,
|
||||
GrPrimitiveType* overridePrimType) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
RETURN_IF_ABANDONED
|
||||
@ -855,7 +857,7 @@ void GrRenderTargetContext::drawVertices(const GrClip& clip,
|
||||
SkASSERT(vertices);
|
||||
GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
|
||||
std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
|
||||
fContext, std::move(paint), std::move(vertices), viewMatrix, aaType,
|
||||
fContext, std::move(paint), std::move(vertices), bones, boneCount, viewMatrix, aaType,
|
||||
this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
|
||||
this->addDrawOp(clip, std::move(op));
|
||||
}
|
||||
|
@ -218,12 +218,16 @@ public:
|
||||
* @param paint describes how to color pixels.
|
||||
* @param viewMatrix transformation matrix
|
||||
* @param vertices specifies the mesh to draw.
|
||||
* @param bones bone deformation matrices.
|
||||
* @param boneCount number of bone matrices.
|
||||
* @param overridePrimType primitive type to draw. If NULL, derive prim type from vertices.
|
||||
*/
|
||||
void drawVertices(const GrClip&,
|
||||
GrPaint&& paint,
|
||||
const SkMatrix& viewMatrix,
|
||||
sk_sp<SkVertices> vertices,
|
||||
const SkMatrix bones[],
|
||||
int boneCount,
|
||||
GrPrimitiveType* overridePrimType = nullptr);
|
||||
|
||||
/**
|
||||
|
@ -365,7 +365,7 @@ void SkGpuDevice::drawPoints(SkCanvas::PointMode mode,
|
||||
nullptr);
|
||||
|
||||
fRenderTargetContext->drawVertices(this->clip(), std::move(grPaint), *viewMatrix,
|
||||
std::move(vertices), &primitiveType);
|
||||
std::move(vertices), nullptr, 0, &primitiveType);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -1480,7 +1480,9 @@ static bool init_vertices_paint(GrContext* context, const GrColorSpaceInfo& colo
|
||||
}
|
||||
|
||||
void SkGpuDevice::wireframeVertices(SkVertices::VertexMode vmode, int vertexCount,
|
||||
const SkPoint vertices[], SkBlendMode bmode,
|
||||
const SkPoint vertices[],
|
||||
const SkMatrix bones[], int boneCount,
|
||||
SkBlendMode bmode,
|
||||
const uint16_t indices[], int indexCount,
|
||||
const SkPaint& paint) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
@ -1538,12 +1540,13 @@ void SkGpuDevice::wireframeVertices(SkVertices::VertexMode vmode, int vertexCoun
|
||||
std::move(grPaint),
|
||||
this->ctm(),
|
||||
builder.detach(),
|
||||
bones,
|
||||
boneCount,
|
||||
&primitiveType);
|
||||
}
|
||||
|
||||
void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix* bones, int boneCount,
|
||||
void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix bones[], int boneCount,
|
||||
SkBlendMode mode, const SkPaint& paint) {
|
||||
// TODO: GPU ANIMATION
|
||||
ASSERT_SINGLE_OWNER
|
||||
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawVertices", fContext.get());
|
||||
|
||||
@ -1554,7 +1557,8 @@ void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix* bones
|
||||
if ((!hasTexs || !paint.getShader()) && !hasColors) {
|
||||
// The dreaded wireframe mode. Fallback to drawVertices and go so slooooooow.
|
||||
this->wireframeVertices(vertices->mode(), vertices->vertexCount(), vertices->positions(),
|
||||
mode, vertices->indices(), vertices->indexCount(), paint);
|
||||
bones, boneCount, mode, vertices->indices(), vertices->indexCount(),
|
||||
paint);
|
||||
return;
|
||||
}
|
||||
if (!init_vertices_paint(fContext.get(), fRenderTargetContext->colorSpaceInfo(), paint,
|
||||
@ -1562,7 +1566,8 @@ void SkGpuDevice::drawVertices(const SkVertices* vertices, const SkMatrix* bones
|
||||
return;
|
||||
}
|
||||
fRenderTargetContext->drawVertices(this->clip(), std::move(grPaint), this->ctm(),
|
||||
sk_ref_sp(const_cast<SkVertices*>(vertices)));
|
||||
sk_ref_sp(const_cast<SkVertices*>(vertices)),
|
||||
bones, boneCount);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -91,7 +91,7 @@ public:
|
||||
int scalarsPerPos, const SkPoint& offset, const SkPaint&) override;
|
||||
void drawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
|
||||
const SkPaint& paint, SkDrawFilter* drawFilter) override;
|
||||
void drawVertices(const SkVertices*, const SkMatrix* bones, int boneCount, SkBlendMode,
|
||||
void drawVertices(const SkVertices*, const SkMatrix bones[], int boneCount, SkBlendMode,
|
||||
const SkPaint&) override;
|
||||
void drawShadow(const SkPath&, const SkDrawShadowRec&) override;
|
||||
void drawAtlas(const SkImage* atlas, const SkRSXform[], const SkRect[],
|
||||
@ -248,7 +248,8 @@ private:
|
||||
void drawStrokedLine(const SkPoint pts[2], const SkPaint&);
|
||||
|
||||
void wireframeVertices(SkVertices::VertexMode, int vertexCount, const SkPoint verts[],
|
||||
SkBlendMode, const uint16_t indices[], int indexCount, const SkPaint&);
|
||||
const SkMatrix bones[], int boneCount, SkBlendMode,
|
||||
const uint16_t indices[], int indexCount, const SkPaint&);
|
||||
|
||||
static sk_sp<GrRenderTargetContext> MakeRenderTargetContext(GrContext*,
|
||||
SkBudgeted,
|
||||
|
@ -10,10 +10,13 @@
|
||||
#include "GrDefaultGeoProcFactory.h"
|
||||
#include "GrOpFlushState.h"
|
||||
#include "SkGr.h"
|
||||
#include "SkRectPriv.h"
|
||||
|
||||
std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrContext* context,
|
||||
GrPaint&& paint,
|
||||
sk_sp<SkVertices> vertices,
|
||||
const SkMatrix bones[],
|
||||
int boneCount,
|
||||
const SkMatrix& viewMatrix,
|
||||
GrAAType aaType,
|
||||
sk_sp<GrColorSpaceXform> colorSpaceXform,
|
||||
@ -22,13 +25,14 @@ std::unique_ptr<GrDrawOp> GrDrawVerticesOp::Make(GrContext* context,
|
||||
GrPrimitiveType primType = overridePrimType ? *overridePrimType
|
||||
: SkVertexModeToGrPrimitiveType(vertices->mode());
|
||||
return Helper::FactoryHelper<GrDrawVerticesOp>(context, std::move(paint), std::move(vertices),
|
||||
primType, aaType, std::move(colorSpaceXform),
|
||||
viewMatrix);
|
||||
bones, boneCount, primType, aaType,
|
||||
std::move(colorSpaceXform), viewMatrix);
|
||||
}
|
||||
|
||||
GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor color,
|
||||
sk_sp<SkVertices> vertices, GrPrimitiveType primitiveType,
|
||||
GrAAType aaType, sk_sp<GrColorSpaceXform> colorSpaceXform,
|
||||
sk_sp<SkVertices> vertices, const SkMatrix bones[],
|
||||
int boneCount, GrPrimitiveType primitiveType, GrAAType aaType,
|
||||
sk_sp<GrColorSpaceXform> colorSpaceXform,
|
||||
const SkMatrix& viewMatrix)
|
||||
: INHERITED(ClassID())
|
||||
, fHelper(helperArgs, aaType)
|
||||
@ -45,15 +49,28 @@ GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor c
|
||||
mesh.fColor = color;
|
||||
mesh.fViewMatrix = viewMatrix;
|
||||
mesh.fVertices = std::move(vertices);
|
||||
if (bones) {
|
||||
mesh.fBones.assign(bones, bones + boneCount);
|
||||
}
|
||||
mesh.fIgnoreTexCoords = false;
|
||||
mesh.fIgnoreColors = false;
|
||||
mesh.fIgnoreBones = false;
|
||||
|
||||
fFlags = 0;
|
||||
if (mesh.hasPerVertexColors()) {
|
||||
fFlags |= kRequiresPerVertexColors_Flag;
|
||||
}
|
||||
if (mesh.hasExplicitLocalCoords()) {
|
||||
fFlags |= kAnyMeshHasExplicitLocalCoords;
|
||||
fFlags |= kAnyMeshHasExplicitLocalCoords_Flag;
|
||||
}
|
||||
if (mesh.hasBones()) {
|
||||
fFlags |= kHasBones_Flag;
|
||||
}
|
||||
|
||||
// Special case for meshes with a world transform but no bone weights.
|
||||
// These will be considered normal vertices draws without bones.
|
||||
if (!mesh.fVertices->hasBones() && boneCount == 1) {
|
||||
mesh.fViewMatrix.preConcat(bones[0]);
|
||||
}
|
||||
|
||||
IsZeroArea zeroArea;
|
||||
@ -62,7 +79,27 @@ GrDrawVerticesOp::GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor c
|
||||
} else {
|
||||
zeroArea = IsZeroArea::kNo;
|
||||
}
|
||||
this->setTransformedBounds(mesh.fVertices->bounds(), viewMatrix, HasAABloat::kNo, zeroArea);
|
||||
|
||||
if (this->hasBones()) {
|
||||
// We don't know the bounds if there are deformations involved, so attempt to calculate
|
||||
// the maximum possible.
|
||||
SkRect bounds;
|
||||
const SkRect& originalBounds = bones[0].mapRect(mesh.fVertices->bounds());
|
||||
for (int i = 1; i < boneCount; i++) {
|
||||
const SkMatrix& matrix = bones[i];
|
||||
bounds.join(matrix.mapRect(originalBounds));
|
||||
}
|
||||
|
||||
this->setTransformedBounds(bounds,
|
||||
mesh.fViewMatrix,
|
||||
HasAABloat::kNo,
|
||||
zeroArea);
|
||||
} else {
|
||||
this->setTransformedBounds(mesh.fVertices->bounds(),
|
||||
mesh.fViewMatrix,
|
||||
HasAABloat::kNo,
|
||||
zeroArea);
|
||||
}
|
||||
}
|
||||
|
||||
SkString GrDrawVerticesOp::dumpInfo() const {
|
||||
@ -96,13 +133,14 @@ GrDrawOp::RequiresDstTexture GrDrawVerticesOp::finalize(const GrCaps& caps,
|
||||
}
|
||||
if (!fHelper.usesLocalCoords()) {
|
||||
fMeshes[0].fIgnoreTexCoords = true;
|
||||
fFlags &= ~kAnyMeshHasExplicitLocalCoords;
|
||||
fFlags &= ~kAnyMeshHasExplicitLocalCoords_Flag;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
sk_sp<GrGeometryProcessor> GrDrawVerticesOp::makeGP(bool* hasColorAttribute,
|
||||
bool* hasLocalCoordAttribute) const {
|
||||
bool* hasLocalCoordAttribute,
|
||||
bool* hasBoneAttribute) const {
|
||||
using namespace GrDefaultGeoProcFactory;
|
||||
LocalCoords::Type localCoordsType;
|
||||
if (fHelper.usesLocalCoords()) {
|
||||
@ -132,26 +170,53 @@ sk_sp<GrGeometryProcessor> GrDrawVerticesOp::makeGP(bool* hasColorAttribute,
|
||||
} else {
|
||||
*hasColorAttribute = false;
|
||||
};
|
||||
|
||||
const SkMatrix& vm = this->hasMultipleViewMatrices() ? SkMatrix::I() : fMeshes[0].fViewMatrix;
|
||||
return GrDefaultGeoProcFactory::Make(color, Coverage::kSolid_Type, localCoordsType, vm);
|
||||
|
||||
Bones bones(fMeshes[0].fBones.data(), fMeshes[0].fBones.size());
|
||||
*hasBoneAttribute = this->hasBones();
|
||||
|
||||
if (this->hasBones()) {
|
||||
return GrDefaultGeoProcFactory::MakeWithBones(color,
|
||||
Coverage::kSolid_Type,
|
||||
localCoordsType,
|
||||
bones,
|
||||
vm);
|
||||
} else {
|
||||
return GrDefaultGeoProcFactory::Make(color,
|
||||
Coverage::kSolid_Type,
|
||||
localCoordsType,
|
||||
vm);
|
||||
}
|
||||
}
|
||||
|
||||
void GrDrawVerticesOp::onPrepareDraws(Target* target) {
|
||||
if (fMeshes[0].fVertices->isVolatile()) {
|
||||
this->drawVolatile(target);
|
||||
} else {
|
||||
this->drawNonVolatile(target);
|
||||
}
|
||||
}
|
||||
|
||||
void GrDrawVerticesOp::drawVolatile(Target* target) {
|
||||
bool hasColorAttribute;
|
||||
bool hasLocalCoordsAttribute;
|
||||
sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute, &hasLocalCoordsAttribute);
|
||||
bool hasBoneAttribute;
|
||||
sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute,
|
||||
&hasLocalCoordsAttribute,
|
||||
&hasBoneAttribute);
|
||||
|
||||
size_t vertexStride = sizeof(SkPoint) + (hasColorAttribute ? sizeof(uint32_t) : 0) +
|
||||
(hasLocalCoordsAttribute ? sizeof(SkPoint) : 0);
|
||||
// Calculate the stride.
|
||||
size_t vertexStride = sizeof(SkPoint) +
|
||||
(hasColorAttribute ? sizeof(uint32_t) : 0) +
|
||||
(hasLocalCoordsAttribute ? sizeof(SkPoint) : 0) +
|
||||
(hasBoneAttribute ? 4 * (sizeof(uint32_t) + sizeof(float)) : 0);
|
||||
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
|
||||
|
||||
int instanceCount = fMeshes.count();
|
||||
|
||||
const GrBuffer* vertexBuffer;
|
||||
int firstVertex;
|
||||
|
||||
// Allocate buffers.
|
||||
const GrBuffer* vertexBuffer = nullptr;
|
||||
int firstVertex = 0;
|
||||
void* verts = target->makeVertexSpace(vertexStride, fVertexCount, &vertexBuffer, &firstVertex);
|
||||
|
||||
if (!verts) {
|
||||
SkDebugf("Could not allocate vertices\n");
|
||||
return;
|
||||
@ -159,37 +224,157 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) {
|
||||
|
||||
const GrBuffer* indexBuffer = nullptr;
|
||||
int firstIndex = 0;
|
||||
|
||||
uint16_t* indices = nullptr;
|
||||
if (this->isIndexed()) {
|
||||
indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
|
||||
|
||||
if (!indices) {
|
||||
SkDebugf("Could not allocate indices\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the buffers.
|
||||
this->fillBuffers(hasColorAttribute,
|
||||
hasLocalCoordsAttribute,
|
||||
hasBoneAttribute,
|
||||
vertexStride,
|
||||
verts,
|
||||
indices);
|
||||
|
||||
// Draw the vertices.
|
||||
this->drawVertices(target, gp.get(), vertexBuffer, firstVertex, indexBuffer, firstIndex);
|
||||
}
|
||||
|
||||
void GrDrawVerticesOp::drawNonVolatile(Target* target) {
|
||||
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
||||
|
||||
bool hasColorAttribute;
|
||||
bool hasLocalCoordsAttribute;
|
||||
bool hasBoneAttribute;
|
||||
sk_sp<GrGeometryProcessor> gp = this->makeGP(&hasColorAttribute,
|
||||
&hasLocalCoordsAttribute,
|
||||
&hasBoneAttribute);
|
||||
|
||||
int instanceCount = fMeshes.count();
|
||||
SkASSERT(instanceCount == 1); // Non-volatile meshes should never combine.
|
||||
|
||||
// Get the resource provider.
|
||||
GrResourceProvider* rp = target->resourceProvider();
|
||||
|
||||
// Generate keys for the buffers.
|
||||
GrUniqueKey vertexKey, indexKey;
|
||||
GrUniqueKey::Builder vertexKeyBuilder(&vertexKey, kDomain, instanceCount + 1);
|
||||
GrUniqueKey::Builder indexKeyBuilder(&indexKey, kDomain, instanceCount + 1);
|
||||
for (int i = 0; i < instanceCount; i ++) {
|
||||
vertexKeyBuilder[i] = indexKeyBuilder[i] = fMeshes[i].fVertices->uniqueID();
|
||||
}
|
||||
vertexKeyBuilder[instanceCount] = 0;
|
||||
indexKeyBuilder[instanceCount] = 1;
|
||||
vertexKeyBuilder.finish();
|
||||
indexKeyBuilder.finish();
|
||||
|
||||
// Try to grab data from the cache.
|
||||
sk_sp<GrBuffer> vertexBuffer = rp->findByUniqueKey<GrBuffer>(vertexKey);
|
||||
sk_sp<GrBuffer> indexBuffer = rp->findByUniqueKey<GrBuffer>(indexKey);
|
||||
|
||||
// Draw using the cached buffers if possible.
|
||||
if (vertexBuffer) {
|
||||
this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the stride.
|
||||
size_t vertexStride = sizeof(SkPoint) +
|
||||
(hasColorAttribute ? sizeof(uint32_t) : 0) +
|
||||
(hasLocalCoordsAttribute ? sizeof(SkPoint) : 0) +
|
||||
(hasBoneAttribute ? 4 * (sizeof(uint32_t) + sizeof(float)) : 0);
|
||||
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
|
||||
|
||||
// Allocate vertex buffer.
|
||||
vertexBuffer.reset(rp->createBuffer(fVertexCount * vertexStride,
|
||||
kVertex_GrBufferType,
|
||||
kStatic_GrAccessPattern,
|
||||
0));
|
||||
void* verts = vertexBuffer ? vertexBuffer->map() : nullptr;
|
||||
if (!verts) {
|
||||
SkDebugf("Could not allocate vertices\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate index buffer.
|
||||
uint16_t* indices = nullptr;
|
||||
if (this->isIndexed()) {
|
||||
indexBuffer.reset(rp->createBuffer(fIndexCount * sizeof(uint16_t),
|
||||
kIndex_GrBufferType,
|
||||
kStatic_GrAccessPattern,
|
||||
0));
|
||||
indices = indexBuffer ? static_cast<uint16_t*>(indexBuffer->map()) : nullptr;
|
||||
if (!indices) {
|
||||
SkDebugf("Could not allocate indices\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the buffers.
|
||||
this->fillBuffers(hasColorAttribute,
|
||||
hasLocalCoordsAttribute,
|
||||
hasBoneAttribute,
|
||||
vertexStride,
|
||||
verts,
|
||||
indices);
|
||||
|
||||
// Unmap the buffers.
|
||||
vertexBuffer->unmap();
|
||||
if (indexBuffer) {
|
||||
indexBuffer->unmap();
|
||||
}
|
||||
|
||||
// Cache the buffers.
|
||||
rp->assignUniqueKeyToResource(vertexKey, vertexBuffer.get());
|
||||
rp->assignUniqueKeyToResource(indexKey, indexBuffer.get());
|
||||
|
||||
// Draw the vertices.
|
||||
this->drawVertices(target, gp.get(), vertexBuffer.get(), 0, indexBuffer.get(), 0);
|
||||
}
|
||||
|
||||
void GrDrawVerticesOp::fillBuffers(bool hasColorAttribute,
|
||||
bool hasLocalCoordsAttribute,
|
||||
bool hasBoneAttribute,
|
||||
size_t vertexStride,
|
||||
void* verts,
|
||||
uint16_t* indices) const {
|
||||
int instanceCount = fMeshes.count();
|
||||
|
||||
// Copy data into the buffers.
|
||||
int vertexOffset = 0;
|
||||
// We have a fast case below for uploading the vertex data when the matrix is translate
|
||||
// only and there are colors but not local coords.
|
||||
bool fastAttrs = hasColorAttribute && !hasLocalCoordsAttribute;
|
||||
// only and there are colors but not local coords. Fast case does not apply when there are bone
|
||||
// transformations.
|
||||
bool fastAttrs = hasColorAttribute && !hasLocalCoordsAttribute && !hasBoneAttribute;
|
||||
for (int i = 0; i < instanceCount; i++) {
|
||||
// Get each mesh.
|
||||
const Mesh& mesh = fMeshes[i];
|
||||
|
||||
// Copy data into the index buffer.
|
||||
if (indices) {
|
||||
int indexCount = mesh.fVertices->indexCount();
|
||||
for (int j = 0; j < indexCount; ++j) {
|
||||
*indices++ = mesh.fVertices->indices()[j] + vertexOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy data into the vertex buffer.
|
||||
int vertexCount = mesh.fVertices->vertexCount();
|
||||
const SkPoint* positions = mesh.fVertices->positions();
|
||||
const SkColor* colors = mesh.fVertices->colors();
|
||||
const SkPoint* localCoords = mesh.fVertices->texCoords();
|
||||
const SkVertices::BoneIndices* boneIndices = mesh.fVertices->boneIndices();
|
||||
const SkVertices::BoneWeights* boneWeights = mesh.fVertices->boneWeights();
|
||||
bool fastMesh = (!this->hasMultipleViewMatrices() ||
|
||||
mesh.fViewMatrix.getType() <= SkMatrix::kTranslate_Mask) &&
|
||||
mesh.hasPerVertexColors();
|
||||
if (fastAttrs && fastMesh) {
|
||||
// Fast case.
|
||||
struct V {
|
||||
SkPoint fPos;
|
||||
uint32_t fColor;
|
||||
@ -207,9 +392,19 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) {
|
||||
}
|
||||
verts = v + vertexCount;
|
||||
} else {
|
||||
// Normal case.
|
||||
static constexpr size_t kColorOffset = sizeof(SkPoint);
|
||||
size_t localCoordOffset =
|
||||
hasColorAttribute ? kColorOffset + sizeof(uint32_t) : kColorOffset;
|
||||
size_t offset = kColorOffset;
|
||||
if (hasColorAttribute) {
|
||||
offset += sizeof(uint32_t);
|
||||
}
|
||||
size_t localCoordOffset = offset;
|
||||
if (hasLocalCoordsAttribute) {
|
||||
offset += sizeof(SkPoint);
|
||||
}
|
||||
size_t boneIndexOffset = offset;
|
||||
offset += 4 * sizeof(uint32_t);
|
||||
size_t boneWeightOffset = offset;
|
||||
|
||||
for (int j = 0; j < vertexCount; ++j) {
|
||||
if (this->hasMultipleViewMatrices()) {
|
||||
@ -231,22 +426,40 @@ void GrDrawVerticesOp::onPrepareDraws(Target* target) {
|
||||
*(SkPoint*)((intptr_t)verts + localCoordOffset) = positions[j];
|
||||
}
|
||||
}
|
||||
if (hasBoneAttribute) {
|
||||
const SkVertices::BoneIndices& indices = boneIndices[j];
|
||||
const SkVertices::BoneWeights& weights = boneWeights[j];
|
||||
for (int k = 0; k < 4; k++) {
|
||||
size_t indexOffset = boneIndexOffset + sizeof(uint32_t) * k;
|
||||
size_t weightOffset = boneWeightOffset + sizeof(float) * k;
|
||||
*(uint32_t*)((intptr_t)verts + indexOffset) = indices.indices[k];
|
||||
*(float*)((intptr_t)verts + weightOffset) = weights.weights[k];
|
||||
}
|
||||
}
|
||||
verts = (void*)((intptr_t)verts + vertexStride);
|
||||
}
|
||||
}
|
||||
vertexOffset += vertexCount;
|
||||
}
|
||||
}
|
||||
|
||||
void GrDrawVerticesOp::drawVertices(Target* target,
|
||||
GrGeometryProcessor* gp,
|
||||
const GrBuffer* vertexBuffer,
|
||||
int firstVertex,
|
||||
const GrBuffer* indexBuffer,
|
||||
int firstIndex) {
|
||||
GrMesh mesh(this->primitiveType());
|
||||
if (!indices) {
|
||||
mesh.setNonIndexedNonInstanced(fVertexCount);
|
||||
} else {
|
||||
mesh.setIndexed(indexBuffer, fIndexCount, firstIndex, 0, fVertexCount - 1,
|
||||
if (this->isIndexed()) {
|
||||
mesh.setIndexed(indexBuffer, fIndexCount,
|
||||
firstIndex, 0, fVertexCount - 1,
|
||||
GrPrimitiveRestart::kNo);
|
||||
} else {
|
||||
mesh.setNonIndexedNonInstanced(fVertexCount);
|
||||
}
|
||||
mesh.setVertexData(vertexBuffer, firstVertex);
|
||||
auto pipe = fHelper.makePipeline(target);
|
||||
target->draw(gp.get(), pipe.fPipeline, pipe.fFixedDynamicState, mesh);
|
||||
target->draw(gp, pipe.fPipeline, pipe.fFixedDynamicState, mesh);
|
||||
}
|
||||
|
||||
bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
|
||||
@ -256,6 +469,20 @@ bool GrDrawVerticesOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Meshes with bones cannot be combined because different meshes use different bones, so to
|
||||
// combine them, the matrices would have to be combined, and the bone indices on each vertex
|
||||
// would change, thus making the vertices uncacheable.
|
||||
if (this->hasBones() || that->hasBones()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Non-volatile meshes cannot batch, because if a non-volatile mesh batches with another mesh,
|
||||
// then on the next frame, if that non-volatile mesh is drawn, it will draw the other mesh
|
||||
// that was saved in its vertex buffer, which is not necessarily there anymore.
|
||||
if (!this->fMeshes[0].fVertices->isVolatile() || !that->fMeshes[0].fVertices->isVolatile()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->combinablePrimitive() || this->primitiveType() != that->primitiveType()) {
|
||||
return false;
|
||||
}
|
||||
@ -410,8 +637,8 @@ GR_DRAW_OP_TEST_DEFINE(GrDrawVerticesOp) {
|
||||
if (GrFSAAType::kUnifiedMSAA == fsaaType && random->nextBool()) {
|
||||
aaType = GrAAType::kMSAA;
|
||||
}
|
||||
return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices), viewMatrix,
|
||||
aaType, std::move(colorSpaceXform), &type);
|
||||
return GrDrawVerticesOp::Make(context, std::move(paint), std::move(vertices), nullptr, 0,
|
||||
viewMatrix, aaType, std::move(colorSpaceXform), &type);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -38,13 +38,15 @@ public:
|
||||
static std::unique_ptr<GrDrawOp> Make(GrContext* context,
|
||||
GrPaint&&,
|
||||
sk_sp<SkVertices>,
|
||||
const SkMatrix bones[],
|
||||
int boneCount,
|
||||
const SkMatrix& viewMatrix,
|
||||
GrAAType,
|
||||
sk_sp<GrColorSpaceXform>,
|
||||
GrPrimitiveType* overridePrimType = nullptr);
|
||||
|
||||
GrDrawVerticesOp(const Helper::MakeArgs& helperArgs, GrColor, sk_sp<SkVertices>,
|
||||
GrPrimitiveType, GrAAType, sk_sp<GrColorSpaceXform>,
|
||||
GrDrawVerticesOp(const Helper::MakeArgs&, GrColor, sk_sp<SkVertices>, const SkMatrix bones[],
|
||||
int boneCount, GrPrimitiveType, GrAAType, sk_sp<GrColorSpaceXform>,
|
||||
const SkMatrix& viewMatrix);
|
||||
|
||||
const char* name() const override { return "DrawVerticesOp"; }
|
||||
@ -68,7 +70,26 @@ private:
|
||||
|
||||
void onPrepareDraws(Target*) override;
|
||||
|
||||
sk_sp<GrGeometryProcessor> makeGP(bool* hasColorAttribute, bool* hasLocalCoordAttribute) const;
|
||||
void drawVolatile(Target*);
|
||||
void drawNonVolatile(Target*);
|
||||
|
||||
void fillBuffers(bool hasColorAttribute,
|
||||
bool hasLocalCoordsAttribute,
|
||||
bool hasBoneAttribute,
|
||||
size_t vertexStride,
|
||||
void* verts,
|
||||
uint16_t* indices) const;
|
||||
|
||||
void drawVertices(Target*,
|
||||
GrGeometryProcessor*,
|
||||
const GrBuffer* vertexBuffer,
|
||||
int firstVertex,
|
||||
const GrBuffer* indexBuffer,
|
||||
int firstIndex);
|
||||
|
||||
sk_sp<GrGeometryProcessor> makeGP(bool* hasColorAttribute,
|
||||
bool* hasLocalCoordAttribute,
|
||||
bool* hasBoneAttribute) const;
|
||||
|
||||
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
|
||||
bool combinablePrimitive() const {
|
||||
@ -82,9 +103,11 @@ private:
|
||||
struct Mesh {
|
||||
GrColor fColor; // Used if this->hasPerVertexColors() is false.
|
||||
sk_sp<SkVertices> fVertices;
|
||||
std::vector<SkMatrix> fBones;
|
||||
SkMatrix fViewMatrix;
|
||||
bool fIgnoreTexCoords;
|
||||
bool fIgnoreColors;
|
||||
bool fIgnoreBones;
|
||||
|
||||
bool hasExplicitLocalCoords() const {
|
||||
return fVertices->hasTexCoords() && !fIgnoreTexCoords;
|
||||
@ -93,6 +116,10 @@ private:
|
||||
bool hasPerVertexColors() const {
|
||||
return fVertices->hasColors() && !fIgnoreColors;
|
||||
}
|
||||
|
||||
bool hasBones() const {
|
||||
return fVertices->hasBones() && fBones.size() && !fIgnoreBones;
|
||||
}
|
||||
};
|
||||
|
||||
bool isIndexed() const {
|
||||
@ -105,18 +132,22 @@ private:
|
||||
}
|
||||
|
||||
bool anyMeshHasExplicitLocalCoords() const {
|
||||
return SkToBool(kAnyMeshHasExplicitLocalCoords & fFlags);
|
||||
return SkToBool(kAnyMeshHasExplicitLocalCoords_Flag & fFlags);
|
||||
}
|
||||
|
||||
bool hasMultipleViewMatrices() const {
|
||||
return SkToBool(kHasMultipleViewMatrices_Flag & fFlags);
|
||||
}
|
||||
|
||||
enum Flags {
|
||||
kRequiresPerVertexColors_Flag = 0x1,
|
||||
kAnyMeshHasExplicitLocalCoords = 0x2,
|
||||
kHasMultipleViewMatrices_Flag = 0x4
|
||||
bool hasBones() const {
|
||||
return SkToBool(kHasBones_Flag & fFlags);
|
||||
}
|
||||
|
||||
enum Flags {
|
||||
kRequiresPerVertexColors_Flag = 0x1,
|
||||
kAnyMeshHasExplicitLocalCoords_Flag = 0x2,
|
||||
kHasMultipleViewMatrices_Flag = 0x4,
|
||||
kHasBones_Flag = 0x8,
|
||||
};
|
||||
|
||||
Helper fHelper;
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
this->updateBones();
|
||||
|
||||
// Update the vertices object.
|
||||
this->updateVerticesObject(false);
|
||||
this->updateVerticesObject(false, false);
|
||||
}
|
||||
|
||||
void renderBackend(SkCanvas* canvas) {
|
||||
@ -70,16 +70,13 @@ public:
|
||||
if (fRenderMode != kBackend_RenderMode) {
|
||||
fRenderMode = kBackend_RenderMode;
|
||||
this->updateVertices();
|
||||
this->updateVerticesObject(false);
|
||||
this->updateVerticesObject(false, false);
|
||||
}
|
||||
|
||||
canvas->save();
|
||||
|
||||
// Update the vertex data.
|
||||
if (fActorImage->doesAnimationVertexDeform() && fActorImage->isVertexDeformDirty()) {
|
||||
if (fActorImage->doesAnimationVertexDeform()) {
|
||||
this->updateVertices();
|
||||
this->updateVerticesObject(false);
|
||||
fActorImage->isVertexDeformDirty(false);
|
||||
this->updateVerticesObject(false, true);
|
||||
}
|
||||
|
||||
// Update the bones.
|
||||
@ -87,8 +84,6 @@ public:
|
||||
|
||||
// Draw the vertices object.
|
||||
this->drawVerticesObject(canvas, true);
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
void renderImmediate(SkCanvas* canvas) {
|
||||
@ -96,7 +91,7 @@ public:
|
||||
if (fRenderMode != kImmediate_RenderMode) {
|
||||
fRenderMode = kImmediate_RenderMode;
|
||||
this->updateVertices();
|
||||
this->updateVerticesObject(true);
|
||||
this->updateVerticesObject(true, true);
|
||||
}
|
||||
|
||||
// Update the vertex data.
|
||||
@ -106,7 +101,7 @@ public:
|
||||
}
|
||||
|
||||
// Update the vertices object.
|
||||
this->updateVerticesObject(true);
|
||||
this->updateVerticesObject(true, true);
|
||||
|
||||
// Draw the vertices object.
|
||||
this->drawVerticesObject(canvas, false);
|
||||
@ -198,7 +193,7 @@ private:
|
||||
nima_to_skmatrix(fActorImage->worldTransform().values(), fBones[0]);
|
||||
}
|
||||
|
||||
void updateVerticesObject(bool applyDeforms) {
|
||||
void updateVerticesObject(bool applyDeforms, bool isVolatile) {
|
||||
std::vector<SkPoint>* positions = &fPositions;
|
||||
|
||||
// Apply deforms if requested.
|
||||
@ -229,7 +224,8 @@ private:
|
||||
fBoneIdx.data(),
|
||||
fBoneWgt.data(),
|
||||
fIndices.size(),
|
||||
fIndices.data());
|
||||
fIndices.data(),
|
||||
isVolatile);
|
||||
}
|
||||
|
||||
void drawVerticesObject(SkCanvas* canvas, bool useBones) const {
|
||||
@ -421,11 +417,19 @@ NIMASlide::~NIMASlide() {}
|
||||
void NIMASlide::draw(SkCanvas* canvas) {
|
||||
canvas->save();
|
||||
|
||||
canvas->translate(500, 500);
|
||||
canvas->scale(1, -1);
|
||||
for (int i = 0; i < 10; i ++) {
|
||||
for (int j = 0; j < 10; j ++) {
|
||||
canvas->save();
|
||||
|
||||
// Render the actor.
|
||||
fActor->render(canvas, fRenderMode);
|
||||
canvas->translate(1250 - 250 * i, 1250 - 250 * j);
|
||||
canvas->scale(0.5, -0.5);
|
||||
|
||||
// Render the actor.
|
||||
fActor->render(canvas, fRenderMode);
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
}
|
||||
|
||||
canvas->restore();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user