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

Store images as canvas for more efficient reuse #14444

Merged
merged 1 commit into from Jan 20, 2023

Conversation

ahocevar
Copy link
Member

Fixes #14436.
Probably also fixes #13362.

This pull request changes the Image wrapper so it can store the loaded image in the canvas of a provided context. This speeds up renderFrame() on maps with many image layers on large screens, because the image does not have to be decoded over and over during drawImage() to the target canvas.

To avoid storing the image twice (once as image, once as canvas), the Image wrapper will replace the image_ with the provided context's canvas on the first getImage() call. To avoid creating a new context whenever the extent changes, which is problematic on iOS due to the limited canvas memory, the sources that use the Image wrapper get a new context_ member, so only a single context is created.

@ahocevar
Copy link
Member Author

The changes in src/ol/renderer/canvas/ImageLayer.js are not necessary for the proposed fix, but I added them for more clarity during the investigation phase before making the changes for this pull request.

@github-actions
Copy link

📦 Preview the website for this branch here: https://deploy-preview-14444--ol-site.netlify.app/.

@tschaub
Copy link
Member

tschaub commented Jan 19, 2023

Nice work, @ahocevar.

Here are the before/after examples (extracted from #14436)

@tschaub
Copy link
Member

tschaub commented Jan 19, 2023

I think this is a good approach given the current image source/layer/renderer setup. As you mention, it avoids hanging on to both an image and a canvas element for each image.

However, this approach is specific to the canvas renderer. In the future, when the webgl renderer renders image layers, it could be nicer to adopt an approach similar to the (evolving) tile source/layer/renderer setup. In the future setup, sources would not hang on to copies of the image (whether a tile or a non-tile). The source just generates the tile/image when asked. The renderer knows about what format it makes sense to cache (e.g. a canvas element or a webgl texture), so it manages the cache.

@ahocevar ahocevar merged commit b8d8419 into openlayers:main Jan 20, 2023
@ahocevar ahocevar deleted the image-canvas branch January 20, 2023 08:17
@werrolf
Copy link

werrolf commented Jan 20, 2023

The performance difference is staggering. >= 6x faster with profiling instrumentation on, so realisitically probably even better if you don't try to measure it :)

Many many thanks @ahocevar :)

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