1Name 2 3 KHR_partial_update 4 5Name Strings 6 7 EGL_KHR_partial_update 8 9Contributors 10 11 Ray Smith 12 Tom Cooksey 13 James Jones 14 Chad Versace 15 Jesse Hall 16 17Contact 18 19 Ray Smith, ARM (Raymond.Smith 'at' arm.com) 20 21IP Status 22 23 No known claims. 24 25Notice 26 27 Copyright (c) 2014 The Khronos Group Inc. Copyright terms at 28 http://www.khronos.org/registry/speccopyright.html 29 30Status 31 32 Complete. 33 Approved by the EGL Working Group on September 17, 2014. 34 Approved by the Khronos Board of Promoters on November 7, 2014. 35 36Version 37 38 Version 12, September 12, 2014 39 40Number 41 42 EGL Extension #83 43 44Extension Type 45 46 EGL display extension 47 48Dependencies 49 50 EGL 1.4 or later is required. 51 52 Written based on the EGL 1.5 specification (March 12, 2014). 53 54 The behavior of part of this extension is different depending on whether the 55 EGL_EXT_buffer_age extension is also present. 56 57 This extension trivially interacts with EGL_KHR_swap_buffers_with_damage and 58 EGL_EXT_swap_buffers_with_damage. This extension is worded against the KHR 59 version, but the interactions with the EXT version are identical. 60 61New Procedures and Functions 62 63 64 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, 65 EGLSurface surface, 66 EGLint *rects, 67 EGLint n_rects); 68 69New Tokens 70 71 Accepted in the <attribute> parameter of eglQuerySurface: 72 73 EGL_BUFFER_AGE_KHR 0x313D 74 75Overview 76 77 The aim of this extension is to allow efficient partial updates for postable 78 surfaces. It allows implementations to completely avoid processing areas of 79 the surface which have not changed between frames, allowing increased 80 efficiency. 81 82 It does so by providing information and guarantees about the content of the 83 current back buffer which allow the application to "repair" only areas that 84 have become out of date since the particular back buffer was last used. 85 86 The information provided is in the form of the "age" of the buffer, that is, 87 how many frames ago it was last used as the back buffer for the surface. If 88 the application tracks what changes it has made to the surface since this 89 back buffer was last used, it can bring the entire back buffer up to date by 90 only re-rendering the areas it knows to be out of date. 91 92 Use of this extension provides a more efficient alternative to 93 EGL_BUFFER_PRESERVED swap behaviour. EGL_BUFFER_PRESERVED typically implies 94 an expensive full-frame copy at the beginning of the frame, as well as a 95 dependency on the previous frame. Usage of this extension avoids both and 96 requires only the necessary updates to a back buffer to be made. 97 98Terminology 99 100 This extension and the EGL_KHR_swap_buffers_with_damage extension both use 101 the word "damage" for subtly but significantly different purposes: 102 103 "Surface damage" is what the EGL_KHR_swap_buffers_with_damage extension 104 is concerned with. This is the area of the *surface* that changes between 105 frames for that surface. It concerns the differences between two buffers - 106 the current back buffer and the current front buffer. It is useful only to 107 the consumer. 108 109 "Buffer damage" is what the EGL_KHR_partial_update extension is concerned 110 with. This is the area of a particular buffer that has changed since that 111 same buffer was last used. As it only concerns changes to a single buffer, 112 there is no dependency on the next or previous frames or any other buffer. 113 It therefore cannot be used to infer anything about changes to the surface, 114 which requires linking one frame or buffer to another. Buffer damage is 115 therefore only useful to the producer. 116 117 Following are examples of the two different damage types. Note that the 118 final surface content is the same in both cases, but the damaged areas 119 differ according to the type of damage being discussed. 120 121Surface damage example (EGL_KHR_swap_buffers_with_damage) 122 123 The surface damage for frame n is the difference between frame n and frame 124 (n-1), and represents the area that a compositor must recompose. 125 126 Frame 0 Frame 1 Frame 2 Frame 3 Frame 4 127 +---------+ +---------+ +---------+ +---------+ +---------+ 128 | | |#########| |#########| |#########| |#########| 129 | | | | |#########| |#########| |#########| Final surface 130 | | | | | | |#########| |#########| content 131 | | | | | | | | |#########| 132 +---------+ +---------+ +---------+ +---------+ +---------+ 133 134 +---------+ +---------+ +---------+ +---------+ +---------+ 135 |@@@@@@@@@| |@@@@@@@@@| | | | | | | 136 |@@@@@@@@@| | | |@@@@@@@@@| | | | | Surface damage 137 |@@@@@@@@@| | | | | |@@@@@@@@@| | | 138 |@@@@@@@@@| | | | | | | |@@@@@@@@@| 139 +---------+ +---------+ +---------+ +---------+ +---------+ 140 141Buffer damage example (EGL_KHR_partial_update) 142 143 The buffer damage for a frame is the area changed since that same buffer was 144 last used. If the buffer has not been used before, the buffer damage is the 145 entire area of the buffer. 146 147 The buffer marked with an 'X' in the top left corner is the buffer that is 148 being used for that frame. This is the buffer to which the buffer age and 149 the buffer damage relate. 150 151 Note that this example shows a double buffered surface - the actual number 152 of buffers could be different and variable throughout the lifetime of the 153 surface. The age *must* therefore be queried for every frame. 154 155 Frame 0 Frame 1 Frame 2 Frame 3 Frame 4 156 +---------+ +---------+ +---------+ +---------+ +---------+ 157 | | |#########| |#########| |#########| |#########| 158 | | | | |#########| |#########| |#########| Final surface 159 | | | | | | |#########| |#########| content 160 | | | | | | | | |#########| 161 +---------+ +---------+ +---------+ +---------+ +---------+ 162 163 X---------+ +---------+ X---------+ +---------+ X---------+ 164 | | | | |#########| |#########| |#########| 165 | | | | |#########| |#########| |#########| Buffer 1 content 166 | | | | | | | | |#########| 167 | | | | | | | | |#########| 168 +---------+ +---------+ +---------+ +---------+ +---------+ 169 170 X---------+ +---------+ X---------+ +---------+ 171 |#########| |#########| |#########| |#########| 172 | | | | |#########| |#########| Buffer 2 content 173 | | | | |#########| |#########| 174 | | | | | | | | 175 +---------+ +---------+ +---------+ +---------+ 176 177 0 0 2 2 2 Buffer age 178 179 +---------+ +---------+ +---------+ +---------+ +---------+ 180 |@@@@@@@@@| |@@@@@@@@@| |@@@@@@@@@| | | | | 181 |@@@@@@@@@| |@@@@@@@@@| |@@@@@@@@@| |@@@@@@@@@| | | Buffer damage 182 |@@@@@@@@@| |@@@@@@@@@| | | |@@@@@@@@@| |@@@@@@@@@| 183 |@@@@@@@@@| |@@@@@@@@@| | | | | |@@@@@@@@@| 184 +---------+ +---------+ +---------+ +---------+ +---------+ 185 186 187Add a new section entitled "Partial updates to postable surfaces" to section 1883.5: 189 190 The "damage region" defines the area of the buffer to which all rendering 191 commands must be restricted. It applies only for surfaces which can be 192 posted, as described in section 3.10, and only when the swap behavior is 193 EGL_BUFFER_DESTROYED. 194 195 The contents of the buffer outside of the damage region may always be relied 196 upon to contain the same content as the last time they were defined for the 197 current back buffer. See section 3.5.6 for how to query when the current 198 back buffer was last used, and therefore what those contents are. 199 200 If EGL_EXT_buffer_age is supported, the contents of the buffer inside the 201 damage region may also be relied upon to contain the same content as the 202 last time they were defined for the current back buffer. If 203 EGL_EXT_buffer_age is not supported, the contents of the buffer inside the 204 damage region are always undefined after calling eglSwapBuffers. 205 206 Setting the damage region appropriately can be used to efficiently update 207 only the necessary areas inbetween frames. 208 209 After posting the back buffer, the damage region is set to the full 210 dimensions of the surface. The damage region can only be changed by the 211 application before any client API commands that draw to the surface have 212 been made. After this, the damage region is frozen until the back buffer is 213 posted again. 214 215 Use the command 216 EGLBoolean eglSetDamageRegionKHR( 217 EGLDisplay dpy, 218 EGLSurface surface, 219 EGLint *rects, 220 EGLint n_rects) 221 222 to set the damage region. 223 224 The damage region for <surface> is set to the area described by <n_rects> and 225 <rects> if all of the following conditions are met: 226 227 * <surface> is the current draw surface of the calling thread 228 * <surface> is a postable surface 229 * There have been no client API commands which result with rendering to 230 <surface> since eglSwapBuffers was last called with <surface>, or since 231 <surface> was created in case eglSwapBuffers has not yet been called with 232 <surface>. 233 * The surface's swap behavior is EGL_BUFFER_DESTROYED 234 235 <n_rects> specifies the number of rectangles comprising the damage region. 236 <rects> is a pointer to a list of values describing the rectangles. The list 237 should consist of <n_rects> groups of four values, with each group 238 representing a single rectangle in surface coordinates in the form {x, y, 239 width, height}. Coordinates are specified relative to the lower left corner 240 of the surface. It is not necessary to avoid overlaps of the specified 241 rectangles. Rectangles that lie (partially) outside of the current surface 242 dimensions (as queryable via the EGL_WIDTH and EGL_HEIGHT attributes) will 243 be clamped to the current surface dimensions. 244 245 If <n_rects> is zero, <rects> is ignored and the damage region is set to the 246 full dimensions of the surface. 247 248 If <n_rects> is not zero but the rectangles in <rects> describe a region of 249 zero area after clamping, the damage region is set to the empty region. 250 251 If <rects> contains more than (4 * <n_rects>) values, the remaining values 252 are ignored. If <rects> contains fewer than (4 * <n_rects>) values, the 253 behavior is undefined, up to and including program termination. 254 255 At all times, any client API rendering which falls outside of the damage 256 region results in undefined framebuffer contents for the entire framebuffer. 257 It is the client's responsibility to ensure that rendering is confined to 258 the current damage area. 259 260 If any client API commands resulting in rendering to <surface> have been 261 issued since eglSwapBuffers was last called with <surface>, or since the 262 surface was created in case eglSwapBuffers has not yet been called on it, 263 attempting to set the damage region will result in undefined framebuffer 264 contents for the entire framebuffer. 265 266 Errors 267 ------ 268 eglSetDamageRegionKHR returns EGL_FALSE on failure: 269 * If <surface> is not a postable surface, an EGL_BAD_MATCH error is 270 generated 271 * If <surface> is not the current draw surface for the calling thread, an 272 EGL_BAD_MATCH error is generated 273 * If the value of EGL_SWAP_BEHAVIOR for <surface> is not 274 EGL_BUFFER_DESTROYED, an EGL_BAD_MATCH error is generated 275 * If eglSetDamageRegionKHR has already been called on <surface> since the 276 most recent frame boundary, an EGL_BAD_ACCESS error is generated 277 * If the EGL_BUFFER_AGE_KHR attribute of <surface> has not been queried 278 since the most recent frame boundary, an EGL_BAD_ACCESS error is generated 279 280Add before the final paragraph in section 3.5.6 "Surface Attributes": 281 282 Querying EGL_BUFFER_AGE_KHR returns the age of the color contents of the 283 current back buffer as the number of frames elapsed since it was most 284 recently defined. Under certain conditions described below, applications 285 can, in conjunction with the surface's damage region (see section 3.5.1), 286 use this age to safely rely on the contents of old back buffers to reduce 287 the amount of redrawing they do each frame. 288 289 To query the age of a surface, it must be the current draw surface for the 290 calling thread. 291 292 Function name 293 -------------------- 294 eglSwapBuffers 295 eglSwapBuffersWithDamageKHR 296 297 Table 3.X, Frame Boundary Functions 298 299 Buffers' ages are initialized to 0 at buffer creation time. When a frame 300 boundary is reached, the following occurs before any exchanging or copying 301 of color buffers: 302 303 * The current back buffer's age is set to 1. 304 * Any other color buffers' ages are incremented by 1 if 305 their age was previously greater than 0. 306 307 For example, with a double buffered surface and an implementation that swaps 308 via buffer exchanges, the age would usually be 2. With a triple buffered 309 surface the age would usually be 3. An age of 1 usually means the previous 310 swap was implemented as a copy. An age of 0 means the buffer has only just 311 been initialized and the contents are undefined. Single buffered surfaces 312 have no frame boundaries and therefore always have an age of 0. 313 314 Where specified in terms of the current damage region (see section 3.5.6), 315 the relevant part of a buffer's content is considered defined when the 316 buffer's age is a value greater than 0. 317 318 Frame boundaries are the only events that can set a buffer's age to a 319 positive value. Once EGL_BUFFER_AGE_KHR has been queried then it can be 320 assumed that the age will remain valid until the next frame boundary. EGL 321 implementations are permitted, but not required, to reset the buffer age in 322 response to pixel ownership test changes for any pixels within the drawable, 323 or if new pixels are added to or removed from the drawable, i.e., the 324 drawable is resized. A reset of this nature does not affect the age of 325 content for pixels that pass the pixel ownership test before and after the 326 event that caused the reset. In other words, applications can assume that 327 no event will invalidate the content of pixels that continuously pass the 328 pixel ownership test between when the buffer age was queried and the 329 following frame boundary. It is up to applications to track pixel ownership 330 using data collected from relevant window system events, such as 331 configuration and expose events on the X11 platform. 332 333 EGL_BUFFER_AGE_KHR state is a property of the EGL surface that owns the 334 buffers and lives in the address space of the application. That is, if an 335 EGL surface has been created from a native window or pixmap that may be 336 shared between processes, the buffer age is not guaranteed to be 337 synchronized across the processes. Binding and unbinding a surface to and 338 from one or more contexts in the same address space will not affect the ages 339 of any buffers in that surface. 340 341Add to the list of errors for eglQuerySurface at the end of section 3.5.6 342"Surface Attributes": 343 344 If <attribute> is EGL_BUFFER_AGE_KHR and <surface> is not the current draw 345 surface for the calling thread, an EGL_BAD_SURFACE error is generated. 346 347Add to the end of section 3.10.1.1 "Native Window Resizing": 348 349 If eglSetDamageRegionKHR has been called with anything other than zero for 350 <n_rects>, a surface resize will cause the damage region to become 351 undefined. This will effectively cause the entire framebuffer content to 352 become undefined until the next frame. 353 354Dependencies on EGL_KHR_swap_buffers_with_damage 355 356 If EGL_KHR_swap_buffers_with_damage is not supported, all references to 357 eglSwapBuffersWithDamageKHR are removed. 358 359Issues 360 361 1) What should happen if the client renders outside of the damage area? 362 363 RESOLVED: The entire framebuffer content will be undefined. 364 365 DISCUSSION: The definedness of different parts of the buffer varies across 366 implementations, making it hard to define, and providing any more specific 367 information may encourage improper and non-portable use of this extension. 368 369 2) How does this interact with EGL_EXT_buffer_age? 370 371 RESOLVED: The initial content of the damage area differs depending on 372 whether EGL_EXT_buffer_age is present or not, making this extension fully 373 backwards compatible with EGL_EXT_buffer_age, while not depending on it. 374 375 3) How does this interact with EGL_KHR_swap_buffers_with_damage? 376 377 RESOLVED: It does not interact materially with 378 EGL_KHR_swap_buffers_with_damage, except for the trivial interaction with 379 eglSwapBuffersWithDamageKHR being a frame boundary function if the extension 380 is also supported. 381 382 DISCUSSION: This extension only provides a way to efficiently update the 383 back buffer for a surface. It does not have any effect on the subsequent 384 posting of that buffer. For maximum efficiency, applications should use both 385 EGL_KHR_partial_update and EGL_KHR_swap_buffers_with_damage simultaneously. 386 387 4) How does this interact with EGL_BUFFER_PRESERVED? 388 389 RESOLVED: It is an error to call eglSetDamageRegionKHR with a surface with 390 EGL_BUFFER_PRESERVED swap behavior. However, it is not an error to query the 391 age of the buffer in this case. 392 393 DISCUSSION: A layered extension will be proposed to guarantee that the age 394 of a buffer is always 1 after the first frame for a surface. This will 395 provide similar (but not identical) semantics to EGL_BUFFER_PRESERVED for 396 applications that need it. 397 398 5) How does surface resizing affect the damage region? 399 400 RESOLVED: The damage region becomes undefined if a surface resize occurs 401 after it has been set to anything except the full buffer. Because rendering 402 outside the damage area results in undefined framebuffer contents, this 403 effectively means that the entire framebuffer content becomes undefined 404 until the next frame. 405 406 6) What happens if the damage region is set after any client rendering 407 commands? 408 409 OPTION 1: An error is returned. Detecting this condition is non-trivial in 410 some implementations. 411 412 OPTION 2: The entire framebuffer contents become undefined. 413 414 RESOLVED: Option 2. 415 416 7) Should the entire region be provided in advance of any rendering, or should 417 each region be supplied immediately before the rendering commands for that 418 region, and multiple regions can be defined per frame? 419 420 RESOLVED: The entire region must be provided in advance of any rendering. 421 422 8) What should be the behavior if eglSetDamageRegionKHR is called multiple 423 times before the first rendering command? 424 425 RESOLVED: This is an error. The entire region must be provided during a 426 single call, with no overwrite or modify behavior needed. 427 428 9) Is it allowed to set the damage region when the buffer age has not been 429 queried? 430 431 RESOLVED: This is an error. This could only make sense when the damage 432 region is the entire buffer, which it is initially anyway. Otherwise the 433 undamaged area needs to be defined to an age that the application doesn't 434 know about. It's not clear that this would ever be useful to the 435 application, because it can't know at this point which areas it needs to 436 update. 437 43810) What is the behavior if, after clamping, the damage region is empty? 439 440 RESOLVED: The damage region is set to empty. 441 442 443Revision History 444 445 Version 1, 28/01/2014 446 - Initial draft 447 Version 2, 05/02/2014 448 - Removed clip behavior, replaced with undefined framebuffer contents if 449 client renders outside of given damage region 450 - Renamed to EGL_KHR_partial_update from EGL_KHR_frame_clip 451 - Added detailed parameter descriptions and error conditions 452 - Added dependency on GL_XXX_damage_region 453 - Defined interactions with EGL_EXT_buffer_age 454 Version 3, 04/03/2014 455 - Removed dependency on GL_XXX_damage_region 456 - Changed error on defining damage region after drawcalls to be undefined 457 rendering results instead 458 - Redefined interactions with EGL_EXT_buffer_age to allow both to exist 459 Version 4, 20/03/2014 460 - Modified language to allow use with EGLStream producer surfaces 461 - Clarified that surface must be the current *draw* surface 462 - Changed n_rects=0 behavior to set the damage region to the entire surface 463 - Clarified that rendering outside the damage region results in the entire 464 framebuffer becoming undefined 465 Version 5, 20/03/2014 466 - Updated to be based on EGL 1.5 spec 467 Version 6, 23/04/2014 468 -Added the pixel ownership logic from EGL_EXT_buffer_age 469 -Ported over the detailed description of buffer age from EGL_EXT_buffer_age 470 -Added a "New Functions" and "New Tokens" section. 471 -Added dependencies on EGL_EXT_swap_buffers_with_damage 472 Version 7, 20/05/2014 473 - Removing a couple of now-obsolete sentences 474 - An age of 1 *usually* means the previous swap was implemented as a copy. 475 - Reworded "For the purposes of buffer age tracking..." to reference the 476 conditions under which the different parts of the buffer are actually 477 defined, which depend on the damage region 478 Version 8, 20/05/2014 479 - Added issues list 480 Version 9, 12/08/2014 481 - Removed outdated modification to "Posting to a Window" 482 - Changed names and order of rects/n_rects to match 483 EGL_EXT_swap_buffers_with_damage 484 - Resolved issue 3 on EGL_EXT_swap_buffers_with_damage interactions 485 - Resolved issue 4 on EGL_BUFFER_PRESERVED swap behavior 486 - Resolved issue 5 on surface resize behavior 487 - Resolved issue 7 on multiple calls to eglSetDamageRegionKHR 488 - Added issue 8 and suggested resolution 489 - Added issue 9 and suggested resolution 490 - Added issue 10 and suggested resolution 491 Version 10, 19/08/2014 492 - Added section on terminology and damage types 493 Version 11, 10/09/2014 494 - Resolved outstanding issues 495 Version 12, 12/09/2014 496 - Added the restriction that you can only query the age of a surface while 497 it is the current draw surface. 498 Version 13, 18/09/2015 499 - Marked as a Display extension 500 - Changed remaining references to EGL_EXT_swap_buffers_with_damage to 501 EGL_KHR_swap_buffers_with_damage 502