Skip to content

Commit 541095a

Browse files
committed
fixes for raster tile layer - raster pmtiles related
Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com>
1 parent 8647f18 commit 541095a

File tree

5 files changed

+641
-99
lines changed

5 files changed

+641
-99
lines changed

src/deckgl-layers/src/raster/images.ts

Lines changed: 115 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,45 @@
11
// SPDX-License-Identifier: MIT
22
// Copyright contributors to the kepler.gl project
33

4-
// @ts-nocheck - Raster images module uses luma.gl Texture APIs that changed in 9.x
5-
// TODO: Refactor to use luma.gl 9.x Texture API
4+
// @ts-nocheck
65

76
import {GL} from '@luma.gl/constants';
87
import isEqual from 'lodash/isEqual';
98

10-
import type {ImageInput, ImageState, Texture2D, Texture2DProps} from './types';
9+
import type {ImageInput, ImageState} from './types';
10+
11+
type Texture2D = any;
12+
type Texture2DProps = any;
1113

1214
/**
13-
* Texture parameters for WebGL2 textures
15+
* Texture sampler parameters for luma.gl 9 textures
1416
*/
15-
const DEFAULT_UNIVERSAL_TEXTURE_PARAMETERS = {
16-
[GL.TEXTURE_MIN_FILTER]: GL.NEAREST,
17-
[GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
18-
[GL.TEXTURE_WRAP_S]: GL.CLAMP_TO_EDGE,
19-
[GL.TEXTURE_WRAP_T]: GL.CLAMP_TO_EDGE
17+
const DEFAULT_SAMPLER_PARAMETERS = {
18+
minFilter: 'nearest',
19+
magFilter: 'nearest',
20+
addressModeU: 'clamp-to-edge',
21+
addressModeV: 'clamp-to-edge'
2022
};
2123

2224
type LoadImagesOptions = {
2325
gl: WebGL2RenderingContext;
26+
device?: any;
2427
images: ImageState;
2528
imagesData: ImageInput;
2629
oldImagesData: ImageInput;
2730
};
2831

2932
/**
3033
* Load image items to webgl context
31-
* @param gl webgl rendering context
32-
* @param imageItem image item, might be single texture or array of textures
33-
* @returns loaded single webgl texture or array of webgl texture or null
3434
*/
3535
function loadImageItem(
3636
gl: WebGL2RenderingContext,
37+
device: any,
3738
imageItem: Texture2DProps | Texture2D | (Texture2DProps | Texture2D)[]
3839
): null | Texture2D | Texture2D[] {
3940
let result: null | Texture2D | Texture2D[];
4041
if (Array.isArray(imageItem)) {
41-
const dirtyResult = imageItem.map(x => loadTexture(gl, x));
42+
const dirtyResult = imageItem.map(x => loadTexture(gl, device, x));
4243
result = [];
4344
for (const texture of dirtyResult) {
4445
if (texture) {
@@ -49,14 +50,15 @@ function loadImageItem(
4950
result = null;
5051
}
5152
} else {
52-
result = loadTexture(gl, imageItem);
53+
result = loadTexture(gl, device, imageItem);
5354
}
5455
return result;
5556
}
5657

5758
// eslint-disable-next-line complexity
5859
export function loadImages({
5960
gl,
61+
device,
6062
images,
6163
imagesData,
6264
oldImagesData
@@ -90,7 +92,7 @@ export function loadImages({
9092
continue;
9193
}
9294

93-
const loadedItem = loadImageItem(gl, imageData);
95+
const loadedItem = loadImageItem(gl, device, imageData);
9496
if (loadedItem) {
9597
images[key] = loadedItem;
9698
}
@@ -105,33 +107,117 @@ export function loadImages({
105107
}
106108

107109
/**
108-
* Create texture object from image data
110+
* Map old GL texture parameter constants to luma.gl 9 sampler parameters
111+
*/
112+
function mapSamplerParameters(oldParams: Record<number, number>): Record<string, string> {
113+
const result: Record<string, string> = {...DEFAULT_SAMPLER_PARAMETERS};
114+
115+
const filterMap = {
116+
[GL.NEAREST]: 'nearest',
117+
[GL.LINEAR]: 'linear',
118+
[GL.LINEAR_MIPMAP_LINEAR]: 'linear',
119+
[GL.NEAREST_MIPMAP_NEAREST]: 'nearest'
120+
};
121+
122+
const wrapMap = {
123+
[GL.CLAMP_TO_EDGE]: 'clamp-to-edge',
124+
[GL.REPEAT]: 'repeat',
125+
[GL.MIRRORED_REPEAT]: 'mirror-repeat'
126+
};
127+
128+
if (oldParams) {
129+
if (oldParams[GL.TEXTURE_MIN_FILTER] !== undefined) {
130+
result.minFilter = filterMap[oldParams[GL.TEXTURE_MIN_FILTER]] || 'nearest';
131+
}
132+
if (oldParams[GL.TEXTURE_MAG_FILTER] !== undefined) {
133+
result.magFilter = filterMap[oldParams[GL.TEXTURE_MAG_FILTER]] || 'nearest';
134+
}
135+
if (oldParams[GL.TEXTURE_WRAP_S] !== undefined) {
136+
result.addressModeU = wrapMap[oldParams[GL.TEXTURE_WRAP_S]] || 'clamp-to-edge';
137+
}
138+
if (oldParams[GL.TEXTURE_WRAP_T] !== undefined) {
139+
result.addressModeV = wrapMap[oldParams[GL.TEXTURE_WRAP_T]] || 'clamp-to-edge';
140+
}
141+
}
142+
143+
return result;
144+
}
145+
146+
/**
147+
* Map old GL format/type to luma.gl 9 texture format string
148+
*/
149+
function mapTextureFormat(glFormat: number, glType?: number): string {
150+
switch (glFormat) {
151+
case GL.R8UI: return 'r8uint';
152+
case GL.R16UI: return 'r16uint';
153+
case GL.R32UI: return 'r32uint';
154+
case GL.R8I: return 'r8sint';
155+
case GL.R16I: return 'r16sint';
156+
case GL.R32I: return 'r32sint';
157+
case GL.R32F: return 'r32float';
158+
case GL.RGBA:
159+
if (glType === GL.UNSIGNED_BYTE) return 'rgba8unorm';
160+
return 'rgba8unorm';
161+
case GL.RGB:
162+
return 'rgba8unorm';
163+
default:
164+
return 'rgba8unorm';
165+
}
166+
}
167+
168+
/**
169+
* Create texture object from image data using luma.gl 9 device API.
170+
* Returns a proper luma.gl Texture object that works with the binding system.
109171
*/
110172
function loadTexture(
111173
gl: WebGL2RenderingContext,
174+
device: any,
112175
imageData: Texture2D | Texture2DProps
113176
): Texture2D | null {
114177
if (!imageData) {
115178
return null;
116179
}
117180

118-
// If already a Texture instance, return as-is
119-
if (imageData.handle || imageData.gl || imageData.device) {
181+
// If already a luma.gl Texture instance, return as-is
182+
if (imageData.handle || imageData.id?.startsWith?.('luma') || imageData.device) {
120183
return imageData as Texture2D;
121184
}
122185

123-
const textureParams: Texture2DProps = {
124-
parameters: DEFAULT_UNIVERSAL_TEXTURE_PARAMETERS,
125-
...imageData
126-
};
186+
const lumaDevice = device || gl.luma?.device || gl.__luma_device;
127187

128-
// In luma.gl 9.x this would be device.createTexture(textureParams)
129-
// For now, maintain backward compatibility
130-
const Texture2DClass = gl.__luma_Texture2D;
131-
if (Texture2DClass) {
132-
return new Texture2DClass(gl, textureParams);
188+
if (!lumaDevice?.createTexture) {
189+
console.warn('RasterLayer: No luma.gl device available for texture creation');
190+
return null;
133191
}
134192

135-
// Fallback: try creating texture through the WebGL context
136-
return textureParams as any;
193+
try {
194+
const samplerParams = mapSamplerParameters(imageData.parameters || {});
195+
const textureFormat = imageData.format
196+
? mapTextureFormat(imageData.format, imageData.type)
197+
: 'rgba8unorm';
198+
199+
const textureProps: any = {
200+
width: imageData.width || (imageData.data?.width) || 1,
201+
height: imageData.height || (imageData.data?.height) || 1,
202+
format: textureFormat,
203+
sampler: samplerParams,
204+
...(imageData.mipmaps === false ? {mipmaps: false} : {})
205+
};
206+
207+
if (imageData.data) {
208+
if (imageData.data instanceof HTMLImageElement ||
209+
imageData.data instanceof HTMLCanvasElement ||
210+
imageData.data instanceof ImageBitmap ||
211+
imageData.data instanceof ImageData) {
212+
textureProps.data = imageData.data;
213+
} else if (ArrayBuffer.isView(imageData.data)) {
214+
textureProps.data = imageData.data;
215+
}
216+
}
217+
218+
return lumaDevice.createTexture(textureProps);
219+
} catch (e) {
220+
console.warn('RasterLayer: Failed to create texture via device.createTexture:', e);
221+
return null;
222+
}
137223
}

0 commit comments

Comments
 (0)