diff options
-rw-r--r-- | libs/hwui/Mesh.cpp | 48 | ||||
-rw-r--r-- | libs/hwui/Mesh.h | 225 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.h | 17 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/hwui/Canvas.h | 2 | ||||
-rw-r--r-- | libs/hwui/jni/android_graphics_Mesh.cpp | 14 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaDisplayList.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaDisplayList.h | 3 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 2 |
10 files changed, 191 insertions, 143 deletions
diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp index 37a7d74330e9..5ef7acdaf0fa 100644 --- a/libs/hwui/Mesh.cpp +++ b/libs/hwui/Mesh.cpp @@ -21,6 +21,8 @@ #include "SafeMath.h" +namespace android { + static size_t min_vcount_for_mode(SkMesh::Mode mode) { switch (mode) { case SkMesh::Mode::kTriangles: @@ -28,6 +30,7 @@ static size_t min_vcount_for_mode(SkMesh::Mode mode) { case SkMesh::Mode::kTriangleStrip: return 3; } + return 1; } // Re-implementation of SkMesh::validate to validate user side that their mesh is valid. @@ -36,29 +39,30 @@ std::tuple<bool, SkString> Mesh::validate() { if (!mMeshSpec) { FAIL_MESH_VALIDATE("MeshSpecification is required."); } - if (mVertexBufferData.empty()) { + if (mBufferData->vertexData().empty()) { FAIL_MESH_VALIDATE("VertexBuffer is required."); } - auto meshStride = mMeshSpec->stride(); - auto meshMode = SkMesh::Mode(mMode); + size_t vertexStride = mMeshSpec->stride(); + size_t vertexCount = mBufferData->vertexCount(); + size_t vertexOffset = mBufferData->vertexOffset(); SafeMath sm; - size_t vsize = sm.mul(meshStride, mVertexCount); - if (sm.add(vsize, mVertexOffset) > mVertexBufferData.size()) { + size_t vertexSize = sm.mul(vertexStride, vertexCount); + if (sm.add(vertexSize, vertexOffset) > mBufferData->vertexData().size()) { FAIL_MESH_VALIDATE( "The vertex buffer offset and vertex count reads beyond the end of the" " vertex buffer."); } - if (mVertexOffset % meshStride != 0) { + if (vertexOffset % vertexStride != 0) { FAIL_MESH_VALIDATE("The vertex offset (%zu) must be a multiple of the vertex stride (%zu).", - mVertexOffset, meshStride); + vertexOffset, vertexStride); } if (size_t uniformSize = mMeshSpec->uniformSize()) { - if (!mBuilder->fUniforms || mBuilder->fUniforms->size() < uniformSize) { + if (!mUniformBuilder.fUniforms || mUniformBuilder.fUniforms->size() < uniformSize) { FAIL_MESH_VALIDATE("The uniform data is %zu bytes but must be at least %zu.", - mBuilder->fUniforms->size(), uniformSize); + mUniformBuilder.fUniforms->size(), uniformSize); } } @@ -69,29 +73,33 @@ std::tuple<bool, SkString> Mesh::validate() { case SkMesh::Mode::kTriangleStrip: return "triangle-strip"; } + return "unknown"; }; - if (!mIndexBufferData.empty()) { - if (mIndexCount < min_vcount_for_mode(meshMode)) { + + size_t indexCount = mBufferData->indexCount(); + size_t indexOffset = mBufferData->indexOffset(); + if (!mBufferData->indexData().empty()) { + if (indexCount < min_vcount_for_mode(mMode)) { FAIL_MESH_VALIDATE("%s mode requires at least %zu indices but index count is %zu.", - modeToStr(meshMode), min_vcount_for_mode(meshMode), mIndexCount); + modeToStr(mMode), min_vcount_for_mode(mMode), indexCount); } - size_t isize = sm.mul(sizeof(uint16_t), mIndexCount); - if (sm.add(isize, mIndexOffset) > mIndexBufferData.size()) { + size_t isize = sm.mul(sizeof(uint16_t), indexCount); + if (sm.add(isize, indexOffset) > mBufferData->indexData().size()) { FAIL_MESH_VALIDATE( "The index buffer offset and index count reads beyond the end of the" " index buffer."); } // If we allow 32 bit indices then this should enforce 4 byte alignment in that case. - if (!SkIsAlign2(mIndexOffset)) { + if (!SkIsAlign2(indexOffset)) { FAIL_MESH_VALIDATE("The index offset must be a multiple of 2."); } } else { - if (mVertexCount < min_vcount_for_mode(meshMode)) { + if (vertexCount < min_vcount_for_mode(mMode)) { FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.", - modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount); + modeToStr(mMode), min_vcount_for_mode(mMode), vertexCount); } - LOG_ALWAYS_FATAL_IF(mIndexCount != 0); - LOG_ALWAYS_FATAL_IF(mIndexOffset != 0); + LOG_ALWAYS_FATAL_IF(indexCount != 0); + LOG_ALWAYS_FATAL_IF(indexOffset != 0); } if (!sm.ok()) { @@ -100,3 +108,5 @@ std::tuple<bool, SkString> Mesh::validate() { #undef FAIL_MESH_VALIDATE return {true, {}}; } + +} // namespace android diff --git a/libs/hwui/Mesh.h b/libs/hwui/Mesh.h index 69fda34afc78..8c6ca9758479 100644 --- a/libs/hwui/Mesh.h +++ b/libs/hwui/Mesh.h @@ -25,6 +25,8 @@ #include <utility> +namespace android { + class MeshUniformBuilder { public: struct MeshUniform { @@ -103,111 +105,170 @@ private: sk_sp<SkMeshSpecification> fMeshSpec; }; -class Mesh { +// Storage for CPU and GPU copies of the vertex and index data of a mesh. +class MeshBufferData { public: - Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode, - std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset, - std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds) - : mMeshSpec(meshSpec) - , mMode(mode) - , mVertexBufferData(std::move(vertexBufferData)) - , mVertexCount(vertexCount) - , mVertexOffset(vertexOffset) - , mBuilder(std::move(builder)) - , mBounds(bounds) {} - - Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode, - std::vector<uint8_t>&& vertexBufferData, jint vertexCount, jint vertexOffset, - std::vector<uint8_t>&& indexBuffer, jint indexCount, jint indexOffset, - std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds) - : mMeshSpec(meshSpec) - , mMode(mode) - , mVertexBufferData(std::move(vertexBufferData)) - , mVertexCount(vertexCount) + MeshBufferData(std::vector<uint8_t> vertexData, int32_t vertexCount, int32_t vertexOffset, + std::vector<uint8_t> indexData, int32_t indexCount, int32_t indexOffset) + : mVertexCount(vertexCount) , mVertexOffset(vertexOffset) - , mIndexBufferData(std::move(indexBuffer)) , mIndexCount(indexCount) , mIndexOffset(indexOffset) - , mBuilder(std::move(builder)) - , mBounds(bounds) {} - - Mesh(Mesh&&) = default; + , mVertexData(std::move(vertexData)) + , mIndexData(std::move(indexData)) {} - Mesh& operator=(Mesh&&) = default; - - [[nodiscard]] std::tuple<bool, SkString> validate(); - - void updateSkMesh(GrDirectContext* context) const { - GrDirectContext::DirectContextID genId = GrDirectContext::DirectContextID(); - if (context) { - genId = context->directContextID(); + void updateBuffers(GrDirectContext* context) const { + GrDirectContext::DirectContextID currentId = context == nullptr + ? GrDirectContext::DirectContextID() + : context->directContextID(); + if (currentId == mSkiaBuffers.fGenerationId && mSkiaBuffers.fVertexBuffer != nullptr) { + // Nothing to update since the Android API does not support partial updates yet. + return; } - if (mIsDirty || genId != mGenerationId) { - auto vertexData = reinterpret_cast<const void*>(mVertexBufferData.data()); + mSkiaBuffers.fVertexBuffer = #ifdef __ANDROID__ - auto vb = SkMeshes::MakeVertexBuffer(context, - vertexData, - mVertexBufferData.size()); + SkMeshes::MakeVertexBuffer(context, mVertexData.data(), mVertexData.size()); #else - auto vb = SkMeshes::MakeVertexBuffer(vertexData, - mVertexBufferData.size()); + SkMeshes::MakeVertexBuffer(mVertexData.data(), mVertexData.size()); #endif - auto meshMode = SkMesh::Mode(mMode); - if (!mIndexBufferData.empty()) { - auto indexData = reinterpret_cast<const void*>(mIndexBufferData.data()); + if (mIndexCount != 0) { + mSkiaBuffers.fIndexBuffer = #ifdef __ANDROID__ - auto ib = SkMeshes::MakeIndexBuffer(context, - indexData, - mIndexBufferData.size()); + SkMeshes::MakeIndexBuffer(context, mIndexData.data(), mIndexData.size()); #else - auto ib = SkMeshes::MakeIndexBuffer(indexData, - mIndexBufferData.size()); + SkMeshes::MakeIndexBuffer(mIndexData.data(), mIndexData.size()); #endif - mMesh = SkMesh::MakeIndexed(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset, - ib, mIndexCount, mIndexOffset, mBuilder->fUniforms, - SkSpan<SkRuntimeEffect::ChildPtr>(), mBounds) - .mesh; - } else { - mMesh = SkMesh::Make(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset, - mBuilder->fUniforms, SkSpan<SkRuntimeEffect::ChildPtr>(), - mBounds) - .mesh; - } - mIsDirty = false; - mGenerationId = genId; } + mSkiaBuffers.fGenerationId = currentId; } - SkMesh& getSkMesh() const { - LOG_FATAL_IF(mIsDirty, - "Attempt to obtain SkMesh when Mesh is dirty, did you " - "forget to call updateSkMesh with a GrDirectContext? " - "Defensively creating a CPU mesh"); - return mMesh; - } + SkMesh::VertexBuffer* vertexBuffer() const { return mSkiaBuffers.fVertexBuffer.get(); } + + sk_sp<SkMesh::VertexBuffer> refVertexBuffer() const { return mSkiaBuffers.fVertexBuffer; } + int32_t vertexCount() const { return mVertexCount; } + int32_t vertexOffset() const { return mVertexOffset; } - void markDirty() { mIsDirty = true; } + sk_sp<SkMesh::IndexBuffer> refIndexBuffer() const { return mSkiaBuffers.fIndexBuffer; } + int32_t indexCount() const { return mIndexCount; } + int32_t indexOffset() const { return mIndexOffset; } - MeshUniformBuilder* uniformBuilder() { return mBuilder.get(); } + const std::vector<uint8_t>& vertexData() const { return mVertexData; } + const std::vector<uint8_t>& indexData() const { return mIndexData; } private: - sk_sp<SkMeshSpecification> mMeshSpec; - int mMode = 0; + struct CachedSkiaBuffers { + sk_sp<SkMesh::VertexBuffer> fVertexBuffer; + sk_sp<SkMesh::IndexBuffer> fIndexBuffer; + GrDirectContext::DirectContextID fGenerationId = GrDirectContext::DirectContextID(); + }; + + mutable CachedSkiaBuffers mSkiaBuffers; + int32_t mVertexCount = 0; + int32_t mVertexOffset = 0; + int32_t mIndexCount = 0; + int32_t mIndexOffset = 0; + std::vector<uint8_t> mVertexData; + std::vector<uint8_t> mIndexData; +}; - std::vector<uint8_t> mVertexBufferData; - size_t mVertexCount = 0; - size_t mVertexOffset = 0; +class Mesh { +public: + // A snapshot of the mesh for use by the render thread. + // + // After a snapshot is taken, future uniform changes to the original Mesh will not modify the + // uniforms returned by makeSkMesh. + class Snapshot { + public: + Snapshot() = delete; + Snapshot(const Snapshot&) = default; + Snapshot(Snapshot&&) = default; + Snapshot& operator=(const Snapshot&) = default; + Snapshot& operator=(Snapshot&&) = default; + ~Snapshot() = default; - std::vector<uint8_t> mIndexBufferData; - size_t mIndexCount = 0; - size_t mIndexOffset = 0; + const SkMesh& getSkMesh() const { + SkMesh::VertexBuffer* vertexBuffer = mBufferData->vertexBuffer(); + LOG_FATAL_IF(vertexBuffer == nullptr, + "Attempt to obtain SkMesh when vertexBuffer has not been created, did you " + "forget to call MeshBufferData::updateBuffers with a GrDirectContext?"); + if (vertexBuffer != mMesh.vertexBuffer()) mMesh = makeSkMesh(); + return mMesh; + } - std::unique_ptr<MeshUniformBuilder> mBuilder; - SkRect mBounds{}; + private: + friend class Mesh; - mutable SkMesh mMesh{}; - mutable bool mIsDirty = true; - mutable GrDirectContext::DirectContextID mGenerationId = GrDirectContext::DirectContextID(); + Snapshot(sk_sp<SkMeshSpecification> meshSpec, SkMesh::Mode mode, + std::shared_ptr<const MeshBufferData> bufferData, sk_sp<const SkData> uniforms, + const SkRect& bounds) + : mMeshSpec(std::move(meshSpec)) + , mMode(mode) + , mBufferData(std::move(bufferData)) + , mUniforms(std::move(uniforms)) + , mBounds(bounds) {} + + SkMesh makeSkMesh() const { + const MeshBufferData& d = *mBufferData; + if (d.indexCount() != 0) { + return SkMesh::MakeIndexed(mMeshSpec, mMode, d.refVertexBuffer(), d.vertexCount(), + d.vertexOffset(), d.refIndexBuffer(), d.indexCount(), + d.indexOffset(), mUniforms, + SkSpan<SkRuntimeEffect::ChildPtr>(), mBounds) + .mesh; + } + return SkMesh::Make(mMeshSpec, mMode, d.refVertexBuffer(), d.vertexCount(), + d.vertexOffset(), mUniforms, SkSpan<SkRuntimeEffect::ChildPtr>(), + mBounds) + .mesh; + } + + mutable SkMesh mMesh; + sk_sp<SkMeshSpecification> mMeshSpec; + SkMesh::Mode mMode; + std::shared_ptr<const MeshBufferData> mBufferData; + sk_sp<const SkData> mUniforms; + SkRect mBounds; + }; + + Mesh(sk_sp<SkMeshSpecification> meshSpec, SkMesh::Mode mode, std::vector<uint8_t> vertexData, + int32_t vertexCount, int32_t vertexOffset, const SkRect& bounds) + : Mesh(std::move(meshSpec), mode, std::move(vertexData), vertexCount, vertexOffset, + /* indexData = */ {}, /* indexCount = */ 0, /* indexOffset = */ 0, bounds) {} + + Mesh(sk_sp<SkMeshSpecification> meshSpec, SkMesh::Mode mode, std::vector<uint8_t> vertexData, + int32_t vertexCount, int32_t vertexOffset, std::vector<uint8_t> indexData, + int32_t indexCount, int32_t indexOffset, const SkRect& bounds) + : mMeshSpec(std::move(meshSpec)) + , mMode(mode) + , mBufferData(std::make_shared<MeshBufferData>(std::move(vertexData), vertexCount, + vertexOffset, std::move(indexData), + indexCount, indexOffset)) + , mUniformBuilder(mMeshSpec) + , mBounds(bounds) {} + + Mesh(Mesh&&) = default; + + Mesh& operator=(Mesh&&) = default; + + [[nodiscard]] std::tuple<bool, SkString> validate(); + + std::shared_ptr<const MeshBufferData> refBufferData() const { return mBufferData; } + + Snapshot takeSnapshot() const { + return Snapshot(mMeshSpec, mMode, mBufferData, mUniformBuilder.fUniforms, mBounds); + } + + MeshUniformBuilder* uniformBuilder() { return &mUniformBuilder; } + +private: + sk_sp<SkMeshSpecification> mMeshSpec; + SkMesh::Mode mMode; + std::shared_ptr<MeshBufferData> mBufferData; + MeshUniformBuilder mUniformBuilder; + SkRect mBounds; }; + +} // namespace android + #endif // MESH_H_ diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 54aef55f8b90..d0263798d2c2 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -573,9 +573,9 @@ struct DrawSkMesh final : Op { struct DrawMesh final : Op { static const auto kType = Type::DrawMesh; DrawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) - : mesh(mesh), blender(std::move(blender)), paint(paint) {} + : mesh(mesh.takeSnapshot()), blender(std::move(blender)), paint(paint) {} - const Mesh& mesh; + Mesh::Snapshot mesh; sk_sp<SkBlender> blender; SkPaint paint; @@ -1296,14 +1296,5 @@ void RecordingCanvas::drawWebView(skiapipeline::FunctorDrawable* drawable) { fDL->drawWebView(drawable); } -[[nodiscard]] const SkMesh& DrawMeshPayload::getSkMesh() const { - LOG_FATAL_IF(!meshWrapper && !mesh, "One of Mesh or Mesh must be non-null"); - if (meshWrapper) { - return meshWrapper->getSkMesh(); - } else { - return *mesh; - } -} - } // namespace uirenderer } // namespace android diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 965264f31119..f86785274224 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -41,11 +41,12 @@ enum class SkBlendMode; class SkRRect; -class Mesh; namespace android { -namespace uirenderer { +class Mesh; + +namespace uirenderer { namespace skiapipeline { class FunctorDrawable; } @@ -68,18 +69,6 @@ struct DisplayListOp { static_assert(sizeof(DisplayListOp) == 4); -class DrawMeshPayload { -public: - explicit DrawMeshPayload(const SkMesh* mesh) : mesh(mesh) {} - explicit DrawMeshPayload(const Mesh* meshWrapper) : meshWrapper(meshWrapper) {} - - [[nodiscard]] const SkMesh& getSkMesh() const; - -private: - const SkMesh* mesh = nullptr; - const Mesh* meshWrapper = nullptr; -}; - struct DrawImagePayload { explicit DrawImagePayload(Bitmap& bitmap) : image(bitmap.makeImage()), palette(bitmap.palette()) { diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 0b739c361d64..72e83afbd96f 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -596,8 +596,8 @@ void SkiaCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Pain if (recordingContext) { context = recordingContext->asDirectContext(); } - mesh.updateSkMesh(context); - mCanvas->drawMesh(mesh.getSkMesh(), blender, paint); + mesh.refBufferData()->updateBuffers(context); + mCanvas->drawMesh(mesh.takeSnapshot().getSkMesh(), blender, paint); } // ---------------------------------------------------------------------------- diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 14b4f584f0f3..4eb6918d7e9a 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -34,7 +34,6 @@ class SkCanvasState; class SkRRect; class SkRuntimeShaderBuilder; class SkVertices; -class Mesh; namespace minikin { class Font; @@ -61,6 +60,7 @@ typedef std::function<void(uint16_t* text, float* positions)> ReadGlyphFunc; class AnimatedImageDrawable; class Bitmap; +class Mesh; class Paint; struct Typeface; diff --git a/libs/hwui/jni/android_graphics_Mesh.cpp b/libs/hwui/jni/android_graphics_Mesh.cpp index 5cb43e54e499..3109de5055ca 100644 --- a/libs/hwui/jni/android_graphics_Mesh.cpp +++ b/libs/hwui/jni/android_graphics_Mesh.cpp @@ -38,8 +38,8 @@ static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject verte return 0; } auto skRect = SkRect::MakeLTRB(left, top, right, bottom); - auto meshPtr = new Mesh(skMeshSpec, mode, std::move(buffer), vertexCount, vertexOffset, - std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect); + auto meshPtr = new Mesh(skMeshSpec, static_cast<SkMesh::Mode>(mode), std::move(buffer), + vertexCount, vertexOffset, skRect); auto [valid, msg] = meshPtr->validate(); if (!valid) { jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str()); @@ -63,9 +63,9 @@ static jlong makeIndexed(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobjec return 0; } auto skRect = SkRect::MakeLTRB(left, top, right, bottom); - auto meshPtr = new Mesh(skMeshSpec, mode, std::move(vBuf), vertexCount, vertexOffset, - std::move(iBuf), indexCount, indexOffset, - std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect); + auto meshPtr = + new Mesh(skMeshSpec, static_cast<SkMesh::Mode>(mode), std::move(vBuf), vertexCount, + vertexOffset, std::move(iBuf), indexCount, indexOffset, skRect); auto [valid, msg] = meshPtr->validate(); if (!valid) { jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str()); @@ -133,7 +133,6 @@ static void updateFloatUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring ScopedUtfChars name(env, uniformName); const float values[4] = {value1, value2, value3, value4}; nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count, false); - wrapper->markDirty(); } static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring jUniformName, @@ -143,7 +142,6 @@ static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, js AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess); nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(), autoValues.length(), isColor); - wrapper->markDirty(); } static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder, @@ -166,7 +164,6 @@ static void updateIntUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring u ScopedUtfChars name(env, uniformName); const int values[4] = {value1, value2, value3, value4}; nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count); - wrapper->markDirty(); } static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName, @@ -176,7 +173,6 @@ static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstr AutoJavaIntArray autoValues(env, values, 0); nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(), autoValues.length()); - wrapper->markDirty(); } static void MeshWrapper_destroy(Mesh* wrapper) { diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp index 5c8285a8e1e9..e0216b680064 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp @@ -111,8 +111,8 @@ bool SkiaDisplayList::prepareListAndChildren( } auto grContext = info.canvasContext.getGrContext(); - for (auto mesh : mMeshes) { - mesh->updateSkMesh(grContext); + for (const auto& bufferData : mMeshBufferData) { + bufferData->updateBuffers(grContext); } #endif @@ -181,7 +181,7 @@ void SkiaDisplayList::reset() { mDisplayList.reset(); - mMeshes.clear(); + mMeshBufferData.clear(); mMutableImages.clear(); mVectorDrawables.clear(); mAnimatedImages.clear(); diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h index b9dc1c49f09e..071a4e8caaff 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.h +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h @@ -17,6 +17,7 @@ #pragma once #include <deque> +#include <memory> #include "Mesh.h" #include "RecordingCanvas.h" @@ -172,7 +173,7 @@ public: std::deque<RenderNodeDrawable> mChildNodes; std::deque<FunctorDrawable*> mChildFunctors; std::vector<SkImage*> mMutableImages; - std::vector<const Mesh*> mMeshes; + std::vector<std::shared_ptr<const MeshBufferData>> mMeshBufferData; private: std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables; diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index e917f9a66917..45bfe1c4957f 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -342,7 +342,7 @@ double SkiaRecordingCanvas::drawAnimatedImage(AnimatedImageDrawable* animatedIma } void SkiaRecordingCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) { - mDisplayList->mMeshes.push_back(&mesh); + mDisplayList->mMeshBufferData.push_back(mesh.refBufferData()); mRecorder.drawMesh(mesh, blender, paint); } |