1 | "use strict";
|
2 | var constants = require("@pixi/constants"), extensions = require("@pixi/extensions"), settings = require("@pixi/settings");
|
3 | const byteSizeMap = { 5126: 4, 5123: 2, 5121: 1 };
|
4 | class GeometrySystem {
|
5 |
|
6 | constructor(renderer) {
|
7 | this.renderer = renderer, this._activeGeometry = null, this._activeVao = null, this.hasVao = !0, this.hasInstance = !0, this.canUseUInt32ElementIndex = !1, this.managedGeometries = {};
|
8 | }
|
9 |
|
10 | contextChange() {
|
11 | this.disposeAll(!0);
|
12 | const gl = this.gl = this.renderer.gl, context = this.renderer.context;
|
13 | if (this.CONTEXT_UID = this.renderer.CONTEXT_UID, context.webGLVersion !== 2) {
|
14 | let nativeVaoExtension = this.renderer.context.extensions.vertexArrayObject;
|
15 | settings.settings.PREFER_ENV === constants.ENV.WEBGL_LEGACY && (nativeVaoExtension = null), nativeVaoExtension ? (gl.createVertexArray = () => nativeVaoExtension.createVertexArrayOES(), gl.bindVertexArray = (vao) => nativeVaoExtension.bindVertexArrayOES(vao), gl.deleteVertexArray = (vao) => nativeVaoExtension.deleteVertexArrayOES(vao)) : (this.hasVao = !1, gl.createVertexArray = () => null, gl.bindVertexArray = () => null, gl.deleteVertexArray = () => null);
|
16 | }
|
17 | if (context.webGLVersion !== 2) {
|
18 | const instanceExt = gl.getExtension("ANGLE_instanced_arrays");
|
19 | instanceExt ? (gl.vertexAttribDivisor = (a, b) => instanceExt.vertexAttribDivisorANGLE(a, b), gl.drawElementsInstanced = (a, b, c, d, e) => instanceExt.drawElementsInstancedANGLE(a, b, c, d, e), gl.drawArraysInstanced = (a, b, c, d) => instanceExt.drawArraysInstancedANGLE(a, b, c, d)) : this.hasInstance = !1;
|
20 | }
|
21 | this.canUseUInt32ElementIndex = context.webGLVersion === 2 || !!context.extensions.uint32ElementIndex;
|
22 | }
|
23 | |
24 |
|
25 |
|
26 |
|
27 |
|
28 | bind(geometry, shader) {
|
29 | shader = shader || this.renderer.shader.shader;
|
30 | const { gl } = this;
|
31 | let vaos = geometry.glVertexArrayObjects[this.CONTEXT_UID], incRefCount = !1;
|
32 | vaos || (this.managedGeometries[geometry.id] = geometry, geometry.disposeRunner.add(this), geometry.glVertexArrayObjects[this.CONTEXT_UID] = vaos = {}, incRefCount = !0);
|
33 | const vao = vaos[shader.program.id] || this.initGeometryVao(geometry, shader, incRefCount);
|
34 | this._activeGeometry = geometry, this._activeVao !== vao && (this._activeVao = vao, this.hasVao ? gl.bindVertexArray(vao) : this.activateVao(geometry, shader.program)), this.updateBuffers();
|
35 | }
|
36 |
|
37 | reset() {
|
38 | this.unbind();
|
39 | }
|
40 |
|
41 | updateBuffers() {
|
42 | const geometry = this._activeGeometry, bufferSystem = this.renderer.buffer;
|
43 | for (let i = 0; i < geometry.buffers.length; i++) {
|
44 | const buffer = geometry.buffers[i];
|
45 | bufferSystem.update(buffer);
|
46 | }
|
47 | }
|
48 | |
49 |
|
50 |
|
51 |
|
52 |
|
53 | checkCompatibility(geometry, program) {
|
54 | const geometryAttributes = geometry.attributes, shaderAttributes = program.attributeData;
|
55 | for (const j in shaderAttributes)
|
56 | if (!geometryAttributes[j])
|
57 | throw new Error(`shader and geometry incompatible, geometry missing the "${j}" attribute`);
|
58 | }
|
59 | |
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | getSignature(geometry, program) {
|
66 | const attribs = geometry.attributes, shaderAttributes = program.attributeData, strings = ["g", geometry.id];
|
67 | for (const i in attribs)
|
68 | shaderAttributes[i] && strings.push(i, shaderAttributes[i].location);
|
69 | return strings.join("-");
|
70 | }
|
71 | |
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | initGeometryVao(geometry, shader, incRefCount = !0) {
|
80 | const gl = this.gl, CONTEXT_UID = this.CONTEXT_UID, bufferSystem = this.renderer.buffer, program = shader.program;
|
81 | program.glPrograms[CONTEXT_UID] || this.renderer.shader.generateProgram(shader), this.checkCompatibility(geometry, program);
|
82 | const signature = this.getSignature(geometry, program), vaoObjectHash = geometry.glVertexArrayObjects[this.CONTEXT_UID];
|
83 | let vao = vaoObjectHash[signature];
|
84 | if (vao)
|
85 | return vaoObjectHash[program.id] = vao, vao;
|
86 | const buffers = geometry.buffers, attributes = geometry.attributes, tempStride = {}, tempStart = {};
|
87 | for (const j in buffers)
|
88 | tempStride[j] = 0, tempStart[j] = 0;
|
89 | for (const j in attributes)
|
90 | !attributes[j].size && program.attributeData[j] ? attributes[j].size = program.attributeData[j].size : attributes[j].size || console.warn(`PIXI Geometry attribute '${j}' size cannot be determined (likely the bound shader does not have the attribute)`), tempStride[attributes[j].buffer] += attributes[j].size * byteSizeMap[attributes[j].type];
|
91 | for (const j in attributes) {
|
92 | const attribute = attributes[j], attribSize = attribute.size;
|
93 | attribute.stride === void 0 && (tempStride[attribute.buffer] === attribSize * byteSizeMap[attribute.type] ? attribute.stride = 0 : attribute.stride = tempStride[attribute.buffer]), attribute.start === void 0 && (attribute.start = tempStart[attribute.buffer], tempStart[attribute.buffer] += attribSize * byteSizeMap[attribute.type]);
|
94 | }
|
95 | vao = gl.createVertexArray(), gl.bindVertexArray(vao);
|
96 | for (let i = 0; i < buffers.length; i++) {
|
97 | const buffer = buffers[i];
|
98 | bufferSystem.bind(buffer), incRefCount && buffer._glBuffers[CONTEXT_UID].refCount++;
|
99 | }
|
100 | return this.activateVao(geometry, program), vaoObjectHash[program.id] = vao, vaoObjectHash[signature] = vao, gl.bindVertexArray(null), bufferSystem.unbind(constants.BUFFER_TYPE.ARRAY_BUFFER), vao;
|
101 | }
|
102 | |
103 |
|
104 |
|
105 |
|
106 |
|
107 | disposeGeometry(geometry, contextLost) {
|
108 | if (!this.managedGeometries[geometry.id])
|
109 | return;
|
110 | delete this.managedGeometries[geometry.id];
|
111 | const vaos = geometry.glVertexArrayObjects[this.CONTEXT_UID], gl = this.gl, buffers = geometry.buffers, bufferSystem = this.renderer?.buffer;
|
112 | if (geometry.disposeRunner.remove(this), !!vaos) {
|
113 | if (bufferSystem)
|
114 | for (let i = 0; i < buffers.length; i++) {
|
115 | const buf = buffers[i]._glBuffers[this.CONTEXT_UID];
|
116 | buf && (buf.refCount--, buf.refCount === 0 && !contextLost && bufferSystem.dispose(buffers[i], contextLost));
|
117 | }
|
118 | if (!contextLost) {
|
119 | for (const vaoId in vaos)
|
120 | if (vaoId[0] === "g") {
|
121 | const vao = vaos[vaoId];
|
122 | this._activeVao === vao && this.unbind(), gl.deleteVertexArray(vao);
|
123 | }
|
124 | }
|
125 | delete geometry.glVertexArrayObjects[this.CONTEXT_UID];
|
126 | }
|
127 | }
|
128 | |
129 |
|
130 |
|
131 |
|
132 | disposeAll(contextLost) {
|
133 | const all = Object.keys(this.managedGeometries);
|
134 | for (let i = 0; i < all.length; i++)
|
135 | this.disposeGeometry(this.managedGeometries[all[i]], contextLost);
|
136 | }
|
137 | |
138 |
|
139 |
|
140 |
|
141 |
|
142 | activateVao(geometry, program) {
|
143 | const gl = this.gl, CONTEXT_UID = this.CONTEXT_UID, bufferSystem = this.renderer.buffer, buffers = geometry.buffers, attributes = geometry.attributes;
|
144 | geometry.indexBuffer && bufferSystem.bind(geometry.indexBuffer);
|
145 | let lastBuffer = null;
|
146 | for (const j in attributes) {
|
147 | const attribute = attributes[j], buffer = buffers[attribute.buffer], glBuffer = buffer._glBuffers[CONTEXT_UID];
|
148 | if (program.attributeData[j]) {
|
149 | lastBuffer !== glBuffer && (bufferSystem.bind(buffer), lastBuffer = glBuffer);
|
150 | const location = program.attributeData[j].location;
|
151 | if (gl.enableVertexAttribArray(location), gl.vertexAttribPointer(
|
152 | location,
|
153 | attribute.size,
|
154 | attribute.type || gl.FLOAT,
|
155 | attribute.normalized,
|
156 | attribute.stride,
|
157 | attribute.start
|
158 | ), attribute.instance)
|
159 | if (this.hasInstance)
|
160 | gl.vertexAttribDivisor(location, attribute.divisor);
|
161 | else
|
162 | throw new Error("geometry error, GPU Instancing is not supported on this device");
|
163 | }
|
164 | }
|
165 | }
|
166 | |
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 | draw(type, size, start, instanceCount) {
|
177 | const { gl } = this, geometry = this._activeGeometry;
|
178 | if (geometry.indexBuffer) {
|
179 | const byteSize = geometry.indexBuffer.data.BYTES_PER_ELEMENT, glType = byteSize === 2 ? gl.UNSIGNED_SHORT : gl.UNSIGNED_INT;
|
180 | byteSize === 2 || byteSize === 4 && this.canUseUInt32ElementIndex ? geometry.instanced ? gl.drawElementsInstanced(type, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize, instanceCount || 1) : gl.drawElements(type, size || geometry.indexBuffer.data.length, glType, (start || 0) * byteSize) : console.warn("unsupported index buffer type: uint32");
|
181 | } else
|
182 | geometry.instanced ? gl.drawArraysInstanced(type, start, size || geometry.getSize(), instanceCount || 1) : gl.drawArrays(type, start, size || geometry.getSize());
|
183 | return this;
|
184 | }
|
185 |
|
186 | unbind() {
|
187 | this.gl.bindVertexArray(null), this._activeVao = null, this._activeGeometry = null;
|
188 | }
|
189 | destroy() {
|
190 | this.renderer = null;
|
191 | }
|
192 | }
|
193 | GeometrySystem.extension = {
|
194 | type: extensions.ExtensionType.RendererSystem,
|
195 | name: "geometry"
|
196 | };
|
197 | extensions.extensions.add(GeometrySystem);
|
198 | exports.GeometrySystem = GeometrySystem;
|
199 |
|