diff options
author | 2023-02-21 17:00:51 -0800 | |
---|---|---|
committer | 2023-02-25 02:36:54 +0000 | |
commit | 5f0a800ad3d3bf24f2e5bb0c666a51c88819bf3e (patch) | |
tree | 59c2f440ed0d1e76821b29d9674468183709e5e1 /libs/hwui/Mesh.cpp | |
parent | bbf2ceda7571619c7e77cdfe2597afe130b58499 (diff) |
Defer Meshed creation
Refactored Mesh API to defer creation of
SkMesh instances until a GrDirectContext
can be obtained on the RenderThread.
This creates an SkMesh during the prepare
tree step when the UI thread is blocked
to ensure no concurrency issues.
Bug: b/265044322
Test: atest CtsUiRenderingTestCases:MeshTest
Change-Id: Ica8c364b99952e0ee71f7b95b312cf29c51ebc2a
Diffstat (limited to 'libs/hwui/Mesh.cpp')
-rw-r--r-- | libs/hwui/Mesh.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp new file mode 100644 index 000000000000..e59bc9565a59 --- /dev/null +++ b/libs/hwui/Mesh.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Mesh.h" + +#include <GLES/gl.h> +#include <SkMesh.h> + +#include "SafeMath.h" + +static size_t min_vcount_for_mode(SkMesh::Mode mode) { + switch (mode) { + case SkMesh::Mode::kTriangles: + return 3; + case SkMesh::Mode::kTriangleStrip: + return 3; + } +} + +// Re-implementation of SkMesh::validate to validate user side that their mesh is valid. +std::tuple<bool, SkString> Mesh::validate() { +#define FAIL_MESH_VALIDATE(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__)) + if (!mMeshSpec) { + FAIL_MESH_VALIDATE("MeshSpecification is required."); + } + if (mVertexBufferData.empty()) { + FAIL_MESH_VALIDATE("VertexBuffer is required."); + } + + auto meshStride = mMeshSpec->stride(); + auto meshMode = SkMesh::Mode(mMode); + SafeMath sm; + size_t vsize = sm.mul(meshStride, mVertexCount); + if (sm.add(vsize, mVertexOffset) > mVertexBufferData.size()) { + FAIL_MESH_VALIDATE( + "The vertex buffer offset and vertex count reads beyond the end of the" + " vertex buffer."); + } + + if (mVertexOffset % meshStride != 0) { + FAIL_MESH_VALIDATE("The vertex offset (%zu) must be a multiple of the vertex stride (%zu).", + mVertexOffset, meshStride); + } + + if (size_t uniformSize = mMeshSpec->uniformSize()) { + if (!mBuilder->fUniforms || mBuilder->fUniforms->size() < uniformSize) { + FAIL_MESH_VALIDATE("The uniform data is %zu bytes but must be at least %zu.", + mBuilder->fUniforms->size(), uniformSize); + } + } + + auto modeToStr = [](SkMesh::Mode m) { + switch (m) { + case SkMesh::Mode::kTriangles: + return "triangles"; + case SkMesh::Mode::kTriangleStrip: + return "triangle-strip"; + } + }; + if (!mIndexBufferData.empty()) { + if (mIndexCount < min_vcount_for_mode(meshMode)) { + FAIL_MESH_VALIDATE("%s mode requires at least %zu indices but index count is %zu.", + modeToStr(meshMode), min_vcount_for_mode(meshMode), mIndexCount); + } + size_t isize = sm.mul(sizeof(uint16_t), mIndexCount); + if (sm.add(isize, mIndexOffset) > mIndexBufferData.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)) { + FAIL_MESH_VALIDATE("The index offset must be a multiple of 2."); + } + } else { + if (mVertexCount < min_vcount_for_mode(meshMode)) { + FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.", + modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount); + } + SkASSERT(!fICount); + SkASSERT(!fIOffset); + } + + if (!sm.ok()) { + FAIL_MESH_VALIDATE("Overflow"); + } +#undef FAIL_MESH_VALIDATE + return {true, {}}; +} |