import {describe, expect, test} from 'vitest'; import {Context} from './context.ts'; import {Texture} from './texture.ts'; import {premultiplyAlpha, RGBAImage} from '../util/image.ts'; import {createNullGL} from '../util/test/null_gl.ts'; describe('Texture', () => { describe('glPixelStore state is reset after texture creation', () => { const testImage = new RGBAImage({ width: 2, height: 1, }, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])); function getContext(): Context { return new Context(createNullGL()); } function expectPixelStoreState(context: Context): void { expect(context.pixelStoreUnpack.current).toEqual(context.pixelStoreUnpack.default); expect(context.pixelStoreUnpackFlipY.current).toEqual(context.pixelStoreUnpackFlipY.default); expect(context.pixelStoreUnpackPremultiplyAlpha.current).toEqual(context.pixelStoreUnpackPremultiplyAlpha.default); } test('premultiply=false', () => { const context = getContext(); // We test the Texture constructor's side effects // eslint-disable-next-line @typescript-eslint/no-unused-vars const _texture = new Texture(context, testImage, context.gl.RGBA, {premultiply: false}); expectPixelStoreState(context); }); test('premultiply=true', () => { const context = getContext(); // We test the Texture constructor's side effects // eslint-disable-next-line @typescript-eslint/no-unused-vars const _texture = new Texture(context, testImage, context.gl.RGBA, {premultiply: true}); expectPixelStoreState(context); }); }); test('bind restores handle after corruption (#2811)', () => { const gl = createNullGL(); const context = new Context(gl); const image = new RGBAImage({width: 2, height: 1}, new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8])); const texture = new Texture(context, image, gl.RGBA); const originalHandle = texture.texture; texture.texture = gl.createTexture(); texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE); expect(texture.texture).toBe(originalHandle); }); test('RGBA texture recreates on resize via texStorage2D', () => { const gl = createNullGL(); const context = new Context(gl); const image1 = new RGBAImage({width: 2, height: 2}, new Uint8Array(2 * 2 * 4)); const texture = new Texture(context, image1, gl.RGBA); const firstHandle = texture.texture; expect(texture.size).toEqual([2, 2]); const image2 = new RGBAImage({width: 4, height: 4}, new Uint8Array(4 * 4 * 4)); texture.update(image2); expect(texture.size).toEqual([4, 4]); expect(texture.texture).not.toBe(firstHandle); expect(gl.deleteTexture).toHaveBeenCalled(); }); test('premultiplyAlpha produces correct output', () => { // pixel: r=200, g=100, b=50, a=128 (half transparent) const data = new Uint8Array([200, 100, 50, 128]); const result = premultiplyAlpha(data); expect(result[0]).toBe(Math.round(200 * 128 / 255)); // 100 expect(result[1]).toBe(Math.round(100 * 128 / 255)); // 50 expect(result[2]).toBe(Math.round(50 * 128 / 255)); // 25 expect(result[3]).toBe(128); }); });