зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset b99610a6833f (bug 1661427) for Talos perma failures.
This commit is contained in:
Родитель
7144bdce89
Коммит
b16f595134
|
@ -4,18 +4,16 @@
|
||||||
|
|
||||||
use bindings::{GeckoProfilerThreadListener, WrCompositor};
|
use bindings::{GeckoProfilerThreadListener, WrCompositor};
|
||||||
use gleam::{gl, gl::GLenum, gl::Gl};
|
use gleam::{gl, gl::GLenum, gl::Gl};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::Cell;
|
||||||
use std::collections::hash_map::HashMap;
|
use std::collections::hash_map::HashMap;
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::{AtomicU32, AtomicU8, AtomicUsize, Ordering};
|
use std::sync::{mpsc, Arc, Condvar, Mutex};
|
||||||
use std::sync::Arc;
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use webrender::{
|
use webrender::{
|
||||||
api::channel, api::units::*, api::ExternalImageId, api::ImageRendering, api::YuvColorSpace, Compositor,
|
api::units::*, api::ExternalImageId, api::ImageRendering, api::YuvColorSpace, Compositor, CompositorCapabilities,
|
||||||
CompositorCapabilities, CompositorSurfaceTransform, NativeSurfaceId, NativeSurfaceInfo, NativeTileId,
|
CompositorSurfaceTransform, NativeSurfaceId, NativeSurfaceInfo, NativeTileId, ThreadListener,
|
||||||
ThreadListener,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -129,8 +127,6 @@ pub struct SwTile {
|
||||||
overlaps: Cell<u32>,
|
overlaps: Cell<u32>,
|
||||||
/// Whether the tile's contents has been invalidated
|
/// Whether the tile's contents has been invalidated
|
||||||
invalid: Cell<bool>,
|
invalid: Cell<bool>,
|
||||||
/// Graph node for job dependencies of this tile
|
|
||||||
graph_node: Arc<SwCompositeGraphNode>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SwTile {
|
impl SwTile {
|
||||||
|
@ -146,7 +142,6 @@ impl SwTile {
|
||||||
valid_rect: DeviceIntRect::zero(),
|
valid_rect: DeviceIntRect::zero(),
|
||||||
overlaps: Cell::new(0),
|
overlaps: Cell::new(0),
|
||||||
invalid: Cell::new(false),
|
invalid: Cell::new(false),
|
||||||
graph_node: SwCompositeGraphNode::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +410,6 @@ impl DrawTileHelper {
|
||||||
|
|
||||||
/// A source for a composite job which can either be a single BGRA locked SWGL
|
/// A source for a composite job which can either be a single BGRA locked SWGL
|
||||||
/// resource or a collection of SWGL resources representing a YUV surface.
|
/// resource or a collection of SWGL resources representing a YUV surface.
|
||||||
#[derive(Clone)]
|
|
||||||
enum SwCompositeSource {
|
enum SwCompositeSource {
|
||||||
BGRA(swgl::LockedResource),
|
BGRA(swgl::LockedResource),
|
||||||
YUV(
|
YUV(
|
||||||
|
@ -431,7 +425,6 @@ unsafe impl Send for SwCompositeSource {}
|
||||||
|
|
||||||
/// A tile composition job to be processed by the SwComposite thread.
|
/// A tile composition job to be processed by the SwComposite thread.
|
||||||
/// Stores relevant details about the tile and where to composite it.
|
/// Stores relevant details about the tile and where to composite it.
|
||||||
#[derive(Clone)]
|
|
||||||
struct SwCompositeJob {
|
struct SwCompositeJob {
|
||||||
/// Locked texture that will be unlocked immediately following the job
|
/// Locked texture that will be unlocked immediately following the job
|
||||||
locked_src: SwCompositeSource,
|
locked_src: SwCompositeSource,
|
||||||
|
@ -442,152 +435,6 @@ struct SwCompositeJob {
|
||||||
opaque: bool,
|
opaque: bool,
|
||||||
flip_y: bool,
|
flip_y: bool,
|
||||||
filter: ImageRendering,
|
filter: ImageRendering,
|
||||||
/// The total number of bands for this job
|
|
||||||
num_bands: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SwCompositeJob {
|
|
||||||
/// Process a composite job
|
|
||||||
fn process(&self, band_index: u8) {
|
|
||||||
// Calculate the Y extents for the job's band, starting at the current index and spanning to
|
|
||||||
// the following index.
|
|
||||||
let band_index = band_index as i32;
|
|
||||||
let num_bands = self.num_bands as i32;
|
|
||||||
let band_offset = (self.dst_rect.size.height * band_index) / num_bands;
|
|
||||||
let band_height = (self.dst_rect.size.height * (band_index + 1)) / num_bands - band_offset;
|
|
||||||
match self.locked_src {
|
|
||||||
SwCompositeSource::BGRA(ref resource) => {
|
|
||||||
self.locked_dst.composite(
|
|
||||||
resource,
|
|
||||||
self.src_rect.origin.x,
|
|
||||||
self.src_rect.origin.y,
|
|
||||||
self.src_rect.size.width,
|
|
||||||
self.src_rect.size.height,
|
|
||||||
self.dst_rect.origin.x,
|
|
||||||
self.dst_rect.origin.y,
|
|
||||||
self.dst_rect.size.width,
|
|
||||||
self.dst_rect.size.height,
|
|
||||||
self.opaque,
|
|
||||||
self.flip_y,
|
|
||||||
image_rendering_to_gl_filter(self.filter),
|
|
||||||
band_offset,
|
|
||||||
band_height,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
SwCompositeSource::YUV(ref y, ref u, ref v, color_space) => {
|
|
||||||
let swgl_color_space = match color_space {
|
|
||||||
YuvColorSpace::Rec601 => swgl::YUVColorSpace::Rec601,
|
|
||||||
YuvColorSpace::Rec709 => swgl::YUVColorSpace::Rec709,
|
|
||||||
YuvColorSpace::Rec2020 => swgl::YUVColorSpace::Rec2020,
|
|
||||||
YuvColorSpace::Identity => swgl::YUVColorSpace::Identity,
|
|
||||||
};
|
|
||||||
self.locked_dst.composite_yuv(
|
|
||||||
y,
|
|
||||||
u,
|
|
||||||
v,
|
|
||||||
swgl_color_space,
|
|
||||||
self.src_rect.origin.x,
|
|
||||||
self.src_rect.origin.y,
|
|
||||||
self.src_rect.size.width,
|
|
||||||
self.src_rect.size.height,
|
|
||||||
self.dst_rect.origin.x,
|
|
||||||
self.dst_rect.origin.y,
|
|
||||||
self.dst_rect.size.width,
|
|
||||||
self.dst_rect.size.height,
|
|
||||||
self.flip_y,
|
|
||||||
band_offset,
|
|
||||||
band_height,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dependency graph of composite jobs to be completed. Keeps a list of child jobs that are dependent on the completion of this job.
|
|
||||||
/// Also keeps track of the number of parent jobs that this job is dependent upon before it can be processed. Once there are no more
|
|
||||||
/// in-flight parent jobs that it depends on, the graph node is finally added to the job queue for processing.
|
|
||||||
struct SwCompositeGraphNode {
|
|
||||||
/// Job to be queued for this graph node once ready.
|
|
||||||
job: RefCell<Option<SwCompositeJob>>,
|
|
||||||
/// The number of remaining bands associated with this job.
|
|
||||||
num_bands: AtomicU8,
|
|
||||||
/// The number of bands that have been taken for processing.
|
|
||||||
band_index: AtomicU8,
|
|
||||||
/// Count of parents this graph node depends on.
|
|
||||||
parents: AtomicU32,
|
|
||||||
/// Graph nodes of child jobs that are dependent on this job
|
|
||||||
children: RefCell<Vec<Arc<SwCompositeGraphNode>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Sync for SwCompositeGraphNode {}
|
|
||||||
|
|
||||||
impl SwCompositeGraphNode {
|
|
||||||
fn new() -> Arc<SwCompositeGraphNode> {
|
|
||||||
Arc::new(SwCompositeGraphNode {
|
|
||||||
job: RefCell::new(None),
|
|
||||||
num_bands: AtomicU8::new(0),
|
|
||||||
band_index: AtomicU8::new(0),
|
|
||||||
parents: AtomicU32::new(0),
|
|
||||||
children: RefCell::new(Vec::new()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset the node's state for a new frame
|
|
||||||
fn reset(&self) {
|
|
||||||
self.job.replace(None);
|
|
||||||
self.num_bands.store(0, Ordering::SeqCst);
|
|
||||||
self.band_index.store(0, Ordering::SeqCst);
|
|
||||||
self.parents.store(0, Ordering::SeqCst);
|
|
||||||
self.children.borrow_mut().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a dependent child node to dependency list. Update its parent count.
|
|
||||||
fn add_child(&self, child: Arc<SwCompositeGraphNode>) {
|
|
||||||
child.parents.fetch_add(1, Ordering::SeqCst);
|
|
||||||
self.children.borrow_mut().push(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Install a job for this node. Return whether or not the job has any unprocessed parents
|
|
||||||
/// that would block immediate composition.
|
|
||||||
fn set_job(&self, job: SwCompositeJob, num_bands: u8) -> bool {
|
|
||||||
self.job.replace(Some(job));
|
|
||||||
// Only set bands after job has been stored to ensure we access it atomically later.
|
|
||||||
self.num_bands.store(num_bands, Ordering::SeqCst);
|
|
||||||
// Check whether there are any remaining parent dependencies to see if this job is ready
|
|
||||||
self.parents.load(Ordering::SeqCst) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to take the job from this node for processing and then process it within the current band.
|
|
||||||
fn process_job(&self) {
|
|
||||||
unsafe {
|
|
||||||
// Borrow the job unguarded so that we don't update the borrow count which would be unsafe.
|
|
||||||
// The job itself will never be modified while it is in use, so this is actually safe.
|
|
||||||
if let Ok(Some(ref job)) = self.job.try_borrow_unguarded() {
|
|
||||||
let band_index = self.band_index.fetch_add(1, Ordering::SeqCst);
|
|
||||||
job.process(band_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// After processing a band, check all child dependencies and remove this parent from
|
|
||||||
/// their dependency counts. If applicable, queue the new child bands for composition.
|
|
||||||
fn unblock_children(&self, sender: &channel::Sender<Arc<SwCompositeGraphNode>>) {
|
|
||||||
if self.num_bands.fetch_sub(1, Ordering::SeqCst) > 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Clear the job to release any locked resources.
|
|
||||||
self.job.replace(None);
|
|
||||||
for child in self.children.borrow().iter() {
|
|
||||||
// Remove the child's parent dependency on this node. If there are no more
|
|
||||||
// parent dependencies left, send all the bands for composition.
|
|
||||||
if child.parents.fetch_sub(1, Ordering::SeqCst) <= 1 {
|
|
||||||
let num_bands = child.num_bands.load(Ordering::SeqCst);
|
|
||||||
for _ in 0..num_bands {
|
|
||||||
sender.send(child.clone()).expect("Failed sending SwComposite job");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The SwComposite thread processes a queue of composite jobs, also signaling
|
/// The SwComposite thread processes a queue of composite jobs, also signaling
|
||||||
|
@ -595,12 +442,11 @@ impl SwCompositeGraphNode {
|
||||||
/// the job count.
|
/// the job count.
|
||||||
struct SwCompositeThread {
|
struct SwCompositeThread {
|
||||||
/// Queue of available composite jobs
|
/// Queue of available composite jobs
|
||||||
job_sender: channel::Sender<Arc<SwCompositeGraphNode>>,
|
job_queue: mpsc::Sender<SwCompositeJob>,
|
||||||
job_receiver: channel::Receiver<Arc<SwCompositeGraphNode>>,
|
|
||||||
/// Count of unprocessed jobs still in the queue
|
/// Count of unprocessed jobs still in the queue
|
||||||
job_count: AtomicUsize,
|
job_count: Mutex<usize>,
|
||||||
/// Condition signaled when there are no more jobs left to process.
|
/// Condition signaled when there are no more jobs left to process
|
||||||
jobs_completed: channel::Receiver<()>,
|
done_cond: Condvar,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The SwCompositeThread struct is shared between the SwComposite thread
|
/// The SwCompositeThread struct is shared between the SwComposite thread
|
||||||
|
@ -611,13 +457,11 @@ impl SwCompositeThread {
|
||||||
/// Create the SwComposite thread. Requires a SWGL context in which
|
/// Create the SwComposite thread. Requires a SWGL context in which
|
||||||
/// to do the composition.
|
/// to do the composition.
|
||||||
fn new() -> Arc<SwCompositeThread> {
|
fn new() -> Arc<SwCompositeThread> {
|
||||||
let (job_sender, job_receiver) = channel::unbounded_channel();
|
let (job_queue, job_rx) = mpsc::channel();
|
||||||
let (notify_completed, jobs_completed) = channel::fast_channel(1);
|
|
||||||
let info = Arc::new(SwCompositeThread {
|
let info = Arc::new(SwCompositeThread {
|
||||||
job_sender,
|
job_queue,
|
||||||
job_receiver,
|
job_count: Mutex::new(0),
|
||||||
job_count: AtomicUsize::new(0),
|
done_cond: Condvar::new(),
|
||||||
jobs_completed,
|
|
||||||
});
|
});
|
||||||
let result = info.clone();
|
let result = info.clone();
|
||||||
let thread_name = "SwComposite";
|
let thread_name = "SwComposite";
|
||||||
|
@ -629,10 +473,56 @@ impl SwCompositeThread {
|
||||||
// Process any available jobs. This will return a non-Ok
|
// Process any available jobs. This will return a non-Ok
|
||||||
// result when the job queue is dropped, causing the thread
|
// result when the job queue is dropped, causing the thread
|
||||||
// to eventually exit.
|
// to eventually exit.
|
||||||
while let Ok(graph_node) = info.job_receiver.recv() {
|
while let Ok(job) = job_rx.recv() {
|
||||||
if info.process_job(graph_node) {
|
match job.locked_src {
|
||||||
// If this was the final job, signal completion.
|
SwCompositeSource::BGRA(ref resource) => {
|
||||||
let _ = notify_completed.try_send(());
|
job.locked_dst.composite(
|
||||||
|
resource,
|
||||||
|
job.src_rect.origin.x,
|
||||||
|
job.src_rect.origin.y,
|
||||||
|
job.src_rect.size.width,
|
||||||
|
job.src_rect.size.height,
|
||||||
|
job.dst_rect.origin.x,
|
||||||
|
job.dst_rect.origin.y,
|
||||||
|
job.dst_rect.size.width,
|
||||||
|
job.dst_rect.size.height,
|
||||||
|
job.opaque,
|
||||||
|
job.flip_y,
|
||||||
|
image_rendering_to_gl_filter(job.filter),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SwCompositeSource::YUV(ref y, ref u, ref v, color_space) => {
|
||||||
|
let swgl_color_space = match color_space {
|
||||||
|
YuvColorSpace::Rec601 => swgl::YUVColorSpace::Rec601,
|
||||||
|
YuvColorSpace::Rec709 => swgl::YUVColorSpace::Rec709,
|
||||||
|
YuvColorSpace::Rec2020 => swgl::YUVColorSpace::Rec2020,
|
||||||
|
YuvColorSpace::Identity => swgl::YUVColorSpace::Identity,
|
||||||
|
};
|
||||||
|
job.locked_dst.composite_yuv(
|
||||||
|
y,
|
||||||
|
u,
|
||||||
|
v,
|
||||||
|
swgl_color_space,
|
||||||
|
job.src_rect.origin.x,
|
||||||
|
job.src_rect.origin.y,
|
||||||
|
job.src_rect.size.width,
|
||||||
|
job.src_rect.size.height,
|
||||||
|
job.dst_rect.origin.x,
|
||||||
|
job.dst_rect.origin.y,
|
||||||
|
job.dst_rect.size.width,
|
||||||
|
job.dst_rect.size.height,
|
||||||
|
job.flip_y,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// Release locked resources before modifying job count
|
||||||
|
drop(job);
|
||||||
|
// Decrement the job count. If applicable, signal that all jobs
|
||||||
|
// have been completed.
|
||||||
|
let mut count = info.job_count.lock().unwrap();
|
||||||
|
*count -= 1;
|
||||||
|
if *count <= 0 {
|
||||||
|
info.done_cond.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thread_listener.thread_stopped(thread_name);
|
thread_listener.thread_stopped(thread_name);
|
||||||
|
@ -641,19 +531,6 @@ impl SwCompositeThread {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process a job contained in a dependency graph node received from the job queue.
|
|
||||||
/// Any child dependencies will be unblocked as appropriate after processing. The
|
|
||||||
/// job count will be updated to reflect this. Returns whether or not this was the
|
|
||||||
/// final job to be processed.
|
|
||||||
fn process_job(&self, graph_node: Arc<SwCompositeGraphNode>) -> bool {
|
|
||||||
// Do the actual processing of the job contained in this node.
|
|
||||||
graph_node.process_job();
|
|
||||||
// Unblock any child dependencies now that this job has been processed.
|
|
||||||
graph_node.unblock_children(&self.job_sender);
|
|
||||||
// Decrement the job count. If applicable, signal that all jobs have been completed.
|
|
||||||
self.job_count.fetch_sub(1, Ordering::SeqCst) <= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Queue a tile for composition by adding to the queue and increasing the job count.
|
/// Queue a tile for composition by adding to the queue and increasing the job count.
|
||||||
fn queue_composite(
|
fn queue_composite(
|
||||||
&self,
|
&self,
|
||||||
|
@ -664,74 +541,31 @@ impl SwCompositeThread {
|
||||||
opaque: bool,
|
opaque: bool,
|
||||||
flip_y: bool,
|
flip_y: bool,
|
||||||
filter: ImageRendering,
|
filter: ImageRendering,
|
||||||
graph_node: &Arc<SwCompositeGraphNode>,
|
|
||||||
) {
|
) {
|
||||||
// For jobs that would span a sufficiently large destination rectangle, split
|
// There are still tile updates happening, so send the job to the SwComposite thread.
|
||||||
// it into multiple horizontal bands so that multiple threads can process them.
|
*self.job_count.lock().unwrap() += 1;
|
||||||
let num_bands = if dst_rect.size.width >= 64 && dst_rect.size.height >= 64 {
|
self.job_queue
|
||||||
(dst_rect.size.height / 64).min(4) as u8
|
.send(SwCompositeJob {
|
||||||
} else {
|
locked_src,
|
||||||
1
|
locked_dst,
|
||||||
};
|
src_rect,
|
||||||
let job = SwCompositeJob {
|
dst_rect,
|
||||||
locked_src,
|
opaque,
|
||||||
locked_dst,
|
flip_y,
|
||||||
src_rect,
|
filter,
|
||||||
dst_rect,
|
})
|
||||||
opaque,
|
.expect("Failing queuing SwComposite job");
|
||||||
flip_y,
|
|
||||||
filter,
|
|
||||||
num_bands,
|
|
||||||
};
|
|
||||||
self.job_count.fetch_add(num_bands as usize, Ordering::SeqCst);
|
|
||||||
if graph_node.set_job(job, num_bands) {
|
|
||||||
for _ in 0..num_bands {
|
|
||||||
self.job_sender
|
|
||||||
.send(graph_node.clone())
|
|
||||||
.expect("Failed sending SwComposite job");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_compositing(&self) {
|
/// Wait for all queued composition jobs to be processed by checking the done condition.
|
||||||
// Initialize the job count to 1 to prevent spurious signaling of job completion
|
|
||||||
// in the middle of queuing compositing jobs until we're actually waiting for
|
|
||||||
// composition.
|
|
||||||
self.job_count.store(1, Ordering::SeqCst);
|
|
||||||
// Drain any erroneous completion signals.
|
|
||||||
while self.jobs_completed.try_recv().is_ok() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wait for all queued composition jobs to be processed.
|
|
||||||
/// Instead of blocking on the SwComposite thread to complete all jobs,
|
|
||||||
/// this may steal some jobs and attempt to process them while waiting.
|
|
||||||
fn wait_for_composites(&self) {
|
fn wait_for_composites(&self) {
|
||||||
// Subtract off the bias to signal we're now waiting on composition and
|
let mut jobs = self.job_count.lock().unwrap();
|
||||||
// need to know if jobs are completed. If the job count hits zero here,
|
while *jobs > 0 {
|
||||||
// then we know the SwComposite thread is already done since all queued
|
jobs = self.done_cond.wait(jobs).unwrap();
|
||||||
// jobs have been processed.
|
|
||||||
if self.job_count.fetch_sub(1, Ordering::SeqCst) <= 1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Otherwise, there are remaining jobs that we need to wait for.
|
|
||||||
loop {
|
|
||||||
channel::select! {
|
|
||||||
// Steal jobs from the SwComposite thread if it is busy.
|
|
||||||
recv(self.job_receiver) -> graph_node => if let Ok(graph_node) = graph_node {
|
|
||||||
if self.process_job(graph_node) {
|
|
||||||
// If this was the final job, then just exit.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// If all jobs have been completed, it is safe to exit.
|
|
||||||
recv(self.jobs_completed) -> _ => break,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adapter for RenderCompositors to work with SWGL that shuttles between
|
|
||||||
/// WebRender and the RenderCompositr via the Compositor API.
|
|
||||||
pub struct SwCompositor {
|
pub struct SwCompositor {
|
||||||
gl: swgl::Context,
|
gl: swgl::Context,
|
||||||
native_gl: Option<Rc<dyn gl::Gl>>,
|
native_gl: Option<Rc<dyn gl::Gl>>,
|
||||||
|
@ -817,7 +651,6 @@ impl SwCompositor {
|
||||||
for tile in &mut surface.tiles {
|
for tile in &mut surface.tiles {
|
||||||
tile.overlaps.set(0);
|
tile.overlaps.set(0);
|
||||||
tile.invalid.set(false);
|
tile.invalid.set(false);
|
||||||
tile.graph_node.reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -834,20 +667,8 @@ impl SwCompositor {
|
||||||
/// surface hasn't yet been added to the current frame list of surfaces to composite
|
/// surface hasn't yet been added to the current frame list of surfaces to composite
|
||||||
/// so that we only process potential blockers from surfaces that would come earlier
|
/// so that we only process potential blockers from surfaces that would come earlier
|
||||||
/// in composition.
|
/// in composition.
|
||||||
fn init_overlaps(
|
fn get_overlaps(&self, overlap_rect: &DeviceIntRect) -> u32 {
|
||||||
&self,
|
let mut overlaps = 0;
|
||||||
overlap_surface: &SwSurface,
|
|
||||||
overlap_tile: &SwTile,
|
|
||||||
overlap_transform: &CompositorSurfaceTransform,
|
|
||||||
overlap_clip_rect: &DeviceIntRect,
|
|
||||||
) {
|
|
||||||
let overlap_rect = match overlap_tile.overlap_rect(overlap_surface, overlap_transform, overlap_clip_rect) {
|
|
||||||
Some(overlap_rect) => overlap_rect,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
// Record an extra overlap for an invalid tile to track the tile's dependency
|
|
||||||
// on its own future update.
|
|
||||||
let mut overlaps = if overlap_tile.invalid.get() { 1 } else { 0 };
|
|
||||||
for &(ref id, ref transform, ref clip_rect, _) in &self.frame_surfaces {
|
for &(ref id, ref transform, ref clip_rect, _) in &self.frame_surfaces {
|
||||||
// If the surface's clip rect doesn't overlap the tile's rect,
|
// If the surface's clip rect doesn't overlap the tile's rect,
|
||||||
// then there is no need to check any tiles within the surface.
|
// then there is no need to check any tiles within the surface.
|
||||||
|
@ -858,21 +679,13 @@ impl SwCompositor {
|
||||||
for tile in &surface.tiles {
|
for tile in &surface.tiles {
|
||||||
// If there is a deferred tile that might overlap the destination rectangle,
|
// If there is a deferred tile that might overlap the destination rectangle,
|
||||||
// record the overlap.
|
// record the overlap.
|
||||||
if tile.may_overlap(surface, transform, clip_rect, &overlap_rect) {
|
if tile.overlaps.get() > 0 && tile.may_overlap(surface, transform, clip_rect, overlap_rect) {
|
||||||
if tile.overlaps.get() > 0 {
|
overlaps += 1;
|
||||||
overlaps += 1;
|
|
||||||
}
|
|
||||||
// Regardless of whether this tile is deferred, if it has dependency
|
|
||||||
// overlaps, then record that it is potentially a dependency parent.
|
|
||||||
tile.graph_node.add_child(overlap_tile.graph_node.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if overlaps > 0 {
|
overlaps
|
||||||
// Has a dependency on some invalid tiles, so need to defer composition.
|
|
||||||
overlap_tile.overlaps.set(overlaps);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function that queues a composite job to the current locked framebuffer
|
/// Helper function that queues a composite job to the current locked framebuffer
|
||||||
|
@ -923,15 +736,27 @@ impl SwCompositor {
|
||||||
surface.is_opaque,
|
surface.is_opaque,
|
||||||
flip_y,
|
flip_y,
|
||||||
filter,
|
filter,
|
||||||
&tile.graph_node,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lock a surface with an attached external image for compositing.
|
/// If using the SwComposite thread, we need to compute an overlap count for all tiles
|
||||||
fn try_lock_composite_surface(&mut self, id: &NativeSurfaceId) {
|
/// within the surface being queued for composition this frame. If the tile is immediately
|
||||||
if let Some(surface) = self.surfaces.get_mut(id) {
|
/// ready to composite, then queue that now. Otherwise, set its draw order index for later
|
||||||
|
/// composition.
|
||||||
|
fn init_composites(
|
||||||
|
&mut self,
|
||||||
|
id: &NativeSurfaceId,
|
||||||
|
transform: &CompositorSurfaceTransform,
|
||||||
|
clip_rect: &DeviceIntRect,
|
||||||
|
filter: ImageRendering,
|
||||||
|
) {
|
||||||
|
if self.composite_thread.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(surface) = self.surfaces.get_mut(&id) {
|
||||||
if let Some(external_image) = surface.external_image {
|
if let Some(external_image) = surface.external_image {
|
||||||
// If the surface has an attached external image, attempt to lock the external image
|
// If the surface has an attached external image, attempt to lock the external image
|
||||||
// for compositing. Yields a descriptor of textures and data necessary for their
|
// for compositing. Yields a descriptor of textures and data necessary for their
|
||||||
|
@ -953,16 +778,22 @@ impl SwCompositor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Look for any attached external images that have been locked and then unlock them.
|
if let Some(surface) = self.surfaces.get(&id) {
|
||||||
fn unlock_composite_surfaces(&mut self) {
|
for tile in &surface.tiles {
|
||||||
for &(ref id, _, _, _) in &self.frame_surfaces {
|
if let Some(overlap_rect) = tile.overlap_rect(surface, transform, clip_rect) {
|
||||||
if let Some(surface) = self.surfaces.get_mut(id) {
|
let mut overlaps = self.get_overlaps(&overlap_rect);
|
||||||
if let Some(external_image) = surface.external_image {
|
// Record an extra overlap for an invalid tile to track the tile's dependency
|
||||||
if surface.composite_surface.is_some() {
|
// on its own future update.
|
||||||
unsafe { wr_swgl_unlock_composite_surface(self.gl.into(), external_image) };
|
if tile.invalid.get() {
|
||||||
surface.composite_surface = None;
|
overlaps += 1;
|
||||||
|
}
|
||||||
|
if overlaps == 0 {
|
||||||
|
// Not dependent on any tiles, so go ahead and composite now.
|
||||||
|
self.queue_composite(surface, transform, clip_rect, filter, tile);
|
||||||
|
} else {
|
||||||
|
// Has a dependency on some invalid tiles, so need to defer composition.
|
||||||
|
tile.overlaps.set(overlaps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1383,40 +1214,12 @@ impl Compositor for SwCompositor {
|
||||||
compositor.add_surface(id, transform, clip_rect, filter);
|
compositor.add_surface(id, transform, clip_rect, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.composite_thread.is_some() {
|
// Compute overlap dependencies and issue any initial composite jobs for the SwComposite thread.
|
||||||
// If the surface has an attached external image, try to lock that now.
|
self.init_composites(&id, &transform, &clip_rect, filter);
|
||||||
self.try_lock_composite_surface(&id);
|
|
||||||
|
|
||||||
// Compute overlap dependencies for the surface.
|
|
||||||
if let Some(surface) = self.surfaces.get(&id) {
|
|
||||||
for tile in &surface.tiles {
|
|
||||||
self.init_overlaps(surface, tile, &transform, &clip_rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.frame_surfaces.push((id, transform, clip_rect, filter));
|
self.frame_surfaces.push((id, transform, clip_rect, filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Now that all the dependency graph nodes have been built, start queuing
|
|
||||||
/// composition jobs.
|
|
||||||
fn start_compositing(&mut self) {
|
|
||||||
if let Some(ref composite_thread) = self.composite_thread {
|
|
||||||
composite_thread.start_compositing();
|
|
||||||
// Issue any initial composite jobs for the SwComposite thread.
|
|
||||||
for &(ref id, ref transform, ref clip_rect, filter) in &self.frame_surfaces {
|
|
||||||
if let Some(surface) = self.surfaces.get(id) {
|
|
||||||
for tile in &surface.tiles {
|
|
||||||
if tile.overlaps.get() == 0 {
|
|
||||||
// Not dependent on any tiles, so go ahead and composite now.
|
|
||||||
self.queue_composite(surface, transform, clip_rect, filter, tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end_frame(&mut self) {
|
fn end_frame(&mut self) {
|
||||||
if let Some(compositor) = &mut self.compositor {
|
if let Some(compositor) = &mut self.compositor {
|
||||||
compositor.end_frame();
|
compositor.end_frame();
|
||||||
|
@ -1463,7 +1266,17 @@ impl Compositor for SwCompositor {
|
||||||
composite_thread.wait_for_composites();
|
composite_thread.wait_for_composites();
|
||||||
self.locked_framebuffer = None;
|
self.locked_framebuffer = None;
|
||||||
|
|
||||||
self.unlock_composite_surfaces();
|
// Look for any attached external images that have been locked and then unlock them.
|
||||||
|
for &(ref id, _, _, _) in &self.frame_surfaces {
|
||||||
|
if let Some(surface) = self.surfaces.get_mut(id) {
|
||||||
|
if let Some(external_image) = surface.external_image {
|
||||||
|
if surface.composite_surface.is_some() {
|
||||||
|
unsafe { wr_swgl_unlock_composite_surface(self.gl.into(), external_image) };
|
||||||
|
surface.composite_surface = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ static inline void scale_row(P* dst, int dstWidth, const P* src, int srcWidth,
|
||||||
|
|
||||||
static void scale_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
static void scale_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
||||||
Texture& dsttex, const IntRect& dstReq, int dstZ,
|
Texture& dsttex, const IntRect& dstReq, int dstZ,
|
||||||
bool invertY, int bandOffset, int bandHeight) {
|
bool invertY) {
|
||||||
// Cache scaling ratios
|
// Cache scaling ratios
|
||||||
int srcWidth = srcReq.width();
|
int srcWidth = srcReq.width();
|
||||||
int srcHeight = srcReq.height();
|
int srcHeight = srcReq.height();
|
||||||
|
@ -49,11 +49,8 @@ static void scale_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
||||||
destStride = -destStride;
|
destStride = -destStride;
|
||||||
}
|
}
|
||||||
int span = dstBounds.width();
|
int span = dstBounds.width();
|
||||||
int frac = srcHeight * bandOffset;
|
int frac = 0;
|
||||||
dest += destStride * bandOffset;
|
for (int rows = dstBounds.height(); rows > 0; rows--) {
|
||||||
src += srcStride * (frac / dstHeight);
|
|
||||||
frac %= dstHeight;
|
|
||||||
for (int rows = min(dstBounds.height(), bandHeight); rows > 0; rows--) {
|
|
||||||
if (srcWidth == dstWidth) {
|
if (srcWidth == dstWidth) {
|
||||||
// No scaling, so just do a fast copy.
|
// No scaling, so just do a fast copy.
|
||||||
memcpy(dest, src, span * bpp);
|
memcpy(dest, src, span * bpp);
|
||||||
|
@ -138,7 +135,7 @@ static void linear_row_blit(uint16_t* dest, int span, const vec2_scalar& srcUV,
|
||||||
|
|
||||||
static void linear_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
static void linear_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
||||||
Texture& dsttex, const IntRect& dstReq, int dstZ,
|
Texture& dsttex, const IntRect& dstReq, int dstZ,
|
||||||
bool invertY, int bandOffset, int bandHeight) {
|
bool invertY) {
|
||||||
assert(srctex.internal_format == GL_RGBA8 ||
|
assert(srctex.internal_format == GL_RGBA8 ||
|
||||||
srctex.internal_format == GL_R8 || srctex.internal_format == GL_RG8);
|
srctex.internal_format == GL_R8 || srctex.internal_format == GL_RG8);
|
||||||
// Compute valid dest bounds
|
// Compute valid dest bounds
|
||||||
|
@ -170,10 +167,8 @@ static void linear_blit(Texture& srctex, const IntRect& srcReq, int srcZ,
|
||||||
if (invertY) {
|
if (invertY) {
|
||||||
destStride = -destStride;
|
destStride = -destStride;
|
||||||
}
|
}
|
||||||
dest += destStride * bandOffset;
|
|
||||||
srcUV.y += srcDUV.y * bandOffset;
|
|
||||||
int span = dstBounds.width();
|
int span = dstBounds.width();
|
||||||
for (int rows = min(dstBounds.height(), bandHeight); rows > 0; rows--) {
|
for (int rows = dstBounds.height(); rows > 0; rows--) {
|
||||||
switch (bpp) {
|
switch (bpp) {
|
||||||
case 1:
|
case 1:
|
||||||
linear_row_blit((uint8_t*)dest, span, srcUV, srcDUV.x, srcZOffset,
|
linear_row_blit((uint8_t*)dest, span, srcUV, srcDUV.x, srcZOffset,
|
||||||
|
@ -222,7 +217,7 @@ static void linear_row_composite(uint32_t* dest, int span,
|
||||||
|
|
||||||
static void linear_composite(Texture& srctex, const IntRect& srcReq,
|
static void linear_composite(Texture& srctex, const IntRect& srcReq,
|
||||||
Texture& dsttex, const IntRect& dstReq,
|
Texture& dsttex, const IntRect& dstReq,
|
||||||
bool invertY, int bandOffset, int bandHeight) {
|
bool invertY) {
|
||||||
assert(srctex.bpp() == 4);
|
assert(srctex.bpp() == 4);
|
||||||
assert(dsttex.bpp() == 4);
|
assert(dsttex.bpp() == 4);
|
||||||
// Compute valid dest bounds
|
// Compute valid dest bounds
|
||||||
|
@ -251,10 +246,8 @@ static void linear_composite(Texture& srctex, const IntRect& srcReq,
|
||||||
if (invertY) {
|
if (invertY) {
|
||||||
destStride = -destStride;
|
destStride = -destStride;
|
||||||
}
|
}
|
||||||
dest += destStride * bandOffset;
|
|
||||||
srcUV.y += srcDUV.y * bandOffset;
|
|
||||||
int span = dstBounds.width();
|
int span = dstBounds.width();
|
||||||
for (int rows = min(dstBounds.height(), bandHeight); rows > 0; rows--) {
|
for (int rows = dstBounds.height(); rows > 0; rows--) {
|
||||||
linear_row_composite((uint32_t*)dest, span, srcUV, srcDUV.x, &sampler);
|
linear_row_composite((uint32_t*)dest, span, srcUV, srcDUV.x, &sampler);
|
||||||
dest += destStride;
|
dest += destStride;
|
||||||
srcUV.y += srcDUV.y;
|
srcUV.y += srcDUV.y;
|
||||||
|
@ -300,10 +293,10 @@ void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||||
(srctex.internal_format == GL_RGBA8 || srctex.internal_format == GL_R8 ||
|
(srctex.internal_format == GL_RGBA8 || srctex.internal_format == GL_R8 ||
|
||||||
srctex.internal_format == GL_RG8)) {
|
srctex.internal_format == GL_RG8)) {
|
||||||
linear_blit(srctex, srcReq, srcfb->layer, dsttex, dstReq, dstfb->layer,
|
linear_blit(srctex, srcReq, srcfb->layer, dsttex, dstReq, dstfb->layer,
|
||||||
invertY, 0, dstReq.height());
|
invertY);
|
||||||
} else {
|
} else {
|
||||||
scale_blit(srctex, srcReq, srcfb->layer, dsttex, dstReq, dstfb->layer,
|
scale_blit(srctex, srcReq, srcfb->layer, dsttex, dstReq, dstfb->layer,
|
||||||
invertY, 0, dstReq.height());
|
invertY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,13 +357,11 @@ void* GetResourceBuffer(LockedTexture* resource, int32_t* width,
|
||||||
// Extension for optimized compositing of textures or framebuffers that may be
|
// Extension for optimized compositing of textures or framebuffers that may be
|
||||||
// safely used across threads. The source and destination must be locked to
|
// safely used across threads. The source and destination must be locked to
|
||||||
// ensure that they can be safely accessed while the SWGL context might be used
|
// ensure that they can be safely accessed while the SWGL context might be used
|
||||||
// by another thread. Band extents along the Y axis may be used to clip the
|
// by another thread.
|
||||||
// destination rectangle without effecting the integer scaling ratios.
|
|
||||||
void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX,
|
void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX,
|
||||||
GLint srcY, GLsizei srcWidth, GLsizei srcHeight, GLint dstX,
|
GLint srcY, GLsizei srcWidth, GLsizei srcHeight, GLint dstX,
|
||||||
GLint dstY, GLsizei dstWidth, GLsizei dstHeight,
|
GLint dstY, GLsizei dstWidth, GLsizei dstHeight,
|
||||||
GLboolean opaque, GLboolean flip, GLenum filter,
|
GLboolean opaque, GLboolean flip, GLenum filter) {
|
||||||
GLint bandOffset, GLsizei bandHeight) {
|
|
||||||
if (!lockedDst || !lockedSrc) {
|
if (!lockedDst || !lockedSrc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -384,27 +375,25 @@ void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX,
|
||||||
|
|
||||||
if (opaque) {
|
if (opaque) {
|
||||||
if (!srcReq.same_size(dstReq) && filter == GL_LINEAR) {
|
if (!srcReq.same_size(dstReq) && filter == GL_LINEAR) {
|
||||||
linear_blit(srctex, srcReq, 0, dsttex, dstReq, 0, flip, bandOffset, bandHeight);
|
linear_blit(srctex, srcReq, 0, dsttex, dstReq, 0, flip);
|
||||||
} else {
|
} else {
|
||||||
scale_blit(srctex, srcReq, 0, dsttex, dstReq, 0, flip, bandOffset, bandHeight);
|
scale_blit(srctex, srcReq, 0, dsttex, dstReq, 0, flip);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!srcReq.same_size(dstReq) || filter == GL_LINEAR) {
|
if (!srcReq.same_size(dstReq) || filter == GL_LINEAR) {
|
||||||
linear_composite(srctex, srcReq, dsttex, dstReq, flip, bandOffset, bandHeight);
|
linear_composite(srctex, srcReq, dsttex, dstReq, flip);
|
||||||
} else {
|
} else {
|
||||||
const int bpp = 4;
|
const int bpp = 4;
|
||||||
IntRect bounds = dsttex.sample_bounds(dstReq, flip);
|
IntRect bounds = dsttex.sample_bounds(dstReq, flip);
|
||||||
bounds.intersect(srctex.sample_bounds(srcReq));
|
bounds.intersect(srctex.sample_bounds(srcReq));
|
||||||
char* dest = dsttex.sample_ptr(dstReq, bounds, 0, flip);
|
char* dest = dsttex.sample_ptr(dstReq, bounds, 0, flip);
|
||||||
char* src = srctex.sample_ptr(srcReq, bounds, 0);
|
char* src = srctex.sample_ptr(srcReq, bounds, 0);
|
||||||
int srcStride = srctex.stride();
|
size_t destStride = dsttex.stride();
|
||||||
int destStride = dsttex.stride();
|
|
||||||
if (flip) {
|
if (flip) {
|
||||||
destStride = -destStride;
|
destStride = -destStride;
|
||||||
}
|
}
|
||||||
dest += destStride * bandOffset;
|
|
||||||
src += srcStride * bandOffset;
|
for (int y = 0; y < bounds.height(); y++) {
|
||||||
for (int rows = min(bounds.height(), bandHeight); rows > 0; rows--) {
|
|
||||||
char* end = src + bounds.width() * bpp;
|
char* end = src + bounds.width() * bpp;
|
||||||
while (src + 4 * bpp <= end) {
|
while (src + 4 * bpp <= end) {
|
||||||
WideRGBA8 srcpx = unpack(unaligned_load<PackedRGBA8>(src));
|
WideRGBA8 srcpx = unpack(unaligned_load<PackedRGBA8>(src));
|
||||||
|
@ -430,7 +419,7 @@ void Composite(LockedTexture* lockedDst, LockedTexture* lockedSrc, GLint srcX,
|
||||||
src = end;
|
src = end;
|
||||||
}
|
}
|
||||||
dest += destStride - bounds.width() * bpp;
|
dest += destStride - bounds.width() * bpp;
|
||||||
src += srcStride - bounds.width() * bpp;
|
src += srctex.stride() - bounds.width() * bpp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -710,7 +699,7 @@ static void linear_row_yuv(uint32_t* dest, int span, const vec2_scalar& srcUV,
|
||||||
static void linear_convert_yuv(Texture& ytex, Texture& utex, Texture& vtex,
|
static void linear_convert_yuv(Texture& ytex, Texture& utex, Texture& vtex,
|
||||||
YUVColorSpace colorSpace, const IntRect& srcReq,
|
YUVColorSpace colorSpace, const IntRect& srcReq,
|
||||||
Texture& dsttex, const IntRect& dstReq,
|
Texture& dsttex, const IntRect& dstReq,
|
||||||
bool invertY, int bandOffset, int bandHeight) {
|
bool invertY) {
|
||||||
// Compute valid dest bounds
|
// Compute valid dest bounds
|
||||||
IntRect dstBounds = dsttex.sample_bounds(dstReq, invertY);
|
IntRect dstBounds = dsttex.sample_bounds(dstReq, invertY);
|
||||||
// Check if sampling bounds are empty
|
// Check if sampling bounds are empty
|
||||||
|
@ -746,11 +735,8 @@ static void linear_convert_yuv(Texture& ytex, Texture& utex, Texture& vtex,
|
||||||
if (invertY) {
|
if (invertY) {
|
||||||
destStride = -destStride;
|
destStride = -destStride;
|
||||||
}
|
}
|
||||||
dest += destStride * bandOffset;
|
|
||||||
srcUV.y += srcDUV.y * bandOffset;
|
|
||||||
chromaUV.y += chromaDUV.y * bandOffset;
|
|
||||||
int span = dstBounds.width();
|
int span = dstBounds.width();
|
||||||
for (int rows = min(dstBounds.height(), bandHeight); rows > 0; rows--) {
|
for (int rows = dstBounds.height(); rows > 0; rows--) {
|
||||||
switch (colorSpace) {
|
switch (colorSpace) {
|
||||||
case REC_601:
|
case REC_601:
|
||||||
linear_row_yuv<REC_601>((uint32_t*)dest, span, srcUV, srcDUV.x,
|
linear_row_yuv<REC_601>((uint32_t*)dest, span, srcUV, srcDUV.x,
|
||||||
|
@ -788,8 +774,7 @@ void CompositeYUV(LockedTexture* lockedDst, LockedTexture* lockedY,
|
||||||
LockedTexture* lockedU, LockedTexture* lockedV,
|
LockedTexture* lockedU, LockedTexture* lockedV,
|
||||||
YUVColorSpace colorSpace, GLint srcX, GLint srcY,
|
YUVColorSpace colorSpace, GLint srcX, GLint srcY,
|
||||||
GLsizei srcWidth, GLsizei srcHeight, GLint dstX, GLint dstY,
|
GLsizei srcWidth, GLsizei srcHeight, GLint dstX, GLint dstY,
|
||||||
GLsizei dstWidth, GLsizei dstHeight, GLboolean flip,
|
GLsizei dstWidth, GLsizei dstHeight, GLboolean flip) {
|
||||||
GLint bandOffset, GLsizei bandHeight) {
|
|
||||||
if (!lockedDst || !lockedY || !lockedU || !lockedV) {
|
if (!lockedDst || !lockedY || !lockedU || !lockedV) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -810,7 +795,7 @@ void CompositeYUV(LockedTexture* lockedDst, LockedTexture* lockedY,
|
||||||
// scaling. Further fast-paths for non-scaled video might be desirable in the
|
// scaling. Further fast-paths for non-scaled video might be desirable in the
|
||||||
// future.
|
// future.
|
||||||
linear_convert_yuv(ytex, utex, vtex, colorSpace, srcReq, dsttex, dstReq,
|
linear_convert_yuv(ytex, utex, vtex, colorSpace, srcReq, dsttex, dstReq,
|
||||||
flip, bandOffset, bandHeight);
|
flip);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -306,8 +306,6 @@ extern "C" {
|
||||||
opaque: GLboolean,
|
opaque: GLboolean,
|
||||||
flip: GLboolean,
|
flip: GLboolean,
|
||||||
filter: GLenum,
|
filter: GLenum,
|
||||||
band_offset: GLint,
|
|
||||||
band_height: GLsizei,
|
|
||||||
);
|
);
|
||||||
fn CompositeYUV(
|
fn CompositeYUV(
|
||||||
locked_dst: *mut LockedTexture,
|
locked_dst: *mut LockedTexture,
|
||||||
|
@ -324,8 +322,6 @@ extern "C" {
|
||||||
dst_width: GLsizei,
|
dst_width: GLsizei,
|
||||||
dst_height: GLsizei,
|
dst_height: GLsizei,
|
||||||
flip: GLboolean,
|
flip: GLboolean,
|
||||||
band_offset: GLint,
|
|
||||||
band_height: GLsizei,
|
|
||||||
);
|
);
|
||||||
fn CreateContext() -> *mut c_void;
|
fn CreateContext() -> *mut c_void;
|
||||||
fn ReferenceContext(ctx: *mut c_void);
|
fn ReferenceContext(ctx: *mut c_void);
|
||||||
|
@ -2322,9 +2318,7 @@ pub enum YUVColorSpace {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LockedResource {
|
impl LockedResource {
|
||||||
/// Composites from a locked resource to another locked resource. The band
|
/// Composites from a locked resource to another locked resource
|
||||||
/// offset and height are relative to the destination rectangle and specify
|
|
||||||
/// how to clip the composition into appropriate range for this band.
|
|
||||||
pub fn composite(
|
pub fn composite(
|
||||||
&self,
|
&self,
|
||||||
locked_src: &LockedResource,
|
locked_src: &LockedResource,
|
||||||
|
@ -2339,8 +2333,6 @@ impl LockedResource {
|
||||||
opaque: bool,
|
opaque: bool,
|
||||||
flip: bool,
|
flip: bool,
|
||||||
filter: GLenum,
|
filter: GLenum,
|
||||||
band_offset: GLint,
|
|
||||||
band_height: GLsizei,
|
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
Composite(
|
Composite(
|
||||||
|
@ -2357,8 +2349,6 @@ impl LockedResource {
|
||||||
opaque as GLboolean,
|
opaque as GLboolean,
|
||||||
flip as GLboolean,
|
flip as GLboolean,
|
||||||
filter,
|
filter,
|
||||||
band_offset,
|
|
||||||
band_height,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2379,8 +2369,6 @@ impl LockedResource {
|
||||||
dst_width: GLsizei,
|
dst_width: GLsizei,
|
||||||
dst_height: GLsizei,
|
dst_height: GLsizei,
|
||||||
flip: bool,
|
flip: bool,
|
||||||
band_offset: GLint,
|
|
||||||
band_height: GLsizei,
|
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
CompositeYUV(
|
CompositeYUV(
|
||||||
|
@ -2398,8 +2386,6 @@ impl LockedResource {
|
||||||
dst_width,
|
dst_width,
|
||||||
dst_height,
|
dst_height,
|
||||||
flip as GLboolean,
|
flip as GLboolean,
|
||||||
band_offset,
|
|
||||||
band_height,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -964,11 +964,6 @@ pub trait Compositor {
|
||||||
image_rendering: ImageRendering,
|
image_rendering: ImageRendering,
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Notify the compositor that all tiles have been invalidated and all
|
|
||||||
/// native surfaces have been added, thus it is safe to start compositing
|
|
||||||
/// valid surfaces.
|
|
||||||
fn start_compositing(&mut self) {}
|
|
||||||
|
|
||||||
/// Commit any changes in the compositor tree for this frame. WR calls
|
/// Commit any changes in the compositor tree for this frame. WR calls
|
||||||
/// this once when all surface and visual updates are complete, to signal
|
/// this once when all surface and visual updates are complete, to signal
|
||||||
/// that the OS composite transaction should be applied.
|
/// that the OS composite transaction should be applied.
|
||||||
|
|
|
@ -7827,6 +7827,5 @@ impl CompositeState {
|
||||||
surface.image_rendering,
|
surface.image_rendering,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
compositor.start_compositing();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::io::{self, Cursor, Error, ErrorKind, Read};
|
use std::io::{self, Cursor, Error, ErrorKind, Read};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
pub use crossbeam_channel::{select, Sender, Receiver};
|
pub use crossbeam_channel::{Sender, Receiver};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Payload {
|
pub struct Payload {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче