import { Cartesian2 } from "../../Source/Cesium.js"; import { Color } from "../../Source/Cesium.js"; import { loadKTX2 } from "../../Source/Cesium.js"; import { KTX2Transcoder } from "../../Source/Cesium.js"; import { PixelFormat } from "../../Source/Cesium.js"; import { Resource } from "../../Source/Cesium.js"; import { ClearCommand } from "../../Source/Cesium.js"; import { ContextLimits } from "../../Source/Cesium.js"; import { PixelDatatype } from "../../Source/Cesium.js"; import { Sampler } from "../../Source/Cesium.js"; import { Texture } from "../../Source/Cesium.js"; import { TextureMagnificationFilter } from "../../Source/Cesium.js"; import { TextureMinificationFilter } from "../../Source/Cesium.js"; import { TextureWrap } from "../../Source/Cesium.js"; import createContext from "../createContext.js"; import { when } from "../../Source/Cesium.js"; describe( "Renderer/Texture", function () { var context; var greenImage; var blueImage; var blueAlphaImage; var blueOverRedImage; var blueOverRedFlippedImage; var red16x16Image; var greenKTX2Image; var greenBasisKTX2Image; var fs = "uniform sampler2D u_texture;" + "void main() { gl_FragColor = texture2D(u_texture, vec2(0.0)); }"; var fsLuminanceAlpha = "uniform sampler2D u_texture;" + "void main() { gl_FragColor = vec4(texture2D(u_texture, vec2(0.0)).ra, 0.0, 1.0); }"; var texture; var uniformMap = { u_texture: function () { return texture; }, }; beforeAll(function () { context = createContext(); var promises = []; promises.push( Resource.fetchImage("./Data/Images/Green.png").then(function (image) { greenImage = image; }) ); promises.push( Resource.fetchImage("./Data/Images/Blue.png").then(function (image) { blueImage = image; }) ); promises.push( Resource.fetchImage("./Data/Images/BlueAlpha.png").then(function ( image ) { blueAlphaImage = image; }) ); promises.push( Resource.fetchImage("./Data/Images/BlueOverRed.png").then(function ( image ) { blueOverRedImage = image; }) ); // Load this image as an ImageBitmap promises.push( Resource.fetchImage({ url: "./Data/Images/BlueOverRed.png", preferImageBitmap: true, }).then(function (image) { blueOverRedFlippedImage = image; }) ); promises.push( Resource.fetchImage("./Data/Images/Red16x16.png").then(function ( image ) { red16x16Image = image; }) ); var resource = Resource.createIfNeeded("./Data/Images/Green4x4.ktx2"); var loadPromise = resource.fetchArrayBuffer(); promises.push( loadPromise.then(function (buffer) { var promise = KTX2Transcoder.transcode(buffer, {}); return promise.then(function (result) { greenKTX2Image = result; }); }) ); if (context.supportsBasis) { promises.push( loadKTX2("./Data/Images/Green4x4_ETC1S.ktx2").then(function (image) { greenBasisKTX2Image = image; }) ); } return when.all(promises); }); afterAll(function () { context.destroyForSpecs(); }); afterEach(function () { texture = texture && texture.destroy(); }); it("has expected default values for pixel format and datatype", function () { texture = new Texture({ context: context, source: blueImage, }); expect(texture.id).toBeDefined(); expect(texture.pixelFormat).toEqual(PixelFormat.RGBA); expect(texture.pixelDatatype).toEqual(PixelDatatype.UNSIGNED_BYTE); }); it("can create a texture from the framebuffer", function () { var command = new ClearCommand({ color: Color.RED, }); command.execute(context); texture = Texture.fromFramebuffer({ context: context, }); var expectedWidth = context.canvas.clientWidth; var expectedHeight = context.canvas.clientHeight; expect(texture.width).toEqual(expectedWidth); expect(texture.height).toEqual(expectedHeight); expect(texture.sizeInBytes).toEqual( expectedWidth * expectedHeight * PixelFormat.componentsLength(texture.pixelFormat) ); command.color = Color.WHITE; command.execute(context); expect(context).toReadPixels([255, 255, 255, 255]); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender([255, 0, 0, 255]); }); it("can copy from the framebuffer", function () { texture = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.RGB, }); // Render blue expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender([0, 0, 255, 255]); // Clear to red var command = new ClearCommand({ color: Color.RED, }); command.execute(context); expect(context).toReadPixels(Color.RED.toBytes()); texture.copyFromFramebuffer(); var expectedWidth = context.canvas.clientWidth; var expectedHeight = context.canvas.clientHeight; expect(texture.width).toEqual(expectedWidth); expect(texture.height).toEqual(expectedHeight); expect(texture.sizeInBytes).toEqual( expectedWidth * expectedHeight * PixelFormat.componentsLength(texture.pixelFormat) ); // Clear to white command.color = Color.WHITE; command.execute(context); expect(context).toReadPixels(Color.WHITE.toBytes()); // Render red expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender([255, 0, 0, 255]); }); it("draws the expected texture color", function () { texture = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.RGBA, }); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender([0, 0, 255, 255]); }); it("cannot flip texture when using ImageBitmap", function () { var topColor = new Color(0.0, 0.0, 1.0, 1.0); var bottomColor = new Color(1.0, 0.0, 0.0, 1.0); return Resource.supportsImageBitmapOptions().then(function ( supportsImageBitmapOptions ) { if (supportsImageBitmapOptions) { // When imageBitmapOptions is supported, flipY on texture upload is ignored. bottomColor = topColor; } texture = new Texture({ context: context, source: blueOverRedFlippedImage, pixelFormat: PixelFormat.RGBA, flipY: false, }); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(topColor.toBytes()); // Flip the texture. texture = new Texture({ context: context, source: blueOverRedFlippedImage, pixelFormat: PixelFormat.RGBA, flipY: true, }); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(bottomColor.toBytes()); }); }); it("draws the expected floating-point texture color", function () { if (!context.floatingPointTexture) { return; } var color = new Color(0.2, 0.4, 0.6, 1.0); var floats = new Float32Array([ color.red, color.green, color.blue, color.alpha, ]); texture = new Texture({ context: context, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.FLOAT, source: { width: 1, height: 1, arrayBufferView: floats, }, }); expect(texture.sizeInBytes).toEqual(16); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(color.toBytes()); }); it("draws the expected floating-point texture color with linear filtering", function () { if (!context.floatingPointTexture) { return; } var color0 = new Color(0.2, 0.4, 0.6, 1.0); var color1 = new Color(0.1, 0.3, 0.5, 1.0); var floats = new Float32Array([ color0.red, color0.green, color0.blue, color0.alpha, color1.red, color1.green, color1.blue, color1.alpha, ]); texture = new Texture({ context: context, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.FLOAT, source: { width: 2, height: 1, arrayBufferView: floats, }, sampler: new Sampler({ wrapS: TextureWrap.CLAMP_TO_EDGE, wrapT: TextureWrap.CLAMP_TO_EDGE, minificationFilter: TextureMinificationFilter.LINEAR, magnificationFilter: TextureMagnificationFilter.LINEAR, }), }); expect(texture.sizeInBytes).toEqual(32); var fs = "uniform sampler2D u_texture;" + "void main() { gl_FragColor = texture2D(u_texture, vec2(0.5, 0.0)); }"; if (!context.textureFloatLinear) { expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, epsilon: 1, }).contextToRender(color1.toBytes()); } else { Color.multiplyByScalar(color0, 1.0 - 0.5, color0); Color.multiplyByScalar(color1, 0.5, color1); Color.add(color0, color1, color1); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(color1.toBytes()); } }); it("draws the expected half floating-point texture color", function () { if (!context.halfFloatingPointTexture) { return; } var color = new Color(0.2, 0.4, 0.6, 1.0); var floats = new Uint16Array([12902, 13926, 14541, 15360]); texture = new Texture({ context: context, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.HALF_FLOAT, source: { width: 1, height: 1, arrayBufferView: floats, }, flipY: false, }); expect(texture.sizeInBytes).toEqual(8); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(color.toBytes()); }); it("draws the expected half floating-point texture color with linear filtering", function () { if (!context.halfFloatingPointTexture) { return; } var color0 = new Color(0.2, 0.4, 0.6, 1.0); var color1 = new Color(0.1, 0.3, 0.5, 1.0); var floats = new Uint16Array([ 12902, 13926, 14541, 15360, 11878, 13517, 14336, 15360, ]); texture = new Texture({ context: context, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.HALF_FLOAT, source: { width: 2, height: 1, arrayBufferView: floats, }, flipY: false, }); expect(texture.sizeInBytes).toEqual(16); var fs = "uniform sampler2D u_texture;" + "void main() { gl_FragColor = texture2D(u_texture, vec2(0.5, 0.0)); }"; if (!context.textureHalfFloatLinear) { expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, epsilon: 1, }).contextToRender(color1.toBytes()); } else { Color.multiplyByScalar(color0, 1.0 - 0.5, color0); Color.multiplyByScalar(color1, 0.5, color1); Color.add(color0, color1, color1); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(color1.toBytes()); } }); it("draws the expected Basis compressed texture color", function () { if (!context.supportsBasis) { return; } texture = new Texture({ context: context, pixelFormat: greenBasisKTX2Image.internalFormat, source: { width: greenBasisKTX2Image.width, height: greenBasisKTX2Image.height, arrayBufferView: greenBasisKTX2Image.bufferView, }, }); expect(texture.sizeInBytes).toBe(8); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRenderAndCall(function (color) { return expect(color).toEqualEpsilon([2, 255, 2, 255], 2); }); }); it("draws the expected KTX2 uncompressed texture color", function () { texture = new Texture({ context: context, pixelFormat: greenKTX2Image.internalFormat, source: { width: greenKTX2Image.width, height: greenKTX2Image.height, arrayBufferView: greenKTX2Image.bufferView, }, }); expect(texture.sizeInBytes).toBe(48); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRenderAndCall(function (color) { return expect(color).toEqualEpsilon([0, 255, 24, 255], 2); }); }); it("renders with premultiplied alpha", function () { var cxt = createContext({ webgl: { alpha: true, }, }); var texture = new Texture({ context: cxt, source: blueAlphaImage, pixelFormat: PixelFormat.RGBA, preMultiplyAlpha: true, }); var uniformMap = { u_texture: function () { return texture; }, }; expect(texture.preMultiplyAlpha).toEqual(true); expect({ context: cxt, fragmentShader: fs, uniformMap: uniformMap, epsilon: 1, }).contextToRender([0, 0, 127, 127]); texture.destroy(); cxt.destroyForSpecs(); }); it("draws textured blue and red points", function () { texture = new Texture({ context: context, source: blueOverRedImage, pixelFormat: PixelFormat.RGBA, }); var fragmentShaderSource = ""; fragmentShaderSource += "uniform sampler2D u_texture;"; fragmentShaderSource += "uniform mediump vec2 u_txCoords;"; fragmentShaderSource += "void main() { gl_FragColor = texture2D(u_texture, u_txCoords); }"; var txCoords; var um = { u_texture: function () { return texture; }, u_txCoords: function () { return txCoords; }, }; // Blue on top txCoords = new Cartesian2(0.5, 0.75); expect({ context: context, fragmentShader: fragmentShaderSource, uniformMap: um, }).contextToRender([0, 0, 255, 255]); // Red on bottom txCoords = new Cartesian2(0.5, 0.25); expect({ context: context, fragmentShader: fragmentShaderSource, uniformMap: um, }).contextToRender([255, 0, 0, 255]); }); it("draws the expected luminance texture color", function () { var color = new Color(0.6, 0.6, 0.6, 1.0); var arrayBufferView = new Uint8Array([153]); texture = new Texture({ context: context, pixelFormat: PixelFormat.LUMINANCE, pixelDatatype: PixelDatatype.UNSIGNED_BYTE, source: { width: 1, height: 1, arrayBufferView: arrayBufferView, }, flipY: false, }); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(color.toBytes()); }); it("draws the expected luminance alpha texture color", function () { var color = new Color(0.6, 0.8, 0.0, 1.0); var arrayBufferView = new Uint8Array([153, 204]); texture = new Texture({ context: context, pixelFormat: PixelFormat.LUMINANCE_ALPHA, pixelDatatype: PixelDatatype.UNSIGNED_BYTE, source: { width: 1, height: 1, arrayBufferView: arrayBufferView, }, flipY: false, }); expect({ context: context, fragmentShader: fsLuminanceAlpha, uniformMap: uniformMap, }).contextToRender(color.toBytes()); }); it("can be created from a typed array", function () { var bytes = new Uint8Array([0, 255, 0, 255]); texture = new Texture({ context: context, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.UNSIGNED_BYTE, source: { width: 1, height: 1, arrayBufferView: bytes, }, }); expect(texture.width).toEqual(1); expect(texture.height).toEqual(1); expect(texture.sizeInBytes).toEqual(4); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender([0, 255, 0, 255]); }); it("can copy from a typed array", function () { texture = new Texture({ context: context, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.UNSIGNED_BYTE, width: 1, height: 1, }); var bytes = new Uint8Array(Color.NAVY.toBytes()); texture.copyFrom({ source: { width: 1, height: 1, arrayBufferView: bytes, }, }); expect(texture.width).toEqual(1); expect(texture.height).toEqual(1); expect(texture.sizeInBytes).toEqual(4); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender(Color.NAVY.toBytes()); }); it("can copy from a DOM element", function () { texture = new Texture({ context: context, pixelFormat: PixelFormat.RGB, pixelDatatype: PixelDatatype.UNSIGNED_BYTE, width: blueImage.width, height: blueImage.height, }); texture.copyFrom({ source: blueImage, }); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, epsilon: 1, }).contextToRender([0, 0, 255, 255]); }); it("can replace a subset of a texture", function () { texture = new Texture({ context: context, source: blueOverRedImage, pixelFormat: PixelFormat.RGBA, }); var fragmentShaderSource = ""; fragmentShaderSource += "uniform sampler2D u_texture;"; fragmentShaderSource += "uniform mediump vec2 u_txCoords;"; fragmentShaderSource += "void main() { gl_FragColor = texture2D(u_texture, u_txCoords); }"; var txCoords; var um = { u_texture: function () { return texture; }, u_txCoords: function () { return txCoords; }, }; // Blue on top txCoords = new Cartesian2(0.5, 0.75); expect({ context: context, fragmentShader: fragmentShaderSource, uniformMap: um, }).contextToRender([0, 0, 255, 255]); // Red on bottom txCoords = new Cartesian2(0.5, 0.25); expect({ context: context, fragmentShader: fragmentShaderSource, uniformMap: um, }).contextToRender([255, 0, 0, 255]); // After copy... texture.copyFrom({ source: greenImage, xOffset: 0, yOffset: 1, }); // Now green on top txCoords = new Cartesian2(0.5, 0.75); expect({ context: context, fragmentShader: fragmentShaderSource, uniformMap: um, }).contextToRender(Color.LIME.toBytes()); // Still red on bottom txCoords = new Cartesian2(0.5, 0.25); expect({ context: context, fragmentShader: fragmentShaderSource, uniformMap: um, }).contextToRender([255, 0, 0, 255]); }); it("can generate mipmaps", function () { texture = new Texture({ context: context, source: red16x16Image, pixelFormat: PixelFormat.RGBA, sampler: new Sampler({ minificationFilter: TextureMinificationFilter.NEAREST_MIPMAP_LINEAR, }), }); texture.generateMipmap(); expect(texture.sizeInBytes).toEqualEpsilon( (16 * 16 + 8 * 8 + 4 * 4 + 2 * 2 + 1) * 4, 1 ); expect({ context: context, fragmentShader: fs, uniformMap: uniformMap, }).contextToRender([255, 0, 0, 255]); }); it("can set a sampler property", function () { texture = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.RGBA, }); var sampler = new Sampler({ wrapS: TextureWrap.REPEAT, wrapT: TextureWrap.MIRRORED_REPEAT, minificationFilter: TextureMinificationFilter.NEAREST, magnificationFilter: TextureMagnificationFilter.NEAREST, maximumAnisotropy: 2.0, }); texture.sampler = sampler; var s = texture.sampler; expect(s.wrapS).toEqual(sampler.wrapS); expect(s.wrapT).toEqual(sampler.wrapT); expect(s.minificationFilter).toEqual(sampler.minificationFilter); expect(s.magnificationFilter).toEqual(sampler.magnificationFilter); expect(s.maximumAnisotropy).toEqual(2.0); }); it("can set sampler at construction", function () { texture = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.RGBA, sampler: new Sampler({ wrapS: TextureWrap.REPEAT, wrapT: TextureWrap.MIRRORED_REPEAT, minificationFilter: TextureMinificationFilter.NEAREST, magnificationFilter: TextureMagnificationFilter.NEAREST, maximumAnisotropy: 2.0, }), }); var s = texture.sampler; expect(s.wrapS).toEqual(TextureWrap.REPEAT); expect(s.wrapT).toEqual(TextureWrap.MIRRORED_REPEAT); expect(s.minificationFilter).toEqual(TextureMinificationFilter.NEAREST); expect(s.magnificationFilter).toEqual(TextureMagnificationFilter.NEAREST); expect(s.maximumAnisotropy).toEqual(2.0); }); it("can get width and height", function () { texture = new Texture({ context: context, source: blueOverRedImage, pixelFormat: PixelFormat.RGBA, }); expect(texture.width).toEqual(1); expect(texture.height).toEqual(2); }); it("can get whether Y is flipped", function () { texture = new Texture({ context: context, source: blueOverRedImage, pixelFormat: PixelFormat.RGBA, flipY: true, }); expect(texture.flipY).toEqual(true); }); it("can get the dimensions of a texture", function () { texture = new Texture({ context: context, width: 64, height: 16, }); expect(texture.dimensions).toEqual(new Cartesian2(64, 16)); }); function expectTextureByteSize( width, height, pixelFormat, pixelDatatype, expectedSize ) { texture = new Texture({ context: context, width: width, height: height, pixelFormat: pixelFormat, pixelDatatype: pixelDatatype, }); expect(texture.sizeInBytes).toBe(expectedSize); texture = texture && texture.destroy(); } it("can get the size in bytes of a texture", function () { // Depth textures if (context.depthTexture) { expectTextureByteSize( 16, 16, PixelFormat.DEPTH_COMPONENT, PixelDatatype.UNSIGNED_SHORT, 256 * 2 ); expectTextureByteSize( 16, 16, PixelFormat.DEPTH_COMPONENT, PixelDatatype.UNSIGNED_INT, 256 * 4 ); expectTextureByteSize( 16, 16, PixelFormat.DEPTH_STENCIL, PixelDatatype.UNSIGNED_INT_24_8, 256 * 4 ); } // Uncompressed formats expectTextureByteSize( 16, 16, PixelFormat.ALPHA, PixelDatatype.UNSIGNED_BYTE, 256 ); expectTextureByteSize( 16, 16, PixelFormat.RGB, PixelDatatype.UNSIGNED_BYTE, 256 * 3 ); expectTextureByteSize( 16, 16, PixelFormat.RGBA, PixelDatatype.UNSIGNED_BYTE, 256 * 4 ); expectTextureByteSize( 16, 16, PixelFormat.LUMINANCE, PixelDatatype.UNSIGNED_BYTE, 256 ); expectTextureByteSize( 16, 16, PixelFormat.LUMINANCE_ALPHA, PixelDatatype.UNSIGNED_BYTE, 256 * 2 ); }); it("can be destroyed", function () { var t = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.RGBA, }); expect(t.isDestroyed()).toEqual(false); t.destroy(); expect(t.isDestroyed()).toEqual(true); }); it("throws when creating a texture without a options", function () { expect(function () { texture = new Texture(); }).toThrowDeveloperError(); }); it("throws when creating a texture without a source", function () { expect(function () { texture = new Texture({ context: context, }); }).toThrowDeveloperError(); }); it("throws when creating a texture with width and no height", function () { expect(function () { texture = new Texture({ context: context, width: 16, }); }).toThrowDeveloperError(); }); it("throws when creating a texture with height and no width", function () { expect(function () { texture = new Texture({ context: context, height: 16, }); }).toThrowDeveloperError(); }); it("throws when creating a texture with zero width", function () { expect(function () { texture = new Texture({ context: context, width: 0, height: 16, }); }).toThrowDeveloperError(); }); it("throws when creating a texture with width larger than the maximum texture size", function () { expect(function () { texture = new Texture({ context: context, width: ContextLimits.maximumTextureSize + 1, height: 16, }); }).toThrowDeveloperError(); }); it("throws when creating a texture with zero height", function () { expect(function () { texture = new Texture({ context: context, width: 16, height: 0, }); }).toThrowDeveloperError(); }); it("throws when creating a texture with height larger than the maximum texture size", function () { expect(function () { texture = new Texture({ context: context, width: 16, height: ContextLimits.maximumTextureSize + 1, }); }).toThrowDeveloperError(); }); it("throws when creating a texture with an invalid pixel format", function () { expect(function () { texture = new Texture({ context: context, source: blueImage, pixelFormat: "invalid PixelFormat", }); }).toThrowDeveloperError(); }); it("throws when creating a texture with an invalid pixel datatype", function () { expect(function () { texture = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.RGBA, pixelDatatype: "invalid pixelDatatype", }); }).toThrowDeveloperError(); }); it("throws when creating if pixelFormat is DEPTH_COMPONENT and pixelDatatype is not UNSIGNED_SHORT or UNSIGNED_INT", function () { expect(function () { texture = new Texture({ context: context, pixelFormat: PixelFormat.DEPTH_COMPONENT, pixelDatatype: PixelDatatype.UNSIGNED_BYTE, }); }).toThrowDeveloperError(); }); it("throws when creating if pixelFormat is DEPTH_STENCIL and pixelDatatype is not UNSIGNED_INT_24_8", function () { expect(function () { texture = new Texture({ context: context, pixelFormat: PixelFormat.DEPTH_STENCIL, pixelDatatype: PixelDatatype.UNSIGNED_BYTE, }); }).toThrowDeveloperError(); }); it("throws when creating if pixelFormat is DEPTH_COMPONENT or DEPTH_STENCIL, and source is provided", function () { expect(function () { texture = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.DEPTH_COMPONENT, pixelDatatype: PixelDatatype.UNSIGNED_SHORT, }); }).toThrowDeveloperError(); }); it("throws when creating if pixelFormat is DEPTH_COMPONENT or DEPTH_STENCIL, and WEBGL_depth_texture is not supported", function () { if (!context.depthTexture) { expect(function () { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelFormat.DEPTH_COMPONENT, pixelDatatype: PixelDatatype.UNSIGNED_SHORT, }); }).toThrowDeveloperError(); } }); it("throws when creating if pixelDatatype is FLOAT, and OES_texture_float is not supported", function () { if (!context.floatingPointTexture) { expect(function () { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.FLOAT, }); }).toThrowDeveloperError(); } }); it("throws when creating if pixelDatatype = HALF_FLOAT, and OES_texture_half_float is not supported", function () { if (!context.halfFloatingPointTexture) { expect(function () { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelDatatype.RGBA, pixelDatatype: PixelDatatype.HALF_FLOAT, }); }).toThrowDeveloperError(); } }); it("throws when creating compressed texture and the array buffer source is undefined", function () { expect(function () { texture = new Texture({ context: context, width: 4, height: 4, pixelFormat: PixelFormat.RGBA_DXT3, }); }).toThrowDeveloperError(); }); it("throws when creating from the framebuffer with an invalid pixel format", function () { expect(function () { texture = Texture.fromFramebuffer({ context: context, pixelFormat: "invalid PixelFormat", }); }).toThrowDeveloperError(); }); it("throws when creating from the framebuffer if PixelFormat is DEPTH_COMPONENT or DEPTH_STENCIL", function () { expect(function () { texture = Texture.fromFramebuffer({ context: context, pixelFormat: PixelFormat.DEPTH_COMPONENT, }); }).toThrowDeveloperError(); }); it("throws when creating from the framebuffer with a negative framebufferXOffset", function () { expect(function () { texture = Texture.fromFramebuffer({ context: context, pixelFormat: PixelFormat.RGB, framebufferXOffset: -1, }); }).toThrowDeveloperError(); }); it("throws when creating from the framebuffer with a negative framebufferYOffset", function () { expect(function () { texture = Texture.fromFramebuffer({ context: context, pixelFormat: PixelFormat.RGB, framebufferXOffset: 0, framebufferYOffset: -1, }); }).toThrowDeveloperError(); }); it("throws when creating from the framebuffer with a width greater than the canvas clientWidth", function () { expect(function () { texture = Texture.fromFramebuffer({ context: context, pixelFormat: PixelFormat.RGB, framebufferXOffset: 0, framebufferYOffset: 0, width: context.canvas.clientWidth + 1, }); }).toThrowDeveloperError(); }); it("throws when creating from the framebuffer with a height greater than the canvas clientHeight", function () { expect(function () { texture = Texture.fromFramebuffer({ context: context, pixelFormat: PixelFormat.RGB, framebufferXOffset: 0, framebufferYOffset: 0, width: 1, height: context.canvas.clientHeight + 1, }); }).toThrowDeveloperError(); }); it("throws when copying to a texture from the framebuffer with a DEPTH_COMPONENT or DEPTH_STENCIL pixel format", function () { if (context.depthTexture) { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelFormat.DEPTH_COMPONENT, pixelDatatype: PixelDatatype.UNSIGNED_SHORT, }); expect(function () { texture.copyFromFramebuffer(); }).toThrowDeveloperError(); } }); it("throws when copying to a texture from the framebuffer with a compressed pixel format", function () { if (context.supportsBasis) { texture = new Texture({ context: context, width: greenBasisKTX2Image.width, height: greenBasisKTX2Image.height, pixelFormat: greenBasisKTX2Image.internalFormat, source: { arrayBufferView: greenBasisKTX2Image.bufferView, }, }); expect(function () { texture.copyFromFramebuffer(); }).toThrowDeveloperError(); } }); it("throws when copying to a texture from the framebuffer with a FLOAT pixel data type", function () { if (context.floatingPointTexture) { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.FLOAT, }); expect(function () { texture.copyFromFramebuffer(); }).toThrowDeveloperError(); } }); it("throws when copying to a texture from the framebuffer with a HALF_FLOAT pixel data type", function () { if (context.halfFloatingPointTexture) { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelFormat.RGBA, pixelDatatype: PixelDatatype.HALF_FLOAT, }); expect(function () { texture.copyFromFramebuffer(); }).toThrowDeveloperError(); } }); it("throws when copying from the framebuffer with a negative xOffset", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFromFramebuffer(-1); }).toThrowDeveloperError(); }); it("throws when copying from the framebuffer with a negative yOffset", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFromFramebuffer(0, -1); }).toThrowDeveloperError(); }); it("throws when copying from the framebuffer with a negative framebufferXOffset", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFromFramebuffer(0, 0, -1); }).toThrowDeveloperError(); }); it("throws when copying from the framebuffer with a negative framebufferYOffset", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFromFramebuffer(0, 0, 0, -1); }).toThrowDeveloperError(); }); it("throws when copying from the framebuffer with a larger width", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFromFramebuffer(0, 0, 0, 0, texture.width + 1); }).toThrowDeveloperError(); }); it("throws when copying from the framebuffer with a larger height", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFromFramebuffer(0, 0, 0, 0, 0, texture.height + 1); }).toThrowDeveloperError(); }); it("throws when copying to a texture with a DEPTH_COMPONENT or DEPTH_STENCIL pixel format", function () { if (context.depthTexture) { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelFormat.DEPTH_COMPONENT, pixelDatatype: PixelDatatype.UNSIGNED_SHORT, }); expect(function () { texture.copyFrom({ source: { arrayBufferView: new Uint16Array([0]), width: 1, height: 1, }, }); }).toThrowDeveloperError(); } }); it("throws when copyFrom is not given any options", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFrom(); }).toThrowDeveloperError(); }); it("throws when copyFrom is not given a source", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFrom({ xOffset: 0, yOffset: 2, }); }).toThrowDeveloperError(); }); it("throws when copyFrom is given a negative xOffset", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFrom({ source: blueImage, xOffset: -1, }); }).toThrowDeveloperError(); }); it("throws when copyFrom is given a negative yOffset", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.copyFrom({ source: blueImage, xOffset: 0, yOffset: -1, }); }).toThrowDeveloperError(); }); it("throws when copyFrom is given a source with larger width", function () { texture = new Texture({ context: context, source: blueImage, }); var image = new Image(); image.width = blueImage.width + 1; expect(function () { texture.copyFrom({ source: image, }); }).toThrowDeveloperError(); }); it("throws when copyFrom is given a source with larger height", function () { texture = new Texture({ context: context, source: blueImage, }); var image = new Image(); image.height = blueImage.height + 1; expect(function () { texture.copyFrom({ source: image, }); }).toThrowDeveloperError(); }); it("throws when copyFrom is given a source with a compressed pixel format", function () { if (context.supportsBasis) { texture = new Texture({ context: context, width: greenBasisKTX2Image.width, height: greenBasisKTX2Image.height, pixelFormat: greenBasisKTX2Image.internalFormat, source: { arrayBufferView: greenBasisKTX2Image.bufferView, }, }); var image = new Image(); expect(function () { texture.copyFrom({ source: image, }); }).toThrowDeveloperError(); } }); it("throws when generating mipmaps with a DEPTH_COMPONENT or DEPTH_STENCIL pixel format", function () { if (context.depthTexture) { texture = new Texture({ context: context, width: 1, height: 1, pixelFormat: PixelFormat.DEPTH_COMPONENT, pixelDatatype: PixelDatatype.UNSIGNED_SHORT, }); expect(function () { texture.generateMipmap(); }).toThrowDeveloperError(); } }); it("throws when generating mipmaps with a compressed pixel format", function () { if (context.supportsBasis) { texture = new Texture({ context: context, width: greenBasisKTX2Image.width, height: greenBasisKTX2Image.height, pixelFormat: greenBasisKTX2Image.internalFormat, source: { arrayBufferView: greenBasisKTX2Image.bufferView, }, }); expect(function () { texture.generateMipmap(); }).toThrowDeveloperError(); } }); it("throws when generating mipmaps with a non-power of two width", function () { texture = new Texture({ context: context, width: 3, height: 2, }); expect(function () { texture.generateMipmap(); }).toThrowDeveloperError(); }); it("throws when generating mipmaps with a non-power of two height", function () { texture = new Texture({ context: context, width: 2, height: 3, }); expect(function () { texture.generateMipmap(); }).toThrowDeveloperError(); }); it("throws when generating mipmaps with an invalid hint", function () { texture = new Texture({ context: context, source: blueImage, }); expect(function () { texture.generateMipmap("invalid hint"); }).toThrowDeveloperError(); }); it("throws when destroy is called after destroying", function () { var t = new Texture({ context: context, source: blueImage, pixelFormat: PixelFormat.RGBA, }); t.destroy(); expect(function () { t.destroy(); }).toThrowDeveloperError(); }); }, "WebGL" );