Bug 1473284 - Update webrender to commit 0e9563688e575cd662570f54bc9d6f849040dbf8. r=Gankro

MozReview-Commit-ID: 8iH1bGPKpsd

--HG--
rename : gfx/webrender/src/query.rs => gfx/webrender/src/device/query_gl.rs
extra : rebase_source : ee7fcddee44b360cfee098656df7f144cacf270e
This commit is contained in:
Kartikaya Gupta 2018-07-09 09:29:15 -04:00
parent b44f14fe70
commit 624ee847f6
11 changed files with 187 additions and 94 deletions

View File

@ -85,6 +85,8 @@ PictureTask fetch_picture_task(int address) {
return task;
}
#define CLIP_TASK_EMPTY 0x7FFF
struct ClipArea {
RenderTaskCommonData common_data;
vec2 screen_origin;
@ -94,11 +96,10 @@ struct ClipArea {
ClipArea fetch_clip_area(int index) {
ClipArea area;
if (index == 0x7FFF) { //special sentinel task index
area.common_data = RenderTaskCommonData(
RectWithSize(vec2(0.0), vec2(0.0)),
0.0
);
if (index >= CLIP_TASK_EMPTY) {
RectWithSize rect = RectWithSize(vec2(0.0), vec2(0.0));
area.common_data = RenderTaskCommonData(rect, 0.0);
area.screen_origin = vec2(0.0);
area.local_space = false;
} else {

View File

@ -3,5 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
mod gl;
pub mod query_gl;
pub use self::gl::*;
pub use self::query_gl as query;

View File

@ -5,7 +5,7 @@
use api::{AlphaType, BorderDetails, BorderDisplayItem, BuiltDisplayListIter, ClipAndScrollInfo};
use api::{ClipId, ColorF, ComplexClipRegion, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{DevicePixelScale, DeviceUintRect, DisplayItemRef, Epoch, ExtendMode, ExternalScrollId};
use api::{DevicePixelScale, DeviceUintRect, DisplayItemRef, ExtendMode, ExternalScrollId};
use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, GlyphRasterSpace, GradientStop};
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint};
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
@ -150,9 +150,6 @@ pub struct DisplayListFlattener<'a> {
/// The map of all font instances.
font_instances: FontInstanceMap,
/// Used to track the latest flattened epoch for each pipeline.
pipeline_epochs: Vec<(PipelineId, Epoch)>,
/// A set of pipelines that the caller has requested be made available as
/// output textures.
output_pipelines: &'a FastHashSet<PipelineId>,
@ -207,8 +204,6 @@ impl<'a> DisplayListFlattener<'a> {
let root_pipeline_id = scene.root_pipeline_id.unwrap();
let root_pipeline = scene.pipelines.get(&root_pipeline_id).unwrap();
let root_epoch = scene.pipeline_epochs[&root_pipeline_id];
let background_color = root_pipeline
.background_color
.and_then(|color| if color.a > 0.0 { Some(color) } else { None });
@ -218,7 +213,6 @@ impl<'a> DisplayListFlattener<'a> {
clip_scroll_tree,
font_instances,
config: *frame_builder_config,
pipeline_epochs: Vec::new(),
output_pipelines,
id_to_index_mapper: ClipIdToIndexMapper::default(),
hit_testing_runs: recycle_vec(old_builder.hit_testing_runs),
@ -243,8 +237,7 @@ impl<'a> DisplayListFlattener<'a> {
debug_assert!(flattener.picture_stack.is_empty());
new_scene.root_pipeline_id = Some(root_pipeline_id);
new_scene.pipeline_epochs.insert(root_pipeline_id, root_epoch);
new_scene.pipeline_epochs.extend(flattener.pipeline_epochs.drain(..));
new_scene.pipeline_epochs = scene.pipeline_epochs.clone();
new_scene.pipelines = scene.pipelines.clone();
FrameBuilder::with_display_list_flattener(
@ -529,9 +522,6 @@ impl<'a> DisplayListFlattener<'a> {
),
);
let epoch = self.scene.pipeline_epochs[&iframe_pipeline_id];
self.pipeline_epochs.push((iframe_pipeline_id, epoch));
let bounds = item.rect();
let origin = *reference_frame_relative_offset + bounds.origin.to_vector();
self.push_reference_frame(
@ -1892,7 +1882,6 @@ impl<'a> DisplayListFlattener<'a> {
rendering: image_rendering,
tile: None,
},
current_epoch: Epoch::invalid(),
alpha_type,
stretch_size,
tile_spacing,

View File

@ -89,7 +89,6 @@ mod picture;
mod prim_store;
mod print_tree;
mod profiler;
mod query;
mod record;
mod render_backend;
mod render_task;

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{AlphaType, BorderRadius, BoxShadowClipMode, BuiltDisplayList, ClipMode, ColorF};
use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, Epoch, ExtendMode};
use api::{DeviceIntRect, DeviceIntSize, DevicePixelScale, ExtendMode};
use api::{FilterOp, GlyphInstance, GradientStop, ImageKey, ImageRendering, ItemRange, ItemTag, TileOffset};
use api::{GlyphRasterSpace, LayoutPoint, LayoutRect, LayoutSize, LayoutToWorldTransform, LayoutVector2D};
use api::{PipelineId, PremultipliedColorF, PropertyBinding, Shadow, YuvColorSpace, YuvFormat, DeviceIntSideOffsets};
@ -284,7 +284,6 @@ pub enum BrushKind {
},
Image {
request: ImageRequest,
current_epoch: Epoch,
alpha_type: AlphaType,
stretch_size: LayoutSize,
tile_spacing: LayoutSize,
@ -1577,7 +1576,6 @@ impl PrimitiveStore {
sub_rect,
stretch_size,
ref mut tile_spacing,
ref mut current_epoch,
ref mut source,
ref mut opacity_binding,
ref mut visible_tiles,
@ -1590,7 +1588,6 @@ impl PrimitiveStore {
// Set if we need to request the source image from the cache this frame.
if let Some(image_properties) = image_properties {
*current_epoch = image_properties.epoch;
is_tiled = image_properties.tiling.is_some();
// If the opacity changed, invalidate the GPU cache so that
@ -2276,7 +2273,8 @@ impl PrimitiveStore {
prim_screen_rect.intersection(&prim_run_context.clip_chain.combined_outer_screen_rect);
let clip_chain = prim_run_context.clip_chain.nodes.clone();
if cfg!(debug_assertions) && Some(prim_index) == self.chase_id {
println!("\tbase combined outer rect {:?}", combined_outer_rect);
println!("\tbase screen {:?}, combined clip chain {:?}",
prim_screen_rect, prim_run_context.clip_chain.combined_outer_screen_rect);
}
let prim_coordinate_system_id = prim_run_context.scroll_node.coordinate_system_id;
@ -2695,6 +2693,20 @@ impl PrimitiveStore {
inv_parent.pre_mul(&scroll_node.world_content_transform)
});
if run.is_chasing(self.chase_id) {
println!("\teffective clip chain from {:?} {}",
scroll_node.coordinate_system_id,
if pic_context.apply_local_clip_rect { "(applied)" } else { "" },
);
let iter = ClipChainNodeIter { current: clip_chain.nodes.clone() };
for node in iter {
println!("\t\t{:?} {:?}",
node.work_item.coordinate_system_id,
node.local_clip_rect,
);
}
}
let clip_chain_rect = if pic_context.apply_local_clip_rect {
get_local_clip_rect_for_nodes(scroll_node, clip_chain)
} else {

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::ColorF;
use query::{GpuTimer, NamedTag};
use device::query::{GpuTimer, NamedTag};
use std::collections::vec_deque::VecDeque;
use std::f32;
use time::precise_time_ns;
@ -13,7 +13,7 @@ cfg_if! {
use api::ColorU;
use debug_render::DebugRenderer;
use euclid::{Point2D, Rect, Size2D, vec2};
use query::GpuSampler;
use device::query::GpuSampler;
use internal_types::FastHashMap;
use renderer::MAX_VERTEX_TEXTURE_WIDTH;
use std::mem;

View File

@ -39,7 +39,7 @@ use internal_types::{RenderTargetInfo, SavedTargetIndex};
use prim_store::DeferredResolve;
use profiler::{BackendProfileCounters, FrameProfileCounters,
GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
use query::GpuProfiler;
use device::query::GpuProfiler;
use rayon::{ThreadPool, ThreadPoolBuilder};
use record::ApiRecordingReceiver;
use render_backend::RenderBackend;
@ -83,7 +83,7 @@ cfg_if! {
use api::ColorU;
use debug_render::DebugRenderer;
use profiler::{Profiler, ChangeIndicator};
use query::GpuTimer;
use device::query::GpuTimer;
}
}

View File

@ -5,7 +5,7 @@
use api::{AddFont, BlobImageResources, ResourceUpdate};
use api::{BlobImageDescriptor, BlobImageError, BlobImageRenderer, BlobImageRequest};
use api::{ClearCache, ColorF, DevicePoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
use api::{Epoch, FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
use api::{FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
use api::{ExternalImageData, ExternalImageType};
use api::{FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
use api::{GlyphDimensions, IdNamespace};
@ -32,7 +32,8 @@ use render_backend::FrameId;
use render_task::{RenderTaskCache, RenderTaskCacheKey, RenderTaskId};
use render_task::{RenderTaskCacheEntry, RenderTaskCacheEntryHandle, RenderTaskTree};
use std::collections::hash_map::Entry::{self, Occupied, Vacant};
use std::cmp;
use std::collections::hash_map::ValuesMut;
use std::{cmp, mem};
use std::fmt::Debug;
use std::hash::Hash;
#[cfg(any(feature = "capture", feature = "replay"))]
@ -85,7 +86,6 @@ pub struct ImageProperties {
pub descriptor: ImageDescriptor,
pub external_image: Option<ExternalImageData>,
pub tiling: Option<TileSize>,
pub epoch: Epoch,
}
#[derive(Debug, Copy, Clone, PartialEq)]
@ -99,9 +99,7 @@ enum State {
struct ImageResource {
data: ImageData,
descriptor: ImageDescriptor,
epoch: Epoch,
tiling: Option<TileSize>,
dirty_rect: Option<DeviceUintRect>,
}
#[derive(Clone, Debug)]
@ -137,7 +135,7 @@ impl ImageTemplates {
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct CachedImageInfo {
texture_cache_handle: TextureCacheHandle,
epoch: Epoch,
dirty_rect: Option<DeviceUintRect>,
}
#[cfg_attr(feature = "capture", derive(Serialize))]
@ -168,6 +166,24 @@ pub fn intersect_for_tile(
})
}
fn merge_dirty_rect(
prev_dirty_rect: &Option<DeviceUintRect>,
dirty_rect: &Option<DeviceUintRect>,
descriptor: &ImageDescriptor,
) -> Option<DeviceUintRect> {
// It is important to never assume an empty dirty rect implies a full reupload here,
// although we are able to do so elsewhere. We store the descriptor's full rect instead
// There are update sequences which could cause us to forget the correct dirty regions
// regions if we cleared the dirty rect when we received None, e.g.:
// 1) Update with no dirty rect. We want to reupload everything.
// 2) Update with dirty rect B. We still want to reupload everything, not just B.
// 3) Perform the upload some time later.
match (dirty_rect, prev_dirty_rect) {
(&Some(ref rect), &Some(ref prev_rect)) => Some(rect.union(&prev_rect)),
(&Some(ref rect), &None) => Some(*rect),
(&None, _) => Some(descriptor.full_rect()),
}
}
impl<K, V, U> ResourceClassCache<K, V, U>
where
@ -190,15 +206,27 @@ where
self.resources.insert(key, value);
}
pub fn remove(&mut self, key: &K) {
self.resources.remove(key);
}
pub fn get_mut(&mut self, key: &K) -> &mut V {
self.resources.get_mut(key)
.expect("Didn't find a cached resource with that ID!")
}
pub fn try_get_mut(&mut self, key: &K) -> Option<&mut V> {
self.resources.get_mut(key)
}
pub fn entry(&mut self, key: K) -> Entry<K, V> {
self.resources.entry(key)
}
pub fn values_mut(&mut self) -> ValuesMut<K, V> {
self.resources.values_mut()
}
pub fn clear(&mut self) {
self.resources.clear();
}
@ -225,6 +253,13 @@ where
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct CachedImageKey {
pub rendering: ImageRendering,
pub tile: Option<TileOffset>,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "capture", derive(Serialize))]
@ -243,6 +278,10 @@ impl ImageRequest {
tile: Some(offset),
}
}
pub fn is_untiled_auto(&self) -> bool {
self.tile.is_none() && self.rendering == ImageRendering::Auto
}
}
impl Into<BlobImageRequest> for ImageRequest {
@ -254,6 +293,15 @@ impl Into<BlobImageRequest> for ImageRequest {
}
}
impl Into<CachedImageKey> for ImageRequest {
fn into(self) -> CachedImageKey {
CachedImageKey {
rendering: self.rendering,
tile: self.tile,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Clone, Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
@ -261,7 +309,15 @@ pub enum ImageCacheError {
OverLimitSize,
}
type ImageCache = ResourceClassCache<ImageRequest, Result<CachedImageInfo, ImageCacheError>, ()>;
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
enum ImageResult {
UntiledAuto(CachedImageInfo),
Multi(ResourceClassCache<CachedImageKey, CachedImageInfo, ()>),
Err(ImageCacheError),
}
type ImageCache = ResourceClassCache<ImageKey, ImageResult, ()>;
pub type FontInstanceMap = Arc<RwLock<FastHashMap<FontInstanceKey, FontInstance>>>;
#[derive(Default)]
@ -510,14 +566,11 @@ impl ResourceCache {
tiling,
);
}
let dirty_rect = Some(descriptor.full_rect());
let resource = ImageResource {
descriptor,
data,
epoch: Epoch(0),
tiling,
dirty_rect,
};
self.resources.image_templates.insert(image_key, resource);
@ -548,24 +601,31 @@ impl ResourceCache {
.update(image_key, Arc::clone(blob), dirty_rect);
}
// Each cache entry stores its own copy of the image's dirty rect. This allows them to be
// updated independently.
match self.cached_images.try_get_mut(&image_key) {
Some(&mut ImageResult::UntiledAuto(ref mut entry)) => {
entry.dirty_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
}
Some(&mut ImageResult::Multi(ref mut entries)) => {
for entry in entries.values_mut() {
entry.dirty_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
}
}
_ => {}
}
*image = ImageResource {
descriptor,
data,
epoch: Epoch(image.epoch.0 + 1),
tiling,
dirty_rect: match (dirty_rect, image.dirty_rect) {
(Some(rect), Some(prev_rect)) => Some(rect.union(&prev_rect)),
(Some(rect), None) => Some(rect),
(None, _) => None,
},
};
}
pub fn delete_image_template(&mut self, image_key: ImageKey) {
let value = self.resources.image_templates.remove(image_key);
self.cached_images
.clear_keys(|request| request.key == image_key);
self.cached_images.remove(&image_key);
match value {
Some(image) => if image.data.is_blob() {
@ -606,41 +666,76 @@ impl ResourceCache {
// The image or tiling size is too big for hardware texture size.
warn!("Dropping image, image:(w:{},h:{}, tile:{}) is too big for hardware!",
template.descriptor.size.width, template.descriptor.size.height, template.tiling.unwrap_or(0));
self.cached_images.insert(request, Err(ImageCacheError::OverLimitSize));
self.cached_images.insert(request.key, ImageResult::Err(ImageCacheError::OverLimitSize));
return;
}
// If this image exists in the texture cache, *and* the epoch
// in the cache matches that of the template, then it is
// valid to use as-is.
let (entry, needs_update) = match self.cached_images.entry(request) {
Occupied(entry) => {
let info = entry.into_mut();
let needs_update = info.as_mut().unwrap().epoch != template.epoch;
info.as_mut().unwrap().epoch = template.epoch;
(info, needs_update)
}
Vacant(entry) => (
entry.insert(Ok(
CachedImageInfo {
epoch: template.epoch,
texture_cache_handle: TextureCacheHandle::new(),
let storage = match self.cached_images.entry(request.key) {
Occupied(e) => {
// We might have an existing untiled entry, and need to insert
// a second entry. In such cases we need to move the old entry
// out first, replacing it with a dummy entry, and then creating
// the tiled/multi-entry variant.
let entry = e.into_mut();
if !request.is_untiled_auto() {
let untiled_entry = match entry {
&mut ImageResult::UntiledAuto(ref mut entry) => {
Some(mem::replace(entry, CachedImageInfo {
texture_cache_handle: TextureCacheHandle::new(),
dirty_rect: None,
}))
}
_ => None
};
if let Some(untiled_entry) = untiled_entry {
let mut entries = ResourceClassCache::new();
let untiled_key = CachedImageKey {
rendering: ImageRendering::Auto,
tile: None,
};
entries.insert(untiled_key, untiled_entry);
*entry = ImageResult::Multi(entries);
}
)),
true,
),
}
entry
}
Vacant(entry) => {
entry.insert(if request.is_untiled_auto() {
ImageResult::UntiledAuto(CachedImageInfo {
texture_cache_handle: TextureCacheHandle::new(),
dirty_rect: Some(template.descriptor.full_rect()),
})
} else {
ImageResult::Multi(ResourceClassCache::new())
})
}
};
// If this image exists in the texture cache, *and* the dirty rect
// in the cache is empty, then it is valid to use as-is.
let entry = match *storage {
ImageResult::UntiledAuto(ref mut entry) => entry,
ImageResult::Multi(ref mut entries) => {
entries.entry(request.into())
.or_insert(CachedImageInfo {
texture_cache_handle: TextureCacheHandle::new(),
dirty_rect: Some(template.descriptor.full_rect()),
})
},
ImageResult::Err(_) => panic!("Errors should already have been handled"),
};
let needs_upload = self.texture_cache
.request(&entry.as_ref().unwrap().texture_cache_handle, gpu_cache);
.request(&entry.texture_cache_handle, gpu_cache);
let dirty_rect = if needs_upload {
// the texture cache entry has been evicted, treat it as all dirty
Some(template.descriptor.full_rect())
} else if needs_update {
template.dirty_rect
} else {
None
} else if entry.dirty_rect.is_none() {
return
} else {
entry.dirty_rect
};
if !self.pending_image_requests.insert(request) {
@ -666,6 +761,7 @@ impl ResourceCache {
if let Some(dirty) = dirty_rect {
if intersect_for_tile(dirty, actual_size, tile_size, tile_offset).is_none() {
// don't bother requesting unchanged tiles
entry.dirty_rect = None;
self.pending_image_requests.remove(&request);
return
}
@ -849,11 +945,15 @@ impl ResourceCache {
// TODO(Jerry): add a debug option to visualize the corresponding area for
// the Err() case of CacheItem.
match *self.cached_images.get(&request) {
Ok(ref image_info) => {
match *self.cached_images.get(&request.key) {
ImageResult::UntiledAuto(ref image_info) => {
Ok(self.texture_cache.get(&image_info.texture_cache_handle))
}
Err(_) => {
ImageResult::Multi(ref entries) => {
let image_info = entries.get(&request.into());
Ok(self.texture_cache.get(&image_info.texture_cache_handle))
}
ImageResult::Err(_) => {
Err(())
}
}
@ -888,7 +988,6 @@ impl ResourceCache {
descriptor: image_template.descriptor,
external_image,
tiling: image_template.tiling,
epoch: image_template.epoch,
}
})
}
@ -934,8 +1033,6 @@ impl ResourceCache {
}
fn update_texture_cache(&mut self, gpu_cache: &mut GpuCache) {
let mut keys_to_clear_dirty_rect = FastHashSet::default();
for request in self.pending_image_requests.drain() {
let image_template = self.resources.image_templates.get_mut(request.key).unwrap();
debug_assert!(image_template.data.uses_texture_cache());
@ -974,7 +1071,11 @@ impl ResourceCache {
}
};
let entry = self.cached_images.get_mut(&request).as_mut().unwrap();
let entry = match *self.cached_images.get_mut(&request.key) {
ImageResult::UntiledAuto(ref mut entry) => entry,
ImageResult::Multi(ref mut entries) => entries.get_mut(&request.into()),
ImageResult::Err(_) => panic!("Update requested for invalid entry")
};
let mut descriptor = image_template.descriptor.clone();
let local_dirty_rect;
@ -982,12 +1083,10 @@ impl ResourceCache {
let tile_size = image_template.tiling.unwrap();
let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
local_dirty_rect = if let Some(ref rect) = image_template.dirty_rect {
keys_to_clear_dirty_rect.insert(request.key.clone());
local_dirty_rect = if let Some(rect) = entry.dirty_rect.take() {
// We should either have a dirty rect, or we are re-uploading where the dirty
// rect is ignored anyway.
let intersection = intersect_for_tile(*rect, clipped_tile_size, tile_size, tile);
let intersection = intersect_for_tile(rect, clipped_tile_size, tile_size, tile);
debug_assert!(intersection.is_some() ||
self.texture_cache.needs_upload(&entry.texture_cache_handle));
intersection
@ -1010,7 +1109,7 @@ impl ResourceCache {
descriptor.size = clipped_tile_size;
} else {
local_dirty_rect = image_template.dirty_rect.take();
local_dirty_rect = entry.dirty_rect.take();
}
let filter = match request.rendering {
@ -1052,11 +1151,6 @@ impl ResourceCache {
UvRectKind::Rect,
);
}
for key in keys_to_clear_dirty_rect.drain() {
let image_template = self.resources.image_templates.get_mut(key).unwrap();
image_template.dirty_rect.take();
}
}
pub fn end_frame(&mut self) {
@ -1088,7 +1182,7 @@ impl ResourceCache {
.images
.retain(|key, _| key.0 != namespace);
self.cached_images
.clear_keys(|request| request.key.0 == namespace);
.clear_keys(|key| key.0 == namespace);
self.resources.font_instances
.write()
@ -1151,7 +1245,6 @@ enum PlainFontTemplate {
struct PlainImageTemplate {
data: String,
descriptor: ImageDescriptor,
epoch: Epoch,
tiling: Option<TileSize>,
}
@ -1350,7 +1443,6 @@ impl ResourceCache {
},
descriptor: template.descriptor.clone(),
tiling: template.tiling,
epoch: template.epoch,
})
})
.collect(),
@ -1475,8 +1567,6 @@ impl ResourceCache {
data,
descriptor: template.descriptor,
tiling: template.tiling,
epoch: template.epoch,
dirty_rect: None,
});
}

View File

@ -1 +1 @@
34a498f7e46c385a189299e7369e204e1cb2060c
0e9563688e575cd662570f54bc9d6f849040dbf8

View File

@ -55,7 +55,7 @@ fn render_blob(
};
let mut dirty_rect = dirty_rect.unwrap_or(DeviceUintRect::new(
DeviceUintPoint::origin(),
descriptor.offset.to_u32(),
descriptor.size,
));