Add experimental API to render WebGL textures on the Compose' canvas - #3323
Conversation
|
This is quite close to what MapLibre Compose needs. I use Compose/Skiko's WebGL2 context and share it with MapLibre GL JS, MapLibre renders into an offscreen RGBA8 texture and Skia samples that texture in the Compose draw frame. Today I do this with some fragile Emscripten context discovery and skiko DirectContext interception. For our current MapLibre GL JS integration, the framebuffer exposed by this API is sufficient: I can render MapLibre into it and use drawWebGLTexture to place the result in the Compose draw tree. This PR should let MapLibre Compose remove this fragile hack on the web target. I would also like to use this API with something like my MapLibre Native Wasm prototype (maplibre/maplibre-native-ffi#443). That renderer runs in a separate Emscripten module, so it needs access to the actual WebGLTexture, not only the framebuffer. It registers that browser texture in its own Emscripten object table and passes the resulting handle to MapLibre Native. It would help to expose the color texture as a borrowed resource. We would also need a notification before the texture is replaced or released. On resize, MapLibre must destroy the native render session that refers to the old texture before Compose releases it. Additional context from a Codex / GPT 5.6 Sol agent
|
|
Sargun Vohra (@sargunv) thanks for the feedback. I updated the API to simplify your use case: |
I believe we have older skiko in this branch. Try to test with 0.152.0-alpha02 There was a problem that resize would cause webgl context recreation. And this PR assumes the context is stable. It's fixed in latest skiko. |
|
works great with one more fix in #3344 you can see my integration here: maplibre/maplibre-compose#1114 |
|
and confirmed works great on Kotlin/Wasm too, in this draft. |
Fix `WebGLRenderTarget` rendering after its size changes. `Image.adoptTextureFrom` transfers ownership of the WebGL texture to Skia, so closing the old image deletes that texture. The previous resize path then tried to allocate storage on the deleted texture, which left the framebuffer incomplete. This change creates a texture for each size generation and releases the previous texture through one path after notifying borrowers. PR #3323 and its Skiko update are now on `jb-main`. This PR is the focused resize follow-up. ## Testing In this repo: - `./gradlew :compose:ui:ui:jsBrowserTest --no-daemon --no-configuration-cache` - `./gradlew :mpp:publishComposeJbToMavenLocal -Pcompose.platforms=web -Pjetbrains.publication.libraries=COMPOSE --no-daemon --no-configuration-cache` In maplibre/maplibre-compose#1114: - MapLibre Compose demo startup and resize in Chromium, Safari, and Firefox. - MapLibre Compose JS browser suite: 204 tests, no failures or skips. ## Release Notes N/A

New public experimental APIs:
Simplest usage example:
Fixes https://youtrack.jetbrains.com/issue/CMP-9245/WebGL-interop-for-Wasm-target
Screen.Recording.2026-08-18.at.16.24.24.mov
Testing
Release Notes
Features - Web