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  Copyright (c) 2009      Jason Booth
  6 
  7  http://www.cocos2d-x.org
  8 
  9  Permission is hereby granted, free of charge, to any person obtaining a copy
 10  of this software and associated documentation files (the "Software"), to deal
 11  in the Software without restriction, including without limitation the rights
 12  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 13  copies of the Software, and to permit persons to whom the Software is
 14  furnished to do so, subject to the following conditions:
 15 
 16  The above copyright notice and this permission notice shall be included in
 17  all copies or substantial portions of the Software.
 18 
 19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 25  THE SOFTWARE.
 26  ****************************************************************************/
 27 
 28 /**
 29  * enum for jpg
 30  * @constant
 31  * @type Number
 32  */
 33 cc.IMAGE_FORMAT_JPEG = 0;
 34 /**
 35  * enum for png
 36  * @constant
 37  * @type Number
 38  */
 39 cc.IMAGE_FORMAT_PNG = 1;
 40 /**
 41  * enum for raw
 42  * @constant
 43  * @type Number
 44  */
 45 cc.IMAGE_FORMAT_RAWDATA = 9;
 46 
 47 /**
 48  * @param {Number} x
 49  * @return {Number}
 50  * Constructor
 51  */
 52 cc.NextPOT = function (x) {
 53     x = x - 1;
 54     x = x | (x >> 1);
 55     x = x | (x >> 2);
 56     x = x | (x >> 4);
 57     x = x | (x >> 8);
 58     x = x | (x >> 16);
 59     return x + 1;
 60 };
 61 
 62 /**
 63  * cc.RenderTexture is a generic rendering target. To render things into it,<br/>
 64  * simply construct a render target, call begin on it, call visit on any cocos<br/>
 65  * scenes or objects to render them, and call end. For convenience, render texture<br/>
 66  * adds a sprite as it's display child with the results, so you can simply add<br/>
 67  * the render texture to your scene and treat it like any other CocosNode.<br/>
 68  * There are also functions for saving the render texture to disk in PNG or JPG format.
 69  * @class
 70  * @extends cc.Node
 71  *
 72  * @property {cc.Sprite}    sprite          - The sprite.
 73  * @property {cc.Sprite}    clearFlags      - Code for "auto" update.
 74  * @property {Number}       clearDepthVal   - Clear depth value.
 75  * @property {Boolean}      autoDraw        - Indicate auto draw mode activate or not.
 76  * @property {Number}       clearStencilVal - Clear stencil value.
 77  * @property {cc.Color}     clearColorVal   - Clear color value, valid only when "autoDraw" is true.
 78  */
 79 cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{
 80 	sprite:null,
 81 
 82 	//
 83 	// <p>Code for "auto" update<br/>
 84 	// Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT.<br/>
 85 	// They can be OR'ed. Valid when "autoDraw is YES.</p>
 86 	// @public
 87 	//
 88 	clearFlags:0,
 89 
 90 	clearDepthVal:0,
 91 	autoDraw:false,
 92 
 93     //
 94     // the off-screen canvas for rendering and storing the texture
 95     // @type HTMLCanvasElement
 96     //
 97     _cacheCanvas:null,
 98     /**
 99      * stores a reference to the canvas context object
100      * @type CanvasRenderingContext2D
101      */
102     _cacheContext:null,
103 
104     _fBO:0,
105     _depthRenderBuffer:0,
106     _oldFBO:0,
107     _texture:null,
108     _textureCopy:null,
109     _uITextureImage:null,
110 
111     _pixelFormat:cc.Texture2D.PIXEL_FORMAT_RGBA8888,
112 
113     _clearColor:null,
114     clearStencilVal:0,
115 
116     _clearColorStr:null,
117     _className:"RenderTexture",
118 
119     /**
120      * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid
121      * Constructor of cc.RenderTexture for Canvas
122      * @param {Number} width
123      * @param {Number} height
124      * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
125      * @param {Number} depthStencilFormat
126      * @example
127      * // Example
128      * var rt = new cc.RenderTexture(width, height, format, depthStencilFormat)
129      * @function
130      */
131     ctor: null,
132 
133     _ctorForCanvas: function (width, height, format, depthStencilFormat) {
134         cc.Node.prototype.ctor.call(this);
135         this._cascadeColorEnabled = true;
136         this._cascadeOpacityEnabled = true;
137         this._clearColor = cc.color(255, 255, 255, 255);
138         this._clearColorStr = "rgba(255,255,255,1)";
139 
140         this._cacheCanvas = cc.newElement('canvas');
141         this._cacheContext = this._cacheCanvas.getContext('2d');
142         this.anchorX = 0;
143 	    this.anchorY = 0;
144 
145         if(width !== undefined && height !== undefined){
146             format = format || cc.Texture2D.PIXEL_FORMAT_RGBA8888;
147             depthStencilFormat = depthStencilFormat || 0;
148             this.initWithWidthAndHeight(width, height, format, depthStencilFormat);
149         }
150     },
151 
152     _ctorForWebGL: function (width, height, format, depthStencilFormat) {
153         cc.Node.prototype.ctor.call(this);
154         this._cascadeColorEnabled = true;
155         this._cascadeOpacityEnabled = true;
156         this._clearColor = cc.color(0, 0, 0, 0);
157 
158         if(width !== undefined && height !== undefined){
159             format = format || cc.Texture2D.PIXEL_FORMAT_RGBA8888;
160             depthStencilFormat = depthStencilFormat || 0;
161             this.initWithWidthAndHeight(width, height, format, depthStencilFormat);
162         }
163     },
164 
165     /**
166      * Clear RenderTexture.
167      * @function
168      */
169     cleanup:null,
170 
171     _cleanupForCanvas:function () {
172         cc.Node.prototype.onExit.call(this);
173         this._cacheContext = null;
174         this._cacheCanvas = null;
175     },
176 
177     _cleanupForWebGL: function () {
178         cc.Node.prototype.onExit.call(this);
179 
180         //this.sprite = null;
181         this._textureCopy = null;
182 
183         var gl = cc._renderContext;
184         gl.deleteFramebuffer(this._fBO);
185         if (this._depthRenderBuffer)
186             gl.deleteRenderbuffer(this._depthRenderBuffer);
187         this._uITextureImage = null;
188         //if (this._texture)
189         //    this._texture.releaseTexture();
190     },
191 
192     /**
193      * Gets the sprite
194      * @return {cc.Sprite}
195      */
196     getSprite:function () {
197         return this.sprite;
198     },
199 
200     /**
201      * Set the sprite
202      * @param {cc.Sprite} sprite
203      */
204     setSprite:function (sprite) {
205         this.sprite = sprite;
206     },
207 
208     /**
209      * Initializes the instance of cc.RenderTexture
210      * @function
211      * @param {Number} width
212      * @param {Number} height
213      * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} [format]
214      * @param {Number} [depthStencilFormat]
215      * @return {Boolean}
216      */
217     initWithWidthAndHeight: null,
218 
219     _initWithWidthAndHeightForCanvas: function (width, height, format, depthStencilFormat) {
220         var locCacheCanvas = this._cacheCanvas, locScaleFactor = cc.contentScaleFactor();
221         locCacheCanvas.width = 0 | (width * locScaleFactor);
222         locCacheCanvas.height = 0 | (height * locScaleFactor);
223         this._cacheContext.translate(0, locCacheCanvas.height);
224         var texture = new cc.Texture2D();
225         texture.initWithElement(locCacheCanvas);
226         texture.handleLoadedTexture();
227         var locSprite = this.sprite = cc.Sprite.create(texture);
228         locSprite.setBlendFunc(cc.ONE, cc.ONE_MINUS_SRC_ALPHA);
229         // Disabled by default.
230         this.autoDraw = false;
231         // add sprite for backward compatibility
232         this.addChild(locSprite);
233         return true;
234     },
235 
236     _initWithWidthAndHeightForWebGL: function (width, height, format, depthStencilFormat) {
237         if(format == cc.Texture2D.PIXEL_FORMAT_A8)
238             cc.log( "cc.RenderTexture._initWithWidthAndHeightForWebGL() : only RGB and RGBA formats are valid for a render texture;");
239 
240         var gl = cc._renderContext, locScaleFactor = cc.contentScaleFactor();
241 
242         width = 0 | (width * locScaleFactor);
243         height = 0 | (height * locScaleFactor);
244 
245         this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
246 
247         // textures must be power of two squared
248         var powW , powH;
249 
250         if (cc.configuration.supportsNPOT()) {
251             powW = width;
252             powH = height;
253         } else {
254             powW = cc.NextPOT(width);
255             powH = cc.NextPOT(height);
256         }
257 
258         //void *data = malloc(powW * powH * 4);
259         var dataLen = powW * powH * 4;
260         var data = new Uint8Array(dataLen);
261         //memset(data, 0, (int)(powW * powH * 4));
262         for (var i = 0; i < powW * powH * 4; i++)
263             data[i] = 0;
264 
265         this._pixelFormat = format;
266 
267         this._texture = new cc.Texture2D();
268         if (!this._texture)
269             return false;
270 
271         var locTexture = this._texture;
272         locTexture.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height));
273         //free( data );
274 
275         var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING);
276 
277         if (cc.configuration.checkForGLExtension("GL_QCOM")) {
278             this._textureCopy = new cc.Texture2D();
279             if (!this._textureCopy) {
280                 return false;
281             }
282             this._textureCopy.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height));
283         }
284 
285         // generate FBO
286         this._fBO = gl.createFramebuffer();
287         gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);
288 
289         // associate texture with FBO
290         gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, locTexture._webTextureObj, 0);
291 
292         if (depthStencilFormat != 0) {
293             //create and attach depth buffer
294             this._depthRenderBuffer = gl.createRenderbuffer();
295             gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderBuffer);
296             gl.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, powW, powH);
297             if(depthStencilFormat == gl.DEPTH_STENCIL)
298                 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
299             else if(depthStencilFormat == gl.STENCIL_INDEX || depthStencilFormat == gl.STENCIL_INDEX8)
300                 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
301             else if(depthStencilFormat == gl.DEPTH_COMPONENT16)
302                 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer);
303         }
304 
305         // check if it worked (probably worth doing :) )
306         if(gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE)
307             cc.log("Could not attach texture to the framebuffer");
308 
309         locTexture.setAliasTexParameters();
310 
311         this.sprite = cc.Sprite.create(locTexture);
312         var locSprite = this.sprite;
313         locSprite.scaleY = -1;
314         locSprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
315 
316         gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO);
317         gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
318 
319         // Disabled by default.
320         this.autoDraw = false;
321 
322         // add sprite for backward compatibility
323         this.addChild(locSprite);
324         return true;
325     },
326 
327     /**
328      * starts grabbing
329      * @function
330      */
331     begin: null,
332 
333     _beginForCanvas: function () {
334         cc._renderContext = this._cacheContext;
335         cc.view._setScaleXYForRenderTexture();
336 
337         /*// Save the current matrix
338          cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
339          cc.kmGLPushMatrix();
340          cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
341          cc.kmGLPushMatrix();*/
342     },
343 
344     _beginForWebGL: function () {
345         // Save the current matrix
346         cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
347         cc.kmGLPushMatrix();
348         cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
349         cc.kmGLPushMatrix();
350 
351         var director = cc.director;
352         director.setProjection(director.getProjection());
353 
354         var texSize = this._texture.getContentSizeInPixels();
355 
356         // Calculate the adjustment ratios based on the old and new projections
357         var size = cc.director.getWinSizeInPixels();
358         var widthRatio = size.width / texSize.width;
359         var heightRatio = size.height / texSize.height;
360 
361         var gl = cc._renderContext;
362 
363         // Adjust the orthographic projection and viewport
364         gl.viewport(0, 0, texSize.width, texSize.height);
365 
366         var orthoMatrix = new cc.kmMat4();
367         cc.kmMat4OrthographicProjection(orthoMatrix, -1.0 / widthRatio, 1.0 / widthRatio,
368             -1.0 / heightRatio, 1.0 / heightRatio, -1, 1);
369         cc.kmGLMultMatrix(orthoMatrix);
370 
371         this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING);
372         gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO);//Will direct drawing to the frame buffer created above
373 
374         /*  Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture.
375          *   The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture.
376          *   Create a temporary texture to overcome this. At the end of CCRenderTexture::begin(), switch the attached texture to the second one, call glClear,
377          *   and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers.
378          */
379         if (cc.configuration.checkForGLExtension("GL_QCOM")) {
380             // -- bind a temporary texture so we can clear the render buffer without losing our texture
381             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._textureCopy._webTextureObj, 0);
382             //cc.checkGLErrorDebug();
383             gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
384             gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._texture._webTextureObj, 0);
385         }
386     },
387 
388     /**
389      * starts rendering to the texture while clearing the texture first.<br/>
390      * This is more efficient then calling -clear first and then -begin
391      * @param {Number} r red 0-255
392      * @param {Number} g green 0-255
393      * @param {Number} b blue 0-255
394      * @param {Number} a alpha 0-255 0 is transparent
395      * @param {Number} [depthValue=]
396      * @param {Number} [stencilValue=]
397      */
398     beginWithClear:function (r, g, b, a, depthValue, stencilValue) {
399         var gl = cc._renderContext;
400         depthValue = depthValue || gl.COLOR_BUFFER_BIT;
401         stencilValue = stencilValue || (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
402 
403         this._beginWithClear(r , g , b , a , depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT));
404     },
405 
406     _beginWithClear: null,
407 
408     _beginWithClearForCanvas: function (r, g, b, a, depthValue, stencilValue, flags) {
409         this.begin();
410 
411         r = r || 0;
412         g = g || 0;
413         b = b || 0;
414         a = isNaN(a) ? 1 : a;
415 
416         //var context = cc._renderContext;
417         var context = this._cacheContext;
418         var locCanvas = this._cacheCanvas;
419         context.save();
420         context.fillStyle = "rgba(" + (0 | r) + "," + (0 | g) + "," + (0 | b) + "," + a / 255 + ")";
421         context.clearRect(0, 0, locCanvas.width, -locCanvas.height);
422         context.fillRect(0, 0, locCanvas.width, -locCanvas.height);
423         context.restore();
424     },
425 
426     _beginWithClearForWebGL: function (r, g, b, a, depthValue, stencilValue, flags) {
427         r = r / 255;
428         g = g / 255;
429         b = b / 255;
430         a = a / 255;
431 
432         this.begin();
433 
434         var gl = cc._renderContext;
435 
436         // save clear color
437         var clearColor = [0.0, 0.0, 0.0, 0.0];
438         var depthClearValue = 0.0;
439         var stencilClearValue = 0;
440 
441         if (flags & gl.COLOR_BUFFER_BIT) {
442             clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
443             gl.clearColor(r, g, b, a);
444         }
445 
446         if (flags & gl.DEPTH_BUFFER_BIT) {
447             depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
448             gl.clearDepth(depthValue);
449         }
450 
451         if (flags & gl.STENCIL_BUFFER_BIT) {
452             stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
453             gl.clearStencil(stencilValue);
454         }
455 
456         gl.clear(flags);
457 
458         // restore
459         if (flags & gl.COLOR_BUFFER_BIT)
460             gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
461 
462         if (flags & gl.DEPTH_BUFFER_BIT)
463             gl.clearDepth(depthClearValue);
464 
465         if (flags & gl.STENCIL_BUFFER_BIT)
466             gl.clearStencil(stencilClearValue);
467     },
468 
469     /**
470      * ends grabbing
471      * @function
472      */
473     end: null,
474 
475     _endForCanvas: function () {
476         cc._renderContext = cc._mainRenderContextBackup;
477         cc.view._resetScale();
478 
479         //TODO
480         /*//restore viewport
481          director.setViewport();
482          cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
483          cc.kmGLPopMatrix();
484          cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
485          cc.kmGLPopMatrix();*/
486     },
487 
488     _endForWebGL: function () {
489         var gl = cc._renderContext;
490         var director = cc.director;
491         gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO);
492 
493         //restore viewport
494         director.setViewport();
495         cc.kmGLMatrixMode(cc.KM_GL_PROJECTION);
496         cc.kmGLPopMatrix();
497         cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW);
498         cc.kmGLPopMatrix();
499 
500         /* var size = director.getWinSizeInPixels();
501 
502          // restore viewport
503          gl.viewport(0, 0, size.width * cc.contentScaleFactor(), size.height * cc.contentScaleFactor());
504 
505          // special viewport for 3d projection + retina display
506          if (director.getProjection() == cc.Director.PROJECTION_3D && cc.contentScaleFactor() != 1) {
507          gl.viewport((-size.width / 2), (-size.height / 2), (size.width * cc.contentScaleFactor()), (size.height * cc.contentScaleFactor()));
508          }
509 
510          director.setProjection(director.getProjection());*/
511     },
512 
513     /**
514      * clears the texture with a color
515      * @param {Number|cc.Rect} r red 0-1
516      * @param {Number} g green 0-1
517      * @param {Number} b blue 0-1
518      * @param {Number} a alpha 0-1
519      */
520     clear:function (r, g, b, a) {
521         this.beginWithClear(r, g, b, a);
522         this.end();
523     },
524 
525     /**
526      * clears the texture with rect.
527      * @function
528      * @param {number} x
529      * @param {number} y
530      * @param {number} width
531      * @param {number} height
532      */
533     clearRect:null,
534 
535     _clearRectForCanvas:function(x, y, width, height){
536         this._cacheContext.clearRect(x, y, width, -height);
537     },
538 
539     _clearRectForWebGL:function(x, y, width, height){
540         //TODO need to implement
541     },
542 
543     /**
544      * clears the texture with a specified depth value
545      * @function
546      * @param {Number} depthValue
547      */
548     clearDepth:null,
549 
550     _clearDepthForCanvas:function (depthValue) {
551         cc.log("clearDepth isn't supported on Cocos2d-Html5");
552     },
553 
554     _clearDepthForWebGL:function (depthValue) {
555         this.begin();
556 
557         var gl = cc._renderContext;
558         //! save old depth value
559         var depthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
560 
561         gl.clearDepth(depthValue);
562         gl.clear(gl.DEPTH_BUFFER_BIT);
563 
564         // restore clear color
565         gl.clearDepth(depthClearValue);
566         this.end();
567     },
568 
569     /**
570      * clears the texture with a specified stencil value
571      * @function
572      * @param {Number} stencilValue
573      */
574     clearStencil:null,
575 
576     _clearStencilForCanvas:function (stencilValue) {
577         cc.log("clearDepth isn't supported on Cocos2d-Html5");
578     },
579 
580     _clearStencilForWebGL:function (stencilValue) {
581         var gl = cc._renderContext;
582         // save old stencil value
583         var stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
584 
585         gl.clearStencil(stencilValue);
586         gl.clear(gl.STENCIL_BUFFER_BIT);
587 
588         // restore clear color
589         gl.clearStencil(stencilClearValue);
590     },
591 
592     /**
593      * Recursive method that visit its children and draw them
594      * @function
595      * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx
596      */
597     visit:null,
598 
599     _visitForCanvas:function (ctx) {
600         // override visit.
601         // Don't call visit on its children
602         if (!this._visible)
603             return;
604 
605         ctx = ctx || cc._renderContext;
606         ctx.save();
607 
608         this.draw(ctx);                                                   // update children of RenderTexture before
609         this.transform(ctx);
610         this.sprite.visit();                                             // draw the RenderTexture
611 
612         ctx.restore();
613 
614         this.arrivalOrder = 0;
615     },
616 
617     _visitForWebGL:function (ctx) {
618         // override visit.
619         // Don't call visit on its children
620         if (!this._visible)
621             return;
622 
623         cc.kmGLPushMatrix();
624 
625         var locGrid = this.grid;
626         if (locGrid && locGrid.isActive()) {
627             locGrid.beforeDraw();
628             this.transformAncestors();
629         }
630 
631         this.transform(ctx);
632         this.sprite.visit();
633         this.draw(ctx);
634 
635         if (locGrid && locGrid.isActive())
636             locGrid.afterDraw(this);
637 
638         cc.kmGLPopMatrix();
639 
640         this.arrivalOrder = 0;
641     },
642 
643     /**
644      * Render function using the canvas 2d context or WebGL context, internal usage only, please do not call this function
645      * @function
646      * @param {CanvasRenderingContext2D | WebGLRenderingContext} ctx The render context
647      */
648     draw:null,
649 
650     _drawForCanvas: function (ctx) {
651         ctx = ctx || cc._renderContext;
652         if (this.autoDraw) {
653             this.begin();
654 
655             if (this.clearFlags) {
656                 var locCanvas = this._cacheCanvas;
657                 ctx.save();
658                 ctx.fillStyle = this._clearColorStr;
659                 ctx.clearRect(0, 0, locCanvas.width, -locCanvas.height);
660                 ctx.fillRect(0, 0, locCanvas.width, -locCanvas.height);
661                 ctx.restore();
662             }
663 
664             //! make sure all children are drawn
665             this.sortAllChildren();
666             var locChildren = this._children;
667             var childrenLen = locChildren.length;
668             var selfSprite = this.sprite;
669             for (var i = 0; i < childrenLen; i++) {
670                 var getChild = locChildren[i];
671                 if (getChild != selfSprite)
672                     getChild.visit();
673             }
674 
675             this.end();
676         }
677     },
678 
679     _drawForWebGL: function (ctx) {
680         var gl = cc._renderContext;
681         if (this.autoDraw) {
682             this.begin();
683 
684             var locClearFlags = this.clearFlags;
685             if (locClearFlags) {
686                 var oldClearColor = [0.0, 0.0, 0.0, 0.0];
687                 var oldDepthClearValue = 0.0;
688                 var oldStencilClearValue = 0;
689 
690                 // backup and set
691                 if (locClearFlags & gl.COLOR_BUFFER_BIT) {
692                     oldClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
693                     gl.clearColor(this._clearColor.r/255, this._clearColor.g/255, this._clearColor.b/255, this._clearColor.a/255);
694                 }
695 
696                 if (locClearFlags & gl.DEPTH_BUFFER_BIT) {
697                     oldDepthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
698                     gl.clearDepth(this.clearDepthVal);
699                 }
700 
701                 if (locClearFlags & gl.STENCIL_BUFFER_BIT) {
702                     oldStencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE);
703                     gl.clearStencil(this.clearStencilVal);
704                 }
705 
706                 // clear
707                 gl.clear(locClearFlags);
708 
709                 // restore
710                 if (locClearFlags & gl.COLOR_BUFFER_BIT)
711                     gl.clearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]);
712 
713                 if (locClearFlags & gl.DEPTH_BUFFER_BIT)
714                     gl.clearDepth(oldDepthClearValue);
715 
716                 if (locClearFlags & gl.STENCIL_BUFFER_BIT)
717                     gl.clearStencil(oldStencilClearValue);
718             }
719 
720             //! make sure all children are drawn
721             this.sortAllChildren();
722             var locChildren = this._children;
723             for (var i = 0; i < locChildren.length; i++) {
724                 var getChild = locChildren[i];
725                 if (getChild != this.sprite)
726                     getChild.visit();
727             }
728 
729             this.end();
730         }
731     },
732 
733     /**
734      * creates a new CCImage from with the texture's data. Caller is responsible for releasing it by calling delete.
735      * @return {*}
736      */
737     newCCImage:function(flipImage){
738         cc.log("saveToFile isn't supported on cocos2d-html5");
739         return null;
740     },
741 
742     _memcpy:function (destArr, destIndex, srcArr, srcIndex, size) {
743         for (var i = 0; i < size; i++) {
744             destArr[destIndex + i] = srcArr[srcIndex + i];
745         }
746     },
747 
748     /**
749      * saves the texture into a file using JPEG format. The file will be saved in the Documents folder.
750      * Returns YES if the operation is successful.
751      * (doesn't support in HTML5)
752      * @param {Number} filePath
753      * @param {Number} format
754      */
755     saveToFile:function (filePath, format) {
756         cc.log("saveToFile isn't supported on Cocos2d-Html5");
757     },
758 
759     /**
760      * Listen "come to background" message, and save render texture. It only has effect on Android.
761      * @param {cc.Class} obj
762      */
763     listenToBackground:function (obj) {
764         cc.log("listenToBackground isn't supported on Cocos2d-Html5");
765     },
766 
767     /**
768      * Listen "come to foreground" message and restore the frame buffer object. It only has effect on Android.
769      * @param {cc.Class} obj
770      */
771     listenToForeground:function (obj) {
772         cc.log("listenToForeground isn't supported on Cocos2d-Html5");
773     },
774 
775     /**
776      * Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES.
777      * @return {Number}
778      */
779     getClearFlags:function () {
780         return this.clearFlags;
781     },
782 
783     /**
784      * Set the clearFlags
785      * @param {Number} clearFlags
786      */
787     setClearFlags:function (clearFlags) {
788         this.clearFlags = clearFlags;
789     },
790 
791     /**
792      * Clear color value. Valid only when "autoDraw" is true.
793      * @function
794      * @return {cc.Color}
795      */
796     getClearColor:function () {
797         return this._clearColor;
798     },
799 
800 	/**
801 	 * Set the clear color value. Valid only when "autoDraw" is true.
802 	 * @function
803 	 * @param {cc.Color} clearColor The clear color
804 	 */
805     setClearColor:null,
806 
807     _setClearColorForCanvas:function (clearColor) {
808         var locClearColor = this._clearColor;
809         locClearColor.r = clearColor.r;
810         locClearColor.g = clearColor.g;
811         locClearColor.b = clearColor.b;
812         locClearColor.a = clearColor.a;
813 
814         this._clearColorStr = "rgba(" + (0 | clearColor.r) + "," + (0 | clearColor.g) + "," + (0 | clearColor.b) + "," + clearColor.a / 255 + ")";
815     },
816 
817     _setClearColorForWebGL:function (clearColor) {
818         var locClearColor = this._clearColor;
819         locClearColor.r = clearColor.r;
820         locClearColor.g = clearColor.g;
821         locClearColor.b = clearColor.b;
822         locClearColor.a = clearColor.a;
823     },
824 
825     /**
826      * Value for clearDepth. Valid only when autoDraw is true.
827      * @return {Number}
828      */
829     getClearDepth:function () {
830         return this.clearDepthVal;
831     },
832 
833     /**
834      * Set value for clearDepth. Valid only when autoDraw is true.
835      * @param {Number} clearDepth
836      */
837     setClearDepth:function (clearDepth) {
838         this.clearDepthVal = clearDepth;
839     },
840 
841     /**
842      * Value for clear Stencil. Valid only when autoDraw is true
843      * @return {Number}
844      */
845     getClearStencil:function () {
846         return this.clearStencilVal;
847     },
848 
849     /**
850      * Set value for clear Stencil. Valid only when autoDraw is true
851      * @return {Number}
852      */
853     setClearStencil:function (clearStencil) {
854         this.clearStencilVal = clearStencil;
855     },
856 
857     /**
858      * When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons. <br/>
859      * Will be enabled in the future.
860      * @return {Boolean}
861      */
862     isAutoDraw:function () {
863         return this.autoDraw;
864     },
865 
866     /**
867      * When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons. <br/>
868      * Will be enabled in the future.
869      * @return {Boolean}
870      */
871     setAutoDraw:function (autoDraw) {
872         this.autoDraw = autoDraw;
873     }
874 });
875 
876 var _p = cc.RenderTexture.prototype;
877 
878 if(cc._renderType == cc._RENDER_TYPE_WEBGL){
879     _p.ctor = _p._ctorForWebGL;
880     _p.cleanup = _p._cleanupForWebGL;
881     _p.initWithWidthAndHeight = _p._initWithWidthAndHeightForWebGL;
882     _p.begin = _p._beginForWebGL;
883     _p._beginWithClear = _p._beginWithClearForWebGL;
884     _p.end = _p._endForWebGL;
885     _p.clearRect = _p._clearRectForWebGL;
886     _p.clearDepth = _p._clearDepthForWebGL;
887     _p.clearStencil = _p._clearStencilForWebGL;
888     _p.visit = _p._visitForWebGL;
889     _p.draw = _p._drawForWebGL;
890     _p.setClearColor = _p._setClearColorForWebGL;
891 } else {
892     _p.ctor = _p._ctorForCanvas;
893     _p.cleanup = _p._cleanupForCanvas;
894     _p.initWithWidthAndHeight = _p._initWithWidthAndHeightForCanvas;
895     _p.begin = _p._beginForCanvas;
896     _p._beginWithClear = _p._beginWithClearForCanvas;
897     _p.end = _p._endForCanvas;
898     _p.clearRect = _p._clearRectForCanvas;
899     _p.clearDepth = _p._clearDepthForCanvas;
900     _p.clearStencil = _p._clearStencilForCanvas;
901     _p.visit = _p._visitForCanvas;
902     _p.draw = _p._drawForCanvas;
903     _p.setClearColor = _p._setClearColorForCanvas;
904 }
905 
906 // Extended
907 /** @expose */
908 _p.clearColorVal;
909 cc.defineGetterSetter(_p, "clearColorVal", _p.getClearColor, _p.setClearColor);
910 
911 
912 /**
913  * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid
914  * @deprecated since v3.0 please use new cc.RenderTexture() instead.
915  * @param {Number} width
916  * @param {Number} height
917  * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format
918  * @param {Number} depthStencilFormat
919  * @return {cc.RenderTexture}
920  * @example
921  * // Example
922  * var rt = cc.RenderTexture.create()
923  */
924 cc.RenderTexture.create = function (width, height, format, depthStencilFormat) {
925     return new cc.RenderTexture(width, height, format, depthStencilFormat);
926 };
927