• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "Mesh.h"
18 
19 #include <GLES/gl.h>
20 #include <SkMesh.h>
21 
22 #include "SafeMath.h"
23 
min_vcount_for_mode(SkMesh::Mode mode)24 static size_t min_vcount_for_mode(SkMesh::Mode mode) {
25     switch (mode) {
26         case SkMesh::Mode::kTriangles:
27             return 3;
28         case SkMesh::Mode::kTriangleStrip:
29             return 3;
30     }
31 }
32 
33 // Re-implementation of SkMesh::validate to validate user side that their mesh is valid.
validate()34 std::tuple<bool, SkString> Mesh::validate() {
35 #define FAIL_MESH_VALIDATE(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))
36     if (!mMeshSpec) {
37         FAIL_MESH_VALIDATE("MeshSpecification is required.");
38     }
39     if (mVertexBufferData.empty()) {
40         FAIL_MESH_VALIDATE("VertexBuffer is required.");
41     }
42 
43     auto meshStride = mMeshSpec->stride();
44     auto meshMode = SkMesh::Mode(mMode);
45     SafeMath sm;
46     size_t vsize = sm.mul(meshStride, mVertexCount);
47     if (sm.add(vsize, mVertexOffset) > mVertexBufferData.size()) {
48         FAIL_MESH_VALIDATE(
49                 "The vertex buffer offset and vertex count reads beyond the end of the"
50                 " vertex buffer.");
51     }
52 
53     if (mVertexOffset % meshStride != 0) {
54         FAIL_MESH_VALIDATE("The vertex offset (%zu) must be a multiple of the vertex stride (%zu).",
55                            mVertexOffset, meshStride);
56     }
57 
58     if (size_t uniformSize = mMeshSpec->uniformSize()) {
59         if (!mBuilder->fUniforms || mBuilder->fUniforms->size() < uniformSize) {
60             FAIL_MESH_VALIDATE("The uniform data is %zu bytes but must be at least %zu.",
61                                mBuilder->fUniforms->size(), uniformSize);
62         }
63     }
64 
65     auto modeToStr = [](SkMesh::Mode m) {
66         switch (m) {
67             case SkMesh::Mode::kTriangles:
68                 return "triangles";
69             case SkMesh::Mode::kTriangleStrip:
70                 return "triangle-strip";
71         }
72     };
73     if (!mIndexBufferData.empty()) {
74         if (mIndexCount < min_vcount_for_mode(meshMode)) {
75             FAIL_MESH_VALIDATE("%s mode requires at least %zu indices but index count is %zu.",
76                                modeToStr(meshMode), min_vcount_for_mode(meshMode), mIndexCount);
77         }
78         size_t isize = sm.mul(sizeof(uint16_t), mIndexCount);
79         if (sm.add(isize, mIndexOffset) > mIndexBufferData.size()) {
80             FAIL_MESH_VALIDATE(
81                     "The index buffer offset and index count reads beyond the end of the"
82                     " index buffer.");
83         }
84         // If we allow 32 bit indices then this should enforce 4 byte alignment in that case.
85         if (!SkIsAlign2(mIndexOffset)) {
86             FAIL_MESH_VALIDATE("The index offset must be a multiple of 2.");
87         }
88     } else {
89         if (mVertexCount < min_vcount_for_mode(meshMode)) {
90             FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.",
91                                modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount);
92         }
93         SkASSERT(!fICount);
94         SkASSERT(!fIOffset);
95     }
96 
97     if (!sm.ok()) {
98         FAIL_MESH_VALIDATE("Overflow");
99     }
100 #undef FAIL_MESH_VALIDATE
101     return {true, {}};
102 }
103