Skip to content

cobalt: Use activity Window surface for UI rendering#11538

Open
kjyoun wants to merge 1 commit into
youtube:mainfrom
kjyoun:window-surface-pr
Open

cobalt: Use activity Window surface for UI rendering#11538
kjyoun wants to merge 1 commit into
youtube:mainfrom
kjyoun:window-surface-pr

Conversation

@kjyoun

@kjyoun kjyoun commented Jul 24, 2026

Copy link
Copy Markdown
Member

Introduces support for rendering UI directly into the Activity's Window surface via Window.takeSurface(), as an alternative to an embedded child SurfaceView.

This behavior is abstracted behind WindowSurfaceBridge and is controlled by the --use-window-surface-for-ui command-line flag (disabled by default).

Before
Idx   | Layer Name                                                   | Type             | Z-Ord  | Active Buffer       
-------------------------------------------------------------------------------------------------------------------
1     | dev.cobalt.coat/dev.cobalt.app.MainActivity#0 (Main Window / UI Container) | BufferQueueLayer | 0      | 1920x1080           
2     | SurfaceView - dev.cobalt.coat/dev.cobalt.app.MainActivity#1 (Active UI SurfaceView) | BufferQueueLayer | -1     | 1920x1080           
3     | SurfaceView - dev.cobalt.coat/dev.cobalt.app.MainActivity#0 (Active Video SurfaceView) | BufferQueueLayer | -2     | 3840x2160           
===================================================================================================================

`use-window-surface-for-ui` is enabled
Idx   | Layer Name                                                   | Type             | Z-Ord  | Active Buffer       
-------------------------------------------------------------------------------------------------------------------
1     | dev.cobalt.coat/dev.cobalt.app.MainActivity#0 (Main Window / UI Container) | BufferQueueLayer | 0      | 1920x1080           
2     | SurfaceView - dev.cobalt.coat/dev.cobalt.app.MainActivity#0 (Active Video SurfaceView) | BufferQueueLayer | -2     | 3840x2160           
===================================================================================================================

Issue: 494590075

@github-actions

Copy link
Copy Markdown
Contributor

🤖 Gemini Suggested Commit Message


android: Support Window surface for UI rendering

Enable rendering the UI directly into the Android Activity's Window
surface as an alternative to an embedded child SurfaceView. This allows
Cobalt to take full ownership of the window surface when requested.

This behavior is toggled via a command-line flag and provides better
integration with certain Android window management scenarios where
a separate SurfaceView is not ideal.

Issue: 494590075

💡 Pro Tips for a Better Commit Message:

  1. Influence the Result: Want to change the output? You can write custom prompts or instructions directly in the Pull Request description. The model uses that text to generate the message.
  2. Re-run the Generator: Post a comment with: /generate-commit-message

@kjyoun
kjyoun force-pushed the window-surface-pr branch from abfea0c to c37b117 Compare July 24, 2026 16:54
@kjyoun
kjyoun marked this pull request as ready for review July 24, 2026 16:55
@kjyoun
kjyoun requested a review from a team as a code owner July 24, 2026 16:55

@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 ContentViewRenderView to support rendering directly to the Activity's Window surface via a new WindowSurfaceBridge strategy, alongside the default child SurfaceView rendering path (SurfaceViewBridge). An abstract SurfaceBridge class is introduced to encapsulate these strategies. The feedback highlights a potential NullPointerException in WindowSurfaceBridge.connect() where windowAndroid.getActivity() is dereferenced without a null check.

Comment thread cobalt/shell/android/java/src/dev/cobalt/shell/ContentViewRenderView.java Outdated
Introduces support for rendering UI directly into the Activity's Window surface
via Window.takeSurface(), as an alternative to an embedded child SurfaceView.

This behavior is abstracted behind WindowSurfaceBridge and is controlled by
the `--use-window-surface-for-ui` command-line flag (disabled by default).

Issue: 494590075

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

The change overall looks good to me, but we need @johnxwork for a final review.


protected SurfaceBridge createSurfaceBridge() {
return new SurfaceBridge();
if (CommandLine.getInstance().hasSwitch("use-window-surface-for-ui")) {

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.

The function is called very early in CobaltActivity.createContent() right after CommandLine is initialized. My understanding is we have to use kimono gcl to run the experiments. And please double check if the change can be properly enabled via the experiments.

if (!(surfaceCallback instanceof SurfaceHolder.Callback2)) {
return;
}
((SurfaceHolder.Callback2) surfaceCallback).surfaceRedrawNeeded(holder);

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.

The input callback is defined as SurfaceHolder.Callback, but takeSurface requires a SurfaceHolder.Callback2. While casting the surfaceCallback to SurfaceHolder.Callback2 is necessary to implement the redraw notification, please ensure that the cast here is intentional and safe.

/**
* @return whether the surface view is initialized and ready to render.
*/
public boolean isInitialized() {

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.

nit: this function was removed, but it appears that it was unused anyway.


@Override
protected void connect(
SurfaceHolder.Callback surfaceCallback, WindowAndroid windowAndroid) {

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.

I think adding a new method ContentViewRenderView.getWindow() in ContentViewRenderView and then retrieving the mWindow during the initialize() would be a cleaner, more consistent approach that aligns better with the SurfaceViewBridge initialization pattern.

*/
@JNINamespace("cobalt")
public class ContentViewRenderView extends FrameLayout {
private static final String TAG = "cobalt";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: use import static dev.cobalt.util.Log.TAG;

mWindowSurfaceHolder = holder;
if (mSurfaceFormat != null) {
Log.i(TAG, "ContentViewRenderView: Applying pending format");
mWindowSurfaceHolder.setFormat(mSurfaceFormat);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should mSurfaceFormat be cleaned up once it is applied?

@borongc

borongc commented Jul 24, 2026

Copy link
Copy Markdown
Member

nit: title should be android: Use activity Window surface for UI rendering

new CobaltA11yHelper(this, mShellManager.getContentViewRenderView().getSurfaceView());

maybeRegisterNetworkRecoveryObserver();
new CobaltA11yHelper(this, mShellManager.getContentViewRenderView().getAnchorView());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should check if this breaks a11y.

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.

3 participants