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