Skip to content

Fix present/link sync regressions and harden framebuffer integrity#103

Merged
RtlZeroMemory merged 10 commits intomainfrom
fix/present-hash-invalidation-and-damage-link-sync
Feb 27, 2026
Merged

Fix present/link sync regressions and harden framebuffer integrity#103
RtlZeroMemory merged 10 commits intomainfrom
fix/present-hash-invalidation-and-damage-link-sync

Conversation

@RtlZeroMemory
Copy link
Owner

@RtlZeroMemory RtlZeroMemory commented Feb 27, 2026

Summary

  • fix present commit/link synchronization and hash invalidation edge cases
  • make framebuffer link clone paths transactional/no-partial-effects
  • add overlap-safe BLIT coverage and present damage resync hyperlink coverage
  • add C++ extern "C" guards to public headers
  • harden framebuffer link table growth bounds to prevent runaway memory

Validation

  • ctest --test-dir build --output-on-failure (12/12)
  • ctest --test-dir build-asan --output-on-failure (12/12)

Summary by CodeRabbit

Release Notes

  • New Features

    • Added C++ compatibility to all public headers via extern "C" guards
    • Introduced hyperlink target tracking with damage resynchronization
    • Added safe rollback mechanism for framebuffer submissions
    • Implemented link compaction and validation for improved memory management
    • New vector pop operation in utility API
  • Bug Fixes

    • Corrected error codes for invalid blit rectangle operations
    • Added safeguards preventing wide-glyph rendering outside boundaries
  • Tests

    • Added comprehensive hyperlink synchronization and damage tracking tests
    • New tests validating wide-glyph boundary safety

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds C++ compatibility through extern "C" guards across multiple public headers, introduces hyperlink payload comparison and target equality checks in diff logic, implements an in-place submit rollback mechanism via framebuffer synchronization tracking, and enhances framebuffer link handling with cloning, compaction, and validation logic. Additional test coverage validates damage resync with hyperlinks and wide-glyph bounds safety.

Changes

Cohort / File(s) Summary
C++ Compatibility Headers
include/zr/zr_caps.h, include/zr/zr_config.h, include/zr/zr_debug.h, include/zr/zr_drawlist.h, include/zr/zr_engine.h, include/zr/zr_event.h, include/zr/zr_metrics.h, include/zr/zr_platform_types.h, include/zr/zr_result.h, include/zr/zr_terminal_caps.h, include/zr/zr_version.h
Added extern "C" linkage guards around public declarations to enable C++ compatibility without altering function or type signatures.
Damage Rectangle & Structure Updates
src/core/zr_damage.h, src/core/zr_damage.c
Added _link field (uint32_t) to zr_damage_rect_t for allocation-free damage coalescing; removed padding from zr_damage_t; initialized _link field in zr_damage_mark_full and zr_damage_add_span.
Engine Synchronization & Rollback
src/core/zr_engine.c, src/core/zr_engine.h
Introduced fb_next_synced_to_prev flag and padding to track framebuffer synchronization state; implemented rollback mechanism to capture pre-submit fb_next snapshot into fb_stage when needed for safe in-flight recovery.
Framebuffer Link Handling
src/core/zr_framebuffer.c
Added link cloning with validation, link compaction for stale entries, capacity limits enforcement, and safeguards in zr_fb_blit_rect to prevent wide-glyph leads from writing beyond bounds; integrated link state synchronization during damage-rect copying.
Diff Hyperlink Comparison
src/core/zr_diff.c
Added zr_fb_links_eq_exact for exact hyperlink payload comparison and zr_row_links_targets_eq for target equality checks; integrated link equality into dirty-row determination; replaced rect.y0 with rect._link for intrusive next-index storage.
Engine Present & Commit Logic
src/core/zr_engine_present.inc
Added zr_fb_links_prefix_equal helper; extended damage-copy decision to require links compatibility and non-zero damage_rects; introduced state-tracking for invalidation and synchronization; conditional link cloning with fallback invalidation paths.
Drawing Error Handling
src/core/zr_drawlist.c
Changed zr_dl_validate_blit_rect_bounds error code from ZR_ERR_INVALID_ARGUMENT to ZR_ERR_FORMAT for bounds/validity violations.
New Public API
src/util/zr_vec.h
Added zr_vec_pop(zr_vec_t\* v, void\* out_elem) function to pop elements from vectors with result type.
Formatting & Whitespace Cleanups
src/core/zr_cursor.h, src/core/zr_metrics.c, src/core/zr_placeholder.c, src/unicode/.../*, src/util/.../*, examples/zr_example_common.h, tests/golden/.../*, tests/zr_test.c
Removed extraneous whitespace, reformatted multi-line definitions to single-line or explicit brace styles, removed trailing blank lines, and adjusted alignment in function/macro declarations without altering logic or behavior.
Event Packing Formatting
src/core/zr_event_pack.h, src/core/zr_event_pack.c
Reformatted zr_evpack_append_record and zr_evpack_append_record2 declarations and calls across single lines without changing signatures or control flow.
Win32 ConPTY API Update
src/platform/win32/zr_win32_conpty_test.h, src/platform/win32/zr_win32_conpty_test.c
Added size_t out_skip_reason_cap parameter to zr_win32_conpty_run_self_capture for buffer capacity validation; integrated capacity checks and usage throughout function.
Test Additions & Updates
tests/unit/test_engine_present_damage_resync_hyperlinks.c, tests/unit/test_drawlist_blit_rect.c, tests/unit/test_blit.c, tests/unit/test_diff_hotpath_telemetry.c, tests/unit/test_framebuffer_init_resize.c, tests/unit/test_limits.c
Added new tests for damage resync with hyperlinks, wide-glyph blit bounds safety, hyperlink target change detection, and link intern compaction; extended existing framebuffer and limits tests with link API usage.
Test Infrastructure
tests/CMakeLists.txt, tests/zr_test.c, tests/unit/test_metrics_struct.c, tests/golden/zr_golden.c, tests/integration/.../*, tests/unit/test_*.c (miscellaneous)
Added new test executables; updated hex dump context utility to accept mismatch offset parameter; adjusted assertion formatting and fixture data layout without functional changes.

Sequence Diagram

sequenceDiagram
    actor App as Application
    participant Engine as zr_engine_t
    participant FBNext as fb_next
    participant FBStage as fb_stage (snapshot)
    participant FBPrev as fb_prev
    participant Diff as diff_logic

    App->>Engine: submit_drawlist(cmds)
    
    alt fb_next not synced to fb_prev
        Engine->>FBStage: capture snapshot of fb_next
        Note over FBStage: rollback source ready
    else fb_next already synced
        Note over FBStage: snapshot not needed
    end
    
    Engine->>FBNext: apply drawlist commands
    
    alt success
        Engine->>Engine: mark fb_next_synced_to_prev = false
        Note over Engine: sync state cleared after submit
    else failure/rollback
        alt snapshot exists
            Engine->>FBNext: restore from fb_stage
        else no snapshot
            Engine->>FBNext: restore from fb_prev
        end
        Engine->>Engine: rollback complete
    end
    
    App->>Engine: present(metrics)
    
    Engine->>Diff: compare fb_prev vs fb_next
    Diff->>Diff: check exact link equality
    alt links match exactly
        Diff->>Diff: use damage_rect_copy
    else links differ
        Diff->>Diff: verify link targets equality
        Diff->>Diff: compute damage rects if targets differ
    end
    
    Engine->>FBPrev: clone links from presented_fb
    Engine->>Engine: update fb_next_synced_to_prev
    Engine->>App: return metrics with damage info
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Possibly related PRs

Poem

🐰 With C++ now in embrace,
Links dance through damage's space,
Rollbacks safe, wide glyphs tamed,
The framebuffer, refined, reclaimed! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix present/link sync regressions and harden framebuffer integrity' accurately and specifically describes the main changes in the pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/present-hash-invalidation-and-damage-link-sync

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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: 3

🧹 Nitpick comments (6)
src/unicode/zr_wrap.h (1)

8-9: Missing C++ linkage guards.

The PR objectives state "Adds C++ guards to public headers," but this header lacks extern "C" wrappers. For consistency with other headers in this PR and C++ compatibility, consider adding guards.

,

♻️ Proposed fix
 `#ifndef` ZR_UNICODE_ZR_WRAP_H_INCLUDED
 `#define` ZR_UNICODE_ZR_WRAP_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 `#include` "unicode/zr_width.h"

And at the end of the file:

+#ifdef __cplusplus
+}
+#endif
+
 `#endif` /* ZR_UNICODE_ZR_WRAP_H_INCLUDED */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/unicode/zr_wrap.h` around lines 8 - 9, This header is missing C++ linkage
guards; wrap the public declarations with extern "C" when compiling under C++ by
adding an `#ifdef` __cplusplus / extern "C" { ... } / `#endif` pair around the
content of the file (i.e., immediately after the existing include guard macro
ZR_UNICODE_ZR_WRAP_H_INCLUDED is defined and before the final `#endif`), so all
symbols in this header use C linkage when included from C++.
tests/unit/test_engine_submit_drawlist_no_partial_effects.c (1)

159-177: Extract new test literals into named constants and add AAA section markers.

This path is readable today, but repeated hard-coded sizes/dimensions and no test sections make future updates brittle.

♻️ Suggested cleanup
+enum {
+  ZR_TEST_DL_HEADER_SIZE = 64u,
+  ZR_TEST_CMD_HEADER_SIZE = 8u,
+  ZR_TEST_CMD_BLIT_RECT_SIZE = 32u,
+  ZR_TEST_FB_COLS = 10u,
+  ZR_TEST_FB_ROWS = 4u,
+};

 static size_t zr_make_dl_invalid_blit_rect(uint8_t* out, size_t out_cap) {
-  const uint32_t cmd_bytes = 8u + 32u;
-  const uint32_t total_size = 64u + cmd_bytes;
+  const uint32_t cmd_bytes = ZR_TEST_CMD_HEADER_SIZE + ZR_TEST_CMD_BLIT_RECT_SIZE;
+  const uint32_t total_size = ZR_TEST_DL_HEADER_SIZE + cmd_bytes;
   size_t at = 0u;
   ...
 }

 ZR_TEST_UNIT(engine_submit_drawlist_invalid_blit_rect_has_no_partial_effects) {
+  /* --- Arrange --- */
   ...
-  mock_plat_set_size(10u, 4u);
+  mock_plat_set_size(ZR_TEST_FB_COLS, ZR_TEST_FB_ROWS);
   ...
-  mock_plat_set_size(10u, 4u);
+  mock_plat_set_size(ZR_TEST_FB_COLS, ZR_TEST_FB_ROWS);
+  /* --- Act --- */
   ...
+  /* --- Assert --- */
   ZR_ASSERT_TRUE(a_len == b_len);
   ZR_ASSERT_MEMEQ(a_bytes, b_bytes, a_len);
 }

As per coding guidelines "Extract magic numbers to named constants with descriptive names instead of using bare literals" and "Add section markers in long functions ... and in tests (/* --- Arrange/Act/Assert --- */)."

Also applies to: 284-317

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_engine_submit_drawlist_no_partial_effects.c` around lines 159
- 177, The test helper zr_make_dl_invalid_blit_rect contains multiple magic
literals (e.g., 8u, 32u, 64u, 9u, framebuffer dims like 10x4 and w=2) and lacks
Arrange/Act/Assert section markers; refactor by introducing descriptive named
constants (e.g., CMD_HEADER_BYTES, BLIT_PAYLOAD_BYTES, DL_TOTAL_SIZE,
INVALID_SRC_X, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, BLIT_W, BLIT_H) and
replace the bare literals in zr_make_dl_invalid_blit_rect with those constants,
then add AAA comments (/* --- Arrange --- */, /* --- Act --- */, /* --- Assert
--- */) to separate logical sections; apply the same cleanup pattern to the
other test block referenced around lines 284-317.
tests/unit/test_diff_hotpath_telemetry.c (2)

16-26: Consider centralizing zr_bytes_contains in shared test helpers.

zr_bytes_contains here is effectively the same implementation as tests/unit/test_diff_extended_styles.c (Line 112-122). Pulling it into shared test utility code would reduce duplication drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_diff_hotpath_telemetry.c` around lines 16 - 26,
zr_bytes_contains is duplicated across tests; move it into a single shared test
helper and update tests to use it: extract the function (remove static) into a
common test helper header/source (e.g., tests/helpers) so both
test_diff_hotpath_telemetry.c and test_diff_extended_styles.c include the
helper, delete the duplicate implementations in each test, and ensure the helper
is declared with external linkage or inline in the header so both tests link
properly.

296-361: Split this test into helpers to satisfy function-length limits.

The new test is ~66 lines and exceeds the project cap for C functions. Extract setup/scratch initialization into helper(s) to keep this unit under 50 lines.

Refactor sketch
+static void zr_init_diff_scratch_10(zr_diff_scratch_t* scratch, uint64_t* prev_hashes,
+                                    uint64_t* next_hashes, uint8_t* dirty_rows) {
+  memset(scratch, 0, sizeof(*scratch));
+  scratch->prev_row_hashes = prev_hashes;
+  scratch->next_row_hashes = next_hashes;
+  scratch->dirty_rows = dirty_rows;
+  scratch->row_cap = 10u;
+  scratch->prev_hashes_valid = 0u;
+}
+
 ZR_TEST_UNIT(diff_row_cache_marks_dirty_when_hyperlink_targets_change_with_same_refs) {
-  /* full setup + scratch wiring inline */
+  /* arrange */
+  /* act */
+  /* assert */
 }

As per coding guidelines, **/*.c: "Functions should be 20-40 lines, with a maximum of 50 lines".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_diff_hotpath_telemetry.c` around lines 296 - 361, The test
function
ZR_TEST_UNIT(diff_row_cache_marks_dirty_when_hyperlink_targets_change_with_same_refs)
is too long; extract repeated/setup code into small helpers: create one helper
(e.g., setup_fb_with_link) that initializes zr_fb_t prev/next, clears them,
interns the URI (wrapping zr_fb_init, zr_fb_clear, zr_fb_link_intern) and
returns framebuffer(s) and link refs, and another helper (e.g.,
init_diff_scratch_and_caps) that initializes zr_limits_t lim, damage array,
prev_hashes/next_hashes/dirty_rows, fills zr_diff_scratch_t fields
(prev_row_hashes/next_row_hashes/dirty_rows/row_cap/prev_hashes_valid), platform
caps (zr_caps_default + supports_hyperlinks), and zr_term_state_t initial; leave
only the core assertions and the zr_diff_render_ex call in the test body so the
test function length falls under 50 lines and naming (setup_fb_with_link,
init_diff_scratch_and_caps, and
ZR_TEST_UNIT(diff_row_cache_marks_dirty_when_hyperlink_targets_change_with_same_refs))
make locating changes trivial.
tests/unit/test_engine_present_damage_resync_hyperlinks.c (1)

61-63: Return type uint8_t for boolean helper is unconventional.

zr_builder_reserve returns uint8_t (0 or 1) for a boolean check. Consider using bool for clarity, or add a brief comment noting the convention.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_engine_present_damage_resync_hyperlinks.c` around lines 61 -
63, The helper zr_builder_reserve currently returns a uint8_t for a boolean
check; change its return type to bool for clarity by updating the function
signature of zr_builder_reserve(const zr_dl_builder_t* b, size_t bytes) to
return bool, add the appropriate include (stdbool.h) if missing, and ensure any
callers or tests expecting uint8_t are adapted to accept/compare a bool;
alternatively, if you must keep uint8_t, add a one-line comment above
zr_builder_reserve documenting that it returns 0/1 as a boolean.
src/core/zr_engine_present.inc (1)

337-341: Consider using checked arithmetic for the links_bytes calculation.

While links_len is limited to 65535 by the framebuffer API, the local multiplication (size_t)prefix->links_len * sizeof(zr_fb_link_t) lacks defensive bounds checking. This pattern is used elsewhere in the codebase with zr_checked_mul_size() (e.g., zr_framebuffer.c:143). For consistency and defensive programming, apply the same approach:

Suggested check
   if (prefix->links_len != 0u) {
-    const size_t links_bytes = (size_t)prefix->links_len * sizeof(zr_fb_link_t);
+    size_t links_bytes = 0u;
+    if (!zr_checked_mul_size((size_t)prefix->links_len, sizeof(zr_fb_link_t), &links_bytes)) {
+      return false;
+    }
     if (memcmp(prefix->links, full->links, links_bytes) != 0) {

Note: The same unprotected pattern exists in zr_diff.c:331.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/zr_engine_present.inc` around lines 337 - 341, The multiplication
for links_bytes should be done with checked arithmetic: use
zr_checked_mul_size(prefix->links_len, sizeof(zr_fb_link_t), &links_bytes)
(referencing prefix->links_len and zr_fb_link_t) and if the helper returns false
handle the overflow path (e.g., return false) before calling memcmp on
prefix->links and full->links; mirror the pattern used elsewhere (e.g.,
zr_framebuffer.c) so the function in src/core/zr_engine_present.inc defends
against size overflow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/zr_diff.c`:
- Around line 330-333: The memcmp length is computed with unchecked
multiplication (links_bytes = (size_t)a->links_len * sizeof(zr_fb_link_t)) which
may overflow; before multiplying, check that a->links_len <= SIZE_MAX /
sizeof(zr_fb_link_t) (or equivalent) and handle the overflow case (e.g., return
false or propagate an error) so you never call memcmp with a wrapped length;
update the check around a->links_len, compute links_bytes only after the guard,
and keep references to a->links_len, links_bytes, zr_fb_link_t and the memcmp
call consistent.

In `@src/core/zr_drawlist.c`:
- Around line 1633-1645: Change the error returns for BLIT payload/bounds checks
from ZR_ERR_INVALID_ARGUMENT to ZR_ERR_FORMAT: whenever the code validates
cmd->w/cmd->h/cmd->src_x/ src_y/dst_x/dst_y or the zr_checked_add_u32 overflow
checks (variables src_x_end, src_y_end, dst_x_end, dst_y_end) fail, and when the
end coordinates exceed fb->cols or fb->rows, return ZR_ERR_FORMAT instead of
ZR_ERR_INVALID_ARGUMENT so drawlist format violations are reported consistently.

In `@tests/unit/test_drawlist_blit_rect.c`:
- Line 413: The test contains a formatting violation around the assertion call
zr_assert_cell_ascii in tests/unit/test_drawlist_blit_rect.c; run the project's
clang-format pass (bash scripts/clang_format_check.sh --all) and fix the
formatting for the assertion and surrounding lines so the file conforms to the
repository style before merging.

---

Nitpick comments:
In `@src/core/zr_engine_present.inc`:
- Around line 337-341: The multiplication for links_bytes should be done with
checked arithmetic: use zr_checked_mul_size(prefix->links_len,
sizeof(zr_fb_link_t), &links_bytes) (referencing prefix->links_len and
zr_fb_link_t) and if the helper returns false handle the overflow path (e.g.,
return false) before calling memcmp on prefix->links and full->links; mirror the
pattern used elsewhere (e.g., zr_framebuffer.c) so the function in
src/core/zr_engine_present.inc defends against size overflow.

In `@src/unicode/zr_wrap.h`:
- Around line 8-9: This header is missing C++ linkage guards; wrap the public
declarations with extern "C" when compiling under C++ by adding an `#ifdef`
__cplusplus / extern "C" { ... } / `#endif` pair around the content of the file
(i.e., immediately after the existing include guard macro
ZR_UNICODE_ZR_WRAP_H_INCLUDED is defined and before the final `#endif`), so all
symbols in this header use C linkage when included from C++.

In `@tests/unit/test_diff_hotpath_telemetry.c`:
- Around line 16-26: zr_bytes_contains is duplicated across tests; move it into
a single shared test helper and update tests to use it: extract the function
(remove static) into a common test helper header/source (e.g., tests/helpers) so
both test_diff_hotpath_telemetry.c and test_diff_extended_styles.c include the
helper, delete the duplicate implementations in each test, and ensure the helper
is declared with external linkage or inline in the header so both tests link
properly.
- Around line 296-361: The test function
ZR_TEST_UNIT(diff_row_cache_marks_dirty_when_hyperlink_targets_change_with_same_refs)
is too long; extract repeated/setup code into small helpers: create one helper
(e.g., setup_fb_with_link) that initializes zr_fb_t prev/next, clears them,
interns the URI (wrapping zr_fb_init, zr_fb_clear, zr_fb_link_intern) and
returns framebuffer(s) and link refs, and another helper (e.g.,
init_diff_scratch_and_caps) that initializes zr_limits_t lim, damage array,
prev_hashes/next_hashes/dirty_rows, fills zr_diff_scratch_t fields
(prev_row_hashes/next_row_hashes/dirty_rows/row_cap/prev_hashes_valid), platform
caps (zr_caps_default + supports_hyperlinks), and zr_term_state_t initial; leave
only the core assertions and the zr_diff_render_ex call in the test body so the
test function length falls under 50 lines and naming (setup_fb_with_link,
init_diff_scratch_and_caps, and
ZR_TEST_UNIT(diff_row_cache_marks_dirty_when_hyperlink_targets_change_with_same_refs))
make locating changes trivial.

In `@tests/unit/test_engine_present_damage_resync_hyperlinks.c`:
- Around line 61-63: The helper zr_builder_reserve currently returns a uint8_t
for a boolean check; change its return type to bool for clarity by updating the
function signature of zr_builder_reserve(const zr_dl_builder_t* b, size_t bytes)
to return bool, add the appropriate include (stdbool.h) if missing, and ensure
any callers or tests expecting uint8_t are adapted to accept/compare a bool;
alternatively, if you must keep uint8_t, add a one-line comment above
zr_builder_reserve documenting that it returns 0/1 as a boolean.

In `@tests/unit/test_engine_submit_drawlist_no_partial_effects.c`:
- Around line 159-177: The test helper zr_make_dl_invalid_blit_rect contains
multiple magic literals (e.g., 8u, 32u, 64u, 9u, framebuffer dims like 10x4 and
w=2) and lacks Arrange/Act/Assert section markers; refactor by introducing
descriptive named constants (e.g., CMD_HEADER_BYTES, BLIT_PAYLOAD_BYTES,
DL_TOTAL_SIZE, INVALID_SRC_X, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, BLIT_W,
BLIT_H) and replace the bare literals in zr_make_dl_invalid_blit_rect with those
constants, then add AAA comments (/* --- Arrange --- */, /* --- Act --- */, /*
--- Assert --- */) to separate logical sections; apply the same cleanup pattern
to the other test block referenced around lines 284-317.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e9ea6f and 333af95.

📒 Files selected for processing (66)
  • docs/abi/c-abi-reference.md
  • docs/abi/drawlist-format.md
  • docs/user-guide/rendering-model.md
  • examples/zr_example_common.h
  • include/zr/zr_caps.h
  • include/zr/zr_config.h
  • include/zr/zr_debug.h
  • include/zr/zr_drawlist.h
  • include/zr/zr_engine.h
  • include/zr/zr_event.h
  • include/zr/zr_metrics.h
  • include/zr/zr_platform_types.h
  • include/zr/zr_result.h
  • include/zr/zr_terminal_caps.h
  • include/zr/zr_version.h
  • src/core/zr_cursor.h
  • src/core/zr_damage.c
  • src/core/zr_damage.h
  • src/core/zr_diff.c
  • src/core/zr_drawlist.c
  • src/core/zr_engine.c
  • src/core/zr_engine_present.inc
  • src/core/zr_event_pack.c
  • src/core/zr_event_pack.h
  • src/core/zr_framebuffer.c
  • src/core/zr_framebuffer.h
  • src/core/zr_metrics.c
  • src/core/zr_placeholder.c
  • src/platform/win32/zr_win32_conpty_test.c
  • src/platform/win32/zr_win32_conpty_test.h
  • src/unicode/zr_grapheme.h
  • src/unicode/zr_unicode_data.h
  • src/unicode/zr_unicode_pins.h
  • src/unicode/zr_utf8.h
  • src/unicode/zr_width.h
  • src/unicode/zr_wrap.h
  • src/util/zr_arena.h
  • src/util/zr_ring.h
  • src/util/zr_string_builder.h
  • src/util/zr_string_view.h
  • src/util/zr_vec.h
  • tests/CMakeLists.txt
  • tests/golden/zr_golden.c
  • tests/golden/zr_golden.h
  • tests/integration/win32_conpty_rawmode.c
  • tests/integration/win32_conpty_wake.c
  • tests/integration/zr_integration_smoke.c
  • tests/unit/test_arena.c
  • tests/unit/test_blit.c
  • tests/unit/test_checked.c
  • tests/unit/test_damage_rects.c
  • tests/unit/test_diff_hotpath_telemetry.c
  • tests/unit/test_drawlist_blit_rect.c
  • tests/unit/test_drawlist_canvas.c
  • tests/unit/test_drawlist_execute.c
  • tests/unit/test_drawlist_image.c
  • tests/unit/test_drawlist_validate.c
  • tests/unit/test_engine_present_damage_resync_hyperlinks.c
  • tests/unit/test_engine_present_single_flush.c
  • tests/unit/test_engine_submit_drawlist_no_partial_effects.c
  • tests/unit/test_engine_tick_events.c
  • tests/unit/test_framebuffer_init_resize.c
  • tests/unit/test_limits.c
  • tests/unit/test_metrics_struct.c
  • tests/zr_test.c
  • tests/zr_tests_main.c
💤 Files with no reviewable changes (9)
  • src/unicode/zr_utf8.h
  • tests/unit/test_damage_rects.c
  • tests/unit/test_arena.c
  • tests/integration/zr_integration_smoke.c
  • tests/zr_tests_main.c
  • src/unicode/zr_unicode_pins.h
  • tests/unit/test_checked.c
  • src/util/zr_string_view.h
  • tests/golden/zr_golden.h

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 333af95b07

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

@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: 2

🧹 Nitpick comments (3)
src/core/zr_framebuffer.c (2)

546-550: Heap allocation in compaction is justified but worth documenting.

The malloc for the remap table could concern hot-path performance, but compaction is gated by growth/limit conditions (line 672), making it amortized rather than per-frame. Consider adding a brief comment noting this is intentional and amortized.

📝 Suggested comment
+  /*
+   * Heap allocation is acceptable here because compaction only triggers when
+   * growth would occur or limits are exceeded—amortized, not per-frame.
+   */
   uint32_t* remap = (uint32_t*)malloc(remap_bytes);

Based on learnings: "Hot paths must avoid per-frame heap churn; buffer output and perform single flush per present operation"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/zr_framebuffer.c` around lines 546 - 550, Add a brief comment above
the remap allocation in src/core/zr_framebuffer.c explaining that the malloc for
"remap" is intentional and not a per-frame hot-path allocation because it only
occurs during compaction (refer to the remap variable and the
compaction/growth/limit gating in this module), and that compaction is amortized
by being triggered only on growth/limit conditions; keep the comment short and
mention that this avoids per-frame heap churn while allowing a single flush
during compaction.

507-625: Function exceeds 50-line limit; consider adding section markers.

At ~112 lines, this function is well above the coding guideline maximum of 50 lines. The logic is linear and correct, but section markers would improve readability.

♻️ Proposed section markers
 static zr_result_t zr_fb_links_compact_live(zr_fb_t* fb) {
   if (!fb) {
     return ZR_ERR_INVALID_ARGUMENT;
   }
+  /* --- Validate --- */
   if (fb->links_len == 0u) {
     fb->link_bytes_len = 0u;
     return ZR_OK;
   }
   // ... validation continues ...

+  /* --- Allocate remap table --- */
   size_t remap_count = 0u;
   // ... allocation ...

-  /* Mark live refs and sanitize any out-of-range link refs in cells. */
+  /* --- Mark live refs --- */
   for (size_t i = 0u; i < cell_count; i++) {
   // ...

+  /* --- Compact live entries --- */
   const uint32_t old_links_len = fb->links_len;
   // ...

+  /* --- Update cell refs --- */
   for (size_t i = 0u; i < cell_count; i++) {
   // ...

Alternatively, the compaction loop (lines 569-607) could be extracted to a helper function like zr_fb_links_compact_entries(fb, remap, &new_links_len, &new_link_bytes_len) to reduce cognitive load.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/zr_framebuffer.c` around lines 507 - 625, The function
zr_fb_links_compact_live exceeds the 50-line guideline—split it into clear
sections or extract the inner compaction loop into a helper to reduce size and
improve readability; either add section comments (e.g., "validate input", "mark
live refs", "compact entries", "remap cells", "finalize") inside
zr_fb_links_compact_live to break it up, or move the loop that builds new
links/bytes (the body that iterates old_links_len, copies span bytes, updates
new_links_len/new_link_bytes_len and sets remap) into a new helper like
zr_fb_links_compact_entries(zr_fb_t* fb, uint32_t* remap, uint32_t
old_links_len, uint32_t* out_new_links_len, uint32_t* out_new_link_bytes_len)
and call it from zr_fb_links_compact_live while preserving error handling and
remap semantics.
tests/unit/test_limits.c (1)

215-268: Split this test into helpers and add test-phase section markers.

This test is over the 50-line cap and lacks /* --- Arrange/Act/Assert --- */ sections, which makes it harder to maintain.

♻️ Suggested refactor shape
+static void zr_limits_add_ephemeral_links(zr_fb_t* fb, zr_cell_t* left, zr_cell_t* right,
+                                          uint32_t* peak_links_len, uint32_t* peak_link_bytes_len) {
+  /* loop body extracted from test */
+}
+
 ZR_TEST_UNIT(limits_link_intern_compacts_stale_refs_and_bounds_growth) {
+  /* --- Arrange --- */
   zr_fb_t fb;
   memset(&fb, 0, sizeof(fb));
   ZR_ASSERT_EQ_U32(zr_fb_init(&fb, 2u, 1u), ZR_OK);
   ...
-  for (uint32_t i = 0u; i < 64u; i++) {
-    ...
-  }
+  /* --- Act --- */
+  zr_limits_add_ephemeral_links(&fb, left, right, &peak_links_len, &peak_link_bytes_len);
 
+  /* --- Assert --- */
   ZR_ASSERT_TRUE(peak_links_len <= ...);
   ...
 }

As per coding guidelines, **/*.c: Functions should be 20-40 lines, with a maximum of 50 lines and Add section markers in long functions ... and in tests (/* --- Arrange/Act/Assert --- */, /* --- Validate/Compute/Emit --- */).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_limits.c` around lines 215 - 268, Split the long test
function limits_link_intern_compacts_stale_refs_and_bounds_growth into smaller
helpers and add explicit test-phase markers: extract setup into a helper like
init_fb_with_persistent_link (handles zr_fb_init, persistent URI intern and
assigning left/right cells), extract the loop that interns ephemeral URIs into a
helper like intern_ephemeral_links_and_track_peaks (returns peak_links_len and
peak_link_bytes_len), and extract the final lookup/assertions into a
validate_persistent_link_lookup helper; then replace the body of
ZR_TEST_UNIT(limits_link_intern_compacts_stale_refs_and_bounds_growth) with
three short sections marked with comments /* --- Arrange --- */, /* --- Act ---
*/, and /* --- Assert --- */ calling those helpers so the top-level test stays
under 50 lines and follows the Arrange/Act/Assert structure.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/test_limits.c`:
- Around line 235-253: Replace the magic literals in the test loop with
descriptive named constants: introduce e.g. URI_BUF_SIZE (replace 96 used in
char uri_buf[96] and sizeof in snprintf), MAX_EPHEMERAL_URIS (replace 64 loop
bound), and EXPECTED_MAX_PEAK_LINKS (replace 5 used in assertions), then use
these constants in the snprintf call, the for-loop condition, and the final
ZR_ASSERT_TRUE checks (including the peak_link_bytes_len expression that
currently multiplies 5 by (ZR_FB_LINK_URI_MAX_BYTES + ZR_FB_LINK_ID_MAX_BYTES));
update references to uri_buf, i, peak_links_len and peak_link_bytes_len
accordingly so the test documents intent and avoids hardcoded thresholds.
- Around line 228-229: Replace explicit NULL comparisons with the
project-standard `!ptr` style for pointer checks: update assertions like
`ZR_ASSERT_TRUE(left != NULL)` and `ZR_ASSERT_TRUE(right != NULL)` (and any
occurrences for `out_uri`, `out_id`) to use `ZR_ASSERT_TRUE(!left) /
ZR_ASSERT_TRUE(!right)` style equivalently (or the inverse
`ZR_ASSERT_FALSE(!ptr)` depending on existing macros) so all pointer checks in
the test file use the `!ptr` idiom; search for `left`, `right`, `out_uri`, and
`out_id` and update their `== NULL`/`!= NULL` comparisons to the `!ptr` form
while preserving the original assertion logic and macro usage (e.g.,
`ZR_ASSERT_TRUE`).

---

Nitpick comments:
In `@src/core/zr_framebuffer.c`:
- Around line 546-550: Add a brief comment above the remap allocation in
src/core/zr_framebuffer.c explaining that the malloc for "remap" is intentional
and not a per-frame hot-path allocation because it only occurs during compaction
(refer to the remap variable and the compaction/growth/limit gating in this
module), and that compaction is amortized by being triggered only on
growth/limit conditions; keep the comment short and mention that this avoids
per-frame heap churn while allowing a single flush during compaction.
- Around line 507-625: The function zr_fb_links_compact_live exceeds the 50-line
guideline—split it into clear sections or extract the inner compaction loop into
a helper to reduce size and improve readability; either add section comments
(e.g., "validate input", "mark live refs", "compact entries", "remap cells",
"finalize") inside zr_fb_links_compact_live to break it up, or move the loop
that builds new links/bytes (the body that iterates old_links_len, copies span
bytes, updates new_links_len/new_link_bytes_len and sets remap) into a new
helper like zr_fb_links_compact_entries(zr_fb_t* fb, uint32_t* remap, uint32_t
old_links_len, uint32_t* out_new_links_len, uint32_t* out_new_link_bytes_len)
and call it from zr_fb_links_compact_live while preserving error handling and
remap semantics.

In `@tests/unit/test_limits.c`:
- Around line 215-268: Split the long test function
limits_link_intern_compacts_stale_refs_and_bounds_growth into smaller helpers
and add explicit test-phase markers: extract setup into a helper like
init_fb_with_persistent_link (handles zr_fb_init, persistent URI intern and
assigning left/right cells), extract the loop that interns ephemeral URIs into a
helper like intern_ephemeral_links_and_track_peaks (returns peak_links_len and
peak_link_bytes_len), and extract the final lookup/assertions into a
validate_persistent_link_lookup helper; then replace the body of
ZR_TEST_UNIT(limits_link_intern_compacts_stale_refs_and_bounds_growth) with
three short sections marked with comments /* --- Arrange --- */, /* --- Act ---
*/, and /* --- Assert --- */ calling those helpers so the top-level test stays
under 50 lines and follows the Arrange/Act/Assert structure.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 333af95 and 268e21f.

📒 Files selected for processing (2)
  • src/core/zr_framebuffer.c
  • tests/unit/test_limits.c

Copy link

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/core/zr_diff.c (1)

1804-1821: ⚠️ Potential issue | 🟡 Minor

Update remaining intrusive-link terminology for consistency.

The helper now uses rect._link, but Line 1947 still says rect.y0, which is stale and can mislead future maintenance.

Suggested doc-only fix
-  /* Active list links are stored intrusively in rect.y0 via zr_diff_rect_link_*(). */
+  /* Active list links are stored intrusively in rect._link via zr_diff_rect_link_*(). */

As per coding guidelines, "Comments in complex paths must explain decision rationale and tradeoffs, not just field glossaries."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/zr_diff.c` around lines 1804 - 1821, Update the stale doc-comment
that still references rect.y0 to reflect the new intrusive-link field usage;
specifically update the explanatory comment above
zr_diff_rect_link_get/zr_diff_rect_link_set (and nearby coalescing comment) to
mention that rect._link is used as a temporary intrusive "next" index during
indexed coalescing and remove or replace the obsolete rect.y0 reference so the
rationale and tradeoffs accurately describe the use of _link in those functions.
🧹 Nitpick comments (2)
tests/unit/test_drawlist_blit_rect.c (1)

71-95: Extract wire-format literals into named constants.

The helper currently embeds protocol/layout constants (64u, 60u, 32u, header field zeros, etc.). Promote these to local named constants/enums to document intent and reduce brittle maintenance.

As per coding guidelines, Extract magic numbers to named constants with descriptive names and Replace magic thresholds and protocol constants with named constants in local enums or macros.

Also applies to: 99-105, 124-159

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_drawlist_blit_rect.c` around lines 71 - 95, In
zr_builder_finish, replace the hard-coded wire-format literals (e.g. 64u header
offset, magic values like 0x4C44525Au is fine but numeric fields such as 64u,
cmd_bytes offsets, the many trailing 0u fields, and any other magic thresholds
found later at lines 99-105 and 124-159) with named constants or a local enum
(e.g. HEADER_SIZE, HEADER_FIELD_COUNT, CMD_SECTION_OFFSET, RESERVED_FIELD_ZERO)
and use those constants when calling zr_w32 and computing total/cmd_bytes;
update any related variables (total, cmd_bytes) to use the new names for clarity
so the protocol layout intent is documented and maintenance is easier.
tests/unit/test_limits.c (1)

215-267: Break this test into sections (and keep under the max function length).

This test is now over the file guideline max and is harder to scan without Arrange/Act/Assert markers. Please split helper/setup logic or add explicit test sections.

As per coding guidelines, Functions should be 20-40 lines, with a maximum of 50 lines and Add section markers in long functions ... and in tests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_limits.c` around lines 215 - 267, The test
ZR_TEST_UNIT(limits_link_intern_compacts_stale_refs_and_bounds_growth) is too
long—split it into smaller logical sections (Arrange/Act/Assert) or extract
setup/teardown and repeated loops into helper functions to keep each function
≤50 lines; e.g., move fb initialization and persistent link creation into a
helper (using zr_fb_init and zr_fb_link_intern), move the ephemeral-link loop
into its own helper that takes zr_cell_t* left/right and updates peak_* values,
and keep final assertions and the zr_fb_link_lookup/zr_fb_release checks in the
main test body so the top-level test reads as clear Arrange, Act, Assert
sections. Ensure helper names are descriptive and referenced from the main test
so reviewers can locate code by symbols like zr_fb_init, zr_fb_link_intern,
zr_fb_cell, zr_fb_link_lookup, and zr_fb_release.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/zr_drawlist.c`:
- Around line 1027-1043: In zr_dl_validate_cmd_blit_rect, add checks to reject
negative coordinates in the parsed zr_dl_cmd_blit_rect_t (specifically
cmd.src_x, cmd.src_y, cmd.dst_x, cmd.dst_y) in addition to the existing
width/height checks; if any of these four fields are < 0 return ZR_ERR_FORMAT so
malformed blit command payloads are rejected early during
zr_dl_validate_cmd_blit_rect rather than deferred to later stages.

In `@tests/unit/test_drawlist_blit_rect.c`:
- Around line 189-193: Replace explicit NULL comparisons with pointer-truthiness
style: in zr_assert_cell_ascii (use the local pointer c returned from
zr_fb_cell_const) change the assertion that currently reads ZR_ASSERT_TRUE(c !=
NULL) to use the project `!ptr` style (e.g. assert non-null by inverting the
truthiness: ZR_ASSERT_FALSE(!c)); do the same for the other occurrence around
the c pointer at the later reported location (line ~367), ensuring all NULL
checks use `!ptr` style consistently.

---

Outside diff comments:
In `@src/core/zr_diff.c`:
- Around line 1804-1821: Update the stale doc-comment that still references
rect.y0 to reflect the new intrusive-link field usage; specifically update the
explanatory comment above zr_diff_rect_link_get/zr_diff_rect_link_set (and
nearby coalescing comment) to mention that rect._link is used as a temporary
intrusive "next" index during indexed coalescing and remove or replace the
obsolete rect.y0 reference so the rationale and tradeoffs accurately describe
the use of _link in those functions.

---

Nitpick comments:
In `@tests/unit/test_drawlist_blit_rect.c`:
- Around line 71-95: In zr_builder_finish, replace the hard-coded wire-format
literals (e.g. 64u header offset, magic values like 0x4C44525Au is fine but
numeric fields such as 64u, cmd_bytes offsets, the many trailing 0u fields, and
any other magic thresholds found later at lines 99-105 and 124-159) with named
constants or a local enum (e.g. HEADER_SIZE, HEADER_FIELD_COUNT,
CMD_SECTION_OFFSET, RESERVED_FIELD_ZERO) and use those constants when calling
zr_w32 and computing total/cmd_bytes; update any related variables (total,
cmd_bytes) to use the new names for clarity so the protocol layout intent is
documented and maintenance is easier.

In `@tests/unit/test_limits.c`:
- Around line 215-267: The test
ZR_TEST_UNIT(limits_link_intern_compacts_stale_refs_and_bounds_growth) is too
long—split it into smaller logical sections (Arrange/Act/Assert) or extract
setup/teardown and repeated loops into helper functions to keep each function
≤50 lines; e.g., move fb initialization and persistent link creation into a
helper (using zr_fb_init and zr_fb_link_intern), move the ephemeral-link loop
into its own helper that takes zr_cell_t* left/right and updates peak_* values,
and keep final assertions and the zr_fb_link_lookup/zr_fb_release checks in the
main test body so the top-level test reads as clear Arrange, Act, Assert
sections. Ensure helper names are descriptive and referenced from the main test
so reviewers can locate code by symbols like zr_fb_init, zr_fb_link_intern,
zr_fb_cell, zr_fb_link_lookup, and zr_fb_release.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 268e21f and 964e72a.

📒 Files selected for processing (5)
  • src/core/zr_diff.c
  • src/core/zr_drawlist.c
  • src/core/zr_engine_present.inc
  • tests/unit/test_drawlist_blit_rect.c
  • tests/unit/test_limits.c

Copy link

@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.

🧹 Nitpick comments (1)
tests/unit/test_limits.c (1)

215-273: Refactor test into sections/smaller helpers to satisfy local C test style rules.

Line 215 introduces a test body that is ~59 lines and currently lacks explicit /* --- Arrange/Act/Assert --- */ section markers. Please split the flow (or extract helpers) so the function stays within the repo’s size limit and uses section markers for readability.

As per coding guidelines, Functions should be 20-40 lines, with a maximum of 50 lines and Add section markers in long functions (/* --- Section Name --- */) and in tests (/* --- Arrange/Act/Assert --- */, /* --- Validate/Compute/Emit --- */).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/unit/test_limits.c` around lines 215 - 273, The test
limits_link_intern_compacts_stale_refs_and_bounds_growth is too long and lacks
section markers; split it into clearer Arrange/Act/Assert sections or extract
small helper functions to keep each function ≤50 lines. Refactor by moving setup
into a helper (e.g., setup_fb_and_persistent_link to init zr_fb_t, create
persistent_uri and set left->style.link_ref), move the loop into a helper (e.g.,
create_ephemeral_links to intern ephemerals, update right->style.link_ref and
track peak values), and move final lookups/assertions into a validate_results
helper; add explicit comment markers /* --- Arrange --- */, /* --- Act --- */,
/* --- Assert --- */ (or similar) inside the test and ensure the main test body
only orchestrates calls to these helpers so the test function length is reduced
and follows the style rules.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/unit/test_limits.c`:
- Around line 215-273: The test
limits_link_intern_compacts_stale_refs_and_bounds_growth is too long and lacks
section markers; split it into clearer Arrange/Act/Assert sections or extract
small helper functions to keep each function ≤50 lines. Refactor by moving setup
into a helper (e.g., setup_fb_and_persistent_link to init zr_fb_t, create
persistent_uri and set left->style.link_ref), move the loop into a helper (e.g.,
create_ephemeral_links to intern ephemerals, update right->style.link_ref and
track peak values), and move final lookups/assertions into a validate_results
helper; add explicit comment markers /* --- Arrange --- */, /* --- Act --- */,
/* --- Assert --- */ (or similar) inside the test and ensure the main test body
only orchestrates calls to these helpers so the test function length is reduced
and follows the style rules.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 964e72a and 89e562c.

📒 Files selected for processing (2)
  • src/core/zr_engine_present.inc
  • tests/unit/test_limits.c

…lidation-and-damage-link-sync

# Conflicts:
#	docs/abi/c-abi-reference.md
#	docs/abi/drawlist-format.md
#	docs/user-guide/rendering-model.md
#	include/zr/zr_version.h
#	src/core/zr_drawlist.c
#	src/core/zr_engine_present.inc
#	tests/unit/test_drawlist_blit_rect.c
#	tests/unit/test_engine_submit_drawlist_no_partial_effects.c
@RtlZeroMemory RtlZeroMemory merged commit 6c90f86 into main Feb 27, 2026
16 checks passed
@RtlZeroMemory RtlZeroMemory deleted the fix/present-hash-invalidation-and-damage-link-sync branch February 27, 2026 03:53
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