Source: core/renderers/webgl/WebGLState.js

core/renderers/webgl/WebGLState.js

  1. import mapWebGLBlendModesToPixi from './utils/mapWebGLBlendModesToPixi';
  2. const BLEND = 0;
  3. const DEPTH_TEST = 1;
  4. const FRONT_FACE = 2;
  5. const CULL_FACE = 3;
  6. const BLEND_FUNC = 4;
  7. /**
  8. * A WebGL state machines
  9. *
  10. * @memberof PIXI
  11. * @class
  12. */
  13. export default class WebGLState
  14. {
  15. /**
  16. * @param {WebGLRenderingContext} gl - The current WebGL rendering context
  17. */
  18. constructor(gl)
  19. {
  20. /**
  21. * The current active state
  22. *
  23. * @member {Uint8Array}
  24. */
  25. this.activeState = new Uint8Array(16);
  26. /**
  27. * The default state
  28. *
  29. * @member {Uint8Array}
  30. */
  31. this.defaultState = new Uint8Array(16);
  32. // default blend mode..
  33. this.defaultState[0] = 1;
  34. /**
  35. * The current state index in the stack
  36. *
  37. * @member {number}
  38. * @private
  39. */
  40. this.stackIndex = 0;
  41. /**
  42. * The stack holding all the different states
  43. *
  44. * @member {Array<*>}
  45. * @private
  46. */
  47. this.stack = [];
  48. /**
  49. * The current WebGL rendering context
  50. *
  51. * @member {WebGLRenderingContext}
  52. */
  53. this.gl = gl;
  54. this.maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
  55. this.attribState = {
  56. tempAttribState: new Array(this.maxAttribs),
  57. attribState: new Array(this.maxAttribs),
  58. };
  59. this.blendModes = mapWebGLBlendModesToPixi(gl);
  60. // check we have vao..
  61. this.nativeVaoExtension = (
  62. gl.getExtension('OES_vertex_array_object')
  63. || gl.getExtension('MOZ_OES_vertex_array_object')
  64. || gl.getExtension('WEBKIT_OES_vertex_array_object')
  65. );
  66. }
  67. /**
  68. * Pushes a new active state
  69. */
  70. push()
  71. {
  72. // next state..
  73. let state = this.stack[this.stackIndex];
  74. if (!state)
  75. {
  76. state = this.stack[this.stackIndex] = new Uint8Array(16);
  77. }
  78. ++this.stackIndex;
  79. // copy state..
  80. // set active state so we can force overrides of gl state
  81. for (let i = 0; i < this.activeState.length; i++)
  82. {
  83. state[i] = this.activeState[i];
  84. }
  85. }
  86. /**
  87. * Pops a state out
  88. */
  89. pop()
  90. {
  91. const state = this.stack[--this.stackIndex];
  92. this.setState(state);
  93. }
  94. /**
  95. * Sets the current state
  96. *
  97. * @param {*} state - The state to set.
  98. */
  99. setState(state)
  100. {
  101. this.setBlend(state[BLEND]);
  102. this.setDepthTest(state[DEPTH_TEST]);
  103. this.setFrontFace(state[FRONT_FACE]);
  104. this.setCullFace(state[CULL_FACE]);
  105. this.setBlendMode(state[BLEND_FUNC]);
  106. }
  107. /**
  108. * Enables or disabled blending.
  109. *
  110. * @param {boolean} value - Turn on or off webgl blending.
  111. */
  112. setBlend(value)
  113. {
  114. value = value ? 1 : 0;
  115. if (this.activeState[BLEND] === value)
  116. {
  117. return;
  118. }
  119. this.activeState[BLEND] = value;
  120. this.gl[value ? 'enable' : 'disable'](this.gl.BLEND);
  121. }
  122. /**
  123. * Sets the blend mode.
  124. *
  125. * @param {number} value - The blend mode to set to.
  126. */
  127. setBlendMode(value)
  128. {
  129. if (value === this.activeState[BLEND_FUNC])
  130. {
  131. return;
  132. }
  133. this.activeState[BLEND_FUNC] = value;
  134. const mode = this.blendModes[value];
  135. if (mode.length === 2)
  136. {
  137. this.gl.blendFunc(mode[0], mode[1]);
  138. }
  139. else
  140. {
  141. this.gl.blendFuncSeparate(mode[0], mode[1], mode[2], mode[3]);
  142. }
  143. }
  144. /**
  145. * Sets whether to enable or disable depth test.
  146. *
  147. * @param {boolean} value - Turn on or off webgl depth testing.
  148. */
  149. setDepthTest(value)
  150. {
  151. value = value ? 1 : 0;
  152. if (this.activeState[DEPTH_TEST] === value)
  153. {
  154. return;
  155. }
  156. this.activeState[DEPTH_TEST] = value;
  157. this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST);
  158. }
  159. /**
  160. * Sets whether to enable or disable cull face.
  161. *
  162. * @param {boolean} value - Turn on or off webgl cull face.
  163. */
  164. setCullFace(value)
  165. {
  166. value = value ? 1 : 0;
  167. if (this.activeState[CULL_FACE] === value)
  168. {
  169. return;
  170. }
  171. this.activeState[CULL_FACE] = value;
  172. this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE);
  173. }
  174. /**
  175. * Sets the gl front face.
  176. *
  177. * @param {boolean} value - true is clockwise and false is counter-clockwise
  178. */
  179. setFrontFace(value)
  180. {
  181. value = value ? 1 : 0;
  182. if (this.activeState[FRONT_FACE] === value)
  183. {
  184. return;
  185. }
  186. this.activeState[FRONT_FACE] = value;
  187. this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']);
  188. }
  189. /**
  190. * Disables all the vaos in use
  191. *
  192. */
  193. resetAttributes()
  194. {
  195. for (let i = 0; i < this.attribState.tempAttribState.length; i++)
  196. {
  197. this.attribState.tempAttribState[i] = 0;
  198. }
  199. for (let i = 0; i < this.attribState.attribState.length; i++)
  200. {
  201. this.attribState.attribState[i] = 0;
  202. }
  203. // im going to assume one is always active for performance reasons.
  204. for (let i = 1; i < this.maxAttribs; i++)
  205. {
  206. this.gl.disableVertexAttribArray(i);
  207. }
  208. }
  209. // used
  210. /**
  211. * Resets all the logic and disables the vaos
  212. */
  213. resetToDefault()
  214. {
  215. // unbind any VAO if they exist..
  216. if (this.nativeVaoExtension)
  217. {
  218. this.nativeVaoExtension.bindVertexArrayOES(null);
  219. }
  220. // reset all attributes..
  221. this.resetAttributes();
  222. // set active state so we can force overrides of gl state
  223. for (let i = 0; i < this.activeState.length; ++i)
  224. {
  225. this.activeState[i] = 32;
  226. }
  227. this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);
  228. this.setState(this.defaultState);
  229. }
  230. }