зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1501319 - Update webrender to commit e7d340b0f39bbd0046e983a75245bdde54013cdb. r=kats
Differential Revision: https://phabricator.services.mozilla.com/D9610 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
de8cde8599
Коммит
f92f9f572e
|
@ -745,8 +745,8 @@ pub struct Device {
|
|||
bound_read_fbo: FBOId,
|
||||
bound_draw_fbo: FBOId,
|
||||
program_mode_id: UniformLocation,
|
||||
default_read_fbo: gl::GLuint,
|
||||
default_draw_fbo: gl::GLuint,
|
||||
default_read_fbo: FBOId,
|
||||
default_draw_fbo: FBOId,
|
||||
|
||||
device_pixel_ratio: f32,
|
||||
upload_method: UploadMethod,
|
||||
|
@ -788,31 +788,61 @@ pub struct Device {
|
|||
extensions: Vec<String>,
|
||||
}
|
||||
|
||||
/// Contains the parameters necessary to bind a texture-backed draw target.
|
||||
/// Contains the parameters necessary to bind a draw target.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct TextureDrawTarget<'a> {
|
||||
/// The target texture.
|
||||
pub texture: &'a Texture,
|
||||
/// The slice within the texture array to draw to.
|
||||
pub layer: LayerIndex,
|
||||
/// Whether to draw with the texture's associated depth target.
|
||||
pub with_depth: bool,
|
||||
pub enum DrawTarget<'a> {
|
||||
/// Use the device's default draw target, with the provided dimensions,
|
||||
/// which are used to set the viewport.
|
||||
Default(DeviceUintSize),
|
||||
/// Use the provided texture.
|
||||
Texture {
|
||||
/// The target texture.
|
||||
texture: &'a Texture,
|
||||
/// The slice within the texture array to draw to.
|
||||
layer: LayerIndex,
|
||||
/// Whether to draw with the texture's associated depth target.
|
||||
with_depth: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> DrawTarget<'a> {
|
||||
/// Returns true if this draw target corresponds to the default framebuffer.
|
||||
pub fn is_default(&self) -> bool {
|
||||
match *self {
|
||||
DrawTarget::Default(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the dimensions of this draw-target.
|
||||
pub fn dimensions(&self) -> DeviceUintSize {
|
||||
match *self {
|
||||
DrawTarget::Default(d) => d,
|
||||
DrawTarget::Texture { texture, .. } => texture.get_dimensions(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains the parameters necessary to bind a texture-backed read target.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct TextureReadTarget<'a> {
|
||||
/// The source texture.
|
||||
pub texture: &'a Texture,
|
||||
/// The slice within the texture array to read from.
|
||||
pub layer: LayerIndex,
|
||||
pub enum ReadTarget<'a> {
|
||||
/// Use the device's default draw target.
|
||||
Default,
|
||||
/// Use the provided texture,
|
||||
Texture {
|
||||
/// The source texture.
|
||||
texture: &'a Texture,
|
||||
/// The slice within the texture array to read from.
|
||||
layer: LayerIndex,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<TextureDrawTarget<'a>> for TextureReadTarget<'a> {
|
||||
fn from(t: TextureDrawTarget<'a>) -> Self {
|
||||
TextureReadTarget {
|
||||
texture: t.texture,
|
||||
layer: t.layer,
|
||||
impl<'a> From<DrawTarget<'a>> for ReadTarget<'a> {
|
||||
fn from(t: DrawTarget<'a>) -> Self {
|
||||
match t {
|
||||
DrawTarget::Default(..) => ReadTarget::Default,
|
||||
DrawTarget::Texture { texture, layer, .. } =>
|
||||
ReadTarget::Texture { texture, layer },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -895,8 +925,8 @@ impl Device {
|
|||
bound_read_fbo: FBOId(0),
|
||||
bound_draw_fbo: FBOId(0),
|
||||
program_mode_id: UniformLocation::INVALID,
|
||||
default_read_fbo: 0,
|
||||
default_draw_fbo: 0,
|
||||
default_read_fbo: FBOId(0),
|
||||
default_draw_fbo: FBOId(0),
|
||||
|
||||
max_texture_size,
|
||||
renderer_name,
|
||||
|
@ -995,12 +1025,12 @@ impl Device {
|
|||
unsafe {
|
||||
self.gl.get_integer_v(gl::READ_FRAMEBUFFER_BINDING, &mut default_read_fbo);
|
||||
}
|
||||
self.default_read_fbo = default_read_fbo[0] as gl::GLuint;
|
||||
self.default_read_fbo = FBOId(default_read_fbo[0] as gl::GLuint);
|
||||
let mut default_draw_fbo = [0];
|
||||
unsafe {
|
||||
self.gl.get_integer_v(gl::DRAW_FRAMEBUFFER_BINDING, &mut default_draw_fbo);
|
||||
}
|
||||
self.default_draw_fbo = default_draw_fbo[0] as gl::GLuint;
|
||||
self.default_draw_fbo = FBOId(default_draw_fbo[0] as gl::GLuint);
|
||||
|
||||
// Texture state
|
||||
for i in 0 .. self.bound_textures.len() {
|
||||
|
@ -1019,8 +1049,8 @@ impl Device {
|
|||
self.gl.bind_vertex_array(0);
|
||||
|
||||
// FBO state
|
||||
self.bound_read_fbo = FBOId(self.default_read_fbo);
|
||||
self.bound_draw_fbo = FBOId(self.default_draw_fbo);
|
||||
self.bound_read_fbo = self.default_read_fbo;
|
||||
self.bound_draw_fbo = self.default_draw_fbo;
|
||||
|
||||
// Pixel op state
|
||||
self.gl.pixel_store_i(gl::UNPACK_ALIGNMENT, 1);
|
||||
|
@ -1066,10 +1096,11 @@ impl Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn bind_read_target(&mut self, texture_target: Option<TextureReadTarget>) {
|
||||
let fbo_id = texture_target.map_or(FBOId(self.default_read_fbo), |target| {
|
||||
target.texture.fbos[target.layer]
|
||||
});
|
||||
pub fn bind_read_target(&mut self, target: ReadTarget) {
|
||||
let fbo_id = match target {
|
||||
ReadTarget::Default => self.default_read_fbo,
|
||||
ReadTarget::Texture { texture, layer } => texture.fbos[layer],
|
||||
};
|
||||
|
||||
self.bind_read_target_impl(fbo_id)
|
||||
}
|
||||
|
@ -1083,29 +1114,40 @@ impl Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn reset_read_target(&mut self) {
|
||||
let fbo = self.default_read_fbo;
|
||||
self.bind_read_target_impl(fbo);
|
||||
}
|
||||
|
||||
|
||||
pub fn reset_draw_target(&mut self) {
|
||||
let fbo = self.default_draw_fbo;
|
||||
self.bind_draw_target_impl(fbo);
|
||||
}
|
||||
|
||||
pub fn bind_draw_target(
|
||||
&mut self,
|
||||
texture_target: Option<TextureDrawTarget>,
|
||||
dimensions: Option<DeviceUintSize>,
|
||||
target: DrawTarget,
|
||||
) {
|
||||
let fbo_id = texture_target.map_or(FBOId(self.default_draw_fbo), |target| {
|
||||
if target.with_depth {
|
||||
target.texture.fbos_with_depth[target.layer]
|
||||
} else {
|
||||
target.texture.fbos[target.layer]
|
||||
let (fbo_id, dimensions) = match target {
|
||||
DrawTarget::Default(d) => (self.default_draw_fbo, d),
|
||||
DrawTarget::Texture { texture, layer, with_depth } => {
|
||||
let dim = texture.get_dimensions();
|
||||
if with_depth {
|
||||
(texture.fbos_with_depth[layer], dim)
|
||||
} else {
|
||||
(texture.fbos[layer], dim)
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
self.bind_draw_target_impl(fbo_id);
|
||||
|
||||
if let Some(dimensions) = dimensions {
|
||||
self.gl.viewport(
|
||||
0,
|
||||
0,
|
||||
dimensions.width as _,
|
||||
dimensions.height as _,
|
||||
);
|
||||
}
|
||||
self.gl.viewport(
|
||||
0,
|
||||
0,
|
||||
dimensions.width as _,
|
||||
dimensions.height as _,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn create_fbo_for_external_texture(&mut self, texture_id: u32) -> FBOId {
|
||||
|
@ -1420,7 +1462,7 @@ impl Device {
|
|||
self.bind_draw_target_impl(*draw_fbo);
|
||||
self.blit_render_target(rect, rect);
|
||||
}
|
||||
self.bind_read_target(None);
|
||||
self.reset_read_target();
|
||||
}
|
||||
|
||||
/// Notifies the device that the contents of a render target are no longer
|
||||
|
@ -2161,8 +2203,8 @@ impl Device {
|
|||
}
|
||||
|
||||
pub fn end_frame(&mut self) {
|
||||
self.bind_draw_target(None, None);
|
||||
self.bind_read_target(None);
|
||||
self.reset_draw_target();
|
||||
self.reset_read_target();
|
||||
|
||||
debug_assert!(self.inside_frame);
|
||||
self.inside_frame = false;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use api::{DeviceIntPoint, DeviceIntRect, DeviceUintSize, FontRenderMode};
|
||||
use api::{ImageFormat, TextureTarget};
|
||||
use debug_colors;
|
||||
use device::{Device, Texture, TextureDrawTarget, TextureFilter, VAO};
|
||||
use device::{DrawTarget, Device, Texture, TextureFilter, VAO};
|
||||
use euclid::{Point2D, Size2D, Transform3D, TypedVector2D, Vector2D};
|
||||
use internal_types::RenderTargetInfo;
|
||||
use pathfinder_gfx_utils::ShelfBinPacker;
|
||||
|
@ -194,11 +194,11 @@ impl Renderer {
|
|||
projection,
|
||||
&mut self.renderer_errors);
|
||||
|
||||
self.device.bind_draw_target(Some(TextureDrawTarget {
|
||||
self.device.bind_draw_target(DrawTarget::Texture {
|
||||
texture: ¤t_page.texture,
|
||||
layer: 0,
|
||||
with_depth: false,
|
||||
}), Some(*target_size));
|
||||
});
|
||||
self.device.clear_target(Some([0.0, 0.0, 0.0, 0.0]), None, None);
|
||||
|
||||
self.device.set_blend(true);
|
||||
|
|
|
@ -36,7 +36,7 @@ use batch::{BatchKind, BatchTextures, BrushBatchKind};
|
|||
use capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
|
||||
use debug_colors;
|
||||
use device::{DepthFunction, Device, FrameId, Program, UploadMethod, Texture, PBO};
|
||||
use device::{ExternalTexture, FBOId, TextureDrawTarget, TextureReadTarget, TextureSlot};
|
||||
use device::{DrawTarget, ExternalTexture, FBOId, ReadTarget, TextureSlot};
|
||||
use device::{ShaderError, TextureFilter,
|
||||
VertexUsageHint, VAO, VBO, CustomVAO};
|
||||
use device::{ProgramCache, ReadPixelsFormat};
|
||||
|
@ -1337,12 +1337,11 @@ impl GpuCacheTexture {
|
|||
device.bind_program(program);
|
||||
device.bind_custom_vao(vao);
|
||||
device.bind_draw_target(
|
||||
Some(TextureDrawTarget {
|
||||
DrawTarget::Texture {
|
||||
texture,
|
||||
layer: 0,
|
||||
with_depth: false,
|
||||
}),
|
||||
Some(texture.get_dimensions()),
|
||||
},
|
||||
);
|
||||
device.draw_nonindexed_points(0, count as _);
|
||||
0
|
||||
|
@ -2570,7 +2569,7 @@ impl Renderer {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
self.device.bind_draw_target(None, None);
|
||||
self.device.reset_draw_target();
|
||||
self.device.enable_depth_write();
|
||||
self.device.clear_target(clear_color, clear_depth_value, None);
|
||||
self.device.disable_depth_write();
|
||||
|
@ -2922,8 +2921,7 @@ impl Renderer {
|
|||
|
||||
fn handle_readback_composite(
|
||||
&mut self,
|
||||
render_target: Option<TextureDrawTarget>,
|
||||
framebuffer_size: DeviceUintSize,
|
||||
draw_target: DrawTarget,
|
||||
scissor_rect: Option<DeviceIntRect>,
|
||||
source: &RenderTask,
|
||||
backdrop: &RenderTask,
|
||||
|
@ -2955,12 +2953,12 @@ impl Renderer {
|
|||
// Called per-instance in case the layer (and therefore FBO)
|
||||
// changes. The device will skip the GL call if the requested
|
||||
// target is already bound.
|
||||
let cache_draw_target = TextureDrawTarget {
|
||||
let cache_draw_target = DrawTarget::Texture {
|
||||
texture: cache_texture,
|
||||
layer: readback_layer.0 as usize,
|
||||
with_depth: false,
|
||||
};
|
||||
self.device.bind_draw_target(Some(cache_draw_target), None);
|
||||
self.device.bind_draw_target(cache_draw_target);
|
||||
|
||||
let mut src = DeviceIntRect::new(
|
||||
source_screen_origin + (backdrop_rect.origin - backdrop_screen_origin),
|
||||
|
@ -2970,18 +2968,19 @@ impl Renderer {
|
|||
|
||||
// Need to invert the y coordinates and flip the image vertically when
|
||||
// reading back from the framebuffer.
|
||||
if render_target.is_none() {
|
||||
src.origin.y = framebuffer_size.height as i32 - src.size.height - src.origin.y;
|
||||
if draw_target.is_default() {
|
||||
src.origin.y = draw_target.dimensions().height as i32 - src.size.height - src.origin.y;
|
||||
dest.origin.y += dest.size.height;
|
||||
dest.size.height = -dest.size.height;
|
||||
}
|
||||
|
||||
self.device.bind_read_target(render_target.map(|r| r.into()));
|
||||
self.device.bind_read_target(draw_target.into());
|
||||
self.device.blit_render_target(src, dest);
|
||||
|
||||
// Restore draw target to current pass render target + layer.
|
||||
// Note: leaving the viewport unchanged, it's not a part of FBO state
|
||||
self.device.bind_draw_target(render_target, None);
|
||||
// Restore draw target to current pass render target + layer, and reset
|
||||
// the read target.
|
||||
self.device.bind_draw_target(draw_target);
|
||||
self.device.reset_read_target();
|
||||
|
||||
if scissor_rect.is_some() {
|
||||
self.device.enable_scissor();
|
||||
|
@ -3008,7 +3007,7 @@ impl Renderer {
|
|||
let texture = self.texture_resolver
|
||||
.resolve(&texture_id)
|
||||
.expect("BUG: invalid source texture");
|
||||
self.device.bind_read_target(Some(TextureReadTarget { texture, layer: layer as usize }));
|
||||
self.device.bind_read_target(ReadTarget::Texture { texture, layer: layer as usize });
|
||||
source_rect
|
||||
}
|
||||
BlitJobSource::RenderTask(task_id) => {
|
||||
|
@ -3020,7 +3019,7 @@ impl Renderer {
|
|||
.expect("BUG: invalid source texture");
|
||||
let source = &render_tasks[task_id];
|
||||
let (source_rect, layer) = source.get_target_rect();
|
||||
self.device.bind_read_target(Some(TextureReadTarget { texture, layer: layer.0 }));
|
||||
self.device.bind_read_target(ReadTarget::Texture { texture, layer: layer.0 });
|
||||
source_rect
|
||||
}
|
||||
};
|
||||
|
@ -3067,10 +3066,9 @@ impl Renderer {
|
|||
|
||||
fn draw_color_target(
|
||||
&mut self,
|
||||
render_target: Option<TextureDrawTarget>,
|
||||
draw_target: DrawTarget,
|
||||
target: &ColorRenderTarget,
|
||||
framebuffer_target_rect: DeviceUintRect,
|
||||
target_size: DeviceUintSize,
|
||||
depth_is_ready: bool,
|
||||
clear_color: Option<[f32; 4]>,
|
||||
render_tasks: &RenderTaskTree,
|
||||
|
@ -3082,11 +3080,11 @@ impl Renderer {
|
|||
let _gm = self.gpu_profile.start_marker("color target");
|
||||
|
||||
// sanity check for the depth buffer
|
||||
if let Some(t) = render_target {
|
||||
assert!(t.texture.supports_depth() >= target.needs_depth());
|
||||
if let DrawTarget::Texture { texture, .. } = draw_target {
|
||||
assert!(texture.supports_depth() >= target.needs_depth());
|
||||
}
|
||||
|
||||
let framebuffer_kind = if render_target.is_none() {
|
||||
let framebuffer_kind = if draw_target.is_default() {
|
||||
FramebufferKind::Main
|
||||
} else {
|
||||
FramebufferKind::Other
|
||||
|
@ -3094,8 +3092,7 @@ impl Renderer {
|
|||
|
||||
{
|
||||
let _timer = self.gpu_profile.start_timer(GPU_TAG_SETUP_TARGET);
|
||||
self.device
|
||||
.bind_draw_target(render_target, Some(target_size));
|
||||
self.device.bind_draw_target(draw_target);
|
||||
self.device.disable_depth();
|
||||
self.set_blend(false, framebuffer_kind);
|
||||
|
||||
|
@ -3106,18 +3103,23 @@ impl Renderer {
|
|||
None
|
||||
};
|
||||
|
||||
let clear_rect = if render_target.is_some() {
|
||||
let clear_rect = if !draw_target.is_default() {
|
||||
if self.enable_clear_scissor {
|
||||
// TODO(gw): Applying a scissor rect and minimal clear here
|
||||
// is a very large performance win on the Intel and nVidia
|
||||
// GPUs that I have tested with. It's possible it may be a
|
||||
// performance penalty on other GPU types - we should test this
|
||||
// and consider different code paths.
|
||||
//
|
||||
// Note: The above measurements were taken when render
|
||||
// target slices were minimum 2048x2048. Now that we size
|
||||
// them adaptively, this may be less of a win (except perhaps
|
||||
// on a mostly-unused last slice of a large texture array).
|
||||
Some(target.used_rect())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else if framebuffer_target_rect == DeviceUintRect::new(DeviceUintPoint::zero(), target_size) {
|
||||
} else if framebuffer_target_rect == DeviceUintRect::new(DeviceUintPoint::zero(), draw_target.dimensions()) {
|
||||
// whole screen is covered, no need for scissor
|
||||
None
|
||||
} else {
|
||||
|
@ -3125,7 +3127,7 @@ impl Renderer {
|
|||
// Note: `framebuffer_target_rect` needs a Y-flip before going to GL
|
||||
// Note: at this point, the target rectangle is not guaranteed to be within the main framebuffer bounds
|
||||
// but `clear_target_rect` is totally fine with negative origin, as long as width & height are positive
|
||||
rect.origin.y = target_size.height as i32 - rect.origin.y - rect.size.height;
|
||||
rect.origin.y = draw_target.dimensions().height as i32 - rect.origin.y - rect.size.height;
|
||||
Some(rect)
|
||||
};
|
||||
|
||||
|
@ -3187,11 +3189,11 @@ impl Renderer {
|
|||
for alpha_batch_container in &target.alpha_batch_containers {
|
||||
if let Some(target_rect) = alpha_batch_container.target_rect {
|
||||
// Note: `framebuffer_target_rect` needs a Y-flip before going to GL
|
||||
let rect = if render_target.is_none() {
|
||||
let rect = if draw_target.is_default() {
|
||||
let mut rect = target_rect
|
||||
.intersection(&framebuffer_target_rect.to_i32())
|
||||
.unwrap_or(DeviceIntRect::zero());
|
||||
rect.origin.y = target_size.height as i32 - rect.origin.y - rect.size.height;
|
||||
rect.origin.y = draw_target.dimensions().height as i32 - rect.origin.y - rect.size.height;
|
||||
rect
|
||||
} else {
|
||||
target_rect
|
||||
|
@ -3240,11 +3242,11 @@ impl Renderer {
|
|||
for alpha_batch_container in &target.alpha_batch_containers {
|
||||
if let Some(target_rect) = alpha_batch_container.target_rect {
|
||||
// Note: `framebuffer_target_rect` needs a Y-flip before going to GL
|
||||
let rect = if render_target.is_none() {
|
||||
let rect = if draw_target.is_default() {
|
||||
let mut rect = target_rect
|
||||
.intersection(&framebuffer_target_rect.to_i32())
|
||||
.unwrap_or(DeviceIntRect::zero());
|
||||
rect.origin.y = target_size.height as i32 - rect.origin.y - rect.size.height;
|
||||
rect.origin.y = draw_target.dimensions().height as i32 - rect.origin.y - rect.size.height;
|
||||
rect
|
||||
} else {
|
||||
target_rect
|
||||
|
@ -3304,8 +3306,7 @@ impl Renderer {
|
|||
// they may overlap and affect each other.
|
||||
debug_assert_eq!(batch.instances.len(), 1);
|
||||
self.handle_readback_composite(
|
||||
render_target,
|
||||
target_size,
|
||||
draw_target,
|
||||
alpha_batch_container.target_rect,
|
||||
&render_tasks[source_id],
|
||||
&render_tasks[task_id],
|
||||
|
@ -3380,7 +3381,7 @@ impl Renderer {
|
|||
dest_rect.origin.y += dest_rect.size.height;
|
||||
dest_rect.size.height *= -1;
|
||||
|
||||
self.device.bind_read_target(render_target.map(|r| r.into()));
|
||||
self.device.bind_read_target(draw_target.into());
|
||||
self.device.bind_external_draw_target(fbo_id);
|
||||
self.device.blit_render_target(src_rect, dest_rect);
|
||||
handler.unlock(output.pipeline_id);
|
||||
|
@ -3390,9 +3391,8 @@ impl Renderer {
|
|||
|
||||
fn draw_alpha_target(
|
||||
&mut self,
|
||||
render_target: TextureDrawTarget,
|
||||
draw_target: DrawTarget,
|
||||
target: &AlphaRenderTarget,
|
||||
target_size: DeviceUintSize,
|
||||
projection: &Transform3D<f32>,
|
||||
render_tasks: &RenderTaskTree,
|
||||
stats: &mut RendererStats,
|
||||
|
@ -3403,8 +3403,7 @@ impl Renderer {
|
|||
|
||||
{
|
||||
let _timer = self.gpu_profile.start_timer(GPU_TAG_SETUP_TARGET);
|
||||
self.device
|
||||
.bind_draw_target(Some(render_target), Some(target_size));
|
||||
self.device.bind_draw_target(draw_target);
|
||||
self.device.disable_depth();
|
||||
self.device.disable_depth_write();
|
||||
|
||||
|
@ -3569,11 +3568,11 @@ impl Renderer {
|
|||
let texture = self.texture_resolver
|
||||
.resolve(&texture_source)
|
||||
.expect("BUG: invalid target texture");
|
||||
self.device.bind_draw_target(Some(TextureDrawTarget {
|
||||
self.device.bind_draw_target(DrawTarget::Texture {
|
||||
texture,
|
||||
layer,
|
||||
with_depth: false,
|
||||
}), Some(target_size));
|
||||
});
|
||||
}
|
||||
|
||||
self.device.disable_depth();
|
||||
|
@ -3801,17 +3800,30 @@ impl Renderer {
|
|||
list: &mut RenderTargetList<T>,
|
||||
counters: &mut FrameProfileCounters,
|
||||
) -> Option<ActiveTexture> {
|
||||
debug_assert_ne!(list.max_size, DeviceUintSize::zero());
|
||||
if list.targets.is_empty() {
|
||||
return None
|
||||
}
|
||||
|
||||
// Get a bounding rect of all the layers, and round it up to a multiple
|
||||
// of 256. This improves render target reuse when resizing the window,
|
||||
// since we don't need to create a new render target for each slightly-
|
||||
// larger frame.
|
||||
let mut bounding_rect = DeviceIntRect::zero();
|
||||
for t in list.targets.iter() {
|
||||
bounding_rect = t.used_rect().union(&bounding_rect);
|
||||
}
|
||||
debug_assert_eq!(bounding_rect.origin, DeviceIntPoint::zero());
|
||||
let dimensions = DeviceUintSize::new(
|
||||
(bounding_rect.size.width as u32 + 255) & !255,
|
||||
(bounding_rect.size.height as u32 + 255) & !255,
|
||||
);
|
||||
|
||||
counters.targets_used.inc();
|
||||
|
||||
// Try finding a match in the existing pool. If there's no match, we'll
|
||||
// create a new texture.
|
||||
let selector = TargetSelector {
|
||||
size: list.max_size,
|
||||
size: dimensions,
|
||||
num_layers: list.targets.len(),
|
||||
format: list.format,
|
||||
};
|
||||
|
@ -3835,8 +3847,8 @@ impl Renderer {
|
|||
self.device.create_texture(
|
||||
TextureTarget::Array,
|
||||
list.format,
|
||||
list.max_size.width,
|
||||
list.max_size.height,
|
||||
dimensions.width,
|
||||
dimensions.height,
|
||||
TextureFilter::Linear,
|
||||
Some(rt_info),
|
||||
list.targets.len() as _,
|
||||
|
@ -3944,10 +3956,9 @@ impl Renderer {
|
|||
);
|
||||
|
||||
self.draw_color_target(
|
||||
None,
|
||||
DrawTarget::Default(framebuffer_size),
|
||||
target,
|
||||
frame.inner_rect,
|
||||
framebuffer_size,
|
||||
framebuffer_depth_is_ready,
|
||||
clear_color,
|
||||
&frame.render_tasks,
|
||||
|
@ -3980,24 +3991,24 @@ impl Renderer {
|
|||
|
||||
for (target_index, target) in alpha.targets.iter().enumerate() {
|
||||
stats.alpha_target_count += 1;
|
||||
let draw_target = DrawTarget::Texture {
|
||||
texture: &alpha_tex.as_ref().unwrap().texture,
|
||||
layer: target_index,
|
||||
with_depth: false,
|
||||
};
|
||||
|
||||
let projection = Transform3D::ortho(
|
||||
0.0,
|
||||
alpha.max_size.width as f32,
|
||||
draw_target.dimensions().width as f32,
|
||||
0.0,
|
||||
alpha.max_size.height as f32,
|
||||
draw_target.dimensions().height as f32,
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
self.draw_alpha_target(
|
||||
TextureDrawTarget {
|
||||
texture: &alpha_tex.as_ref().unwrap().texture,
|
||||
layer: target_index,
|
||||
with_depth: false,
|
||||
},
|
||||
draw_target,
|
||||
target,
|
||||
alpha.max_size,
|
||||
&projection,
|
||||
&frame.render_tasks,
|
||||
stats,
|
||||
|
@ -4006,25 +4017,25 @@ impl Renderer {
|
|||
|
||||
for (target_index, target) in color.targets.iter().enumerate() {
|
||||
stats.color_target_count += 1;
|
||||
let draw_target = DrawTarget::Texture {
|
||||
texture: &color_tex.as_ref().unwrap().texture,
|
||||
layer: target_index,
|
||||
with_depth: target.needs_depth(),
|
||||
};
|
||||
|
||||
let projection = Transform3D::ortho(
|
||||
0.0,
|
||||
color.max_size.width as f32,
|
||||
draw_target.dimensions().width as f32,
|
||||
0.0,
|
||||
color.max_size.height as f32,
|
||||
draw_target.dimensions().height as f32,
|
||||
ORTHO_NEAR_PLANE,
|
||||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
self.draw_color_target(
|
||||
Some(TextureDrawTarget {
|
||||
texture: &color_tex.as_ref().unwrap().texture,
|
||||
layer: target_index,
|
||||
with_depth: target.needs_depth(),
|
||||
}),
|
||||
draw_target,
|
||||
target,
|
||||
frame.inner_rect,
|
||||
color.max_size,
|
||||
false,
|
||||
Some([0.0, 0.0, 0.0, 0.0]),
|
||||
&frame.render_tasks,
|
||||
|
@ -4141,7 +4152,7 @@ impl Renderer {
|
|||
|
||||
let layer_count = texture.get_layer_count() as usize;
|
||||
for layer in 0 .. layer_count {
|
||||
self.device.bind_read_target(Some(TextureReadTarget { texture, layer }));
|
||||
self.device.bind_read_target(ReadTarget::Texture { texture, layer });
|
||||
let x = fb_width - (spacing + size) * (target_index + 1);
|
||||
let y = spacing;
|
||||
|
||||
|
@ -4188,7 +4199,7 @@ impl Renderer {
|
|||
|
||||
let layer_count = texture.get_layer_count() as usize;
|
||||
for layer in 0 .. layer_count {
|
||||
self.device.bind_read_target(Some(TextureReadTarget { texture, layer}));
|
||||
self.device.bind_read_target(ReadTarget::Texture { texture, layer});
|
||||
|
||||
let x = fb_width - (spacing + size) * (i as i32 + 1);
|
||||
|
||||
|
@ -4295,13 +4306,13 @@ impl Renderer {
|
|||
let size = texture.get_dimensions();
|
||||
let mut texels = vec![0; (size.width * size.height * 16) as usize];
|
||||
self.device.begin_frame();
|
||||
self.device.bind_read_target(Some(TextureReadTarget { texture, layer: 0 }));
|
||||
self.device.bind_read_target(ReadTarget::Texture { texture, layer: 0 });
|
||||
self.device.read_pixels_into(
|
||||
DeviceUintRect::new(DeviceUintPoint::zero(), size),
|
||||
ReadPixelsFormat::Standard(ImageFormat::RGBAF32),
|
||||
&mut texels,
|
||||
);
|
||||
self.device.bind_read_target(None);
|
||||
self.device.reset_read_target();
|
||||
self.device.end_frame();
|
||||
(size, texels)
|
||||
}
|
||||
|
@ -4908,7 +4919,7 @@ impl Renderer {
|
|||
config.serialize(&plain_self, "renderer");
|
||||
}
|
||||
|
||||
self.device.bind_read_target(None);
|
||||
self.device.reset_read_target();
|
||||
self.device.end_frame();
|
||||
info!("done.");
|
||||
}
|
||||
|
|
|
@ -28,10 +28,15 @@ use texture_allocator::GuillotineAllocator;
|
|||
#[cfg(feature = "pathfinder")]
|
||||
use webrender_api::{DevicePixel, FontRenderMode};
|
||||
|
||||
const MIN_TARGET_SIZE: u32 = 2048;
|
||||
const STYLE_SOLID: i32 = ((BorderStyle::Solid as i32) << 8) | ((BorderStyle::Solid as i32) << 16);
|
||||
const STYLE_MASK: i32 = 0x00FF_FF00;
|
||||
|
||||
/// According to apitrace, textures larger than 2048 break fast clear
|
||||
/// optimizations on some intel drivers. We sometimes need to go larger, but
|
||||
/// we try to avoid it. This can go away when proper tiling support lands,
|
||||
/// since we can then split large primitives across multiple textures.
|
||||
const IDEAL_MAX_TEXTURE_DIMENSION: u32 = 2048;
|
||||
|
||||
/// Identifies a given `RenderTarget` in a `RenderTargetList`.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -190,6 +195,12 @@ pub enum RenderTargetKind {
|
|||
pub struct RenderTargetList<T> {
|
||||
screen_size: DeviceIntSize,
|
||||
pub format: ImageFormat,
|
||||
/// The maximum width and height of any single primitive we've encountered.
|
||||
///
|
||||
/// We initially create our per-slice allocators with a width and height of
|
||||
/// IDEAL_MAX_TEXTURE_DIMENSION. If we encounter a larger primitive, the
|
||||
/// allocation will fail, but we'll bump max_size, which will cause the
|
||||
/// allocator for the next slice to be just large enough to accomodate it.
|
||||
pub max_size: DeviceUintSize,
|
||||
pub targets: Vec<T>,
|
||||
pub saved_index: Option<SavedTargetIndex>,
|
||||
|
@ -203,7 +214,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
RenderTargetList {
|
||||
screen_size,
|
||||
format,
|
||||
max_size: DeviceUintSize::new(MIN_TARGET_SIZE, MIN_TARGET_SIZE),
|
||||
max_size: DeviceUintSize::new(0, 0),
|
||||
targets: Vec::new(),
|
||||
saved_index: None,
|
||||
}
|
||||
|
@ -268,7 +279,14 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
let origin = match existing_origin {
|
||||
Some(origin) => origin,
|
||||
None => {
|
||||
let mut new_target = T::new(Some(self.max_size), self.screen_size);
|
||||
// Have the allocator restrict slice sizes to our max ideal
|
||||
// dimensions, unless we've already gone bigger on a previous
|
||||
// slice.
|
||||
let allocator_dimensions = DeviceUintSize::new(
|
||||
cmp::max(IDEAL_MAX_TEXTURE_DIMENSION, self.max_size.width),
|
||||
cmp::max(IDEAL_MAX_TEXTURE_DIMENSION, self.max_size.height),
|
||||
);
|
||||
let mut new_target = T::new(Some(allocator_dimensions), self.screen_size);
|
||||
let origin = new_target.allocate(alloc_size).expect(&format!(
|
||||
"Each render task must allocate <= size of one target! ({})",
|
||||
alloc_size
|
||||
|
@ -286,7 +304,9 @@ impl<T: RenderTarget> RenderTargetList<T> {
|
|||
}
|
||||
|
||||
pub fn check_ready(&self, t: &Texture) {
|
||||
assert_eq!(t.get_dimensions(), self.max_size);
|
||||
let dimensions = t.get_dimensions();
|
||||
assert!(dimensions.width >= self.max_size.width);
|
||||
assert!(dimensions.height >= self.max_size.height);
|
||||
assert_eq!(t.get_format(), self.format);
|
||||
assert_eq!(t.get_layer_count() as usize, self.targets.len());
|
||||
assert!(t.supports_depth() >= self.needs_depth());
|
||||
|
|
|
@ -1 +1 @@
|
|||
a7052abfe8e41bcc8904cb5b3add99735fedcd1f
|
||||
e7d340b0f39bbd0046e983a75245bdde54013cdb
|
||||
|
|
Загрузка…
Ссылка в новой задаче