Skip to content

Move compositor frame ownership into the view renderers#189162

Open
robert-ancell wants to merge 1 commit into
flutter:masterfrom
robert-ancell:linux-subsurface-pre-refactor
Open

Move compositor frame ownership into the view renderers#189162
robert-ancell wants to merge 1 commit into
flutter:masterfrom
robert-ancell:linux-subsurface-pre-refactor

Conversation

@robert-ancell

Copy link
Copy Markdown
Contributor

Make FlCompositorSoftware and FlCompositorOpenGL stateless so they only composite layers into a caller-provided target. The view renderers now own the Cairo surface / OpenGL framebuffer and CPU pixel buffers, size them, and read frames back as required.

Add FlOpenGLFrame to encapsulate the OpenGL framebuffer and CPU pixel copy managed by the OpenGL renderer, and move the shared window-resize logic into a common fl_view_renderer_resize_to_frame method on FlViewRenderer. Drop the now unused return value from fl_compositor_opengl_composite_layers. Update the tests and compositor class descriptions to match.

Make FlCompositorSoftware and FlCompositorOpenGL stateless so they only
composite layers into a caller-provided target. The view renderers now
own the Cairo surface / OpenGL framebuffer and CPU pixel buffers, size
them, and read frames back as required.

Add FlOpenGLFrame to encapsulate the OpenGL framebuffer and CPU pixel
copy managed by the OpenGL renderer, and move the shared window-resize
logic into a common fl_view_renderer_resize_to_frame method on
FlViewRenderer. Drop the now unused return value from
fl_compositor_opengl_composite_layers. Update the tests and compositor
class descriptions to match.
@robert-ancell robert-ancell requested a review from a team as a code owner July 9, 2026 01:24
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jul 9, 2026
@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. platform-linux Building on or for Linux specifically a: desktop Running on desktop team-linux Owned by the Linux platform team labels Jul 9, 2026
@robert-ancell robert-ancell requested a review from mattkae July 9, 2026 01:26

@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 Linux platform rendering by introducing FlOpenGLFrame to manage OpenGL framebuffers and CPU pixel copies, and updating FlCompositorOpenGL and FlCompositorSoftware to composite layers directly into caller-provided contexts. Feedback suggests comparing logical dimensions instead of physical dimensions during resize checks and frame waiting to prevent potential infinite resize loops or deadlocks caused by subpixel rounding mismatches. Additionally, defensive checks are recommended to avoid creating invalid 0x0 framebuffers or Cairo surfaces.

Comment on lines +120 to +125
size_t width = allocation.width * scale_factor;
size_t height = allocation.height * scale_factor;
gboolean frame_size_matches = width == frame_width && height == frame_height;
if (frame_size_matches) {
return FALSE;
}

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.

high

Comparing physical dimensions (width and height) directly with frame_width and frame_height can lead to an infinite resize loop if the physical frame size is not a perfect multiple of the scale_factor (e.g., due to subpixel rounding or layout constraints). Comparing logical dimensions directly using allocation.width and allocation.height avoids this issue entirely.

  size_t logical_frame_width = frame_width / scale_factor;
  size_t logical_frame_height = frame_height / scale_factor;
  gboolean frame_size_matches = allocation.width == logical_frame_width &&
                                allocation.height == logical_frame_height;
  if (frame_size_matches) {
    return FALSE;
  }

size_t frame_width, frame_height;
fl_compositor_opengl_get_frame_size(self->compositor, &frame_width,
&frame_height);
get_frame_size(self, &frame_width, &frame_height);

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.

high

In wait_for_frame, comparing physical dimensions (frame_width == width) can cause a deadlock/freeze if there is a subpixel rounding mismatch (e.g., if the physical frame size is not a perfect multiple of the scale factor). It is safer to compare logical dimensions instead:

    size_t logical_width = gdk_window_get_width(window);
    size_t logical_height = gdk_window_get_height(window);
    size_t frame_width, frame_height;
    get_frame_size(self, &frame_width, &frame_height);
    if (frame_width / scale_factor == logical_width &&
        frame_height / scale_factor == logical_height) {
      break;
    }

size_t frame_width, frame_height;
fl_compositor_software_get_frame_size(self->compositor, &frame_width,
&frame_height);
get_frame_size(self, &frame_width, &frame_height);

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.

high

In wait_for_frame, comparing physical dimensions (frame_width == width) can cause a deadlock/freeze if there is a subpixel rounding mismatch (e.g., if the physical frame size is not a perfect multiple of the scale factor). It is safer to compare logical dimensions instead:

    size_t logical_width = gdk_window_get_width(window);
    size_t logical_height = gdk_window_get_height(window);
    size_t frame_width, frame_height;
    get_frame_size(self, &frame_width, &frame_height);
    if (frame_width / scale_factor == logical_width &&
        frame_height / scale_factor == logical_height) {
      break;
    }

Comment on lines +68 to +69
size_t width = layers[0]->size.width;
size_t height = layers[0]->size.height;

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

Add a defensive check to ensure that width and height are greater than zero before attempting to recreate the framebuffer or allocate memory. Creating a 0x0 framebuffer is invalid in OpenGL and can lead to errors or undefined behavior.

  size_t width = layers[0]->size.width;
  size_t height = layers[0]->size.height;
  if (width == 0 || height == 0) {
    return;
  }

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.

This seems like it may be worthwile?

Comment on lines +175 to +176
size_t width = layers[0]->size.width;
size_t height = layers[0]->size.height;

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

Add a defensive check to ensure that width and height are greater than zero before attempting to recreate the Cairo surface. Creating a 0x0 surface is invalid and will put the surface in an error state. Remember to unlock the mutex before returning.

    size_t width = layers[0]->size.width;
    size_t height = layers[0]->size.height;
    if (width == 0 || height == 0) {
      g_mutex_unlock(&self->frame_mutex);
      return;
    }

@robert-ancell

Copy link
Copy Markdown
Contributor Author

Next step in robert-ancell#2

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

Good by me!

Comment on lines +68 to +69
size_t width = layers[0]->size.width;
size_t height = layers[0]->size.height;

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.

This seems like it may be worthwile?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-linux Building on or for Linux specifically team-linux Owned by the Linux platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants