diff --git a/examples/basemap-browser/src/config/build-config.ts b/examples/basemap-browser/src/config/build-config.ts index f7bfe2ceadf..2eea9cdede1 100644 --- a/examples/basemap-browser/src/config/build-config.ts +++ b/examples/basemap-browser/src/config/build-config.ts @@ -24,7 +24,8 @@ export function buildConfig( dimensions: Dimensions, onViewStateChange?: ViewStateChangeCallback ): Config { - const {basemap, framework, interleaved, globe, multiView, maskDemo, stressTest} = dimensions; + const {basemap, framework, interleaved, globe, multiView, maskDemo, stressTest, useDevicePixels} = + dimensions; // Validate dimensions (warnings only) const validation = validateDimensions(dimensions); @@ -58,6 +59,7 @@ export function buildConfig( multiView, maskDemo, stressTest, + useDevicePixels, // Computed configuration mapStyle, diff --git a/examples/basemap-browser/src/config/dimensions.ts b/examples/basemap-browser/src/config/dimensions.ts index 5cd3ac3efb5..6099c2c6aec 100644 --- a/examples/basemap-browser/src/config/dimensions.ts +++ b/examples/basemap-browser/src/config/dimensions.ts @@ -14,7 +14,8 @@ export const DEFAULT_DIMENSIONS: Dimensions = { globe: false, multiView: false, maskDemo: false, - stressTest: 'none' + stressTest: 'none', + useDevicePixels: true }; /** diff --git a/examples/basemap-browser/src/control-panel.tsx b/examples/basemap-browser/src/control-panel.tsx index 9881e3a1254..c60372cbebc 100644 --- a/examples/basemap-browser/src/control-panel.tsx +++ b/examples/basemap-browser/src/control-panel.tsx @@ -68,6 +68,20 @@ function getDimensionsFromUrl(): Partial { result.stressTest = stressTest; } + if (params.has('useDevicePixels')) { + const udp = params.get('useDevicePixels'); + if (udp === 'true') { + result.useDevicePixels = true; + } else if (udp === 'false') { + result.useDevicePixels = false; + } else { + const num = Number(udp); + if (Number.isFinite(num) && num > 0) { + result.useDevicePixels = num; + } + } + } + return result; } @@ -81,6 +95,7 @@ function setUrlFromDimensions(dimensions: Dimensions) { params.set('multiView', String(dimensions.multiView)); params.set('maskDemo', String(dimensions.maskDemo)); params.set('stressTest', dimensions.stressTest); + params.set('useDevicePixels', String(dimensions.useDevicePixels)); const newUrl = `${window.location.pathname}?${params.toString()}`; window.history.replaceState({}, '', newUrl); } @@ -262,6 +277,20 @@ export default function ControlPanel({onConfigChange}: ControlPanelProps) { + {/* Pixel Ratio Override */} +
+ +
+ {/* Stress Test Selection */}
Stress Test:
diff --git a/examples/basemap-browser/src/renderers/pure-js/deck-only.ts b/examples/basemap-browser/src/renderers/pure-js/deck-only.ts index 04e11304a2c..16f3e80feb0 100644 --- a/examples/basemap-browser/src/renderers/pure-js/deck-only.ts +++ b/examples/basemap-browser/src/renderers/pure-js/deck-only.ts @@ -7,8 +7,16 @@ import type {Config} from '../../types'; import {getBaseMapViewState} from '../../config'; export function mount(container: HTMLElement, config: Config): () => void { - const {initialViewState, layers, multiView, views, layerFilter, globe, onViewStateChange} = - config; + const { + initialViewState, + layers, + multiView, + views, + layerFilter, + globe, + useDevicePixels, + onViewStateChange + } = config; // Create a wrapper div for Deck to render into const wrapper = document.createElement('div'); @@ -24,7 +32,8 @@ export function mount(container: HTMLElement, config: Config): () => void { height: '100%', initialViewState: viewState, controller: true, - layers + layers, + useDevicePixels }; // Use GlobeView for globe projection diff --git a/examples/basemap-browser/src/renderers/pure-js/google-maps.ts b/examples/basemap-browser/src/renderers/pure-js/google-maps.ts index 32b44008083..54b21a60569 100644 --- a/examples/basemap-browser/src/renderers/pure-js/google-maps.ts +++ b/examples/basemap-browser/src/renderers/pure-js/google-maps.ts @@ -47,7 +47,7 @@ function loadGoogleMapsAPI(apiKey: string): Promise { } export function mount(container: HTMLElement, config: Config): () => void { - const {initialViewState, layers, interleaved, onViewStateChange} = config; + const {initialViewState, layers, interleaved, useDevicePixels, onViewStateChange} = config; const viewState = getBaseMapViewState(initialViewState); // eslint-disable-next-line no-process-env @@ -84,7 +84,8 @@ export function mount(container: HTMLElement, config: Config): () => void { overlay = new GoogleMapsOverlay({ interleaved, - layers + layers, + useDevicePixels }); overlay.setMap(map); diff --git a/examples/basemap-browser/src/renderers/pure-js/mapbox.ts b/examples/basemap-browser/src/renderers/pure-js/mapbox.ts index 62eff5e8e64..6912981df7d 100644 --- a/examples/basemap-browser/src/renderers/pure-js/mapbox.ts +++ b/examples/basemap-browser/src/renderers/pure-js/mapbox.ts @@ -17,6 +17,7 @@ export function mount(container: HTMLElement, config: Config): () => void { multiView, views, layerFilter, + useDevicePixels, onViewStateChange } = config; @@ -38,18 +39,25 @@ export function mount(container: HTMLElement, config: Config): () => void { // For multi-view, extract the mapbox view state for the base map const mapInitialViewState = getBaseMapViewState(initialViewState); - const map = new mapboxgl.Map({ + const mapOpts: any = { container, style: mapStyle, center: [mapInitialViewState.longitude, mapInitialViewState.latitude], zoom: mapInitialViewState.zoom, bearing: mapInitialViewState.bearing || 0, pitch: mapInitialViewState.pitch || 0 - }); + }; + if (typeof useDevicePixels === 'number') { + mapOpts.pixelRatio = useDevicePixels; + } else if (useDevicePixels === false) { + mapOpts.pixelRatio = 1; + } + const map = new mapboxgl.Map(mapOpts); const overlayConfig: any = { interleaved, - layers + layers, + useDevicePixels }; if (multiView && views) { diff --git a/examples/basemap-browser/src/renderers/pure-js/maplibre.ts b/examples/basemap-browser/src/renderers/pure-js/maplibre.ts index c3229aab89e..7e26371cf53 100644 --- a/examples/basemap-browser/src/renderers/pure-js/maplibre.ts +++ b/examples/basemap-browser/src/renderers/pure-js/maplibre.ts @@ -17,24 +17,32 @@ export function mount(container: HTMLElement, config: Config): () => void { multiView, views, layerFilter, + useDevicePixels, onViewStateChange } = config; // For multi-view, extract the mapbox view state for the base map const mapInitialViewState = getBaseMapViewState(initialViewState); - const map = new maplibregl.Map({ + const mapOpts: maplibregl.MapOptions = { container, style: mapStyle, center: [mapInitialViewState.longitude, mapInitialViewState.latitude], zoom: mapInitialViewState.zoom, bearing: mapInitialViewState.bearing || 0, pitch: mapInitialViewState.pitch || 0 - }); + }; + if (typeof useDevicePixels === 'number') { + mapOpts.pixelRatio = useDevicePixels; + } else if (useDevicePixels === false) { + mapOpts.pixelRatio = 1; + } + const map = new maplibregl.Map(mapOpts); const overlayConfig: any = { interleaved, - layers + layers, + useDevicePixels }; if (multiView && views) { diff --git a/examples/basemap-browser/src/renderers/react/deck-only-component.tsx b/examples/basemap-browser/src/renderers/react/deck-only-component.tsx index 8d6ced90bd3..439f394148e 100644 --- a/examples/basemap-browser/src/renderers/react/deck-only-component.tsx +++ b/examples/basemap-browser/src/renderers/react/deck-only-component.tsx @@ -13,8 +13,16 @@ type DeckOnlyComponentProps = { }; export default function DeckOnlyComponent({config}: DeckOnlyComponentProps) { - const {initialViewState, layers, multiView, views, layerFilter, globe, onViewStateChange} = - config; + const { + initialViewState, + layers, + multiView, + views, + layerFilter, + globe, + useDevicePixels, + onViewStateChange + } = config; const handleViewStateChange = useCallback( ({viewState: vs}: {viewState: any}) => { @@ -63,6 +71,7 @@ export default function DeckOnlyComponent({config}: DeckOnlyComponentProps) { controller={true} layers={layers} views={effectiveViews} + useDevicePixels={useDevicePixels} layerFilter={multiView ? layerFilter : undefined} onViewStateChange={handleViewStateChange} /> diff --git a/examples/basemap-browser/src/renderers/react/google-maps-component.tsx b/examples/basemap-browser/src/renderers/react/google-maps-component.tsx index 11338feb0fa..b0d7f4b385e 100644 --- a/examples/basemap-browser/src/renderers/react/google-maps-component.tsx +++ b/examples/basemap-browser/src/renderers/react/google-maps-component.tsx @@ -12,14 +12,19 @@ import {getBaseMapViewState} from '../../config'; function GoogleMapsDeckOverlay({ layers, interleaved, + useDevicePixels, onViewStateChange }: { layers: any[]; interleaved: boolean; + useDevicePixels?: boolean | number; onViewStateChange?: (vs: InitialViewState) => void; }) { const map = useMap(); - const overlay = useMemo(() => new GoogleMapsOverlay({interleaved}), [interleaved]); + const overlay = useMemo( + () => new GoogleMapsOverlay({interleaved, useDevicePixels}), + [interleaved, useDevicePixels] + ); useEffect(() => { if (map) { @@ -62,7 +67,7 @@ export default function GoogleMapsComponent({config}: GoogleMapsComponentProps) // eslint-disable-next-line no-process-env const mapId = process.env.GoogleMapsMapId || 'DEMO_MAP_ID'; - const {initialViewState, layers, interleaved, onViewStateChange} = config; + const {initialViewState, layers, interleaved, useDevicePixels, onViewStateChange} = config; const viewState = getBaseMapViewState(initialViewState); return ( @@ -79,6 +84,7 @@ export default function GoogleMapsComponent({config}: GoogleMapsComponentProps) diff --git a/examples/basemap-browser/src/renderers/react/mapbox-component.tsx b/examples/basemap-browser/src/renderers/react/mapbox-component.tsx index 322ac4ff8c5..560a08dfe9e 100644 --- a/examples/basemap-browser/src/renderers/react/mapbox-component.tsx +++ b/examples/basemap-browser/src/renderers/react/mapbox-component.tsx @@ -33,6 +33,7 @@ export default function MapboxComponent({config}: MapboxComponentProps) { multiView, views, layerFilter, + useDevicePixels, onViewStateChange } = config; @@ -42,10 +43,17 @@ export default function MapboxComponent({config}: MapboxComponentProps) { return (
{ onViewStateChange?.({ latitude: e.viewState.latitude, @@ -59,6 +67,7 @@ export default function MapboxComponent({config}: MapboxComponentProps) { { if (globe && isMountedRef.current) { // Set projection before rendering overlay (critical for globe + interleaved mode) @@ -90,6 +98,7 @@ export default function MapLibreComponent({config}: MapLibreComponentProps) { + + + + useDevicePixels test (CDN - deck.gl 9.2) + + + + + + +

useDevicePixels test CDN deck.gl 9.2

+

Side-by-side: standalone Deck vs MapboxOverlay interleaved. Uses published deck.gl 9.1 UMD bundle.

+ +
+ + + + +
+ +
+
+

Standalone Deck (internal device)

+
+
Loading...
+
+
+

MapboxOverlay interleaved (attached gl)

+
+
Loading...
+
+
+ + + + diff --git a/examples/basemap-browser/use-device-pixels-cdn-test-9.3.html b/examples/basemap-browser/use-device-pixels-cdn-test-9.3.html new file mode 100644 index 00000000000..400e9d4409d --- /dev/null +++ b/examples/basemap-browser/use-device-pixels-cdn-test-9.3.html @@ -0,0 +1,158 @@ + + + + + useDevicePixels test (CDN - deck.gl 9.3) + + + + + + +

useDevicePixels test CDN deck.gl 9.3

+

Side-by-side: standalone Deck vs MapboxOverlay interleaved. Uses published deck.gl 9.1 UMD bundle.

+ +
+ + + + +
+ +
+
+

Standalone Deck (internal device)

+
+
Loading...
+
+
+

MapboxOverlay interleaved (attached gl)

+
+
Loading...
+
+
+ + + + diff --git a/examples/basemap-browser/use-device-pixels-cdn-test.html b/examples/basemap-browser/use-device-pixels-cdn-test.html new file mode 100644 index 00000000000..50cc9067401 --- /dev/null +++ b/examples/basemap-browser/use-device-pixels-cdn-test.html @@ -0,0 +1,158 @@ + + + + + useDevicePixels test (CDN - deck.gl 9.1) + + + + + + +

useDevicePixels test CDN deck.gl 9.1

+

Side-by-side: standalone Deck vs MapboxOverlay interleaved. Uses published deck.gl 9.1 UMD bundle.

+ +
+ + + + +
+ +
+
+

Standalone Deck (internal device)

+
+
Loading...
+
+
+

MapboxOverlay interleaved (attached gl)

+
+
Loading...
+
+
+ + + + diff --git a/examples/basemap-browser/use-device-pixels-local-test.html b/examples/basemap-browser/use-device-pixels-local-test.html new file mode 100644 index 00000000000..13a969baef9 --- /dev/null +++ b/examples/basemap-browser/use-device-pixels-local-test.html @@ -0,0 +1,180 @@ + + + + + useDevicePixels test (LOCAL build) + + + +

useDevicePixels test LOCAL BUILD

+

Side-by-side comparison: standalone Deck (useDevicePixels) vs MapboxOverlay interleaved (MapLibre pixelRatio + useDevicePixels).
+ Interleaved mode recreates the map with the appropriate pixelRatio.

+ +
+ + + + +
+ +
+
+

Standalone Deck (internal device)

+
+
Loading...
+
+
+

MapboxOverlay interleaved (attached gl)

+
+
Loading...
+
+
+ + + + diff --git a/examples/basemap-browser/use-device-pixels-maplibre-ratio-test-9.3.html b/examples/basemap-browser/use-device-pixels-maplibre-ratio-test-9.3.html new file mode 100644 index 00000000000..e4a754504be --- /dev/null +++ b/examples/basemap-browser/use-device-pixels-maplibre-ratio-test-9.3.html @@ -0,0 +1,182 @@ + + + + + useDevicePixels test - MapLibre pixelRatio vs Deck useDevicePixels + + + + + + +

MapLibre pixelRatio vs Deck useDevicePixels deck.gl 9.3

+

Left: MapLibre's pixelRatio controls the canvas buffer. Right: Deck's useDevicePixels on standalone.
+ This tests whether the interleaved buffer is controlled by MapLibre's pixelRatio (not Deck's useDevicePixels).

+ +
+ + + + +
+ +
+
+

MapboxOverlay interleaved

+
+
Loading...
+
+
+

Standalone Deck

+
+
Loading...
+
+
+ + + + diff --git a/examples/basemap-browser/use-device-pixels-maplibre-ratio-test.html b/examples/basemap-browser/use-device-pixels-maplibre-ratio-test.html new file mode 100644 index 00000000000..66ca5520c35 --- /dev/null +++ b/examples/basemap-browser/use-device-pixels-maplibre-ratio-test.html @@ -0,0 +1,182 @@ + + + + + useDevicePixels test - MapLibre pixelRatio vs Deck useDevicePixels + + + + + + +

MapLibre pixelRatio vs Deck useDevicePixels deck.gl 9.1

+

Left: MapLibre's pixelRatio controls the canvas buffer. Right: Deck's useDevicePixels on standalone.
+ This tests whether the interleaved buffer is controlled by MapLibre's pixelRatio (not Deck's useDevicePixels).

+ +
+ + + + +
+ +
+
+

MapboxOverlay interleaved

+
+
Loading...
+
+
+

Standalone Deck

+
+
Loading...
+
+
+ + + +