Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion modules/core/src/utils/texture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ export function createTexture(
};
}

const {width, height} = image.data;
// Browser objects are wrapped as `{data: browserImage}` above, so their dimensions live on
// `data`. The plain object form `{data: <Uint8Array>, width, height}` carries them on the object
// itself - reading `image.data` there yields `undefined` and an invalid `mipLevels` count.
const {width, height} = image.data.width === undefined ? image : image.data;
const texture = device.createTexture({
...image,
sampler: {
Expand Down
1 change: 1 addition & 0 deletions test/modules/core/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ import './math-utils.spec';
import './shader.spec';
import './typed-array-manager.spec';
import './apply-styles.spec';
import './texture.spec';
48 changes: 48 additions & 0 deletions test/modules/core/utils/texture.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

import {test, expect} from 'vitest';

import {createTexture, destroyTexture} from '@deck.gl/core/utils/texture';
import {device} from '@deck.gl/test-utils/vitest';

const SIZE = 64;
// 1 + floor(log2(64))
const EXPECTED_MIP_LEVELS = 7;

test('createTexture#plain object image', () => {
// The documented `{data, width, height}` form carries its dimensions on the object itself, not on
// `data`. Reading them from the wrong level produced `mipLevels: NaN`, which rendered as opaque
// black. See issue #10371
const texture = createTexture(
'test-owner',
device,
{data: new Uint8Array(SIZE * SIZE * 4).fill(200), width: SIZE, height: SIZE},
{}
);

expect(texture, 'creates a texture').toBeTruthy();
expect(texture!.width, 'reads width from the plain object').toBe(SIZE);
expect(texture!.height, 'reads height from the plain object').toBe(SIZE);
expect(texture!.mipLevels, 'derives a valid mip level count').toBe(EXPECTED_MIP_LEVELS);

destroyTexture('test-owner', texture!);
});

test('createTexture#browser image object', () => {
// Browser objects are wrapped as `{data: browserImage}`, so their dimensions live on `data`
const texture = createTexture(
'test-owner',
device,
new ImageData(new Uint8ClampedArray(SIZE * SIZE * 4).fill(200), SIZE, SIZE),
{}
);

expect(texture, 'creates a texture').toBeTruthy();
expect(texture!.width, 'reads width from the wrapped image').toBe(SIZE);
expect(texture!.height, 'reads height from the wrapped image').toBe(SIZE);
expect(texture!.mipLevels, 'derives a valid mip level count').toBe(EXPECTED_MIP_LEVELS);

destroyTexture('test-owner', texture!);
});