1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 //CONSTANTS:
 28 
 29 /**
 30  * Horizontal center and vertical center.
 31  * @constant
 32  * @type Number
 33  */
 34 cc.ALIGN_CENTER = 0x33;
 35 
 36 /**
 37  * Horizontal center and vertical top.
 38  * @constant
 39  * @type Number
 40  */
 41 cc.ALIGN_TOP = 0x13;
 42 
 43 /**
 44  * Horizontal right and vertical top.
 45  * @constant
 46  * @type Number
 47  */
 48 cc.ALIGN_TOP_RIGHT = 0x12;
 49 
 50 /**
 51  * Horizontal right and vertical center.
 52  * @constant
 53  * @type Number
 54  */
 55 cc.ALIGN_RIGHT = 0x32;
 56 
 57 /**
 58  * Horizontal right and vertical bottom.
 59  * @constant
 60  * @type Number
 61  */
 62 cc.ALIGN_BOTTOM_RIGHT = 0x22;
 63 
 64 /**
 65  * Horizontal center and vertical bottom.
 66  * @constant
 67  * @type Number
 68  */
 69 cc.ALIGN_BOTTOM = 0x23;
 70 
 71 /**
 72  * Horizontal left and vertical bottom.
 73  * @constant
 74  * @type Number
 75  */
 76 cc.ALIGN_BOTTOM_LEFT = 0x21;
 77 
 78 /**
 79  * Horizontal left and vertical center.
 80  * @constant
 81  * @type Number
 82  */
 83 cc.ALIGN_LEFT = 0x31;
 84 
 85 /**
 86  * Horizontal left and vertical top.
 87  * @constant
 88  * @type Number
 89  */
 90 cc.ALIGN_TOP_LEFT = 0x11;
 91 //----------------------Possible texture pixel formats----------------------------
 92 
 93 
 94 // By default PVR images are treated as if they don't have the alpha channel premultiplied
 95 cc.PVRHaveAlphaPremultiplied_ = false;
 96 
 97 /**
 98  * <p>
 99  * This class allows to easily create OpenGL or Canvas 2D textures from images, text or raw data.                                    <br/>
100  * The created cc.Texture2D object will always have power-of-two dimensions.                                                <br/>
101  * Depending on how you create the cc.Texture2D object, the actual image area of the texture might be smaller than the texture dimensions <br/>
102  *  i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).                                           <br/>
103  * Be aware that the content of the generated textures will be upside-down! </p>
104  * @name cc.Texture2D
105  * @class
106  * @extends cc.Class
107  *
108  * @property {WebGLTexture}     name            - <@readonly> WebGLTexture Object
109  * @property {Number}           pixelFormat     - <@readonly> Pixel format of the texture
110  * @property {Number}           pixelsWidth     - <@readonly> Width in pixels
111  * @property {Number}           pixelsHeight    - <@readonly> Height in pixels
112  * @property {Number}           width           - Content width in points
113  * @property {Number}           height          - Content height in points
114  * @property {cc.GLProgram}     shaderProgram   - The shader program used by drawAtPoint and drawInRect
115  * @property {Number}           maxS            - Texture max S
116  * @property {Number}           maxT            - Texture max T
117  */
118 cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{
119     // By default PVR images are treated as if they don't have the alpha channel premultiplied
120     _pVRHaveAlphaPremultiplied:true,
121     _pixelFormat:null,
122     _pixelsWide:0,
123     _pixelsHigh:0,
124     _name:"",
125     _contentSize:null,
126     maxS:0,
127     maxT:0,
128     _hasPremultipliedAlpha:false,
129     _hasMipmaps:false,
130 
131     shaderProgram:null,
132 
133     _isLoaded:false,
134     _htmlElementObj:null,
135     _webTextureObj:null,
136 
137     url : null,
138     _loadedEventListeners:null,
139 
140     /*public:*/
141     ctor:function () {
142         this._contentSize = cc.size(0, 0);
143         this._pixelFormat = cc.Texture2D.defaultPixelFormat;
144     },
145 
146     releaseTexture:function () {
147         if (this._webTextureObj)
148             cc._renderContext.deleteTexture(this._webTextureObj);
149         cc.loader.release(this.url);
150     },
151 
152     /**
153      * pixel format of the texture
154      * @return {Number}
155      */
156     getPixelFormat:function () {
157         return this._pixelFormat;
158     },
159 
160     /**
161      * width in pixels
162      * @return {Number}
163      */
164     getPixelsWide:function () {
165         return this._pixelsWide;
166     },
167 
168     /**
169      * height in pixels
170      * @return {Number}
171      */
172     getPixelsHigh:function () {
173         return this._pixelsHigh;
174     },
175 
176     /**
177      * get WebGLTexture Object
178      * @return {WebGLTexture}
179      */
180     getName:function () {
181         return this._webTextureObj;
182     },
183 
184     /**
185      * content size
186      * @return {cc.Size}
187      */
188     getContentSize:function () {
189         return cc.size(this._contentSize.width / cc.CONTENT_SCALE_FACTOR(), this._contentSize.height / cc.CONTENT_SCALE_FACTOR());
190     },
191 
192     _getWidth:function () {
193         return this._contentSize.width / cc.CONTENT_SCALE_FACTOR();
194     },
195     _getHeight:function () {
196         return this._contentSize.height / cc.CONTENT_SCALE_FACTOR();
197     },
198 
199     getContentSizeInPixels:function () {
200         return this._contentSize;
201     },
202 
203     /** texture max S */
204     getMaxS:function () {
205         return this.maxS;
206     },
207 
208     setMaxS:function (maxS) {
209         this.maxS = maxS;
210     },
211 
212     /** texture max T */
213     getMaxT:function () {
214         return this.maxT;
215     },
216 
217     setMaxT:function (maxT) {
218         this.maxT = maxT;
219     },
220 
221     /**
222      * return shader program used by drawAtPoint and drawInRect
223      * @return {cc.GLProgram}
224      */
225     getShaderProgram:function () {
226         return this.shaderProgram;
227     },
228 
229     /**
230      * set shader program used by drawAtPoint and drawInRect
231      * @param {cc.GLProgram} shaderProgram
232      */
233     setShaderProgram:function (shaderProgram) {
234         this.shaderProgram = shaderProgram;
235     },
236 
237     /**
238      * whether or not the texture has their Alpha premultiplied
239      * @return {Boolean}
240      */
241     hasPremultipliedAlpha:function () {
242         return this._hasPremultipliedAlpha;
243     },
244 
245     hasMipmaps:function () {
246         return this._hasMipmaps;
247     },
248 
249     description:function () {
250         return "<cc.Texture2D | Name = " + this._name + " | Dimensions = " + this._pixelsWide + " x " + this._pixelsHigh
251             + " | Coordinates = (" + this.maxS + ", " + this.maxT + ")>";
252     },
253 
254     /**
255      * These functions are needed to create mutable textures
256      * @param {Array} data
257      */
258     releaseData:function (data) {
259         data = null;
260     },
261 
262     keepData:function (data, length) {
263         //The texture data mustn't be saved becuase it isn't a mutable texture.
264         return data;
265     },
266 
267     /**
268      * Intializes with a texture2d with data
269      * @param {Array} data
270      * @param {Number} pixelFormat
271      * @param {Number} pixelsWide
272      * @param {Number} pixelsHigh
273      * @param {cc.Size} contentSize
274      * @return {Boolean}
275      */
276     initWithData:function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
277         var self = this, tex2d = cc.Texture2D;
278         var gl = cc._renderContext;
279         var format = gl.RGBA, type = gl.UNSIGNED_BYTE;
280 
281         var bitsPerPixel = cc.Texture2D._B[pixelFormat];
282 
283         var bytesPerRow = pixelsWide * bitsPerPixel / 8;
284         if (bytesPerRow % 8 === 0) {
285             gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8);
286         } else if (bytesPerRow % 4 === 0) {
287             gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
288         } else if (bytesPerRow % 2 === 0) {
289             gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2);
290         } else {
291             gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
292         }
293 
294         self._webTextureObj = gl.createTexture();
295         cc.glBindTexture2D(self);
296 
297         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
298         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
299         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
300         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
301 
302         // Specify OpenGL texture image
303         switch (pixelFormat) {
304 	        case tex2d.PIXEL_FORMAT_RGBA8888:
305 		        format = gl.RGBA;
306 		        break;
307             case tex2d.PIXEL_FORMAT_RGB888:
308                 format = gl.RGB;
309                 break;
310             case tex2d.PIXEL_FORMAT_RGBA4444:
311                 type = gl.UNSIGNED_SHORT_4_4_4_4;
312                 break;
313             case tex2d.PIXEL_FORMAT_RGB5A1:
314                 type = gl.UNSIGNED_SHORT_5_5_5_1;
315                 break;
316             case tex2d.PIXEL_FORMAT_RGB565:
317                 type = gl.UNSIGNED_SHORT_5_6_5;
318                 break;
319             case tex2d.PIXEL_FORMAT_AI88:
320                 format = gl.LUMINANCE_ALPHA;
321                 break;
322             case tex2d.PIXEL_FORMAT_A8:
323                 format = gl.ALPHA;
324                 break;
325             case tex2d.PIXEL_FORMAT_I8:
326                 format = gl.LUMINANCE;
327                 break;
328             default:
329                 throw "NSInternalInconsistencyException";
330         }
331         gl.texImage2D(gl.TEXTURE_2D, 0, format, pixelsWide, pixelsHigh, 0, format, type, data);
332 
333 
334         self._contentSize.width = contentSize.width;
335         self._contentSize.height = contentSize.height;
336         self._pixelsWide = pixelsWide;
337         self._pixelsHigh = pixelsHigh;
338         self._pixelFormat = pixelFormat;
339         self.maxS = contentSize.width / pixelsWide;
340         self.maxT = contentSize.height / pixelsHigh;
341 
342         self._hasPremultipliedAlpha = false;
343         self._hasMipmaps = false;
344         self.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
345 
346         self._isLoaded = true;
347 
348         return true;
349     },
350 
351     /**
352      Drawing extensions to make it easy to draw basic quads using a CCTexture2D object.
353      These functions require gl.TEXTURE_2D and both gl.VERTEX_ARRAY and gl.TEXTURE_COORD_ARRAY client states to be enabled.
354      */
355 
356     /**
357      * draws a texture at a given point
358      * @param {cc.Point} point
359      */
360     drawAtPoint:function (point) {
361         var self = this;
362         var coordinates = [
363             0.0, self.maxT,
364             self.maxS, self.maxT,
365             0.0, 0.0,
366             self.maxS, 0.0 ];
367 
368         var width = self._pixelsWide * self.maxS,
369             height = self._pixelsHigh * self.maxT;
370 
371         var vertices = [
372             point.x, point.y, 0.0,
373             width + point.x, point.y, 0.0,
374             point.x, height + point.y, 0.0,
375             width + point.x, height + point.y, 0.0 ];
376 
377         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS);
378         self._shaderProgram.use();
379         self._shaderProgram.setUniformsForBuiltins();
380 
381         cc.glBindTexture2D(self);
382 
383         var gl = cc._renderContext;
384         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
385         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
386 
387         gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
388     },
389 
390     /**
391      * draws a texture inside a rect
392      * @param {cc.Rect} rect
393      */
394     drawInRect:function (rect) {
395         var self = this;
396         var coordinates = [
397             0.0, self.maxT,
398             self.maxS, self.maxT,
399             0.0, 0.0,
400             self.maxS, 0.0];
401 
402         var vertices = [    rect.x, rect.y, /*0.0,*/
403             rect.x + rect.width, rect.y, /*0.0,*/
404             rect.x, rect.y + rect.height, /*0.0,*/
405             rect.x + rect.width, rect.y + rect.height        /*0.0*/ ];
406 
407         cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEX_COORDS);
408         self._shaderProgram.use();
409         self._shaderProgram.setUniformsForBuiltins();
410 
411         cc.glBindTexture2D(self);
412 
413         var gl = cc._renderContext;
414         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices);
415         gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 0, coordinates);
416 
417         gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
418     },
419 
420     /**
421      Extensions to make it easy to create a CCTexture2D object from an image file.
422      Note that RGBA type textures will have their alpha premultiplied - use the blending mode (gl.ONE, gl.ONE_MINUS_SRC_ALPHA).
423      */
424 
425     /**
426      * Initializes a texture from a UIImage object
427      * @param uiImage
428      * @return {Boolean}
429      */
430     initWithImage:function (uiImage) {
431         if (uiImage == null) {
432             cc.log("cocos2d: cc.Texture2D. Can't create Texture. UIImage is nil");
433             return false;
434         }
435 
436         var imageWidth = uiImage.getWidth();
437         var imageHeight = uiImage.getHeight();
438 
439         var maxTextureSize = cc.configuration.getMaxTextureSize();
440         if (imageWidth > maxTextureSize || imageHeight > maxTextureSize) {
441             cc.log("cocos2d: WARNING: Image (" + imageWidth + " x " + imageHeight + ") is bigger than the supported " + maxTextureSize + " x " + maxTextureSize);
442             return false;
443         }
444         this._isLoaded = true;
445 
446         // always load premultiplied images
447         return this._initPremultipliedATextureWithImage(uiImage, imageWidth, imageHeight);
448     },
449 
450     initWithElement:function (element) {
451         if (!element)
452             return;
453         this._webTextureObj = cc._renderContext.createTexture();
454         this._htmlElementObj = element;
455     },
456 
457     /**
458      * HTMLElement Object getter
459      * @return {HTMLElement}
460      */
461     getHtmlElementObj:function(){
462         return this._htmlElementObj;
463     },
464 
465     isLoaded:function () {
466         return this._isLoaded;
467     },
468 
469     handleLoadedTexture:function () {
470         var self = this;
471 	    // Not sure about this ! Some texture need to be updated even after loaded
472         if(!cc._rendererInitialized) return;
473         if(!self._htmlElementObj){
474             var img = cc.loader.getRes(self.url);
475             if(!img) return;
476             self.initWithElement(img);
477         }
478         self._isLoaded = true;
479         //upload image to buffer
480         var gl = cc._renderContext;
481 
482         cc.glBindTexture2D(self);
483 
484         gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4);
485 
486         // Specify OpenGL texture image
487         gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self._htmlElementObj);
488 
489         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
490         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
491         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
492         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
493 
494         self.shaderProgram = cc.shaderCache.programForKey(cc.SHADER_POSITION_TEXTURE);
495         cc.glBindTexture2D(null);
496 
497         var pixelsWide = self._htmlElementObj.width;
498         var pixelsHigh = self._htmlElementObj.height;
499 
500         self._pixelsWide = self._contentSize.width = pixelsWide;
501         self._pixelsHigh = self._contentSize.height = pixelsHigh;
502         self._pixelFormat = cc.Texture2D.PIXEL_FORMAT_RGBA8888;
503         self.maxS = 1;
504         self.maxT = 1;
505 
506         self._hasPremultipliedAlpha = false;
507         self._hasMipmaps = false;
508 
509         this._callLoadedEventCallbacks();
510     },
511 
512     /**
513      Extensions to make it easy to create a cc.Texture2D object from a string of text.
514      Note that the generated textures are of type A8 - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
515      */
516     /**
517      * Initializes a texture from a string with dimensions, alignment, font name and font size (note: initWithString does not support on HTML5)
518      * @param {String} text
519      * @param {String | cc.FontDefinition} fontName or fontDefinition
520      * @param {Number} fontSize
521      * @param {cc.Size} dimensions
522      * @param {Number} hAlignment
523      * @param {Number} vAlignment
524      * @return {Boolean}
525      */
526     initWithString:function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
527         cc.log("initWithString isn't supported on cocos2d-html5");
528         return null;
529     },
530 
531     /**
532      * Initializes a texture from a ETC file  (note: initWithETCFile does not support on HTML5)
533      * @note Compatible to Cocos2d-x
534      * @param {String} file
535      * @return {Boolean}
536      */
537     initWithETCFile:function (file) {
538         cc.log("initWithETCFile does not support on HTML5");
539         return false;
540     },
541 
542     /**
543      * Initializes a texture from a PVR file
544      * @param {String} file
545      * @return {Boolean}
546      */
547     initWithPVRFile:function (file) {
548         cc.log("initWithPVRFile does not support on HTML5");
549         return false;
550     },
551 
552     /**
553      Extensions to make it easy to create a cc.Texture2D object from a PVRTC file
554      Note that the generated textures don't have their alpha premultiplied - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA).
555      */
556     /**
557      * Initializes a texture from a PVRTC buffer
558      * @note compatible to cocos2d-iphone interface.
559      * @param {Array} data
560      * @param {Number} level
561      * @param {Number} bpp
562      * @param {Boolean} hasAlpha
563      * @param {Number} length
564      * @param {Number} pixelFormat
565      * @return {Boolean}
566      */
567     initWithPVRTCData:function (data, level, bpp, hasAlpha, length, pixelFormat) {
568         cc.log("initWithPVRTCData does not support on HTML5");
569         return false;
570     },
571 
572     /**
573      * sets the min filter, mag filter, wrap s and wrap t texture parameters. <br/>
574      * If the texture size is NPOT (non power of 2), then in can only use gl.CLAMP_TO_EDGE in gl.TEXTURE_WRAP_{S,T}.
575      * @param texParams
576      */
577     setTexParameters:function (texParams) {
578         var gl = cc._renderContext;
579 
580         cc.assert((this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh)) ||
581             (texParams.wrapS == gl.CLAMP_TO_EDGE && texParams.wrapT == gl.CLAMP_TO_EDGE),
582             "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures");
583 
584         cc.glBindTexture2D(this);
585         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter);
586         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter);
587         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS);
588         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT);
589 
590         //TODO
591         //VolatileTexture::setTexParameters(this, texParams);
592     },
593 
594     /**
595      * sets antialias texture parameters:              <br/>
596      *  - GL_TEXTURE_MIN_FILTER = GL_NEAREST           <br/>
597      *  - GL_TEXTURE_MAG_FILTER = GL_NEAREST
598      */
599     setAntiAliasTexParameters:function () {
600         var gl = cc._renderContext;
601 
602         cc.glBindTexture2D(this);
603         if (!this._hasMipmaps)
604             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
605         else
606             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
607         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
608         //TODO
609         /*#if CC_ENABLE_CACHE_TEXTURE_DATA
610          ccTexParams texParams = {m_bHasMipmaps?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR,GL_LINEAR,GL_NONE,GL_NONE};
611          VolatileTexture::setTexParameters(this, &texParams);
612          #endif*/
613     },
614 
615     /**
616      *  sets alias texture parameters:
617      *   GL_TEXTURE_MIN_FILTER = GL_NEAREST
618      *   GL_TEXTURE_MAG_FILTER = GL_NEAREST
619      */
620     setAliasTexParameters:function () {
621         var gl = cc._renderContext;
622 
623         cc.glBindTexture2D(this);
624         if (!this._hasMipmaps)
625             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
626         else
627             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
628         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
629 
630         //TODO
631         /*#if CC_ENABLE_CACHE_TEXTURE_DATA
632          ccTexParams texParams = {m_bHasMipmaps?GL_NEAREST_MIPMAP_NEAREST:GL_NEAREST,GL_NEAREST,GL_NONE,GL_NONE};
633          VolatileTexture::setTexParameters(this, &texParams);
634          #endif*/
635     },
636 
637     /**
638      *  Generates mipmap images for the texture.<br/>
639      *  It only works if the texture size is POT (power of 2).
640      */
641     generateMipmap:function () {
642         cc.assert(this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh), "Mimpap texture only works in POT textures");
643 
644         cc.glBindTexture2D(this);
645         cc._renderContext.generateMipmap(cc._renderContext.TEXTURE_2D);
646         this._hasMipmaps = true;
647     },
648 
649     /**
650      * returns the pixel format.
651      * @return {String}
652      */
653     stringForFormat:function () {
654         return cc.Texture2D._M[this._pixelFormat];
655     },
656 
657     /**
658      * returns the bits-per-pixel of the in-memory OpenGL texture
659      * @return {Number}
660      */
661     bitsPerPixelForFormat:function (format) {//TODO I want to delete the format argument, use this._pixelFormat
662         format = format || this._pixelFormat;
663         var value = cc.Texture2D._B[format];
664         if(value != null) return value;
665         cc.log("bitsPerPixelForFormat: " + format + ", cannot give useful result, it's a illegal pixel format");
666         return -1;
667     },
668 
669     _initPremultipliedATextureWithImage:function (uiImage, width, height) {
670         var tex2d = cc.Texture2D;
671         var tempData = uiImage.getData();
672         var inPixel32 = null;
673         var inPixel8 = null;
674         var outPixel16 = null;
675         var hasAlpha = uiImage.hasAlpha();
676         var imageSize = cc.size(uiImage.getWidth(), uiImage.getHeight());
677         var pixelFormat = tex2d.defaultPixelFormat;
678         var bpp = uiImage.getBitsPerComponent();
679         var i;
680 
681         // compute pixel format
682         if (!hasAlpha) {
683             if (bpp >= 8) {
684                 pixelFormat = tex2d.PIXEL_FORMAT_RGB888;
685             } else {
686                 cc.log("cocos2d: cc.Texture2D: Using RGB565 texture since image has no alpha");
687                 pixelFormat = tex2d.PIXEL_FORMAT_RGB565;
688             }
689         }
690 
691         // Repack the pixel data into the right format
692         var length = width * height;
693 
694         if (pixelFormat == tex2d.PIXEL_FORMAT_RGB565) {
695             if (hasAlpha) {
696                 // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
697                 tempData = new Uint16Array(width * height);
698                 inPixel32 = uiImage.getData();
699 
700                 for (i = 0; i < length; ++i) {
701                     tempData[i] =
702                         ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) | // R
703                             ((((inPixel32[i] >> 8) & 0xFF) >> 2) << 5) | // G
704                             ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 0);    // B
705                 }
706             } else {
707                 // Convert "RRRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB"
708                 tempData = new Uint16Array(width * height);
709                 inPixel8 = uiImage.getData();
710 
711                 for (i = 0; i < length; ++i) {
712                     tempData[i] =
713                         (((inPixel8[i] & 0xFF) >> 3) << 11) | // R
714                             (((inPixel8[i] & 0xFF) >> 2) << 5) | // G
715                             (((inPixel8[i] & 0xFF) >> 3) << 0);    // B
716                 }
717             }
718         } else if (pixelFormat == tex2d.PIXEL_FORMAT_RGBA4444) {
719             // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA"
720             tempData = new Uint16Array(width * height);
721             inPixel32 = uiImage.getData();
722 
723             for (i = 0; i < length; ++i) {
724                 tempData[i] =
725                     ((((inPixel32[i] >> 0) & 0xFF) >> 4) << 12) | // R
726                         ((((inPixel32[i] >> 8) & 0xFF) >> 4) << 8) | // G
727                         ((((inPixel32[i] >> 16) & 0xFF) >> 4) << 4) | // B
728                         ((((inPixel32[i] >> 24) & 0xFF) >> 4) << 0);  // A
729             }
730         } else if (pixelFormat == tex2d.PIXEL_FORMAT_RGB5A1) {
731             // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA"
732             tempData = new Uint16Array(width * height);
733             inPixel32 = uiImage.getData();
734 
735             for (i = 0; i < length; ++i) {
736                 tempData[i] =
737                     ((((inPixel32[i] >> 0) & 0xFF) >> 3) << 11) | // R
738                         ((((inPixel32[i] >> 8) & 0xFF) >> 3) << 6) | // G
739                         ((((inPixel32[i] >> 16) & 0xFF) >> 3) << 1) | // B
740                         ((((inPixel32[i] >> 24) & 0xFF) >> 7) << 0);  // A
741             }
742         } else if (pixelFormat == tex2d.PIXEL_FORMAT_A8) {
743             // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "AAAAAAAA"
744             tempData = new Uint8Array(width * height);
745             inPixel32 = uiImage.getData();
746 
747             for (i = 0; i < length; ++i) {
748                 tempData[i] = (inPixel32 >> 24) & 0xFF;  // A
749             }
750         }
751 
752         if (hasAlpha && pixelFormat == tex2d.PIXEL_FORMAT_RGB888) {
753             // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBBB"
754             inPixel32 = uiImage.getData();
755             tempData = new Uint8Array(width * height * 3);
756 
757             for (i = 0; i < length; ++i) {
758                 tempData[i * 3] = (inPixel32 >> 0) & 0xFF; // R
759                 tempData[i * 3 + 1] = (inPixel32 >> 8) & 0xFF; // G
760                 tempData[i * 3 + 2] = (inPixel32 >> 16) & 0xFF; // B
761             }
762         }
763 
764         this.initWithData(tempData, pixelFormat, width, height, imageSize);
765 
766         if (tempData != uiImage.getData())
767             tempData = null;
768 
769         this._hasPremultipliedAlpha = uiImage.isPremultipliedAlpha();
770         return true;
771     },
772 
773     addLoadedEventListener: function (callback, target) {
774         if(!this._loadedEventListeners)
775             this._loadedEventListeners = [];
776         this._loadedEventListeners.push({eventCallback: callback, eventTarget: target});
777     },
778 
779     removeLoadedEventListener:function(target){
780         if(!this._loadedEventListeners)
781             return;
782         var locListeners = this._loadedEventListeners;
783         for(var i = 0;  i < locListeners.length; i++){
784             var selCallback = locListeners[i];
785             if(selCallback.eventTarget == target){
786                 locListeners.splice(i, 1);
787             }
788         }
789     },
790 
791     _callLoadedEventCallbacks: function () {
792         if(!this._loadedEventListeners)
793             return;
794         var locListeners = this._loadedEventListeners;
795         for (var i = 0, len = locListeners.length; i < len; i++) {
796             var selCallback = locListeners[i];
797             selCallback.eventCallback.call(selCallback.eventTarget, this);
798         }
799         locListeners.length = 0;
800     }
801 });
802 
803 cc.Texture2DCanvas = cc.Class.extend({
804     _contentSize:null,
805     _isLoaded:false,
806     _htmlElementObj:null,
807     _loadedEventListeners:null,
808 
809     url : null,
810 
811     ctor:function () {
812         this._contentSize = cc.size(0,0);
813         this._isLoaded = false;
814         this._htmlElementObj = null;
815     },
816 
817     getPixelsWide:function () {
818         return this._contentSize.width;
819     },
820 
821     getPixelsHigh:function () {
822         return this._contentSize.height;
823     },
824 
825     getContentSize:function () {
826         var locScaleFactor = cc.CONTENT_SCALE_FACTOR();
827         return cc.size(this._contentSize.width / locScaleFactor, this._contentSize.height / locScaleFactor);
828     },
829 
830     _getWidth:function () {
831         return this._contentSize.width / cc.CONTENT_SCALE_FACTOR();
832     },
833     _getHeight:function () {
834         return this._contentSize.height / cc.CONTENT_SCALE_FACTOR();
835     },
836 
837     getContentSizeInPixels:function () {
838         return this._contentSize;
839     },
840 
841     initWithElement:function (element) {
842         if (!element)
843             return;
844         this._htmlElementObj = element;
845     },
846 
847     /**
848      * HTMLElement Object getter
849      * @return {HTMLElement}
850      */
851     getHtmlElementObj:function(){
852         return this._htmlElementObj;
853     },
854 
855     isLoaded:function () {
856         return this._isLoaded;
857     },
858 
859     handleLoadedTexture:function () {
860         var self = this
861         if(self._isLoaded) return;
862         if(!self._htmlElementObj){
863             var img = cc.loader.getRes(self.url);
864             if(!img) return;
865             self.initWithElement(img);
866         }
867 
868         self._isLoaded = true;
869         var locElement =  self._htmlElementObj;
870         self._contentSize.width = locElement.width;
871         self._contentSize.height = locElement.height;
872 
873         self._callLoadedEventCallbacks();
874     },
875 
876     description:function () {
877         return "<cc.Texture2D | width = " + this._contentSize.width + " height " + this._contentSize.height+">";
878     },
879 
880     initWithData:function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) {
881         //support only in WebGl rendering mode
882         return false;
883     },
884 
885     initWithImage:function (uiImage) {
886         //support only in WebGl rendering mode
887         return false;
888     },
889 
890     initWithString:function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) {
891         //support only in WebGl rendering mode
892         return false;
893     },
894 
895     releaseTexture:function () {
896         //support only in WebGl rendering mode
897     },
898 
899     getName:function () {
900         //support only in WebGl rendering mode
901         return null;
902     },
903 
904     getMaxS:function () {
905         //support only in WebGl rendering mode
906         return 1;
907     },
908 
909     setMaxS:function (maxS) {
910         //support only in WebGl rendering mode
911     },
912 
913     getMaxT:function () {
914         return 1;
915     },
916 
917     setMaxT:function (maxT) {
918         //support only in WebGl rendering mode
919     },
920 
921     getPixelFormat:function () {
922         //support only in WebGl rendering mode
923         return null;
924     },
925 
926     getShaderProgram:function () {
927         //support only in WebGl rendering mode
928         return null;
929     },
930 
931     setShaderProgram:function (shaderProgram) {
932         //support only in WebGl rendering mode
933     },
934 
935     hasPremultipliedAlpha:function () {
936         //support only in WebGl rendering mode
937         return false;
938     },
939 
940     hasMipmaps:function () {
941         //support only in WebGl rendering mode
942         return false;
943     },
944 
945     releaseData:function (data) {
946         //support only in WebGl rendering mode
947         data = null;
948     },
949 
950     keepData:function (data, length) {
951         //support only in WebGl rendering mode
952         return data;
953     },
954 
955     drawAtPoint:function (point) {
956         //support only in WebGl rendering mode
957     },
958 
959     drawInRect:function (rect) {
960         //support only in WebGl rendering mode
961     },
962 
963     initWithETCFile:function (file) {
964         cc.log("initWithETCFile does not support on HTML5");
965         return false;
966     },
967 
968     initWithPVRFile:function (file) {
969         cc.log("initWithPVRFile does not support on HTML5");
970         return false;
971     },
972 
973     initWithPVRTCData:function (data, level, bpp, hasAlpha, length, pixelFormat) {
974         cc.log("initWithPVRTCData does not support on HTML5");
975         return false;
976     },
977 
978     setTexParameters:function (texParams) {
979         //support only in WebGl rendering mode
980     },
981 
982     setAntiAliasTexParameters:function () {
983         //support only in WebGl rendering mode
984     },
985 
986     setAliasTexParameters:function () {
987         //support only in WebGl rendering mode
988     },
989 
990     generateMipmap:function () {
991         //support only in WebGl rendering mode
992     },
993 
994     stringForFormat:function () {
995         //support only in WebGl rendering mode
996         return "";
997     },
998 
999     bitsPerPixelForFormat:function (format) {
1000         //support only in WebGl rendering mode
1001         return -1;
1002     },
1003 
1004     addLoadedEventListener:function(callback, target){
1005         if(!this._loadedEventListeners)
1006             this._loadedEventListeners = [];
1007         this._loadedEventListeners.push({eventCallback:callback, eventTarget:target});
1008     },
1009 
1010     removeLoadedEventListener:function(target){
1011         if(!this._loadedEventListeners)
1012             return;
1013         var locListeners = this._loadedEventListeners;
1014         for(var i = 0;  i < locListeners.length; i++){
1015             var selCallback = locListeners[i];
1016             if(selCallback.eventTarget == target){
1017                 locListeners.splice(i, 1);
1018             }
1019         }
1020     },
1021 
1022     _callLoadedEventCallbacks:function(){
1023         if(!this._loadedEventListeners)
1024             return;
1025         var locListeners = this._loadedEventListeners;
1026         for(var i = 0, len = locListeners.length;  i < len; i++){
1027             var selCallback = locListeners[i];
1028             selCallback.eventCallback.call(selCallback.eventTarget, this);
1029         }
1030         locListeners.length = 0;
1031     }
1032 });
1033 
1034 cc.Texture2D = cc._renderType === cc._RENDER_TYPE_WEBGL ? cc.Texture2DWebGL : cc.Texture2DCanvas;
1035 
1036 /**
1037  * <p>
1038  *    treats (or not) PVR files as if they have alpha premultiplied.                                                <br/>
1039  *    Since it is impossible to know at runtime if the PVR images have the alpha channel premultiplied, it is       <br/>
1040  *    possible load them as if they have (or not) the alpha channel premultiplied.                                  <br/>
1041  *                                                                                                                  <br/>
1042  *    By default it is disabled.                                                                                    <br/>
1043  * </p>
1044  * @param haveAlphaPremultiplied
1045  * @constructor
1046  */
1047 cc.Texture2D.PVRImagesHavePremultipliedAlpha = function (haveAlphaPremultiplied) {
1048     cc.PVRHaveAlphaPremultiplied_ = haveAlphaPremultiplied;
1049 };
1050 
1051 window._c = cc.Texture2D;
1052 
1053 /**
1054  * 32-bit texture: RGBA8888
1055  * @memberOf cc.Texture2D
1056  * @name PIXEL_FORMAT_RGBA8888
1057  * @static
1058  * @constant
1059  * @type {Number}
1060  */
1061 _c.PIXEL_FORMAT_RGBA8888 = 0;
1062 
1063 /**
1064  * 24-bit texture: RGBA888
1065  * @memberOf cc.Texture2D
1066  * @name PIXEL_FORMAT_RGB888
1067  * @static
1068  * @constant
1069  * @type {Number}
1070  */
1071 _c.PIXEL_FORMAT_RGB888 = 1;
1072 
1073 /**
1074  * 16-bit texture without Alpha channel
1075  * @memberOf cc.Texture2D
1076  * @name PIXEL_FORMAT_RGB565
1077  * @static
1078  * @constant
1079  * @type {Number}
1080  */
1081 _c.PIXEL_FORMAT_RGB565 = 2;
1082 
1083 /**
1084  * 8-bit textures used as masks
1085  * @memberOf cc.Texture2D
1086  * @name PIXEL_FORMAT_A8
1087  * @static
1088  * @constant
1089  * @type {Number}
1090  */
1091 _c.PIXEL_FORMAT_A8 = 3;
1092 
1093 /**
1094  * 8-bit intensity texture
1095  * @memberOf cc.Texture2D
1096  * @name PIXEL_FORMAT_I8
1097  * @static
1098  * @constant
1099  * @type {Number}
1100  */
1101 _c.PIXEL_FORMAT_I8 = 4;
1102 
1103 /**
1104  * 16-bit textures used as masks
1105  * @memberOf cc.Texture2D
1106  * @name PIXEL_FORMAT_AI88
1107  * @static
1108  * @constant
1109  * @type {Number}
1110  */
1111 _c.PIXEL_FORMAT_AI88 = 5;
1112 
1113 /**
1114  * 16-bit textures: RGBA4444
1115  * @memberOf cc.Texture2D
1116  * @name PIXEL_FORMAT_RGBA4444
1117  * @static
1118  * @constant
1119  * @type {Number}
1120  */
1121 _c.PIXEL_FORMAT_RGBA4444 = 6;
1122 
1123 /**
1124  * 16-bit textures: RGB5A1
1125  * @memberOf cc.Texture2D
1126  * @name PIXEL_FORMAT_RGB5A1
1127  * @static
1128  * @constant
1129  * @type {Number}
1130  */
1131 _c.PIXEL_FORMAT_RGB5A1 = 7;
1132 
1133 /**
1134  * 4-bit PVRTC-compressed texture: PVRTC4
1135  * @memberOf cc.Texture2D
1136  * @name PIXEL_FORMAT_PVRTC4
1137  * @static
1138  * @constant
1139  * @type {Number}
1140  */
1141 _c.PIXEL_FORMAT_PVRTC4 = 8;
1142 
1143 /**
1144  * 2-bit PVRTC-compressed texture: PVRTC2
1145  * @memberOf cc.Texture2D
1146  * @name PIXEL_FORMAT_PVRTC2
1147  * @static
1148  * @constant
1149  * @type {Number}
1150  */
1151 _c.PIXEL_FORMAT_PVRTC2 = 9;
1152 
1153 /**
1154  * Default texture format: RGBA8888
1155  * @memberOf cc.Texture2D
1156  * @name PIXEL_FORMAT_DEFAULT
1157  * @static
1158  * @constant
1159  * @type {Number}
1160  */
1161 _c.PIXEL_FORMAT_DEFAULT = _c.PIXEL_FORMAT_RGBA8888;
1162 
1163 window._M = cc.Texture2D._M = {};
1164 _M[_c.PIXEL_FORMAT_RGBA8888] = "RGBA8888";
1165 _M[_c.PIXEL_FORMAT_RGB888] = "RGB888";
1166 _M[_c.PIXEL_FORMAT_RGB565] = "RGB565";
1167 _M[_c.PIXEL_FORMAT_A8] = "A8";
1168 _M[_c.PIXEL_FORMAT_I8] = "I8";
1169 _M[_c.PIXEL_FORMAT_AI88] = "AI88";
1170 _M[_c.PIXEL_FORMAT_RGBA4444] = "RGBA4444";
1171 _M[_c.PIXEL_FORMAT_RGB5A1] = "RGB5A1";
1172 _M[_c.PIXEL_FORMAT_PVRTC4] = "PVRTC4";
1173 _M[_c.PIXEL_FORMAT_PVRTC2] = "PVRTC2";
1174 
1175 window._B = cc.Texture2D._B = {};
1176 _B[_c.PIXEL_FORMAT_RGBA8888] = 32;
1177 _B[_c.PIXEL_FORMAT_RGB888] = 24;
1178 _B[_c.PIXEL_FORMAT_RGB565] = 16;
1179 _B[_c.PIXEL_FORMAT_A8] = 8;
1180 _B[_c.PIXEL_FORMAT_I8] = 8;
1181 _B[_c.PIXEL_FORMAT_AI88] = 16;
1182 _B[_c.PIXEL_FORMAT_RGBA4444] = 16;
1183 _B[_c.PIXEL_FORMAT_RGB5A1] = 16;
1184 _B[_c.PIXEL_FORMAT_PVRTC4] = 4;
1185 _B[_c.PIXEL_FORMAT_PVRTC2] = 3;
1186 
1187 
1188 window._p = cc.Texture2D.prototype;
1189 
1190 // Extended properties
1191 /** @expose */
1192 _p.name;
1193 cc.defineGetterSetter(_p, "name", _p.getName);
1194 /** @expose */
1195 _p.pixelFormat;
1196 cc.defineGetterSetter(_p, "pixelFormat", _p.getPixelFormat);
1197 /** @expose */
1198 _p.pixelsWidth;
1199 cc.defineGetterSetter(_p, "pixelsWidth", _p.getPixelsWide);
1200 /** @expose */
1201 _p.pixelsHeight;
1202 cc.defineGetterSetter(_p, "pixelsHeight", _p.getPixelsHigh);
1203 //cc.defineGetterSetter(_p, "size", _p.getContentSize, _p.setContentSize);
1204 /** @expose */
1205 _p.width;
1206 cc.defineGetterSetter(_p, "width", _p._getWidth, _p._setWidth);
1207 /** @expose */
1208 _p.height;
1209 cc.defineGetterSetter(_p, "height", _p._getHeight, _p._setHeight);
1210 
1211 cc.Texture2D.defaultPixelFormat = _c.PIXEL_FORMAT_DEFAULT;
1212 
1213 /** @expose */
1214 window._c;
1215 /** @expose */
1216 window._M;
1217 /** @expose */
1218 window._B;
1219 
1220 delete window._p;
1221 delete window._c;
1222 delete window._M;
1223 delete window._B;
1224