Source: core/renderers/webgl/TextureManager.js

core/renderers/webgl/TextureManager.js

  1. // 修改依赖库应对小程序环境
  2. import { GLTexture } from '../../../dependencies/pixi-gl-core/';
  3. // import { GLTexture } from 'pixi-gl-core';
  4. import { WRAP_MODES, SCALE_MODES } from '../../const';
  5. import RenderTarget from './utils/RenderTarget';
  6. import { removeItems } from '../../utils';
  7. /**
  8. * Helper class to create a webGL Texture
  9. *
  10. * @class
  11. * @memberof PIXI
  12. */
  13. export default class TextureManager
  14. {
  15. /**
  16. * @param {PIXI.WebGLRenderer} renderer - A reference to the current renderer
  17. */
  18. constructor(renderer)
  19. {
  20. /**
  21. * A reference to the current renderer
  22. *
  23. * @member {PIXI.WebGLRenderer}
  24. */
  25. this.renderer = renderer;
  26. /**
  27. * The current WebGL rendering context
  28. *
  29. * @member {WebGLRenderingContext}
  30. */
  31. this.gl = renderer.gl;
  32. /**
  33. * Track textures in the renderer so we can no longer listen to them on destruction.
  34. *
  35. * @member {Array<*>}
  36. * @private
  37. */
  38. this._managedTextures = [];
  39. }
  40. /**
  41. * Binds a texture.
  42. *
  43. */
  44. bindTexture()
  45. {
  46. // empty
  47. }
  48. /**
  49. * Gets a texture.
  50. *
  51. */
  52. getTexture()
  53. {
  54. // empty
  55. }
  56. /**
  57. * Updates and/or Creates a WebGL texture for the renderer's context.
  58. *
  59. * @param {PIXI.BaseTexture|PIXI.Texture} texture - the texture to update
  60. * @param {number} location - the location the texture will be bound to.
  61. * @return {GLTexture} The gl texture.
  62. */
  63. updateTexture(texture, location)
  64. {
  65. // assume it good!
  66. // texture = texture.baseTexture || texture;
  67. const gl = this.gl;
  68. const isRenderTexture = !!texture._glRenderTargets;
  69. if (!texture.hasLoaded)
  70. {
  71. return null;
  72. }
  73. const boundTextures = this.renderer.boundTextures;
  74. // if the location is undefined then this may have been called by n event.
  75. // this being the case the texture may already be bound to a slot. As a texture can only be bound once
  76. // we need to find its current location if it exists.
  77. if (location === undefined)
  78. {
  79. location = 0;
  80. // TODO maybe we can use texture bound ids later on...
  81. // check if texture is already bound..
  82. for (let i = 0; i < boundTextures.length; ++i)
  83. {
  84. if (boundTextures[i] === texture)
  85. {
  86. location = i;
  87. break;
  88. }
  89. }
  90. }
  91. boundTextures[location] = texture;
  92. gl.activeTexture(gl.TEXTURE0 + location);
  93. let glTexture = texture._glTextures[this.renderer.CONTEXT_UID];
  94. if (!glTexture)
  95. {
  96. if (isRenderTexture)
  97. {
  98. const renderTarget = new RenderTarget(
  99. this.gl,
  100. texture.width,
  101. texture.height,
  102. texture.scaleMode,
  103. texture.resolution
  104. );
  105. renderTarget.resize(texture.width, texture.height);
  106. texture._glRenderTargets[this.renderer.CONTEXT_UID] = renderTarget;
  107. glTexture = renderTarget.texture;
  108. // framebuffer constructor disactivates current framebuffer
  109. if (!this.renderer._activeRenderTarget.root)
  110. {
  111. this.renderer._activeRenderTarget.frameBuffer.bind();
  112. }
  113. }
  114. else
  115. {
  116. glTexture = new GLTexture(this.gl, null, null, null, null);
  117. glTexture.bind(location);
  118. glTexture.premultiplyAlpha = true;
  119. glTexture.upload(texture.source);
  120. }
  121. texture._glTextures[this.renderer.CONTEXT_UID] = glTexture;
  122. texture.on('update', this.updateTexture, this);
  123. texture.on('dispose', this.destroyTexture, this);
  124. this._managedTextures.push(texture);
  125. if (texture.isPowerOfTwo)
  126. {
  127. if (texture.mipmap)
  128. {
  129. glTexture.enableMipmap();
  130. }
  131. if (texture.wrapMode === WRAP_MODES.CLAMP)
  132. {
  133. glTexture.enableWrapClamp();
  134. }
  135. else if (texture.wrapMode === WRAP_MODES.REPEAT)
  136. {
  137. glTexture.enableWrapRepeat();
  138. }
  139. else
  140. {
  141. glTexture.enableWrapMirrorRepeat();
  142. }
  143. }
  144. else
  145. {
  146. glTexture.enableWrapClamp();
  147. }
  148. if (texture.scaleMode === SCALE_MODES.NEAREST)
  149. {
  150. glTexture.enableNearestScaling();
  151. }
  152. else
  153. {
  154. glTexture.enableLinearScaling();
  155. }
  156. }
  157. // the texture already exists so we only need to update it..
  158. else if (isRenderTexture)
  159. {
  160. texture._glRenderTargets[this.renderer.CONTEXT_UID].resize(texture.width, texture.height);
  161. }
  162. else
  163. {
  164. glTexture.upload(texture.source);
  165. }
  166. return glTexture;
  167. }
  168. /**
  169. * Deletes the texture from WebGL
  170. *
  171. * @param {PIXI.BaseTexture|PIXI.Texture} texture - the texture to destroy
  172. * @param {boolean} [skipRemove=false] - Whether to skip removing the texture from the TextureManager.
  173. */
  174. destroyTexture(texture, skipRemove)
  175. {
  176. texture = texture.baseTexture || texture;
  177. if (!texture.hasLoaded)
  178. {
  179. return;
  180. }
  181. const renderer = this.renderer;
  182. const uid = renderer.CONTEXT_UID;
  183. const glTextures = texture._glTextures;
  184. const glRenderTargets = texture._glRenderTargets;
  185. if (glTextures[uid])
  186. {
  187. renderer.unbindTexture(texture);
  188. glTextures[uid].destroy();
  189. texture.off('update', this.updateTexture, this);
  190. texture.off('dispose', this.destroyTexture, this);
  191. delete glTextures[uid];
  192. if (!skipRemove)
  193. {
  194. const i = this._managedTextures.indexOf(texture);
  195. if (i !== -1)
  196. {
  197. removeItems(this._managedTextures, i, 1);
  198. }
  199. }
  200. }
  201. if (glRenderTargets && glRenderTargets[uid])
  202. {
  203. if (renderer._activeRenderTarget === glRenderTargets[uid])
  204. {
  205. renderer.bindRenderTarget(renderer.rootRenderTarget);
  206. }
  207. glRenderTargets[uid].destroy();
  208. delete glRenderTargets[uid];
  209. }
  210. }
  211. /**
  212. * Deletes all the textures from WebGL
  213. */
  214. removeAll()
  215. {
  216. // empty all the old gl textures as they are useless now
  217. for (let i = 0; i < this._managedTextures.length; ++i)
  218. {
  219. const texture = this._managedTextures[i];
  220. if (texture._glTextures[this.renderer.CONTEXT_UID])
  221. {
  222. delete texture._glTextures[this.renderer.CONTEXT_UID];
  223. }
  224. }
  225. }
  226. /**
  227. * Destroys this manager and removes all its textures
  228. */
  229. destroy()
  230. {
  231. // destroy managed textures
  232. for (let i = 0; i < this._managedTextures.length; ++i)
  233. {
  234. const texture = this._managedTextures[i];
  235. this.destroyTexture(texture, true);
  236. texture.off('update', this.updateTexture, this);
  237. texture.off('dispose', this.destroyTexture, this);
  238. }
  239. this._managedTextures = null;
  240. }
  241. }