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 var _currBuffer; 42 43 WebGLRenderingContext.prototype.glBindBuffer = WebGLRenderingContext.prototype.bindBuffer; 44 WebGLRenderingContext.prototype.bindBuffer = function (target, buffer) { 45 if (_currBuffers[target] !== buffer) { 46 _currBuffers[target] = buffer; 47 this.glBindBuffer(target, buffer); 48 } 49 50 if (!_currBuffer || _currBuffer !== buffer) { 51 _currBuffer = buffer; 52 return false; 53 } 54 else { 55 return true; 56 } 57 }; 58 59 WebGLRenderingContext.prototype.glEnableVertexAttribArray = WebGLRenderingContext.prototype.enableVertexAttribArray; 60 WebGLRenderingContext.prototype.enableVertexAttribArray = function (index) { 61 if (index === cc.VERTEX_ATTRIB_FLAG_POSITION) { 62 if (!this._vertexAttribPosition) { 63 this.glEnableVertexAttribArray(index); 64 this._vertexAttribPosition = true; 65 } 66 } 67 else if (index === cc.VERTEX_ATTRIB_FLAG_COLOR) { 68 if (!this._vertexAttribColor) { 69 this.glEnableVertexAttribArray(index); 70 this._vertexAttribColor = true; 71 } 72 } 73 else if (index === cc.VERTEX_ATTRIB_FLAG_TEX_COORDS) { 74 if (!this._vertexAttribTexCoords) { 75 this.glEnableVertexAttribArray(index); 76 this._vertexAttribTexCoords = true; 77 } 78 } 79 else { 80 this.glEnableVertexAttribArray(index); 81 } 82 }; 83 84 WebGLRenderingContext.prototype.glDisableVertexAttribArray = WebGLRenderingContext.prototype.disableVertexAttribArray; 85 WebGLRenderingContext.prototype.disableVertexAttribArray = function (index) { 86 if (index === cc.VERTEX_ATTRIB_FLAG_COLOR) { 87 if (this._vertexAttribColor) { 88 this.glDisableVertexAttribArray(index); 89 this._vertexAttribColor = false; 90 } 91 } 92 else if (index === cc.VERTEX_ATTRIB_FLAG_TEX_COORDS) { 93 if (this._vertexAttribTexCoords) { 94 this.glDisableVertexAttribArray(index); 95 this._vertexAttribTexCoords = false; 96 } 97 } 98 else if (index !== 0) { 99 this.glDisableVertexAttribArray(index); 100 } 101 }; 102 } 103 104 // GL State Cache functions 105 106 /** 107 * Invalidates the GL state cache.<br/> 108 * If CC_ENABLE_GL_STATE_CACHE it will reset the GL state cache. 109 * @function 110 */ 111 cc.glInvalidateStateCache = function () { 112 cc.kmGLFreeAll(); 113 cc._currentProjectionMatrix = -1; 114 if (cc.ENABLE_GL_STATE_CACHE) { 115 cc._currentShaderProgram = -1; 116 for (var i = 0; i < cc.MAX_ACTIVETEXTURE; i++) { 117 cc._currentBoundTexture[i] = -1; 118 } 119 cc._blendingSource = -1; 120 cc._blendingDest = -1; 121 cc._GLServerState = 0; 122 } 123 }; 124 125 /** 126 * Uses the GL program in case program is different than the current one.<br/> 127 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glUseProgram() directly. 128 * @function 129 * @param {WebGLProgram} program 130 */ 131 cc.glUseProgram = function (program) { 132 if (program !== cc._currentShaderProgram) { 133 cc._currentShaderProgram = program; 134 cc._renderContext.useProgram(program); 135 } 136 }; 137 138 if(!cc.ENABLE_GL_STATE_CACHE){ 139 cc.glUseProgram = function (program) { 140 cc._renderContext.useProgram(program); 141 }; 142 } 143 144 /** 145 * Deletes the GL program. If it is the one that is being used, it invalidates it.<br/> 146 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glDeleteProgram() directly. 147 * @function 148 * @param {WebGLProgram} program 149 */ 150 cc.glDeleteProgram = function (program) { 151 if (cc.ENABLE_GL_STATE_CACHE) { 152 if (program === cc._currentShaderProgram) 153 cc._currentShaderProgram = -1; 154 } 155 gl.deleteProgram(program); 156 }; 157 158 /** 159 * Uses a blending function in case it not already used.<br/> 160 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glBlendFunc() directly. 161 * @function 162 * @param {Number} sfactor 163 * @param {Number} dfactor 164 */ 165 cc.glBlendFunc = function (sfactor, dfactor) { 166 if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) { 167 cc._blendingSource = sfactor; 168 cc._blendingDest = dfactor; 169 cc.setBlending(sfactor, dfactor); 170 } 171 }; 172 173 /** 174 * @function 175 * @param {Number} sfactor 176 * @param {Number} dfactor 177 */ 178 cc.setBlending = function (sfactor, dfactor) { 179 var ctx = cc._renderContext; 180 if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) { 181 ctx.disable(ctx.BLEND); 182 } else { 183 ctx.enable(ctx.BLEND); 184 cc._renderContext.blendFunc(sfactor,dfactor); 185 //TODO need fix for WebGL 186 //ctx.blendFuncSeparate(ctx.SRC_ALPHA, dfactor, sfactor, dfactor); 187 } 188 }; 189 190 /** 191 * @function 192 * @param {Number} sfactor 193 * @param {Number} dfactor 194 */ 195 cc.glBlendFuncForParticle = function(sfactor, dfactor) { 196 if ((sfactor !== cc._blendingSource) || (dfactor !== cc._blendingDest)) { 197 cc._blendingSource = sfactor; 198 cc._blendingDest = dfactor; 199 var ctx = cc._renderContext; 200 if ((sfactor === ctx.ONE) && (dfactor === ctx.ZERO)) { 201 ctx.disable(ctx.BLEND); 202 } else { 203 ctx.enable(ctx.BLEND); 204 //TODO need fix for WebGL 205 ctx.blendFuncSeparate(ctx.SRC_ALPHA, dfactor, sfactor, dfactor); 206 } 207 } 208 }; 209 210 if (!cc.ENABLE_GL_STATE_CACHE) { 211 cc.glBlendFunc = cc.setBlending; 212 } 213 214 /** 215 * Resets the blending mode back to the cached state in case you used glBlendFuncSeparate() or glBlendEquation().<br/> 216 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will just set the default blending mode using GL_FUNC_ADD. 217 * @function 218 */ 219 cc.glBlendResetToCache = function () { 220 var ctx = cc._renderContext; 221 ctx.blendEquation(ctx.FUNC_ADD); 222 if (cc.ENABLE_GL_STATE_CACHE) 223 cc.setBlending(cc._blendingSource, cc._blendingDest); 224 else 225 cc.setBlending(ctx.BLEND_SRC, ctx.BLEND_DST); 226 }; 227 228 /** 229 * sets the projection matrix as dirty 230 * @function 231 */ 232 cc.setProjectionMatrixDirty = function () { 233 cc._currentProjectionMatrix = -1; 234 }; 235 236 /** 237 * If the texture is not already bound, it binds it.<br/> 238 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. 239 * @function 240 * @param {cc.Texture2D} textureId 241 */ 242 cc.glBindTexture2D = function (textureId) { 243 cc.glBindTexture2DN(0, textureId); 244 }; 245 246 /** 247 * If the texture is not already bound to a given unit, it binds it.<br/> 248 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. 249 * @function 250 * @param {Number} textureUnit 251 * @param {cc.Texture2D} textureId 252 */ 253 cc.glBindTexture2DN = function (textureUnit, textureId) { 254 if (cc._currentBoundTexture[textureUnit] === textureId) 255 return; 256 cc._currentBoundTexture[textureUnit] = textureId; 257 258 var ctx = cc._renderContext; 259 ctx.activeTexture(ctx.TEXTURE0 + textureUnit); 260 if(textureId) 261 ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj); 262 else 263 ctx.bindTexture(ctx.TEXTURE_2D, null); 264 }; 265 if (!cc.ENABLE_GL_STATE_CACHE){ 266 cc.glBindTexture2DN = function (textureUnit, textureId) { 267 var ctx = cc._renderContext; 268 ctx.activeTexture(ctx.TEXTURE0 + textureUnit); 269 if(textureId) 270 ctx.bindTexture(ctx.TEXTURE_2D, textureId._webTextureObj); 271 else 272 ctx.bindTexture(ctx.TEXTURE_2D, null); 273 }; 274 } 275 276 /** 277 * It will delete a given texture. If the texture was bound, it will invalidate the cached. <br/> 278 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. 279 * @function 280 * @param {WebGLTexture} textureId 281 */ 282 cc.glDeleteTexture = function (textureId) { 283 cc.glDeleteTextureN(0, textureId); 284 }; 285 286 /** 287 * It will delete a given texture. If the texture was bound, it will invalidate the cached for the given texture unit.<br/> 288 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. 289 * @function 290 * @param {Number} textureUnit 291 * @param {WebGLTexture} textureId 292 */ 293 cc.glDeleteTextureN = function (textureUnit, textureId) { 294 if (cc.ENABLE_GL_STATE_CACHE) { 295 if (textureId === cc._currentBoundTexture[ textureUnit ]) 296 cc._currentBoundTexture[ textureUnit ] = -1; 297 } 298 cc._renderContext.deleteTexture(textureId); 299 }; 300 301 /** 302 * If the vertex array is not already bound, it binds it.<br/> 303 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindVertexArray() directly. 304 * @function 305 * @param {Number} vaoId 306 */ 307 cc.glBindVAO = function (vaoId) { 308 if (!cc.TEXTURE_ATLAS_USE_VAO) 309 return; 310 311 if (cc.ENABLE_GL_STATE_CACHE) { 312 if (cc._uVAO !== vaoId) { 313 cc._uVAO = vaoId; 314 //TODO need fixed 315 //glBindVertexArray(vaoId); 316 } 317 } else { 318 //glBindVertexArray(vaoId); 319 } 320 }; 321 322 /** 323 * It will enable / disable the server side GL states.<br/> 324 * If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glEnable() directly. 325 * @function 326 * @param {Number} flags 327 */ 328 cc.glEnable = function (flags) { 329 if (cc.ENABLE_GL_STATE_CACHE) { 330 /*var enabled; 331 332 */ 333 /* GL_BLEND */ 334 /* 335 if ((enabled = (flags & cc.GL_BLEND)) != (cc._GLServerState & cc.GL_BLEND)) { 336 if (enabled) { 337 cc._renderContext.enable(cc._renderContext.BLEND); 338 cc._GLServerState |= cc.GL_BLEND; 339 } else { 340 cc._renderContext.disable(cc._renderContext.BLEND); 341 cc._GLServerState &= ~cc.GL_BLEND; 342 } 343 }*/ 344 } else { 345 /*if ((flags & cc.GL_BLEND)) 346 cc._renderContext.enable(cc._renderContext.BLEND); 347 else 348 cc._renderContext.disable(cc._renderContext.BLEND);*/ 349 } 350 }; 351