# Allocate Surface ID
Local surface id is used to synchronize the surface.
This is a short note to look how and when the local surface id is allocated in Exo.
## SurfaceTreeHost
[SurfaceTreeHost::AllocateLocalSurfaceId](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface_tree_host.cc;l=532;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) is API to allocate local surface id.
SurfaceTreeHost has [child_local_surface_id_allocator_](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/common/surfaces/child_local_surface_id_allocator.h;l=23;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) which is a helper class to generate the id for FrameSink.
[GenerateId](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/common/surfaces/child_local_surface_id_allocator.cc;l=76;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) API increments [`child_sequence_number_`](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/common/surfaces/local_surface_id.h;l=164;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) of the LocalSurfaceId [`current_local_surface_id_`](https://source.chromium.org/chromium/chromium/src/+/main:components/viz/common/surfaces/child_local_surface_id_allocator.h;l=46;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).
SurfaceTreeHost allocates new id on [PrepareToSubmitCompositorFrame](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface_tree_host.cc;l=585;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).
It allocates id when the size is changed or the device scale factor has changed.
```cpp=
if (output_surface_size_in_pixels !=
layer_tree_frame_sink_holder_->LastSizeInPixels() ||
device_scale_factor !=
layer_tree_frame_sink_holder_->LastDeviceScaleFactor()) {
AllocateLocalSurfaceId();
}
```
The previous size and device scale factor is stored in [`layer_tree_frame_sink_holder_`](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface_tree_host.h;l=285;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).
[LayerTreeFrameSinkHolder](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/layer_tree_frame_sink_holder.h;l=56;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) is responsible for tracking the references to the contents of Buffers through interacting with CompositorFrameSink. This is inside Exo.
After allocating surface id, the incremented id will be [set to `layer_tree_frame_sink_holder_`](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface_tree_host.cc;l=641;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).
[SubmitCompositorFrame](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface_tree_host.cc;l=310;drc=8e78783dc1f7007bad46d657c9f332614e240fd8) will prepare and get `frame` as viz::CompositorFrame.
Then [AppendSurfaceHierarchyContentsToFrame](https://source.chromium.org/chromium/chromium/src/+/main:components/exo/surface_tree_host.cc;l=341;drc=8e78783dc1f7007bad46d657c9f332614e240fd8).