---
# System prepended metadata

title: Damage in Exo Surface
tags: [Chromium-Graphics, elkurin-daily-note]

---

# Damage in Exo Surface
Damage represents an area in surface where needs the update in image.  

We checked damage handling in WaylandSurface with [this note](https://github.com/elkurin/elkurin-daily-notes/blob/main/docs/day167.md).  
This time, let's focus on Exo side.

## When full damage?
Sometimes, we need full updates.  
In what condition we should update fully?

[`needs_full_damage`](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=995;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) is the flag representing whether it needs full damage.  
```cpp=
needs_full_damage =
    sub_surfaces_changed_ ||
    cached_state_.basic_state.opaque_region !=
        state_.basic_state.opaque_region ||
    cached_state_.basic_state.buffer_scale !=
        state_.basic_state.buffer_scale ||
    cached_state_.basic_state.buffer_transform !=
        state_.basic_state.buffer_transform ||
    cached_state_.basic_state.viewport != state_.basic_state.viewport ||
    cached_state_.rounded_corners_bounds !=
        state_.rounded_corners_bounds ||
    cached_state_.basic_state.crop != state_.basic_state.crop ||
    cached_state_.basic_state.only_visible_on_secure_output !=
        state_.basic_state.only_visible_on_secure_output ||
    cached_state_.basic_state.blend_mode !=
        state_.basic_state.blend_mode ||
    cached_state_.basic_state.alpha != state_.basic_state.alpha ||
    cached_state_.basic_state.color_space !=
        state_.basic_state.color_space ||
    cached_state_.basic_state.is_tracking_occlusion !=
        state_.basic_state.is_tracking_occlusion;
```
If some of the important properties has changed, it requires full update.  
For example, viewport which is the area of display, or rounded corners bounds which is a mask filter to make the corner of the window rounded, buffer scale and so on.

Most of the conditions are specifically selected, but `sub_surfaces_changed_` seems to be more rough condition.  
[`sub_surfaces_changed_`](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.h;l=668;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) is flipped to true when
- Any subsurface is added by [AddSubSurface](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=471;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)
- Any subsurface is removed by [RemoveSubSurface](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=507;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)
- Any subsurface position has being set by [SetSubSurfacePosition](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=529;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)
- Any subsurfaces have changed their order by [PlaceSubSurfaceAbove](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=542;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) or [PlaceSubSurfaceBelow](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=574;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).

These conditions stand when any of the subsurfaces are affected. Even if the affected subsurface is so small like 4x4, it still marks as full damage and triggers the full update of the frame.  
`sub_surfaces_changed_` is reset to false when the subsurfaces are [synchronized](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=1164;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) and all pending states has been pushed.

### What happesn on need_full_damage
When `needs_full_damage` is set to true, it means we need to update whole area.  
Therefore, [the damage area is set as `output_rect`](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=1169;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) as a pending state.  
Here, `output_rect` is [`content_size_`](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.h;l=674;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) which represents the size of the last comitted contents.  
Since this size is for the last comitted contents, instead of the current contents, it does not miss the area where it was painted before but not in the latest commit.

If `need_full_damage` is set to false, it keeps refereing the damage registered to the pending state.  
Also, it takes the intersection with the [last comitted area](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=1173;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).

This value is also passed to [AppendContentsToFrame](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=1544;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) and again `damage_rect_dp` will be set to `content_size_` is it's true, damage of the pending state if not.

This `damage_rect_dp` takes [1 DIP outset](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=1551;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) so that it contains the all damages area even with incorrect decimal rounding caused by device scale factor.

If `damage_rect_px` is filled with the above logic, now it will be set as [`texture_quad->damage_rect`](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface.cc;l=1785-1786;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).  
[TextureDrawQuad](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/common/quads/texture_draw_quad.h;l=22;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) is one of the DrawQuad with texture.


The union of each quad's damage rect will be stored as [`damage_rect`](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/common/quads/render_pass_internal.h;l=44;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) in the RenderPass.

## Note: In viz
[SurfaceAggregator](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/service/display/surface_aggregator.h;l=40;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) accumulates surface data and computes params.  
[SetRenderPassDamageRect](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/service/display/surface_aggregator.cc;l=1695;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) compuets the damage rect.  

`damage_rect` takes the [intersection with the reder pass space](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/service/display/surface_aggregator.cc;l=1710;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).

There are multiple codes that tries to take the intersection with some area which may cause unexpected omitting of the area.