Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COG -> GeoTIFF() + normalize:false -> TileLayer is broken on many newer Android phones #15581

Open
potion-cellar opened this issue Feb 23, 2024 · 3 comments
Labels

Comments

@potion-cellar
Copy link

potion-cellar commented Feb 23, 2024

Describe the bug

When using a TileLayer with a GeoTIFF source that has sources with normalize: false, the TileLayer fails to draw properly on devices which do not support the OES_texture_float GL extension and in a browser that does not manage to provide the extension anyways for WebGL1.0 contexts.

WebGL: INVALID_ENUM: texImage2D: invalid type

Context and Severity

I am now aware that the maintainers of openlayers have been considering and working towards implementing WebGL2 (with a WebGL1 fallback?) and I want to call attention to the below number if it helps influence the decision on if or when this should be implemented:

OES_texture_float support has dropped from ~95% support on Android devices to ~88%, per https://web3dsurvey.com/webgl/extensions/OES_texture_float.

Filtering by Android 14 on this list reveals a troubling collection of popular devices:
https://opengles.gpuinfo.org/listreports.php?extension=GL_OES_texture_float&option=not

I've fleshed out the list here: #15581 (comment)

This number seems pretty reasonable to us as we have hundreds of Android users and we are getting increasing reports of unusable maps, likely a couple dozen users now. All from people with new Pixels and in a variety of browsers including Chrome.

For more color, as of right now this has become a significant, high priority production problem for us as people have upgraded their phones in the past year. We're trying to get some sort of workaround deployed, which may end up having to be an openlayers fork with WebGL2 support.

Of course, I understand that this is a fairly niche feature of the library and this growing production-level problem does not impact probably 99% of the openlayers userbase.

Anyways, the culprit is that newer Exynos chipsets that use Mali GPUs -- these chipsets are used in many flagship and major phone lines, particularly the Pixel, but also some flavors of Samsung Galaxy.

In the code, since normalize: false creates a Float32Array, webgl/TileTexture.js tries to call texImage2D with a FLOAT texel type that is invalid in WebGL1 contexts with no OES_texture_float extension.

Reproduction Steps

  1. Find a device that does not provide the GL_OES_texture_float GL extension.
  2. Make sure your browser does not provide a workaround for this missing extension (for instance, on Pixel 6, Chrome will still show OES_texture_float as an available extension for a WebGL1 context, but WebView will not)
  3. Visit https://openlayers.org/en/latest/examples/cog-style.html or any other example that uses a GeoTIFF with normalize: false. Note the incorrect rendering (solid black, white, green, etc.)
  4. Visit a GeoTIFF example that doesn't use normalize: false and note correct rendering.

Expected Behavior

I should be able to use normalize: false in the sources property of a GeoTIFF source and have my TileLayer style drawn properly across all devices.

At the very least, I should be made aware in the documentation and/or examples that the use of normalize: false is not supported on some significant subset of modern devices, and that normalize: true has better support.

Workarounds?

We're trying to implement some sort of workaround right now. If you have any insights, we'd really appreciate it.

We use singleband Float32 COGs and render contoured gradients using palette. Much of our data is fairly logarithmic so despite our best efforts to use normalize: true we've encountered datasets where the data near the minima becomes unacceptably coarse when normalized.

Here are our only ideas:

  • Fork a WebGL2 version of openlayers -- no code changes in our products needed, but obviously a maintenance headache
  • Use normalize: true and apply some sort of scaling to the data to make it work in at least an acceptable fashion. We would need to change our upstream data pipeline
  • Use RGBA COGs instead, but one of our big features is dynamic/adjustable colorbars. But maybe we can pack the single band float data into RGBA in a way that might work.
  • Stack multiple tile layers with different GeoTIFF min and max settings? Sounds very wasteful

Maybe we're missing something easy here or have been incorrectly trying to use normalize: true. We're happy to provide a few example COGs or even a CodePen if it helps.

@potion-cellar potion-cellar changed the title COG -> GeoTIFF() + normalize:false -> TileLayer() fails to draw on some Android devices, with render warning COG -> GeoTIFF() + normalize:false -> TileLayer() fails to draw on some (newer) Android devices, with WebGL render warning Feb 23, 2024
@potion-cellar potion-cellar changed the title COG -> GeoTIFF() + normalize:false -> TileLayer() fails to draw on some (newer) Android devices, with WebGL render warning COG -> GeoTIFF() + normalize:false -> TileLayer() relies on WebGL extension which is not supported by many newer Android phones especially Google Pixel Feb 23, 2024
@mike-000
Copy link
Contributor

See #13367 #13529 #14366 #14377 #15136

@potion-cellar
Copy link
Author

Ah cool, didn't know a webgl2 port has been in the works for awhile. If more work is needed on a PR I'd be happy to jump in.

@potion-cellar potion-cellar changed the title COG -> GeoTIFF() + normalize:false -> TileLayer() relies on WebGL extension which is not supported by many newer Android phones especially Google Pixel COG -> GeoTIFF() + normalize:false -> TileLayer is broken on many newer Android phones Feb 23, 2024
@potion-cellar
Copy link
Author

potion-cellar commented Feb 23, 2024

As I've slowly wrapped my ahead around the issue and the context for everything I've rewritten the issue to be more straightforward hopefully. I also brought in some additional statistics in case it helps the openlayers maintainers make decisions about future WebGL2 implementation.

In the past few years OES_texture_float support has dropped from ~95% support on Android devices (at least from an archive.org version of webglstats.com in 2021) to ~88%, per the latest web3d survey data: https://web3dsurvey.com/webgl/extensions/OES_texture_float

According to gpuinfo.org, the following devices running Android 13 or 14 have limited (broken in some browsers) or no (broken in all browsers) OES_texture_float support:

  • Pixel 6, Pixel 6a
  • Pixel 7, Pixel 7 Pro
  • Pixel 8, Pixel 8 Pro
  • Samsung Galaxy Tab A7, Active3, A8, S6 Lite,
  • Samsung Galaxy A03, A12, A13, A14, A22, A24, A32, A34, A51, A53, A54, A71 (unlocked/dual sim models)
  • Samsung Galaxy S20, S20 Ultra, S21 (unlocked/dual sim models)
  • Samsung Galaxy Note 9 (dual sim)
  • Oppo Reno8 Pro
  • Xiaomi 11T
  • Xiaomi Redmi 12, Note 12 Pro, 12C
  • Xiaomi 14T
  • Xiaomi Poco M5, X6 Pro

Given the above list, this has not been as problematic in North America and Europe until the newer Pixel versions started gaining market share. For us, we have enough users on Pixel 7 & 8 where it is now a high priority production problem, albeit due to our usage of a niche openlayers feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants