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