Skip to content

Desktop: Use dirty rects for UI texture uploads#4305

Open
timon-schelling wants to merge 1 commit into
masterfrom
desktop-improve-cef-view
Open

Desktop: Use dirty rects for UI texture uploads#4305
timon-schelling wants to merge 1 commit into
masterfrom
desktop-improve-cef-view

Conversation

@timon-schelling

Copy link
Copy Markdown
Member

Slightly improves latency for large windows. Most noticeable on low end hardware with a "slow" CPU to GPU bus. Almost no effect on faster systems or systems with unified memory.
Mostly useful for Linux, we have ui acceleration disabled by default currently.

Wanted to do this for quite some time now.
Not as effective as I hoped and dose nothing about the still not optimal resize latency.
Still consider it a good idea to merge this and if only for the cleanup.

@timon-schelling

Copy link
Copy Markdown
Member Author

@TrueDoctor Would likely self merge soon. Not sure if this needs your review.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the CEF rendering pipeline by introducing a new View struct to manage texture uploads and state, replacing the previous FrameBufferRef implementation. It also updates RenderState::bind_ui_texture to optimize redundant texture bindings. Feedback on the changes highlights a bug in the dirty rectangle clamping logic within View::upload_frame_buffer when dealing with negative coordinates, which could lead to incorrect pixel copies, and suggests a robust intersection-based calculation to resolve it.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread desktop/src/cef/view.rs
Comment on lines +64 to +70
let x = (rect.x.max(0) as u32).min(width);
let y = (rect.y.max(0) as u32).min(height);
let rect_width = (rect.width.max(0) as u32).min(width - x);
let rect_height = (rect.height.max(0) as u32).min(height - y);
if rect_width == 0 || rect_height == 0 {
continue;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current clamping logic does not correctly handle cases where the dirty rectangle starts off-screen (e.g., rect.x < 0). If rect.x is negative, x is clamped to 0, but rect_width is not adjusted to account for the shifted start. This causes the copy operation to upload pixels outside the actual dirty region, and can even result in copying pixels when the dirty rect is entirely off-screen (e.g., rect.x = -100, rect.width = 50).

Using proper rectangle intersection ensures that only the visible portion of the dirty rectangle is uploaded, avoiding unnecessary GPU writes.

			let x1 = rect.x.max(0).min(width as i32);
			let y1 = rect.y.max(0).min(height as i32);
			let x2 = (rect.x + rect.width).max(0).min(width as i32);
			let y2 = (rect.y + rect.height).max(0).min(height as i32);

			let rect_width = (x2 - x1).max(0) as u32;
			let rect_height = (y2 - y1).max(0) as u32;
			if rect_width == 0 || rect_height == 0 {
				continue;
			}
			let x = x1 as u32;
			let y = y1 as u32;

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 9 files

Confidence score: 2/5

  • In desktop/src/cef/internal/render_handler.rs, the accelerated paint callback currently does info.unwrap(), so a missing texture info (None) will panic and can crash the app during rendering; this is a concrete runtime stability risk in a user-facing path—handle None locally (log and return early) before merging.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="desktop/src/cef/internal/render_handler.rs">

<violation number="1" location="desktop/src/cef/internal/render_handler.rs:54">
P1: Accelerated paint can crash the app when no texture info is provided, because `info.unwrap()` panics in a callback path. Handling `None` locally (log + return) keeps rendering resilient.

(Based on your team's feedback about avoiding panicking Option/Result handling in application code.) [FEEDBACK_USED]</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment on lines +54 to +55
self.view.import_shared_texture(info.unwrap());
self.event_handler.draw(&self.view)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1: Accelerated paint can crash the app when no texture info is provided, because info.unwrap() panics in a callback path. Handling None locally (log + return) keeps rendering resilient.

(Based on your team's feedback about avoiding panicking Option/Result handling in application code.)

View Feedback: 1 2

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At desktop/src/cef/internal/render_handler.rs, line 54:

<comment>Accelerated paint can crash the app when no texture info is provided, because `info.unwrap()` panics in a callback path. Handling `None` locally (log + return) keeps rendering resilient.

(Based on your team's feedback about avoiding panicking Option/Result handling in application code.) </comment>

<file context>
@@ -31,29 +33,26 @@ impl<H: CefEventHandler> ImplRenderHandler for RenderHandlerImpl<H> {
-		}
-
-		self.event_handler.draw_gpu(shared_handle);
+		self.view.import_shared_texture(info.unwrap());
+		self.event_handler.draw(&self.view)
 	}
</file context>
Suggested change
self.view.import_shared_texture(info.unwrap());
self.event_handler.draw(&self.view)
if let Some(info) = info {
self.view.import_shared_texture(info);
self.event_handler.draw(&self.view)
} else {
tracing::error!("Missing accelerated paint info");
}

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