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

MAP-16: only render what’s visible #690

Closed
wants to merge 3 commits into from

Conversation

maerki
Copy link
Contributor

@maerki maerki commented Feb 28, 2025

Summary by CodeRabbit

  • New Features

    • Introduced enhanced control over map object visibility, allowing certain map elements to be dynamically hidden or shown.
  • Refactor

    • Streamlined rendering logic across vector, polygon, and raster layers to improve performance.
    • Optimized zoom range handling and state management for smoother map transitions and more efficient processing.

Copy link
Contributor

coderabbitai bot commented Feb 28, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The changes introduce new visibility management methods for render objects across multiple layers of the codebase. New abstract methods setHidden and isHidden are added to the RenderObject interfaces and propagated into their respective platform-specific implementations (Android, iOS, C++ via JNI, and Djinni). Shared render object classes now maintain a hidden state, and tile rendering logic has been adjusted to conditionally skip processing of hidden objects and streamline zoom-based visibility checks.

Changes

File(s) Change Summary
bridging/android/.../RenderObjectInterface.kt
bridging/android/jni/graphics/NativeRenderObjectInterface.cpp
bridging/android/jni/graphics/NativeRenderObjectInterface.h
Added abstract methods setHidden/isHidden in the RenderObjectInterface, with implementations in CppProxy and new JNI export functions to invoke native visibility updates with error/exception checks.
bridging/ios/MCRenderObjectInterface+Private.mm
bridging/ios/MCRenderObjectInterface.h
Introduced setHidden/isHidden methods in Objective-C proxy classes and protocol, converting booleans between Objective-C and C++ via djinni.
djinni/graphics/core.djinni Extended the djinni interface with set_hidden(hidden: bool) and is_hidden(): bool to support visibility management across language boundaries.
shared/public/RenderObject.h
shared/public/RenderObjectInterface.h
shared/src/graphics/RenderObject.cpp
Added virtual/pure virtual methods setHidden/isHidden and introduced a private hidden variable in RenderObject to manage its visibility state.
shared/src/graphics/Renderer.cpp Modified the drawFrame method to include a preparation flag and to conditionally skip processing for hidden render objects, optimizing the rendering flow.
Tiled layer and tile files:
Tiled2dMapVectorLayerParserHelper.cpp
Tiled2dMapVectorSourceVectorTileDataManager.cpp
`Tiled2dMapVectorLineTile.[cpp
h]<br>Tiled2dMapVectorPolygonPatternTile.[cpp

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Interface as RenderObjectInterface (CppProxy)
    participant JNI as JNI Bridge
    participant Native as Native Layer
    Client->>Interface: setHidden(flag)
    Interface->>Interface: Assert object not destroyed
    Interface->>JNI: Call native_setHidden(flag)
    JNI->>Native: Execute native visibility update
    Native-->>JNI: Return result
    JNI-->>Interface: Pass result
    Interface-->>Client: Acknowledge updated hidden state
Loading
sequenceDiagram
    participant Renderer as Renderer
    participant RenderObj as RenderObject
    Renderer->>RenderObj: isHidden()
    alt RenderObj is hidden
        Renderer->>Renderer: Skip rendering operations
    else RenderObj is visible
        Renderer->>RenderObj: Perform rendering preparation
        Renderer->>RenderObj: Render object
    end
Loading

Possibly related PRs

  • MAP-16: Only render what's visible #664: Introduces similar setHidden and isHidden methods in the RenderObjectInterface and its CppProxy, aligning closely with these changes.
  • Dynamic icon image #673: Adds visibility control in the native JNI layer via the NativeRenderObjectInterface::JavaProxy, directly related to the JNI changes implemented here.

Suggested reviewers

  • stmitt
  • maurhofer-ubique
  • zimmermannubique

Poem

I'm a bunny in the code burrow,
Hopping along with methods so mellow.
Hidden states now softly gleam,
Across Android, iOS, and every stream.
A playful skip in the rendering show,
Where render objects hide and glow.
🐇💻 Happy coding as the pixels flow!


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (8)
shared/src/graphics/RenderObject.cpp (1)

31-37: Implementation of visibility methods looks good.

The implementation is straightforward and correctly manages the hidden state via the member variable.

Consider adding validation or logging in a debug build if this visibility state has implications for performance or rendering behavior.

shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceVectorTileDataManager.cpp (1)

147-150: Efficient filtering for out-of-zoom-range tiles

This condition optimizes performance by skipping the processing of tiles that fall outside of the layer's defined zoom range, with an exception for tiles that match the source's maximum zoom level.

Consider extracting this zoom range check into a separate method for better readability and reusability, especially if similar checks exist elsewhere in the codebase.

-if ((tile->tileInfo.tileInfo.zoomIdentifier < layer->minZoom ||
-     tile->tileInfo.tileInfo.zoomIdentifier > layer->maxZoom) && tile->tileInfo.tileInfo.zoomIdentifier != layer->sourceMaxZoom) {
-    continue;
-}
+if (!isInZoomRange(tile->tileInfo.tileInfo.zoomIdentifier, layer)) {
+    continue;
+}

// Add this helper method to the class
+bool Tiled2dMapVectorSourceVectorTileDataManager::isInZoomRange(int zoomIdentifier, const std::shared_ptr<VectorLayerDescription>& layer) {
+    return (zoomIdentifier >= layer->minZoom && 
+            zoomIdentifier <= layer->maxZoom) || 
+           zoomIdentifier == layer->sourceMaxZoom;
+}
shared/src/graphics/Renderer.cpp (2)

51-52: Initialize prepared more clearly (optional).

Defining the prepared variable is a good approach to ensure stencil and scissor operations are only applied once per pass. However, consider adding a brief comment or renaming the variable to clarify its purpose (e.g., renderPreparationDone) for improved readability.


90-98: Symmetry in post-render logic.

The conditional un-application of scissoring and stencil operations looks correct. Ensure other render states or resources influenced by renderingContext->setupDrawFrame() also do not require cleanup if no object is rendered.

shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h (1)

81-81: Visibility state naming.

Having a tile-level isVisible boolean is consistent, but note that the RenderObjectInterface uses isHidden() as the inverted concept. Consider aligning naming or clarifying if tile visibility differs from object-level visibility.

shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp (3)

362-371: Refactor magic defaults for line layers.

This block sets local int minZoom = 0, maxZoom = 24; by default and then overwrites them if a matching source is found. Consider logging or error-handling when the source is missing to avoid silent fallback.


435-445: Avoid duplicating min/max zoom logic for symbol layers.

The approach of iterating through sourceDescriptions to find matching minZoom/maxZoom is repeated in multiple blocks. A small helper function could eliminate duplication and improve maintainability.


470-478: Consistent min/max zoom for fill layers.

Similar to line and symbol layers, adding an explicit error message or fallback logic if no matching source is found for fill layers could improve debugging and consistency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 869bc72 and 6620e58.

📒 Files selected for processing (20)
  • bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/RenderObjectInterface.kt (2 hunks)
  • bridging/android/jni/graphics/NativeRenderObjectInterface.cpp (2 hunks)
  • bridging/android/jni/graphics/NativeRenderObjectInterface.h (2 hunks)
  • bridging/ios/MCRenderObjectInterface+Private.mm (2 hunks)
  • bridging/ios/MCRenderObjectInterface.h (1 hunks)
  • djinni/graphics/core.djinni (2 hunks)
  • shared/public/RenderObject.h (1 hunks)
  • shared/public/RenderObjectInterface.h (1 hunks)
  • shared/src/graphics/RenderObject.cpp (1 hunks)
  • shared/src/graphics/Renderer.cpp (2 hunks)
  • shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp (4 hunks)
  • shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceVectorTileDataManager.cpp (1 hunks)
  • shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp (8 hunks)
  • shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h (2 hunks)
  • shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp (4 hunks)
  • shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h (1 hunks)
  • shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp (3 hunks)
  • shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h (2 hunks)
  • shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp (1 hunks)
  • shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.h (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (35)
djinni/graphics/core.djinni (1)

61-62: Well-designed visibility control methods added to render_object_interface.

The addition of set_hidden and is_hidden methods provides a clean way to control visibility of render objects across all platforms. This is a good design choice that maintains consistency with the interface's existing style.

bridging/ios/MCRenderObjectInterface.h (1)

18-21: Auto-generated visibility methods look good.

The Objective-C interface correctly includes the new visibility control methods that were defined in the Djinni specification.

shared/public/RenderObjectInterface.h (1)

22-24: LGTM: Pure virtual methods for visibility control.

The pure virtual methods properly establish the contract that all implementing classes must provide visibility control functionality.

shared/public/RenderObject.h (2)

33-35: Added visibility control methods

These methods provide a clean way to control the visibility of render objects, which aligns with the PR objective of only rendering what's visible.


42-42: Added hidden state member

This boolean field correctly tracks the visibility state with a sensible default (visible).

shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.h (1)

55-55: Simplified visibility tracking

Replacing an optional boolean with a direct boolean flag simplifies the state management and improves code readability.

shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp (1)

69-77: Efficient visibility management implementation

This implementation properly updates the render object's visibility state when the zoom range changes and prevents unnecessary processing when the tile is out of the zoom range.

The early return when the tile is not visible is an excellent optimization that prevents unnecessary style calculations and updates.

shared/src/graphics/Renderer.cpp (2)

55-60: Confirm behavior with hidden objects.

Skipping hidden objects early is beneficial for performance. Verify that external code does not rely on any side-effects (e.g., uniform updates, logging, or debugging) that might need to be run even for hidden objects.


61-75: Ensure correct setup on first visible object.

Applying the scissor rect, stencil mask, and mask object rendering only once is a solid optimization. Just confirm that if a pass has all hidden objects, the logic of not calling these operations remains correct (i.e., no additional cleanup is necessary).

shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h (1)

74-75: Consider safe usage of renderObjects.

Storing render objects in a std::vector<std::shared_ptr<RenderObjectInterface>> is straightforward. Confirm that no concurrency or reference cycle issues arise, and ensure the vector is kept in sync with tile lifecycle events (e.g., clearing or invalidation).

shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp (1)

213-246: Validate presence of tile arrays before indexing.

When constructing VectorMapSourceDescription, the code immediately does tileJson["tiles"].begin()->get<std::string>(). Confirm that each tileJson definitely contains a non-empty tiles array to avoid potential out-of-bounds or undefined behavior.

bridging/android/jni/graphics/NativeRenderObjectInterface.h (2)

40-41: Functionality added to improve visibility management.

The addition of these abstract methods enhances the RenderObjectInterface with visibility controls, which aligns with the PR objective of only rendering what's visible.


52-53: Method IDs correctly defined with proper JNI signatures.

The JNI method IDs are correctly defined with proper signatures:

  • (Z)V for setHidden (boolean parameter, void return)
  • ()Z for isHidden (no parameters, boolean return)
shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h (2)

66-66: Added collection to track render objects.

The addition of a vector to store render objects will enable direct management of visibility through the newly added RenderObjectInterface methods.


75-75: Simplified visibility tracking.

Replacing lastInZoomRange (std::optional) with a direct boolean flag isVisible simplifies the visibility state management and aligns with the new visibility control approach.

shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h (2)

63-63: Added collection to track render objects consistently.

Similar to the polygon tile implementation, this new vector enables direct management of render objects' visibility. This maintains consistency in the visibility management approach across different tile types.


73-73: Simplified visibility tracking.

Replacing the optional boolean with a direct isVisible flag simplifies the state management and makes the visibility control more straightforward, matching the approach used in other tile classes.

bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/RenderObjectInterface.kt (2)

19-21: Added visibility control methods to the interface.

These new abstract methods provide the necessary API for controlling render object visibility from Kotlin/Java code.


62-72: Properly implemented visibility methods in CppProxy.

The implementation follows the established pattern:

  1. Checks if the object has been destroyed before proceeding
  2. Delegates to the native implementation
  3. Includes appropriate error handling

This ensures proper bridging between the Java and C++ layers.

shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp (4)

88-97: Add visibility state management for zoom-based conditional rendering.

The code now properly controls the visibility state of render objects based on the zoom range. This optimization prevents render objects from being processed unnecessarily when they're not in the visible zoom range.


114-116: Simplified property retrieval logic.

Removed conditional checks against inZoomRange when retrieving properties. This is a good simplification since the early return above (line 95) already handles the zoom range check.

Also applies to: 122-122


325-332: Centralized render object creation in addPolygons method.

Moving the render object creation to the addPolygons method improves code organization by ensuring render objects are updated whenever polygons change, rather than deferring creation to when they're requested.


357-359: Simplified generateRenderObjects to return cached collection.

Now that render objects are properly maintained when polygons are added or modified, the method can simply return the existing collection instead of creating new objects on each call.

shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp (4)

91-100: Add visibility state management for zoom-based conditional rendering.

This change mirrors the implementation in the Tiled2dMapVectorPolygonTile class, ensuring consistent behavior across different tile types. The early return when outside the zoom range is an effective optimization.


121-124: Simplified opacity calculation.

Removed conditional checks against inZoomRange when calculating opacity. This is appropriate since the early return above (line 98) already handles the zoom range check.


333-340: Centralized render object creation in addPolygons method.

Similar to the change in Tiled2dMapVectorPolygonTile, this ensures render objects are updated whenever polygons change. This approach provides better encapsulation of the render object lifecycle.


366-368: Simplified generateRenderObjects to return cached collection.

Consistent with the changes in other tile types, this simplifies the method to return the existing collection rather than creating new objects on each call.

bridging/ios/MCRenderObjectInterface+Private.mm (2)

63-74: Add visibility state management methods to iOS interface.

The implementation properly handles boolean type conversion between Objective-C and C++ and includes appropriate exception handling. These methods support the visibility management feature added to the tile rendering classes.


113-125: Add ObjcProxy implementations for visibility methods.

The proxy implementation correctly bridges between Objective-C and C++, maintaining the same pattern as other methods in the class. This provides a consistent interface for visibility management across platforms.

shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp (4)

90-100: Add visibility state management for zoom-based conditional rendering.

This implementation mirrors the changes in the polygon tile classes, ensuring a consistent approach to visibility management across different tile types. The early return optimization prevents unnecessary processing when tiles are outside the visible zoom range.


124-125: Simplified property calculation logic.

Removed conditional checks against inZoomRange when retrieving various line properties (color, opacity, blur, width, dash array, offset). This is appropriate since the early return above (line 98) already handles the zoom range check.

Also applies to: 134-135, 141-142, 156-157, 163-164, 196-197


410-417: Centralized render object creation in addLines method.

This change ensures render objects are updated whenever lines are added or modified. Moving this logic to the addLines method provides better encapsulation of the render object lifecycle.


444-446: Simplified generateRenderObjects to return cached collection.

Consistent with the changes in other tile types, this simplifies the method to return the existing collection rather than creating new objects on each call.

bridging/android/jni/graphics/NativeRenderObjectInterface.cpp (2)

50-65: Correctly implemented JavaProxy methods for visibility control

The implementation of setHidden and isHidden follows the established pattern for JavaProxy methods in this file, with proper JNI environment handling, exception checking, and type conversion between C++ and Java.


110-125: JNI export functions properly implemented

The native JNI export functions for setHidden and isHidden are correctly implemented, following the same pattern as other methods in this file. They properly handle reference conversion, exception translation, and type marshaling between Java and C++.

@stmitt stmitt changed the base branch from main to develop February 28, 2025 14:00
@maerki maerki closed this Feb 28, 2025
@maerki maerki deleted the bugfix/MAP-16-avoid-invisible-rendering branch February 28, 2025 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant