gluTexture.js (16449B)
1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 3 * ------------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ 20 21 'use strict'; 22 goog.provide('framework.opengl.gluTexture'); 23 goog.require('framework.common.tcuCompressedTexture'); 24 goog.require('framework.common.tcuTexture'); 25 goog.require('framework.delibs.debase.deMath'); 26 goog.require('framework.opengl.gluTextureUtil'); 27 28 goog.scope(function() { 29 30 var gluTexture = framework.opengl.gluTexture; 31 var gluTextureUtil = framework.opengl.gluTextureUtil; 32 var tcuTexture = framework.common.tcuTexture; 33 var tcuCompressedTexture = framework.common.tcuCompressedTexture; 34 var deMath = framework.delibs.debase.deMath; 35 36 var DE_ASSERT = function(x) { 37 if (!x) 38 throw new Error('Assert failed'); 39 }; 40 41 /** @enum {number} */ 42 gluTexture.Type = { 43 TYPE_NONE: 0, 44 TYPE_2D: 1, 45 TYPE_CUBE_MAP: 2, 46 TYPE_2D_ARRAY: 3, 47 TYPE_3D: 4 48 }; 49 50 /** 51 * @constructor 52 */ 53 gluTexture.Texture2D = function(gl, format, isCompressed, refTexture) { 54 this.gl = gl; 55 this.m_glTexture = gl.createTexture(); 56 this.m_isCompressed = isCompressed; 57 this.m_format = format; // Internal format 58 this.m_refTexture = refTexture; 59 this.m_type = gluTexture.Type.TYPE_2D; 60 }; 61 62 gluTexture.Texture2D.prototype.getType = function() { 63 return this.m_type; 64 }; 65 66 gluTexture.Texture2D.prototype.getRefTexture = function() { 67 return this.m_refTexture; 68 }; 69 70 gluTexture.Texture2D.prototype.getGLTexture = function() { 71 return this.m_glTexture; 72 }; 73 74 gluTexture.texture2DFromFormat = function(gl, format, dataType, width, height) { 75 var tex = new gluTexture.Texture2D(gl, format, false, new tcuTexture.Texture2D(gluTextureUtil.mapGLTransferFormat(format, dataType), width, height)); 76 return tex; 77 }; 78 79 gluTexture.texture2DFromInternalFormat = function(gl, internalFormat, width, height) { 80 var tex = new gluTexture.Texture2D(gl, internalFormat, false, new tcuTexture.Texture2D(gluTextureUtil.mapGLInternalFormat(internalFormat), width, height)); 81 return tex; 82 }; 83 84 /** 85 * @param {number} numLevels 86 * @param {Array<tcuCompressedTexture.CompressedTexture>} levels 87 * @return {gluTexture.Texture2D} 88 */ 89 gluTexture.texture2DFromCompressedTexture = function(gl, numLevels, levels) { 90 var level = levels[0]; 91 var format = gluTextureUtil.getGLFormat(level.getFormat()); 92 var refTex = new tcuTexture.Texture2D(level.getUncompressedFormat(), level.getWidth(), level.getHeight()); 93 /** @type {gluTexture.Texture2D} */ var tex2d = new gluTexture.Texture2D(gl, format, true, refTex); 94 95 tex2d.loadCompressed(numLevels, levels); 96 97 return tex2d; 98 }; 99 /** 100 * @param {number} numLevels 101 * @param {Array<tcuCompressedTexture.CompressedTexture>} levels 102 */ 103 gluTexture.Texture2D.prototype.loadCompressed = function(numLevels, levels) { 104 /** @type {number} */ var compressedFormat = gluTextureUtil.getGLFormat(levels[0].getFormat()); 105 106 assertMsgOptions(this.m_glTexture, 'm_glTexture not defined', false, true); 107 gl.bindTexture(gl.TEXTURE_2D, this.m_glTexture); 108 109 for (var levelNdx = 0; levelNdx < numLevels; levelNdx++) { 110 /** @type {tcuCompressedTexture.CompressedTexture} */ var level = levels[levelNdx]; 111 112 // Decompress to reference texture. 113 this.m_refTexture.allocLevel(levelNdx); 114 /** @type {tcuTexture.PixelBufferAccess} */ var refLevelAccess = this.m_refTexture.getLevel(levelNdx); 115 assertMsgOptions(level.getWidth() == refLevelAccess.getWidth() && level.getHeight() == refLevelAccess.getHeight(), 'level and reference sizes not equal', false, true); 116 level.decompress(refLevelAccess); 117 118 // Upload to GL texture in compressed form. 119 gl.compressedTexImage2D(gl.TEXTURE_2D, levelNdx, compressedFormat, 120 level.getWidth(), level.getHeight(), 0, level.getData()); 121 } 122 }; 123 124 gluTexture.computePixelStore = function(/*const tcu::TextureFormat&*/ format) { 125 var pixelSize = format.getPixelSize(); 126 if (deMath.deIsPowerOfTwo32(pixelSize)) 127 return Math.min(pixelSize, 8); 128 else 129 return 1; 130 }; 131 132 gluTexture.cubeFaceToGLFace = function(/*tcu::CubeFace*/ face) { 133 switch (face) { 134 case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_X: return gl.TEXTURE_CUBE_MAP_NEGATIVE_X; 135 case tcuTexture.CubeFace.CUBEFACE_POSITIVE_X: return gl.TEXTURE_CUBE_MAP_POSITIVE_X; 136 case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Y: return gl.TEXTURE_CUBE_MAP_NEGATIVE_Y; 137 case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Y: return gl.TEXTURE_CUBE_MAP_POSITIVE_Y; 138 case tcuTexture.CubeFace.CUBEFACE_NEGATIVE_Z: return gl.TEXTURE_CUBE_MAP_NEGATIVE_Z; 139 case tcuTexture.CubeFace.CUBEFACE_POSITIVE_Z: return gl.TEXTURE_CUBE_MAP_POSITIVE_Z; 140 } 141 throw new Error('Unrecognized face: ' + face); 142 }; 143 144 gluTexture.Texture2D.prototype.upload = function() { 145 DE_ASSERT(!this.m_isCompressed); 146 147 if (this.m_glTexture == null) 148 testFailedOptions('Failed to create GL texture', true); 149 150 gl.bindTexture(gl.TEXTURE_2D, this.m_glTexture); 151 gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat())); 152 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Setting pixel store failed', false, true); 153 154 var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat()); 155 156 for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) { 157 if (this.m_refTexture.isLevelEmpty(levelNdx)) 158 continue; // Don't upload. 159 160 var access = this.m_refTexture.getLevel(levelNdx); 161 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth()); 162 var data = access.getDataPtr(); 163 gl.texImage2D(gl.TEXTURE_2D, levelNdx, this.m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 164 } 165 166 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 167 }; 168 169 /** 170 * @constructor 171 * @extends {gluTexture.Texture2D} 172 */ 173 gluTexture.TextureCube = function(gl, format, isCompressed, refTexture) { 174 gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture); 175 this.m_type = gluTexture.Type.TYPE_CUBE_MAP; 176 }; 177 178 gluTexture.TextureCube.prototype = Object.create(gluTexture.Texture2D.prototype); 179 gluTexture.TextureCube.prototype.constructor = gluTexture.TextureCube; 180 181 gluTexture.TextureCube.prototype.upload = function() { 182 DE_ASSERT(!this.m_isCompressed); 183 184 if (this.m_glTexture == null) 185 testFailedOptions('Failed to create GL texture', true); 186 187 gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.m_glTexture); 188 gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat())); 189 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Setting pixel store failed', false, true); 190 191 var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat()); 192 193 for (var face in tcuTexture.CubeFace) { 194 for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) { 195 if (this.m_refTexture.isLevelEmpty(tcuTexture.CubeFace[face], levelNdx)) 196 continue; // Don't upload. 197 198 /*tcu::ConstPixelBufferAccess*/ var access = this.m_refTexture.getLevelFace(levelNdx, tcuTexture.CubeFace[face]); 199 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth()); 200 gl.texImage2D(gluTexture.cubeFaceToGLFace(tcuTexture.CubeFace[face]), levelNdx, this.m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 201 } 202 } 203 204 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 205 }; 206 207 gluTexture.cubeFromFormat = function(gl, format, dataType, size) { 208 var tex = new gluTexture.TextureCube(gl, format, false, new tcuTexture.TextureCube(gluTextureUtil.mapGLTransferFormat(format, dataType), size)); 209 return tex; 210 }; 211 212 gluTexture.cubeFromInternalFormat = function(gl, internalFormat, size) { 213 var tex = new gluTexture.TextureCube(gl, internalFormat, false, new tcuTexture.TextureCube(gluTextureUtil.mapGLInternalFormat(internalFormat), size)); 214 return tex; 215 }; 216 217 /** 218 * @constructor 219 * @extends {gluTexture.Texture2D} 220 */ 221 gluTexture.Texture2DArray = function(gl, format, isCompressed, refTexture) { 222 gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture); 223 this.m_type = gluTexture.Type.TYPE_2D_ARRAY; 224 }; 225 226 gluTexture.Texture2DArray.prototype = Object.create(gluTexture.Texture2D.prototype); 227 gluTexture.Texture2DArray.prototype.constructor = gluTexture.Texture2DArray; 228 229 gluTexture.Texture2DArray.prototype.upload = function() { 230 if (!gl.texImage3D) 231 throw new Error('gl.TexImage3D() is not supported'); 232 233 gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.m_glTexture); 234 gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat())); 235 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 236 237 var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat()); 238 239 for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) { 240 if (this.m_refTexture.isLevelEmpty(levelNdx)) 241 continue; // Don't upload. 242 243 /*tcu::ConstPixelBufferAccess*/ var access = this.m_refTexture.getLevel(levelNdx); 244 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth()); 245 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight()); 246 gl.texImage3D(gl.TEXTURE_2D_ARRAY, levelNdx, this.m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 247 } 248 249 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 250 }; 251 252 gluTexture.texture2DArrayFromFormat = function(gl, format, dataType, width, height, numLayers) { 253 var tex = new gluTexture.Texture2DArray(gl, format, false, new tcuTexture.Texture2DArray(gluTextureUtil.mapGLTransferFormat(format, dataType), width, height, numLayers)); 254 return tex; 255 }; 256 257 gluTexture.texture2DArrayFromInternalFormat = function(gl, internalFormat, width, height, numLayers) { 258 var tex = new gluTexture.Texture2DArray(gl, internalFormat, false, new tcuTexture.Texture2DArray(gluTextureUtil.mapGLInternalFormat(internalFormat), width, height, numLayers)); 259 return tex; 260 }; 261 262 /** 263 * @constructor 264 * @extends {gluTexture.Texture2D} 265 */ 266 gluTexture.Texture3D = function(gl, format, isCompressed, refTexture) { 267 gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture); 268 this.m_type = gluTexture.Type.TYPE_3D; 269 }; 270 271 gluTexture.Texture3D.prototype = Object.create(gluTexture.Texture2D.prototype); 272 gluTexture.Texture3D.prototype.constructor = gluTexture.Texture3D; 273 274 gluTexture.Texture3D.prototype.upload = function() { 275 if (!gl.texImage3D) 276 throw new Error('gl.TexImage3D() is not supported'); 277 278 gl.bindTexture(gl.TEXTURE_3D, this.m_glTexture); 279 gl.pixelStorei(gl.UNPACK_ALIGNMENT, gluTexture.computePixelStore(this.m_refTexture.getFormat())); 280 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 281 282 var transferFormat = gluTextureUtil.getTransferFormat(this.m_refTexture.getFormat()); 283 284 for (var levelNdx = 0; levelNdx < this.m_refTexture.getNumLevels(); levelNdx++) { 285 if (this.m_refTexture.isLevelEmpty(levelNdx)) 286 continue; // Don't upload. 287 288 /*tcu::ConstPixelBufferAccess*/ var access = this.m_refTexture.getLevel(levelNdx); 289 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth()); 290 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight()); 291 gl.texImage3D(gl.TEXTURE_3D, levelNdx, this.m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 292 } 293 294 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 295 }; 296 297 gluTexture.texture3DFromFormat = function(gl, format, dataType, width, height, depth) { 298 var tex = new gluTexture.Texture3D(gl, format, false, new tcuTexture.Texture3D(gluTextureUtil.mapGLTransferFormat(format, dataType), width, height, depth)); 299 return tex; 300 }; 301 302 gluTexture.texture3DFromInternalFormat = function(gl, internalFormat, width, height, depth) { 303 var tex = new gluTexture.Texture3D(gl, internalFormat, false, new tcuTexture.Texture3D(gluTextureUtil.mapGLInternalFormat(internalFormat), width, height, depth)); 304 return tex; 305 }; 306 307 /** 308 * @constructor 309 * @extends {gluTexture.Texture2D} 310 */ 311 gluTexture.Compressed2D = function(gl, format, isCompressed, refTexture) { 312 gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture); 313 }; 314 315 gluTexture.Compressed2D.prototype = Object.create(gluTexture.Texture2D.prototype); 316 gluTexture.Compressed2D.prototype.constructor = gluTexture.Compressed2D; 317 318 gluTexture.Compressed2D.prototype.uploadLevel = function(level, source) { 319 DE_ASSERT(this.m_isCompressed); 320 321 if (this.m_glTexture == null) 322 testFailedOptions('Failed to create GL texture', true); 323 324 gl.bindTexture(gl.TEXTURE_2D, this.m_glTexture); 325 326 gl.compressedTexImage2D(gl.TEXTURE_2D, level, this.m_format, source.m_width, source.m_height, 0 /* border */, source.m_data); 327 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 328 }; 329 330 /** 331 * @constructor 332 * @extends {gluTexture.Texture2D} 333 */ 334 gluTexture.CompressedCube = function(gl, format, isCompressed, refTexture) { 335 gluTexture.Texture2D.call(this, gl, format, isCompressed, refTexture); 336 }; 337 338 gluTexture.CompressedCube.prototype = Object.create(gluTexture.Texture2D.prototype); 339 gluTexture.CompressedCube.prototype.constructor = gluTexture.CompressedCube; 340 341 gluTexture.CompressedCube.prototype.uploadLevel = function(level, source) { 342 DE_ASSERT(this.m_isCompressed); 343 344 if (this.m_glTexture == null) 345 testFailedOptions('Failed to create GL texture', true); 346 347 gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.m_glTexture); 348 349 for (var face in tcuTexture.CubeFace) { 350 351 // Upload to GL texture in compressed form. 352 gl.compressedTexImage2D(gluTexture.cubeFaceToGLFace(tcuTexture.CubeFace[face]), 0, this.m_format, 353 source.m_width, source.m_height, 0 /* border */, source.m_data); 354 assertMsgOptions(gl.getError() === gl.NO_ERROR, 'Texture upload failed', false, true); 355 } 356 357 }; 358 359 gluTexture.compressed2DFromInternalFormat = function(gl, format, width, height, compressed) { 360 var tex = new gluTexture.Compressed2D(gl, gluTextureUtil.getGLFormat(format), true, new tcuTexture.Texture2D(compressed.getUncompressedFormat(), width, height)); 361 tex.m_refTexture.allocLevel(0); 362 compressed.decompress(tex.m_refTexture.getLevel(0)); 363 tex.uploadLevel(0, compressed); 364 return tex; 365 }; 366 367 gluTexture.compressedCubeFromInternalFormat = function(gl, format, size, compressed) { 368 var tex = new gluTexture.CompressedCube(gl, gluTextureUtil.getGLFormat(format), true, new tcuTexture.TextureCube(compressed.getUncompressedFormat(), size)); 369 for (var face in tcuTexture.CubeFace) { 370 tex.m_refTexture.allocLevel(tcuTexture.CubeFace[face], 0); 371 372 /*tcu::ConstPixelBufferAccess*/ var access = tex.m_refTexture.getLevelFace(0, tcuTexture.CubeFace[face]); 373 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth()); 374 compressed.decompress(access); 375 } 376 tex.uploadLevel(0, compressed); 377 return tex; 378 }; 379 380 });