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