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