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