UNPKG

9.1 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var constants = require('@pixi/constants');
6var extensions = require('@pixi/extensions');
7var utils = require('@pixi/utils');
8var BaseTexture = require('./BaseTexture.js');
9var GLTexture = require('./GLTexture.js');
10var mapTypeAndFormatToInternalFormat = require('./utils/mapTypeAndFormatToInternalFormat.js');
11
12class TextureSystem {
13 constructor(renderer) {
14 this.renderer = renderer;
15 this.boundTextures = [];
16 this.currentLocation = -1;
17 this.managedTextures = [];
18 this._unknownBoundTextures = false;
19 this.unknownTexture = new BaseTexture.BaseTexture();
20 this.hasIntegerTextures = false;
21 }
22 contextChange() {
23 const gl = this.gl = this.renderer.gl;
24 this.CONTEXT_UID = this.renderer.CONTEXT_UID;
25 this.webGLVersion = this.renderer.context.webGLVersion;
26 this.internalFormats = mapTypeAndFormatToInternalFormat.mapTypeAndFormatToInternalFormat(gl);
27 const maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
28 this.boundTextures.length = maxTextures;
29 for (let i = 0; i < maxTextures; i++) {
30 this.boundTextures[i] = null;
31 }
32 this.emptyTextures = {};
33 const emptyTexture2D = new GLTexture.GLTexture(gl.createTexture());
34 gl.bindTexture(gl.TEXTURE_2D, emptyTexture2D.texture);
35 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
36 this.emptyTextures[gl.TEXTURE_2D] = emptyTexture2D;
37 this.emptyTextures[gl.TEXTURE_CUBE_MAP] = new GLTexture.GLTexture(gl.createTexture());
38 gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.emptyTextures[gl.TEXTURE_CUBE_MAP].texture);
39 for (let i = 0; i < 6; i++) {
40 gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
41 }
42 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
43 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
44 for (let i = 0; i < this.boundTextures.length; i++) {
45 this.bind(null, i);
46 }
47 }
48 bind(texture, location = 0) {
49 const { gl } = this;
50 texture = texture?.castToBaseTexture();
51 if (texture?.valid && !texture.parentTextureArray) {
52 texture.touched = this.renderer.textureGC.count;
53 const glTexture = texture._glTextures[this.CONTEXT_UID] || this.initTexture(texture);
54 if (this.boundTextures[location] !== texture) {
55 if (this.currentLocation !== location) {
56 this.currentLocation = location;
57 gl.activeTexture(gl.TEXTURE0 + location);
58 }
59 gl.bindTexture(texture.target, glTexture.texture);
60 }
61 if (glTexture.dirtyId !== texture.dirtyId) {
62 if (this.currentLocation !== location) {
63 this.currentLocation = location;
64 gl.activeTexture(gl.TEXTURE0 + location);
65 }
66 this.updateTexture(texture);
67 } else if (glTexture.dirtyStyleId !== texture.dirtyStyleId) {
68 this.updateTextureStyle(texture);
69 }
70 this.boundTextures[location] = texture;
71 } else {
72 if (this.currentLocation !== location) {
73 this.currentLocation = location;
74 gl.activeTexture(gl.TEXTURE0 + location);
75 }
76 gl.bindTexture(gl.TEXTURE_2D, this.emptyTextures[gl.TEXTURE_2D].texture);
77 this.boundTextures[location] = null;
78 }
79 }
80 reset() {
81 this._unknownBoundTextures = true;
82 this.hasIntegerTextures = false;
83 this.currentLocation = -1;
84 for (let i = 0; i < this.boundTextures.length; i++) {
85 this.boundTextures[i] = this.unknownTexture;
86 }
87 }
88 unbind(texture) {
89 const { gl, boundTextures } = this;
90 if (this._unknownBoundTextures) {
91 this._unknownBoundTextures = false;
92 for (let i = 0; i < boundTextures.length; i++) {
93 if (boundTextures[i] === this.unknownTexture) {
94 this.bind(null, i);
95 }
96 }
97 }
98 for (let i = 0; i < boundTextures.length; i++) {
99 if (boundTextures[i] === texture) {
100 if (this.currentLocation !== i) {
101 gl.activeTexture(gl.TEXTURE0 + i);
102 this.currentLocation = i;
103 }
104 gl.bindTexture(texture.target, this.emptyTextures[texture.target].texture);
105 boundTextures[i] = null;
106 }
107 }
108 }
109 ensureSamplerType(maxTextures) {
110 const { boundTextures, hasIntegerTextures, CONTEXT_UID } = this;
111 if (!hasIntegerTextures) {
112 return;
113 }
114 for (let i = maxTextures - 1; i >= 0; --i) {
115 const tex = boundTextures[i];
116 if (tex) {
117 const glTexture = tex._glTextures[CONTEXT_UID];
118 if (glTexture.samplerType !== constants.SAMPLER_TYPES.FLOAT) {
119 this.renderer.texture.unbind(tex);
120 }
121 }
122 }
123 }
124 initTexture(texture) {
125 const glTexture = new GLTexture.GLTexture(this.gl.createTexture());
126 glTexture.dirtyId = -1;
127 texture._glTextures[this.CONTEXT_UID] = glTexture;
128 this.managedTextures.push(texture);
129 texture.on("dispose", this.destroyTexture, this);
130 return glTexture;
131 }
132 initTextureType(texture, glTexture) {
133 glTexture.internalFormat = this.internalFormats[texture.type]?.[texture.format] ?? texture.format;
134 if (this.webGLVersion === 2 && texture.type === constants.TYPES.HALF_FLOAT) {
135 glTexture.type = this.gl.HALF_FLOAT;
136 } else {
137 glTexture.type = texture.type;
138 }
139 }
140 updateTexture(texture) {
141 const glTexture = texture._glTextures[this.CONTEXT_UID];
142 if (!glTexture) {
143 return;
144 }
145 const renderer = this.renderer;
146 this.initTextureType(texture, glTexture);
147 if (texture.resource?.upload(renderer, texture, glTexture)) {
148 if (glTexture.samplerType !== constants.SAMPLER_TYPES.FLOAT) {
149 this.hasIntegerTextures = true;
150 }
151 } else {
152 const width = texture.realWidth;
153 const height = texture.realHeight;
154 const gl = renderer.gl;
155 if (glTexture.width !== width || glTexture.height !== height || glTexture.dirtyId < 0) {
156 glTexture.width = width;
157 glTexture.height = height;
158 gl.texImage2D(texture.target, 0, glTexture.internalFormat, width, height, 0, texture.format, glTexture.type, null);
159 }
160 }
161 if (texture.dirtyStyleId !== glTexture.dirtyStyleId) {
162 this.updateTextureStyle(texture);
163 }
164 glTexture.dirtyId = texture.dirtyId;
165 }
166 destroyTexture(texture, skipRemove) {
167 const { gl } = this;
168 texture = texture.castToBaseTexture();
169 if (texture._glTextures[this.CONTEXT_UID]) {
170 this.unbind(texture);
171 gl.deleteTexture(texture._glTextures[this.CONTEXT_UID].texture);
172 texture.off("dispose", this.destroyTexture, this);
173 delete texture._glTextures[this.CONTEXT_UID];
174 if (!skipRemove) {
175 const i = this.managedTextures.indexOf(texture);
176 if (i !== -1) {
177 utils.removeItems(this.managedTextures, i, 1);
178 }
179 }
180 }
181 }
182 updateTextureStyle(texture) {
183 const glTexture = texture._glTextures[this.CONTEXT_UID];
184 if (!glTexture) {
185 return;
186 }
187 if ((texture.mipmap === constants.MIPMAP_MODES.POW2 || this.webGLVersion !== 2) && !texture.isPowerOfTwo) {
188 glTexture.mipmap = false;
189 } else {
190 glTexture.mipmap = texture.mipmap >= 1;
191 }
192 if (this.webGLVersion !== 2 && !texture.isPowerOfTwo) {
193 glTexture.wrapMode = constants.WRAP_MODES.CLAMP;
194 } else {
195 glTexture.wrapMode = texture.wrapMode;
196 }
197 if (texture.resource?.style(this.renderer, texture, glTexture)) {
198 } else {
199 this.setStyle(texture, glTexture);
200 }
201 glTexture.dirtyStyleId = texture.dirtyStyleId;
202 }
203 setStyle(texture, glTexture) {
204 const gl = this.gl;
205 if (glTexture.mipmap && texture.mipmap !== constants.MIPMAP_MODES.ON_MANUAL) {
206 gl.generateMipmap(texture.target);
207 }
208 gl.texParameteri(texture.target, gl.TEXTURE_WRAP_S, glTexture.wrapMode);
209 gl.texParameteri(texture.target, gl.TEXTURE_WRAP_T, glTexture.wrapMode);
210 if (glTexture.mipmap) {
211 gl.texParameteri(texture.target, gl.TEXTURE_MIN_FILTER, texture.scaleMode === constants.SCALE_MODES.LINEAR ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST);
212 const anisotropicExt = this.renderer.context.extensions.anisotropicFiltering;
213 if (anisotropicExt && texture.anisotropicLevel > 0 && texture.scaleMode === constants.SCALE_MODES.LINEAR) {
214 const level = Math.min(texture.anisotropicLevel, gl.getParameter(anisotropicExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT));
215 gl.texParameterf(texture.target, anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, level);
216 }
217 } else {
218 gl.texParameteri(texture.target, gl.TEXTURE_MIN_FILTER, texture.scaleMode === constants.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
219 }
220 gl.texParameteri(texture.target, gl.TEXTURE_MAG_FILTER, texture.scaleMode === constants.SCALE_MODES.LINEAR ? gl.LINEAR : gl.NEAREST);
221 }
222 destroy() {
223 this.renderer = null;
224 }
225}
226TextureSystem.extension = {
227 type: extensions.ExtensionType.RendererSystem,
228 name: "texture"
229};
230extensions.extensions.add(TextureSystem);
231
232exports.TextureSystem = TextureSystem;
233//# sourceMappingURL=TextureSystem.js.map