Skip to content

Add Device::present_bound_surface API#361

Merged
jdm merged 1 commit into
servo:mainfrom
mrobinson:present-currently-bound-surface
Jun 6, 2026
Merged

Add Device::present_bound_surface API#361
jdm merged 1 commit into
servo:mainfrom
mrobinson:present-currently-bound-surface

Conversation

@mrobinson

@mrobinson mrobinson commented Jun 4, 2026

Copy link
Copy Markdown
Member

In order to present a widget surface that is bound to a context, a user
of surfman must currently:

  • Unbind the surface
  • Present the surface
  • Rebind the surface

On EGL platforms unbinding the surface calls:

eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context);

The expected resize story for Wayland is:

  1. The server calls the application's configure callback with the new
    window size.
  2. The application calls wl_egl_window_resize.
  3. The application waits for the next frame callback.
  4. The application redraws into the surface at the new size.

Notably, wl_egl_window_resize does not resize the surface
immediately. Resizing happens later in a driver-defined way.

In Servo we handle this by:

  1. Receiving the winit resize signal.
  2. Unbinding the surface (calls eglMakeCurrent with NO_SURFACE
    values).
  3. Resizing the surface (calls wl_egl_window_resize)
  4. Rebinding the surface.
  5. Waiting for the redraw signal from winit (presumably triggered by
    the Wayland frame callback).
  6. Repainting the contents at the new size using OpenGL.
  7. Unbinding the surface
  8. Presenting the surface (calls eglSwapBuffers)
  9. Rebinding the surface

Either calling eglMakeCurrent before calling eglSwapBuffers or
calling eglSwapBuffers with no surface bound, means that the driver is
failing to properly resize the surface after wl_egl_window_resize. In
general, constantly having to call eglMakeCurrent multiple times in
order to call eglSwapBuffers is both disruptive and not how typical
OpenGL applications work.

So this change adds a way to present the surface without having to first
unbind it from the context. A followup change will address resizing. It
does not make any changes to existing APIs.

In order to present a widget surface that is bound to a context, a user
of `surfman` must currently:

 - Unbind the surface
 - Present the surface
 - Rebind the surface

On EGL platforms unbinding the surface calls:

```
eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context);
```

The expected resize story for Wayland is:

1. The server calls the application's `configure` callback with the new
   window size.
2. The application calls `wl_egl_window_resize`.
3. The application waits for the next frame callback.
4. The application redraws into the surface at the new size.

Notably, `wl_egl_window_resize` *does not* resize the surface
immediately. Resizing happens later in a driver-defined way.

In Servo we handle this by:

1. Receiving the `winit` resize signal.
2. Unbinding the surface (calls `eglMakeCurrent` with `NO_SURFACE`
   values).
3. Resizing the surface (calls `wl_egl_window_resize`)
4. Rebinding the surface.
5. Waiting for the redraw signal from `winit` (presumably triggered by
   the Wayland frame callback).
6. Repainting the contents at the new size using OpenGL.
7. Unbinding the surface
8. Presenting the surface (calls `eglSwapBuffers`)
9. Rebinding the surface

Either calling `eglMakeCurrent` before calling `eglSwapBuffers` or
calling `eglSwapBuffers` with no surface boudn, means that the driver is
failing to properly resize the surface after `wl_egl_window_resize`. In
general, constantly having to call `eglMakeCurrent` multiple times in
order to call `eglSwapBuffers` is both disruptive and not how typical
OpenGL applications work.

So this change adds a way to present the surface without having to first
unbind it from the context. A followup change will address resizing. It
does make any changes to existing APIs.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
@jdm jdm added this pull request to the merge queue Jun 5, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 5, 2026
@jdm jdm added this pull request to the merge queue Jun 5, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Jun 5, 2026
@jdm jdm added this pull request to the merge queue Jun 6, 2026
Merged via the queue into servo:main with commit 4c50015 Jun 6, 2026
29 checks passed
mrobinson added a commit to mrobinson/surfman that referenced this pull request Jun 7, 2026
Much like servo#361, this change adds a `Device::resize_bound_surface` API so
that widget surfaces can be resized without introducing a spurious
`eglMakeCurrent` with `NO_SURFACE`. This will greatly improve resizing
behavior in Servo.

Signed-off-by: Martin Robinson <martin@abandonedwig.info>
mrobinson added a commit to mrobinson/surfman that referenced this pull request Jun 7, 2026
Much like servo#361, this change adds a `Device::resize_bound_surface` API so
that widget surfaces can be resized without introducing a spurious
`eglMakeCurrent` with `NO_SURFACE`. This will greatly improve resizing
behavior in Servo.

Signed-off-by: Martin Robinson <martin@abandonedwig.info>
mrobinson added a commit to mrobinson/surfman that referenced this pull request Jun 7, 2026
Much like servo#361, this change adds a `Device::resize_bound_surface` API so
that widget surfaces can be resized without introducing a spurious
`eglMakeCurrent` with `NO_SURFACE`. This will greatly improve resizing
behavior in Servo.

Signed-off-by: Martin Robinson <martin@abandonedwig.info>
@mrobinson mrobinson deleted the present-currently-bound-surface branch June 7, 2026 10:20
mrobinson added a commit to mrobinson/surfman that referenced this pull request Jun 7, 2026
Much like servo#361, this change adds a `Device::resize_bound_surface` API so
that widget surfaces can be resized without introducing a spurious
`eglMakeCurrent` with `NO_SURFACE`. This will greatly improve resizing
behavior in Servo.

Signed-off-by: Martin Robinson <martin@abandonedwig.info>
mrobinson added a commit to mrobinson/surfman that referenced this pull request Jun 7, 2026
Much like servo#361, this change adds a `Device::resize_bound_surface` API so
that widget surfaces can be resized without introducing a spurious
`eglMakeCurrent` with `NO_SURFACE`. This will greatly improve resizing
behavior in Servo.

Signed-off-by: Martin Robinson <martin@abandonedwig.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.

2 participants