blob: 310dc390462c91a3e648577ffcdadcd2837843ad [file] [log] [blame]
Name
KHR_swap_buffers_with_damage
Name Strings
EGL_KHR_swap_buffers_with_damage
Contributors
Robert Bragg
Tapani Pälli
Kristian Høgsberg
Benjamin Franzke
Ian Stewart
James Jones
Ray Smith
Contact
Robert Bragg, Intel (robert.bragg 'at' intel.com)
IP Status
No known claims.
Notice
Copyright (c) 2014 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Complete.
Approved by the EGL Working Group on September 17, 2014.
Approved by the Khronos Board of Promoters on November 7, 2014.
Version
Version 13, February 20, 2020
Number
EGL Extension #84
Extension Type
EGL display extension
Dependencies
Requires EGL 1.4
This extension is written against the wording of the EGL 1.4
Specification.
Overview
This extension provides a means to issue a swap buffers request to
display the contents of the current back buffer and also specify a
list of damage rectangles that can be passed to a system
compositor so it can minimize how much it has to recompose.
This should be used in situations where an application is only
animating a small portion of a surface since it enables the
compositor to avoid wasting time recomposing parts of the surface
that haven't changed.
Terminology
This extension and the EGL_KHR_partial_update extension both use the word
"damage" for subtly but significantly different purposes:
"Surface damage" is what the EGL_KHR_swap_buffers_with_damage extension
is concerned with. This is the area of the *surface* that changes between
frames for that surface. It concerns the differences between two buffers -
the current back buffer and the current front buffer. It is useful only to
the consumer.
"Buffer damage" is what the EGL_KHR_partial_update extension is concerned
with. This is the area of a particular buffer that has changed since that
same buffer was last used. As it only concerns changes to a single buffer,
there is no dependency on the next or previous frames or any other buffer.
It therefore cannot be used to infer anything about changes to the surface,
which requires linking one frame or buffer to another. Buffer damage is
therefore only useful to the producer.
Following are examples of the two different damage types. Note that the
final surface content is the same in both cases, but the damaged areas
differ according to the type of damage being discussed.
Surface damage example (EGL_KHR_swap_buffers_with_damage)
The surface damage for frame n is the difference between frame n and frame
(n-1), and represents the area that a compositor must recompose.
Frame 0 Frame 1 Frame 2 Frame 3 Frame 4
+---------+ +---------+ +---------+ +---------+ +---------+
| | |#########| |#########| |#########| |#########|
| | | | |#########| |#########| |#########| Final surface
| | | | | | |#########| |#########| content
| | | | | | | | |#########|
+---------+ +---------+ +---------+ +---------+ +---------+
+---------+ +---------+ +---------+ +---------+ +---------+
|@@@@@@@@@| |@@@@@@@@@| | | | | | |
|@@@@@@@@@| | | |@@@@@@@@@| | | | | Surface damage
|@@@@@@@@@| | | | | |@@@@@@@@@| | |
|@@@@@@@@@| | | | | | | |@@@@@@@@@|
+---------+ +---------+ +---------+ +---------+ +---------+
Buffer damage example (EGL_KHR_partial_update)
The buffer damage for a frame is the area changed since that same buffer was
last used. If the buffer has not been used before, the buffer damage is the
entire area of the buffer.
The buffer marked with an 'X' in the top left corner is the buffer that is
being used for that frame. This is the buffer to which the buffer age and
the buffer damage relate.
Note that this example shows a double buffered surface - the actual number
of buffers could be different and variable throughout the lifetime of the
surface. The age *must* therefore be queried for every frame.
Frame 0 Frame 1 Frame 2 Frame 3 Frame 4
+---------+ +---------+ +---------+ +---------+ +---------+
| | |#########| |#########| |#########| |#########|
| | | | |#########| |#########| |#########| Final surface
| | | | | | |#########| |#########| content
| | | | | | | | |#########|
+---------+ +---------+ +---------+ +---------+ +---------+
X---------+ +---------+ X---------+ +---------+ X---------+
| | | | |#########| |#########| |#########|
| | | | |#########| |#########| |#########| Buffer 1 content
| | | | | | | | |#########|
| | | | | | | | |#########|
+---------+ +---------+ +---------+ +---------+ +---------+
X---------+ +---------+ X---------+ +---------+
|#########| |#########| |#########| |#########|
| | | | |#########| |#########| Buffer 2 content
| | | | |#########| |#########|
| | | | | | | |
+---------+ +---------+ +---------+ +---------+
0 0 2 2 2 Buffer age
+---------+ +---------+ +---------+ +---------+ +---------+
|@@@@@@@@@| |@@@@@@@@@| |@@@@@@@@@| | | | |
|@@@@@@@@@| |@@@@@@@@@| |@@@@@@@@@| |@@@@@@@@@| | | Buffer damage
|@@@@@@@@@| |@@@@@@@@@| | | |@@@@@@@@@| |@@@@@@@@@|
|@@@@@@@@@| |@@@@@@@@@| | | | | |@@@@@@@@@|
+---------+ +---------+ +---------+ +---------+ +---------+
New Procedures and Functions
EGLBoolean eglSwapBuffersWithDamageKHR (
EGLDisplay dpy,
EGLSurface surface,
const EGLint *rects,
EGLint n_rects);
New Tokens
None
Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
Add the following text to subsection 3.9.1 titled "Posting to a
Window" after the description of eglSwapBuffers.
As an alternative to eglSwapBuffers use:
EGLBoolean eglSwapBuffersWithDamageKHR (
EGLDisplay dpy,
EGLSurface surface,
const EGLint *rects,
EGLint n_rects);
to do the same thing as eglSwapBuffers but additionally report
a list of rectangles that define the region that has truly
changed since the last frame. To be clear; the entire contents
of the back buffer will still be swapped to the front so
applications using this API must still ensure that the entire
back buffer is consistent. The rectangles are only a hint for
the system compositor so it can avoid recomposing parts of the
surface that haven't really changed.
<rects> points to a list of integers in groups of four that
each describe a rectangle in screen coordinates in this
layout: {x, y, width, height}. The rectangles are specified
relative to the bottom-left of the surface and the x and y
components of each rectangle specify the bottom-left position
of that rectangle. <n_rects> determines how many groups of 4
integers can be read from <rects>. It is not necessary to
avoid overlaps of the specified rectangles.
If <n_rects> is 0 then <rects> is ignored and the entire
surface is implicitly damaged and the behaviour is equivalent
to calling eglSwapBuffers.
The error conditions checked for are the same as for the
eglSwapBuffers api.
Modify the first paragraph of Section 3.9.1 titled "Native Window
Resizing"
"If the native window corresponding to <surface> has been
resized prior to the swap, <surface> must be resized to match.
<surface> will normally be resized by the EGL implementation
at the time the native window is resized. If the
implementation cannot do this transparently to the client,
then eglSwapBuffers and eglSwapBuffersWithDamageKHR must
detect the change and resize surface prior to copying its
pixels to the native window. In this case the meaningfulness
of any damage rectangles forwarded by
eglSwapBuffersWithDamageKHR to the native window system is
undefined."
Modify the following sentences in Section 3.9.3, page 51 (Posting
Semantics)
Paragraph 2, first sentence:
"If <dpy> and <surface> are the display and surface for the
calling thread's current context, eglSwapBuffers,
eglSwapBuffersWithDamageKHR, and eglCopyBuffers perform an
implicit flush operation on the context (glFlush for OpenGL or
OpenGL ES context, vgFlush for an OpenVG context)."
Paragraph 3, first sentence:
"The destination of a posting operation (a visible window, for
eglSwapBuffers or eglSwapBuffersWithDamageKHR, or a native
pixmap, for eglCopyBuffers) should have the same number of
components and component sizes as the color buffer it's being
copied from."
Paragraph 6, first two sentences:
"The function
EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint
interval);
specifies the minimum number of video frame periods per color
buffer post operation for the window associated with the
current context. The interval takes effect when eglSwapBuffers
or eglSwapBuffersWithDamageKHR is first called subsequent to
the eglSwapInterval call."
Modify the following sentences in Section 3.9.4, page 52 (Posting
Errors)
Paragraph 1, first sentence:
"eglSwapBuffers, eglSwapBuffersWithDamageKHR, and
eglCopyBuffers return EGL_FALSE on failure."
Paragraph 1, seventh sentence:
"If eglSwapBuffers or eglSwapBuffersWithDamageKHR are called
and the native window associated with <surface> is no longer
valid, an EGL_BAD_NATIVE_WINDOW error is generated. If
eglSwapBuffersWithDamageKHR is called and <n_rects>, is less
than zero or <n_rects> is greater than zero but <rects> is
NULL, EGL_BAD_PARAMETER is generated."
Dependencies on OpenGL ES
None
Dependencies on OpenVG
None
Issues
1) Do applications have to make sure the rectangles don't overlap?
RESOLVED: No, that would be inconvenient for applications and we
see no difficulty for implementations to supporting overlapping
rectangles.
2) Would it be valid for an implementation to discard the list of
rectangles internally and work just in terms of the
eglSwapBuffers api?
RESOLVED: Yes, the rectangles are only there for optimization
purposes so although it wouldn't be beneficial to applications if
it was convenient at times then it would be compliant for an
implementation to discard the rectangles and just call
eglSwapBuffers instead. The error conditions that should be
checked for are compatible with the requirements for
eglSwapBuffers.
3) What origin should be used for damage rectangles?
RESOLVED: Bottom left since this is consistent with all other
uses of 2D window coordinates in EGL and OpenGL that specify a
bottom left origin.
Originally this specification was written with a top-left origin
for the damage rectangles even though it was known to be
inconsistent and that was because most window systems use a
top-left origin and there are some awkward semantic details
related to handling native window resizing that we had hoped to
simplify.
This extension and also several other existing EGL extensions
struggle to guarantee a reliable behaviour in response to native
window resizing which can happen asynchronously on some platforms
and this can make it difficult for applications to avoid certain
visual artefacts.
The crux of the problem is that when a native window is
asynchronously resized then the window system may maintain the old
buffer contents with respect to a different origin than EGL's
bottom left origin. For this extension that means that EGL damage
rectangles that are intended to map to specific surface contents
may end up mapping to different contents when a native window is
resized because the rectangles and buffer contents will be moved in
different directions in relation to the new window size.
In the end we decided that this issue isn't simply solved by
choosing to use a top-left origin and so we can instead aim for
consistency and clarify what guarantees we offer in relation to
native window resizing separate from this issue.
4) What guarantees do we provide about the meaningfulness of EGL
damage rectangles that are forwarded to the native window system
when presenting to a native window that has been resized?
RESOLVED: The meaningfulness of those forwarded damage rectangles
is undefined since this simplifies the implementation requirements
and we saw very little benefit to applications from providing
stricter guarantees.
The number of applications that would be able to avoid fully
redrawing the contents of a window in response to a window resize
is expected to be so low that there would be almost no benefit to
defining strict guarantees here.
Since EGL already states that the contents of window surface
buffers become undefined when a native window has been resized,
this limitation doesn't introduce any new issue for applications
to consider. Applications should already fully redraw buffer
contents in response to a native window resize, unless they are
following some platform specific documentation that provides
additional guarantees.
For an example of the implementation details that make this an
awkward issue to provide guarantees for we can consider X11 based
platforms where native windows can be resized asynchronously with
respect to a client side EGL surface:
With X11 there may be multiple "gravity" transformations that can
affect how surface buffer content is positioned with respect to a
new native window size; there is the core X "bit gravity" and
there is the EGL driver gravity that determines how a surface's
contents with one size should be mapped to a native window with a
different size. Without very careful cooperation between the EGL
driver and the core X implementation and without the right
architecture to be able to do transforms atomically with respect
to different clients that may enact a window resize then it is not
possible to reliably map EGL damage rectangles to native window
coordinates.
The disadvantage of a driver that is not able to reliably map EGL
damage rectangles to native window coordinates is that a native
compositor may re-compose the wrong region of window. This may
result in a temporary artefact until the full window gets redrawn
and then re-composed. X11 already suffers other similar transient
artefacts when resizing windows.
The authors of this spec believe that even if a driver can't do
reliable mappings of EGL damage rectangles then compositors would
be able mitigate the majority of related artefacts by ignoring
sub-window damage during an interactive window resize.
The authors of this spec believe that that if an X11 driver did
want to reliably map EGL damage rectangles to the native window
coordinates then that may be technically feasible depending on the
driver architecture. For reference one approach that had been
considered (but not tested) is as follows:
1) When eglSwapBuffersWithDamageKHR is called, send EGL damage
rectangles from the client to a driver component within the
xserver un-transformed in EGL window surface coordinates with a
bottom-left origin.
2) Within the X server the driver component should look at the
bit-gravity of a window and use the bit-gravity convention to
copy EGL surface content to the front-buffer of a native window.
3) Within the X server the driver component should use the same
gravity transform that was used to present the surface content
to also transform the EGL damage rectangle coordinates.
Note that because this transform is done in the xserver then
this is implicitly synchronized with all clients that would
otherwise be able to enact an asynchronous window resize.
Revision History
Version 1, 29/07/2011
- First draft
Version 2, 03/08/2011
- Clarify that the rectangles passed may overlap
Version 3, 01/09/2011
- Fix a missing '*' in prototype to make rects a pointer
Version 4, 11,02,2012
- Clarify that implementing in terms of eglSwapBuffers would be
compliant.
Version 5, 11,02,2012
- Tweak the cases where we report BAD_PARAMETER errors
Version 6, 05/02/2013
- Specify more thorough updates across the EGL 1.4 spec
wherever it relates to the eglSwapBuffers api
- Clarify that passing <n_rects> of 0 behaves as if
eglSwapBuffers were called.
Version 7, 14/02/2013
- Specify that a bottom-left origin should be used for rectangles
Version 8, 19/03/2013
- Add Ian and James as contributors
- Add an issue explaining why we changed to a bottom-left origin
- Clarify that the behaviour is undefined when presenting to a
native window that has been resized.
- Document the awkward details that would be involved in
providing more strict guarantees when presenting to a native
window that has been resized.
Version 9, 12/06/2013, Chad Versace <chad.versace@intel.com>
- Remove the "all rights reserved" clause from the copyright notice. The
removal does not change the copyright notice's semantics, since the
clause is already implied by any unadorned copyright notice. But, the
removal does diminish the likelihood of unwarranted caution in readers
of the spec.
- Add "IP Status" section to explicitly state that this extension has no
knonw IP claims.
Version 10, 19/08/2014
- Draft for promoting to KHR
- Added section on terminology and damage types
Version 11, 10/09/2014
- Marked as display extension
Version 12, 11/05/2014
- Change copyright to Khronos after signoff from Intel.
Version 13, 20/02/2020, Jon Leech
- Constify rects parameter (EGL-Registry issue 98).