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() }); ```
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 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.