UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

454 lines (353 loc) 15.4 kB
var WebGLTextureWrapper = require('../../../../src/renderer/webgl/wrappers/WebGLTextureWrapper'); function makeMockGl (overrides) { var gl = { isContextLost: vi.fn().mockReturnValue(false), createTexture: vi.fn().mockReturnValue({ __SPECTOR_Metadata: {} }), deleteTexture: vi.fn(), texParameteri: vi.fn(), texImage2D: vi.fn(), compressedTexImage2D: vi.fn(), generateMipmap: vi.fn(), TEXTURE_2D: 3553, TEXTURE_MIN_FILTER: 10241, TEXTURE_MAG_FILTER: 10240, TEXTURE_WRAP_S: 10242, TEXTURE_WRAP_T: 10243, UNSIGNED_BYTE: 5121, REPEAT: 10497, CLAMP_TO_EDGE: 33071, LINEAR: 9729, NEAREST: 9728, RGBA: 6408 }; if (overrides) { Object.assign(gl, overrides); } return gl; } function makeMockRenderer (glOverrides) { var gl = makeMockGl(glOverrides); return { config: { antialias: true }, gl: gl, glTextureUnits: { bind: vi.fn() }, glWrapper: { updateTexturing: vi.fn() } }; } function makeWrapper (options) { options = options || {}; var renderer = options.renderer || makeMockRenderer(); var mipLevel = options.mipLevel !== undefined ? options.mipLevel : 0; var minFilter = options.minFilter !== undefined ? options.minFilter : 9729; var magFilter = options.magFilter !== undefined ? options.magFilter : 9729; var wrapT = options.wrapT !== undefined ? options.wrapT : 33071; var wrapS = options.wrapS !== undefined ? options.wrapS : 33071; var format = options.format !== undefined ? options.format : 6408; var pixels = options.pixels !== undefined ? options.pixels : null; var width = options.width !== undefined ? options.width : 256; var height = options.height !== undefined ? options.height : 256; var pma = options.pma !== undefined ? options.pma : true; var forceSize = options.forceSize !== undefined ? options.forceSize : false; var flipY = options.flipY !== undefined ? options.flipY : true; return new WebGLTextureWrapper(renderer, mipLevel, minFilter, magFilter, wrapT, wrapS, format, pixels, width, height, pma, forceSize, flipY); } describe('WebGLTextureWrapper', function () { describe('Constructor', function () { it('should store the renderer reference', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer }); expect(wrapper.renderer).toBe(renderer); }); it('should store constructor parameters as properties', function () { var wrapper = makeWrapper({ mipLevel: 1, minFilter: 9728, magFilter: 9728, wrapT: 10497, wrapS: 10497, format: 6408, width: 128, height: 64 }); expect(wrapper.mipLevel).toBe(1); expect(wrapper.minFilter).toBe(9728); expect(wrapper.magFilter).toBe(9728); expect(wrapper.wrapT).toBe(10497); expect(wrapper.wrapS).toBe(10497); expect(wrapper.format).toBe(6408); expect(wrapper.width).toBe(128); expect(wrapper.height).toBe(64); }); it('should default pma to true when undefined', function () { var wrapper = makeWrapper({ pma: undefined }); expect(wrapper.pma).toBe(true); }); it('should default pma to true when null', function () { var wrapper = makeWrapper({ pma: null }); expect(wrapper.pma).toBe(true); }); it('should store pma as false when explicitly set', function () { var wrapper = makeWrapper({ pma: false }); expect(wrapper.pma).toBe(false); }); it('should cast forceSize to boolean', function () { var wrapper = makeWrapper({ forceSize: 1 }); expect(wrapper.forceSize).toBe(true); }); it('should default forceSize to false when undefined', function () { var wrapper = makeWrapper({ forceSize: undefined }); expect(wrapper.forceSize).toBe(false); }); it('should cast flipY to boolean', function () { var wrapper = makeWrapper({ flipY: 1 }); expect(wrapper.flipY).toBe(true); }); it('should default flipY to true when undefined', function () { var renderer = makeMockRenderer(); var wrapper = new WebGLTextureWrapper(renderer, 0, 9729, 9729, 33071, 33071, 6408, null, 256, 256); expect(wrapper.flipY).toBe(true); }); it('should initialise isRenderTexture to false', function () { var wrapper = makeWrapper(); expect(wrapper.isRenderTexture).toBe(false); }); it('should initialise batchUnit to -1', function () { var wrapper = makeWrapper(); expect(wrapper.batchUnit).toBe(-1); }); it('should initialise __SPECTOR_Metadata to an empty object', function () { var wrapper = makeWrapper(); expect(wrapper.__SPECTOR_Metadata).toEqual({}); }); it('should call createResource during construction', function () { var renderer = makeMockRenderer(); new WebGLTextureWrapper(renderer, 0, 9729, 9729, 33071, 33071, 6408, null, 256, 256); expect(renderer.gl.createTexture).toHaveBeenCalled(); }); }); describe('createResource', function () { it('should not create a texture when context is lost', function () { var renderer = makeMockRenderer({ isContextLost: vi.fn().mockReturnValue(true) }); var wrapper = new WebGLTextureWrapper(renderer, 0, 9729, 9729, 33071, 33071, 6408, null, 256, 256); expect(renderer.gl.createTexture).not.toHaveBeenCalled(); expect(wrapper.webGLTexture).toBeNull(); }); it('should create a WebGLTexture and assign it when context is valid', function () { var fakeTexture = { __SPECTOR_Metadata: {} }; var renderer = makeMockRenderer({ createTexture: vi.fn().mockReturnValue(fakeTexture) }); var wrapper = makeWrapper({ renderer: renderer }); expect(wrapper.webGLTexture).toBe(fakeTexture); }); it('should use the source texture when pixels is a WebGLTextureWrapper', function () { var sourceRenderer = makeMockRenderer(); var fakeTexture = { __SPECTOR_Metadata: {} }; sourceRenderer.gl.createTexture.mockReturnValue(fakeTexture); var sourceWrapper = makeWrapper({ renderer: sourceRenderer }); var consumerRenderer = makeMockRenderer(); var consumerWrapper = makeWrapper({ renderer: consumerRenderer, pixels: sourceWrapper }); expect(consumerWrapper.webGLTexture).toBe(sourceWrapper.webGLTexture); expect(consumerRenderer.gl.createTexture).not.toHaveBeenCalled(); }); it('should set __SPECTOR_Metadata on the created texture', function () { var fakeTexture = { __SPECTOR_Metadata: {} }; var renderer = makeMockRenderer({ createTexture: vi.fn().mockReturnValue(fakeTexture) }); var wrapper = makeWrapper({ renderer: renderer }); wrapper.__SPECTOR_Metadata = { url: 'test.png' }; // Recreate resource with the metadata set wrapper.webGLTexture = null; wrapper.createResource(); expect(fakeTexture.__SPECTOR_Metadata).toEqual({ url: 'test.png' }); }); }); describe('resize', function () { it('should not update dimensions when size is unchanged', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer, width: 128, height: 128 }); var callsBefore = renderer.gl.texParameteri.mock.calls.length; wrapper.resize(128, 128); expect(wrapper.width).toBe(128); expect(wrapper.height).toBe(128); expect(renderer.gl.texParameteri.mock.calls.length).toBe(callsBefore); }); it('should update width and height', function () { var wrapper = makeWrapper({ width: 128, height: 128 }); wrapper.resize(512, 256); expect(wrapper.width).toBe(512); expect(wrapper.height).toBe(256); }); it('should set REPEAT wrap modes for power-of-two dimensions', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer, width: 128, height: 128 }); wrapper.resize(256, 256); expect(wrapper.wrapS).toBe(renderer.gl.REPEAT); expect(wrapper.wrapT).toBe(renderer.gl.REPEAT); }); it('should set CLAMP_TO_EDGE wrap modes for non-power-of-two dimensions', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer, width: 128, height: 128 }); wrapper.resize(300, 200); expect(wrapper.wrapS).toBe(renderer.gl.CLAMP_TO_EDGE); expect(wrapper.wrapT).toBe(renderer.gl.CLAMP_TO_EDGE); }); it('should call _processTexture after resizing', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer, width: 128, height: 128 }); var callsBefore = renderer.gl.texParameteri.mock.calls.length; wrapper.resize(64, 64); expect(renderer.gl.texParameteri.mock.calls.length).toBeGreaterThan(callsBefore); }); }); describe('update', function () { it('should not update when width is zero', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer, width: 128, height: 128 }); var callsBefore = renderer.gl.texParameteri.mock.calls.length; wrapper.update(null, 0, 128, true, 33071, 33071, 9729, 9729, 6408); expect(wrapper.width).toBe(128); expect(renderer.gl.texParameteri.mock.calls.length).toBe(callsBefore); }); it('should not update when height is zero', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer, width: 128, height: 128 }); var callsBefore = renderer.gl.texParameteri.mock.calls.length; wrapper.update(null, 128, 0, true, 33071, 33071, 9729, 9729, 6408); expect(wrapper.height).toBe(128); expect(renderer.gl.texParameteri.mock.calls.length).toBe(callsBefore); }); it('should update all texture properties', function () { var wrapper = makeWrapper({ width: 128, height: 128 }); var newPixels = { width: 64, height: 64 }; wrapper.update(newPixels, 64, 64, false, 10497, 10497, 9728, 9728, 6408); expect(wrapper.pixels).toBe(newPixels); expect(wrapper.width).toBe(64); expect(wrapper.height).toBe(64); expect(wrapper.flipY).toBe(false); expect(wrapper.wrapS).toBe(10497); expect(wrapper.wrapT).toBe(10497); expect(wrapper.minFilter).toBe(9728); expect(wrapper.magFilter).toBe(9728); expect(wrapper.format).toBe(6408); }); it('should call _processTexture after updating', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer, width: 128, height: 128 }); var callsBefore = renderer.gl.texParameteri.mock.calls.length; wrapper.update(null, 256, 256, true, 33071, 33071, 9729, 9729, 6408); expect(renderer.gl.texParameteri.mock.calls.length).toBeGreaterThan(callsBefore); }); it('should allow null source without throwing', function () { var wrapper = makeWrapper({ width: 128, height: 128 }); expect(function () { wrapper.update(null, 64, 64, true, 33071, 33071, 9729, 9729, 6408); }).not.toThrow(); }); }); describe('destroy', function () { it('should do nothing when webGLTexture is already null', function () { var renderer = makeMockRenderer(); var wrapper = makeWrapper({ renderer: renderer }); wrapper.webGLTexture = null; wrapper.destroy(); expect(renderer.gl.deleteTexture).not.toHaveBeenCalled(); }); it('should delete the WebGLTexture from the GPU', function () { var fakeTexture = { __SPECTOR_Metadata: {} }; var renderer = makeMockRenderer({ createTexture: vi.fn().mockReturnValue(fakeTexture) }); var wrapper = makeWrapper({ renderer: renderer }); wrapper.destroy(); expect(renderer.gl.deleteTexture).toHaveBeenCalledWith(fakeTexture); }); it('should set webGLTexture to null after destroy', function () { var wrapper = makeWrapper(); wrapper.destroy(); expect(wrapper.webGLTexture).toBeNull(); }); it('should set pixels to null after destroy', function () { var wrapper = makeWrapper({ pixels: null }); wrapper.destroy(); expect(wrapper.pixels).toBeNull(); }); it('should set renderer to null after destroy', function () { var wrapper = makeWrapper(); wrapper.destroy(); expect(wrapper.renderer).toBeNull(); }); it('should not call deleteTexture when pixels is a WebGLTextureWrapper', function () { var sourceRenderer = makeMockRenderer(); var sourceWrapper = makeWrapper({ renderer: sourceRenderer }); var consumerRenderer = makeMockRenderer(); var consumerWrapper = makeWrapper({ renderer: consumerRenderer, pixels: sourceWrapper }); consumerWrapper.destroy(); expect(consumerRenderer.gl.deleteTexture).not.toHaveBeenCalled(); }); it('should still null out properties when pixels is a WebGLTextureWrapper', function () { var sourceWrapper = makeWrapper({ renderer: makeMockRenderer() }); var consumerRenderer = makeMockRenderer(); var consumerWrapper = makeWrapper({ renderer: consumerRenderer, pixels: sourceWrapper }); consumerWrapper.destroy(); expect(consumerWrapper.webGLTexture).toBeNull(); expect(consumerWrapper.pixels).toBeNull(); expect(consumerWrapper.renderer).toBeNull(); }); }); });