Bug 1893205 Comment 13 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

The invalidation occurs in `Tile::update_dirty_rects`. The invalidation reason is `PrimCount`. It changes the `Tile` for example from:

```rust
id=210
is_valid=1
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((0.0, 0.0), (0.0, 0.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

To:

```rust
id=210
is_valid=0
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((3456.0, 1536.0), (3584.0, 2048.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

Below are the lines in `PicturePrimitive::take_context` that seem relevant (the intersection is empty and then we take the `else` branch):

```rust
// Ensure that the dirty rect doesn't extend outside the local valid rect.
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(PictureRect::zero);
// ...
if tile.is_valid {
    // ...
} else {
    // ...
    if let TileSurface::Texture { ref mut descriptor } = tile.surface.as_mut().unwrap() {
        // ...
        let scissor_rect = frame_state.composite_state.get_surface_rect(
            &tile.local_dirty_rect,
            &tile.local_tile_rect,
            tile_cache.transform_index,
        ).to_i32();
```

In another part of `PicturePrimitive::take_context`, to reset the dirty rect we not only set `tile.local_dirty_rect` to `PictureRect::zero()` but also set `tile.is_valid` to `true`. The latter seems to be missing here and that could explain why taking the `else` branch here is a mistake. Updating to the code below seems to safely make the issue disappear (assuming I've tested long enough). As an outsider to this code I cannot confirm if that this is the correct fix, but it seems like a reasonable explanation.

```rust
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(|| { tile.is_valid = true; PictureRect::zero() });
```
The invalidation occurs in `Tile::update_dirty_rects`. The invalidation reason is `PrimCount`. It changes the `Tile` for example from:

```rust
id=210
is_valid=1
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((0.0, 0.0), (0.0, 0.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

To:

```rust
id=210
is_valid=0
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((3456.0, 1536.0), (3584.0, 2048.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

Below are the lines in `PicturePrimitive::take_context` that seem relevant when we later reach it (the intersection is empty and then we take the `else` branch):

```rust
// Ensure that the dirty rect doesn't extend outside the local valid rect.
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(PictureRect::zero);
// ...
if tile.is_valid {
    // ...
} else {
    // ...
    if let TileSurface::Texture { ref mut descriptor } = tile.surface.as_mut().unwrap() {
        // ...
        let scissor_rect = frame_state.composite_state.get_surface_rect(
            &tile.local_dirty_rect,
            &tile.local_tile_rect,
            tile_cache.transform_index,
        ).to_i32();
```

In another part of `PicturePrimitive::take_context`, to reset the dirty rect we not only set `tile.local_dirty_rect` to `PictureRect::zero()` but also set `tile.is_valid` to `true`. The latter seems to be missing here and that could explain why taking the `else` branch here is a mistake. Updating to the code below seems to safely make the issue disappear (assuming I've tested long enough). As an outsider to this code I cannot confirm if that this is the correct fix, but it seems like a reasonable explanation.

```rust
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(|| { tile.is_valid = true; PictureRect::zero() });
```
The invalidation occurs in `Tile::update_dirty_rects`. The invalidation reason is `PrimCount`. It changes the `Tile` for example from:

```rust
id=210
is_valid=1
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((0.0, 0.0), (0.0, 0.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

To:

```rust
id=210
is_valid=0
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((3456.0, 1536.0), (3584.0, 2048.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

Below are the lines in `PicturePrimitive::take_context` that seem relevant when we later reach it (the intersection is empty and then we take the `else` branch):

```rust
// Ensure that the dirty rect doesn't extend outside the local valid rect.
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(PictureRect::zero);
// ...
if tile.is_valid {
    // ...
} else {
    // ...
    if let TileSurface::Texture { ref mut descriptor } = tile.surface.as_mut().unwrap() {
        // ...
        let scissor_rect = frame_state.composite_state.get_surface_rect(
            &tile.local_dirty_rect,
            &tile.local_tile_rect,
            tile_cache.transform_index,
        ).to_i32();
```

In another part of `PicturePrimitive::take_context`, to reset the dirty rect we not only set `tile.local_dirty_rect` to `PictureRect::zero()` but we also set `tile.is_valid` to `true`. The latter seems to be missing here and that could explain why taking the `else` branch here is a mistake. Updating to the code below seems to safely make the issue disappear (assuming I've tested long enough). As an outsider to this code I cannot confirm if that this is the correct fix, but it seems like a reasonable explanation.

```rust
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(|| { tile.is_valid = true; PictureRect::zero() });
```
The invalidation occurs in `Tile::update_dirty_rects`. The invalidation reason is `PrimCount`. It changes the `Tile` for example from:

```rust
id=210
is_valid=1
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((0.0, 0.0), (0.0, 0.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

To:

```rust
id=210
is_valid=0
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((3456.0, 1536.0), (3584.0, 2048.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

Below are the lines in `PicturePrimitive::take_context` that seem relevant when we later reach it (the intersection is empty and then we take the `else` branch):

```rust
// Ensure that the dirty rect doesn't extend outside the local valid rect.
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(PictureRect::zero);
// ...
if tile.is_valid {
    // ...
} else {
    // ...
    if let TileSurface::Texture { ref mut descriptor } = tile.surface.as_mut().unwrap() {
        // ...
        let scissor_rect = frame_state.composite_state.get_surface_rect(
            &tile.local_dirty_rect,
            &tile.local_tile_rect,
            tile_cache.transform_index,
        ).to_i32();
```

In another part of `PicturePrimitive::take_context`, to reset the dirty rect we not only set `tile.local_dirty_rect` to `PictureRect::zero()` but we also set `tile.is_valid` to `true`. The latter seems to be missing here and that could explain why taking the `else` branch here would be a mistake. Updating to the code below seems to safely make the issue disappear (assuming I've tested long enough). As an outsider to this code I cannot confirm if that this is the correct fix, but it seems like a reasonable explanation.

```rust
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(|| { tile.is_valid = true; PictureRect::zero() });
```
The invalidation occurs in `Tile::update_dirty_rects`. The invalidation reason is `PrimCount`. It changes the `Tile` for example from:

```rust
id=210
is_valid=1
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((0.0, 0.0), (0.0, 0.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

To:

```rust
id=210
is_valid=0
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((3456.0, 1536.0), (3584.0, 2048.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

Below are the lines in `PicturePrimitive::take_context` that seem relevant when we later reach it (the intersection is empty and then we take the `else` branch):

```rust
// Ensure that the dirty rect doesn't extend outside the local valid rect.
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(PictureRect::zero);
// ...
if tile.is_valid {
    // ...
} else {
    // ...
    if let TileSurface::Texture { ref mut descriptor } = tile.surface.as_mut().unwrap() {
        // ...
        let scissor_rect = frame_state.composite_state.get_surface_rect(
            &tile.local_dirty_rect,
            &tile.local_tile_rect,
            tile_cache.transform_index,
        ).to_i32();
```

In another part of `PicturePrimitive::take_context`, to reset the dirty rect we not only set `tile.local_dirty_rect` to `PictureRect::zero()` but we also set `tile.is_valid` to `true`. The latter seems to be missing here and that could explain why taking the `else` branch here would be a mistake. Updating to the code below seems to safely make the issue disappear (assuming I've tested long enough). As an outsider to this code I cannot confirm if that is the correct fix, but it seems like a reasonable explanation.

```rust
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(|| { tile.is_valid = true; PictureRect::zero() });
```
The invalidation occurs in `Tile::update_dirty_rects`. The invalidation reason is `PrimCount`. It changes the `Tile` for example from:

```rust
id=210
is_valid=1
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((0.0, 0.0), (0.0, 0.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

To:

```rust
id=210
is_valid=0
local_tile_rect=Box2D((3072.0, 1536.0), (4096.0, 2048.0))
local_valid_rect=Box2D((-13214.886, -169.00008), (3456.0005, 4861.522))
local_dirty_rect=Box2D((3456.0, 1536.0), (3584.0, 2048.0))
current_descriptor.local_valid_rect=Box2D((3072.0, 1536.0), (3456.0, 2048.0))
```

Below are the lines in `PicturePrimitive::take_context` that seem relevant when we later reach it (the intersection is empty and then we take the `else` branch):

```rust
// Ensure that the dirty rect doesn't extend outside the local valid rect.
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(PictureRect::zero);
// ...
if tile.is_valid {
    // ...
} else {
    // ...
    if let TileSurface::Texture { ref mut descriptor } = tile.surface.as_mut().unwrap() {
        // ...
        let scissor_rect = frame_state.composite_state.get_surface_rect(
            &tile.local_dirty_rect,
            &tile.local_tile_rect,
            tile_cache.transform_index,
        ).to_i32();
```

In another part of `PicturePrimitive::take_context`, to reset the dirty rect we not only set `tile.local_dirty_rect` to `PictureRect::zero()` but we also set `tile.is_valid` to `true`. The latter seems to be missing here and that could explain why taking the `else` branch here would be a mistake. Updating to the code below seems to safely make the issue disappear (assuming I've tested long enough):

```rust
tile.local_dirty_rect = tile.local_dirty_rect
    .intersection(&tile.current_descriptor.local_valid_rect)
    .unwrap_or_else(|| { tile.is_valid = true; PictureRect::zero() });
```

As an outsider to this code I cannot confirm if that is the correct fix, but it seems like a reasonable explanation.

Back to Bug 1893205 Comment 13