1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 27 cc._currentProjectionMatrix = -1; 28 29 if (cc.ENABLE_GL_STATE_CACHE) { 30 cc.MAX_ACTIVETEXTURE = 16; 31 32 cc._currentShaderProgram = -1; 33 cc._currentBoundTexture = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; 34 cc._blendingSource = -1; 35 cc._blendingDest = -1; 36 cc._GLServerState = 0; 37 if(cc.TEXTURE_ATLAS_USE_VAO) 38 cc._uVAO = 0; 39 40 var _currBuffers = {}; 41 42 WebGLRenderingContext.prototype.glBindBuffer = WebGLRenderingContext.prototype.bindBuffer; 43 WebGLRenderingContext.prototype.bindBuffer = function (target, buffer) { 44 if (_currBuffers[target] !== buffer) { 45 this.glBindBuffer(target, buffer); 46 _currBuffers[target] = buffer; 47 return false; 48 } 49 else { 50 return true; 51 } 52 }; 53 54 WebGLRenderingContext.prototype.glEnableVertexAttribArray = WebGLRenderingContext.prototype.enableVertexAttribArray; 55 WebGLRenderingContext.prototype.enableVertexAttribArray = function (index) { 56 if (index === cc.VERTEX_ATTRIB_FLAG_POSITION) { 57 if (!this._vertexAttribPosition) { 58 this.glEnableVertexAttribArray(index); 59 this._vertexAttribPosition = true; 60 } 61 } 62 else if (index === cc.VERTEX_ATTRIB_FLAG_COLOR) { 63 if (!this._vertexAttribColor) { 64 this.glEnableVertexAttribArray(index); 65 this._vertexAttribColor = true; 66 } 67 } 68 else if (index === cc.VERTEX_ATTRIB_FLAG_TEX_COORDS) { 69 if (!this._vertexAttribTexCoords) { 70 this.glEnableVertexAttribArray(index); 71 this._vertexAttribTexCoords = true; 72 } 73 } 74 else { 75 this.glEnableVertexAttribArray(index); 76 } 77 }; 78 79 WebGLRenderingContext.prototype.glDisableVertexAttribArray = WebGLRenderingContext.prototype.disableVertexAttribArray; 80 WebGLRenderingContext.prototype.disableVertexAttribArray = function (index) { 81 if (index === cc.VERTEX_ATTRIB_FLAG_COLOR) { 82 if (this._vertexAttribColor) { 83 this.glDisableVertexAttribArray(index); 84 this._vertexAttribColor = false; 85 } 86 } 87 else if (index === cc.VERTEX_ATTRIB_FLAG_TEX_COORDS) { 88 if (this._vertexAttribTexCoords) { 89 this.glDisableVertexAttribArray(index); 90 this._vertexAttribTexCoords = false; 91 } 92 } 93 else if (index !== 0) { 94 this.glDisableVertexAttribArray(index); 95 } 96 }; 97 } 98 99 // GL State Cache functions 100 101 /** 102 * Invalidates the GL state cache.<br/> 103 * If CC_ENABLE_GL_STATE_CACHE it will reset the GL state cache. 104 * @function 105 */ 106 cc.glInvalidateStateCache = function () { 107 cc.kmGLFreeAll(); 108 cc._currentProjectionMatrix = -1; 109 if (cc.ENABLE_GL_STATE_CACHE) { 110 cc._currentShaderProgram = -1; 111 for (var i = 0; i < cc.MAX_ACTIVETEXTURE; i++) { 112 cc._currentBoundTexture[i] = -1; 113 } 114 cc._blendingSource = -1; 115 cc._blendingDest = -1; 116 cc._GLServerState = 0; 117 } 118 }; 119 120 /** 121 * Uses the GL program in case program is different than the current one.<br/> 122 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glUseProgram() directly. 123 * @function 124 * @param {WebGLProgram} program 125 */ 126 cc.glUseProgram = cc.ENABLE_GL_STATE_CACHE ? function (program) { 127 if (program !== cc._currentShaderProgram) { 128 cc._currentShaderProgram = program; 129 cc._renderContext.useProgram(program); 130 } 131 } : function (program) { 132 cc._renderContext.useProgram(program); 133 }; 134 135 /** 136 * Deletes the GL program. If it is the one that is being used, it invalidates it.<br/> 137 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glDeleteProgram() directly. 138 * @function 139 * @param {WebGLProgram} program 140 */ 141 cc.glDeleteProgram = function (program) { 142 if (cc.ENABLE_GL_STATE_CACHE) { 143 if (program === cc._currentShaderProgram) 144 cc._currentShaderProgram = -1; 145 } 146 gl.deleteProgram(program); 147 }; 148 149 /** 150 * @function 151 * @param {Number} sfactor 152 * @param {Number} dfactor 153 */ 154 cc.setBlending = function (sfactor, dfactor) { 155 var ctx = cc._renderContext; 156 if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) { 157 ctx.disable(ctx.BLEND); 158 } else { 159 ctx.enable(ctx.BLEND); 160 cc._renderContext.blendFunc(sfactor,dfactor); 161 //TODO need fix for WebGL 162 //ctx.blendFuncSeparate(ctx.SRC_ALPHA, dfactor, sfactor, dfactor); 163 } 164 }; 165 166 /** 167 * Uses a blending function in case it not already used.<br/> 168 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glBlendFunc() directly. 169 * @function 170 * @param {Number} sfactor 171 * @param {Number} dfactor 172 */ 173 cc.glBlendFunc = cc.ENABLE_GL_STATE_CACHE ? function (sfactor, dfactor) { 174 if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) { 175 cc._blendingSource = sfactor; 176 cc._blendingDest = dfactor; 177 cc.setBlending(sfactor, dfactor); 178 } 179 } : cc.setBlending; 180 181 /** 182 * @function 183 * @param {Number} sfactor 184 * @param {Number} dfactor 185 */ 186 cc.glBlendFuncForParticle = function(sfactor, dfactor) { 187 if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) { 188 cc._blendingSource = sfactor; 189 cc._blendingDest = dfactor; 190 var ctx = cc._renderContext; 191 if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) { 192 ctx.disable(ctx.BLEND); 193 } else { 194 ctx.enable(ctx.BLEND); 195 //TODO need fix for WebGL 196 ctx.blendFuncSeparate(ctx.SRC_ALPHA, dfactor, sfactor, dfactor); 197 } 198 } 199 }; 200 201 /** 202 * Resets the blending mode back to the cached state in case you used glBlendFuncSeparate() or glBlendEquation().<br/> 203 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will just set the default blending mode using GL_FUNC_ADD. 204 * @function 205 */ 206 cc.glBlendResetToCache = function () { 207 var ctx = cc._renderContext; 208 ctx.blendEquation(ctx.FUNC_ADD); 209 if (cc.ENABLE_GL_STATE_CACHE) 210 cc.setBlending(cc._blendingSource, cc._blendingDest); 211 else 212 cc.setBlending(ctx.BLEND_SRC, ctx.BLEND_DST); 213 }; 214 215 /** 216 * sets the projection matrix as dirty 217 * @function 218 */ 219 cc.setProjectionMatrixDirty = function () { 220 cc._currentProjectionMatrix = -1; 221 }; 222 223 /** 224 * If the texture is not already bound, it binds it.<br/> 225 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. 226 * @function 227 * @param {cc.Texture2D} textureId 228 */ 229 cc.glBindTexture2D = function (textureId) { 230 cc.glBindTexture2DN(0, textureId); 231 }; 232 233 /** 234 * If the texture is not already bound to a given unit, it binds it.<br/> 235 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. 236 * @function 237 * @param {Number} textureUnit 238 * @param {cc.Texture2D} textureId 239 */ 240 cc.glBindTexture2DN = cc.ENABLE_GL_STATE_CACHE ? function (textureUnit, textureId) { 241 if (cc._currentBoundTexture[textureUnit] === textureId) 242 return; 243 cc._currentBoundTexture[textureUnit] = textureId; 244 245 var ctx = cc._renderContext; 246 ctx.activeTexture(ctx.TEXTURE0 + textureUnit); 247 if(textureId) 248 ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj); 249 else 250 ctx.bindTexture(ctx.TEXTURE_2D, null); 251 } : function (textureUnit, textureId) { 252 var ctx = cc._renderContext; 253 ctx.activeTexture(ctx.TEXTURE0 + textureUnit); 254 if(textureId) 255 ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj); 256 else 257 ctx.bindTexture(ctx.TEXTURE_2D, null); 258 }; 259 260 /** 261 * It will delete a given texture. If the texture was bound, it will invalidate the cached. <br/> 262 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. 263 * @function 264 * @param {WebGLTexture} textureId 265 */ 266 cc.glDeleteTexture = function (textureId) { 267 cc.glDeleteTextureN(0, textureId); 268 }; 269 270 /** 271 * It will delete a given texture. If the texture was bound, it will invalidate the cached for the given texture unit.<br/> 272 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. 273 * @function 274 * @param {Number} textureUnit 275 * @param {WebGLTexture} textureId 276 */ 277 cc.glDeleteTextureN = function (textureUnit, textureId) { 278 if (cc.ENABLE_GL_STATE_CACHE) { 279 if (textureId === cc._currentBoundTexture[ textureUnit ]) 280 cc._currentBoundTexture[ textureUnit ] = -1; 281 } 282 cc._renderContext.deleteTexture(textureId._webTextureObj); 283 }; 284 285 /** 286 * If the vertex array is not already bound, it binds it.<br/> 287 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindVertexArray() directly. 288 * @function 289 * @param {Number} vaoId 290 */ 291 cc.glBindVAO = function (vaoId) { 292 if (!cc.TEXTURE_ATLAS_USE_VAO) 293 return; 294 295 if (cc.ENABLE_GL_STATE_CACHE) { 296 if (cc._uVAO !== vaoId) { 297 cc._uVAO = vaoId; 298 //TODO need fixed 299 //glBindVertexArray(vaoId); 300 } 301 } else { 302 //glBindVertexArray(vaoId); 303 } 304 }; 305 306 /** 307 * It will enable / disable the server side GL states.<br/> 308 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glEnable() directly. 309 * @function 310 * @param {Number} flags 311 */ 312 cc.glEnable = function (flags) { 313 if (cc.ENABLE_GL_STATE_CACHE) { 314 /*var enabled; 315 316 */ 317 /* GL_BLEND */ 318 /* 319 if ((enabled = (flags & cc.GL_BLEND)) != (cc._GLServerState & cc.GL_BLEND)) { 320 if (enabled) { 321 cc._renderContext.enable(cc._renderContext.BLEND); 322 cc._GLServerState |= cc.GL_BLEND; 323 } else { 324 cc._renderContext.disable(cc._renderContext.BLEND); 325 cc._GLServerState &= ~cc.GL_BLEND; 326 } 327 }*/ 328 } else { 329 /*if ((flags & cc.GL_BLEND)) 330 cc._renderContext.enable(cc._renderContext.BLEND); 331 else 332 cc._renderContext.disable(cc._renderContext.BLEND);*/ 333 } 334 }; 335