Skip to content

Commit 977b935

Browse files
authored
Merge pull request #1109 from mahkoh/jorth/color-pipeline-prp
metal: color pipeline preparations
2 parents 2054f83 + 0f98975 commit 977b935

4 files changed

Lines changed: 218 additions & 152 deletions

File tree

src/backends/metal/present.rs

Lines changed: 123 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use {
77
transaction::{DrmConnectorState, DrmPlaneState},
88
video::{MetalConnector, MetalCrtc, MetalHardwareCursorChange, MetalPlane},
99
},
10-
cmm::cmm_description::ColorDescription,
10+
cmm::{cmm_description::ColorDescription, cmm_render_intent::RenderIntent},
1111
gfx_api::{
1212
AcquireSync, BufferResv, DirectScanoutPosition, GfxRenderPass, GfxTexture, LazyTexture,
1313
ReleaseSync, SyncFile, TextureUse, create_render_pass,
@@ -27,6 +27,7 @@ use {
2727
},
2828
},
2929
arrayvec::ArrayVec,
30+
jay_proc::jay_hash,
3031
std::rc::{Rc, Weak},
3132
uapi::{OwnedFd, c},
3233
};
@@ -44,24 +45,44 @@ pub struct DirectScanoutCache {
4445
fb: Option<Rc<DrmFramebuffer>>,
4546
}
4647

48+
#[jay_hash]
49+
#[derive(Copy, Clone, Debug)]
50+
pub struct DirectScanoutKey {
51+
dma_buf_id: DmaBufId,
52+
has_cursor_plane: bool,
53+
}
54+
55+
#[derive(Debug)]
56+
struct DirectScanoutData {
57+
fb_cd: Rc<ColorDescription>,
58+
fb_intent: RenderIntent,
59+
key: DirectScanoutKey,
60+
}
61+
4762
#[derive(Debug)]
48-
pub struct DirectScanoutData {
63+
struct DirectScanoutDataCore {
4964
tex: Rc<dyn GfxTexture>,
5065
tex_resv: Option<Rc<dyn BufferResv>>,
5166
acquire_sync: AcquireSync,
5267
release_sync: ReleaseSync,
5368
_fb_resv: Option<Rc<dyn BufferResv>>,
5469
lazy: Option<Rc<dyn LazyTexture>>,
5570
fb: Rc<DrmFramebuffer>,
56-
dma_buf_id: DmaBufId,
5771
position: DirectScanoutPosition,
5872
}
5973

60-
pub struct PresentFb {
74+
struct PresentFb {
75+
fb_intent: RenderIntent,
76+
copy: RenderBufferCopy,
77+
direct_scanout_key: Option<DirectScanoutKey>,
78+
core: PresentFbCore,
79+
}
80+
81+
pub struct PresentFbCore {
6182
fb: Rc<DrmFramebuffer>,
83+
fb_cd: Rc<ColorDescription>,
6284
tex: Rc<dyn GfxTexture>,
63-
direct_scanout_data: Option<DirectScanoutData>,
64-
copy: RenderBufferCopy,
85+
direct_scanout_data: Option<DirectScanoutDataCore>,
6586
pub locked: bool,
6687
}
6788

@@ -218,10 +239,10 @@ impl MetalConnector {
218239
}
219240

220241
let mut present_fb = None;
221-
let mut direct_scanout_id = None;
242+
let mut direct_scanout_key = None;
222243
if let Some(latched) = &latched {
223244
let fb = self.prepare_present_fb(&cd, blend_cd, buffer, &plane, latched, true)?;
224-
direct_scanout_id = fb.direct_scanout_data.as_ref().map(|d| d.dma_buf_id);
245+
direct_scanout_key = fb.direct_scanout_key;
225246
present_fb = Some(fb);
226247
}
227248
self.await_present_fb(present_fb.as_mut(), PresentFbWait::Render)
@@ -231,7 +252,7 @@ impl MetalConnector {
231252
// could interfere with scanout. However, perform_screencopies just uses the
232253
// current PresentFb if present_fb is None, potentially mutating the fb that is
233254
// currently being scanned out, which would render such a wait absurd.
234-
self.perform_screencopies(&present_fb, &node, &cd);
255+
self.perform_screencopies(&present_fb, &node);
235256
if let Some(sync) = self.cursor_sync.take() {
236257
sync.signaled(&self.state.ring, "cursor").await;
237258
}
@@ -248,7 +269,7 @@ impl MetalConnector {
248269
&mut connector_drm_state,
249270
);
250271
if res.is_err()
251-
&& let Some(dsd_id) = direct_scanout_id
272+
&& let Some(dsk) = direct_scanout_key
252273
{
253274
let fb = self.prepare_present_fb(
254275
&cd,
@@ -271,16 +292,7 @@ impl MetalConnector {
271292
&mut connector_drm_state,
272293
);
273294
if res.is_ok() {
274-
let mut cache = self.scanout_buffers.borrow_mut();
275-
if let Some(buffer) = cache.remove(&dsd_id) {
276-
cache.insert(
277-
dsd_id,
278-
DirectScanoutCache {
279-
dmabuf: buffer.dmabuf,
280-
fb: None,
281-
},
282-
);
283-
}
295+
self.scanout_impossible_cache.insert(dsk, ());
284296
}
285297
}
286298
let reset_damage = || {
@@ -307,15 +319,17 @@ impl MetalConnector {
307319
*plane.plane.drm_state.borrow_mut() = plane.state;
308320
}
309321
if let Some(fb) = present_fb {
322+
self.fb_color_description.set(fb.core.fb_cd.clone());
323+
self.fb_render_intent.set(fb.fb_intent);
310324
self.presentation_is_zero_copy
311-
.set(fb.direct_scanout_data.is_some());
312-
if fb.direct_scanout_data.is_none() {
325+
.set(fb.core.direct_scanout_data.is_some());
326+
if fb.core.direct_scanout_data.is_none() {
313327
buffer.damage_queue.clear();
314328
} else {
315329
reset_damage();
316330
}
317-
buffer.locked.set(fb.locked);
318-
self.next_framebuffer.set(Some(fb));
331+
buffer.locked.set(fb.core.locked);
332+
self.next_framebuffer.set(Some(fb.core));
319333
}
320334
if let Some(programming) = cursor_programming
321335
&& let CursorProgrammingType::Enable { swap: true, .. } = &programming.ty
@@ -372,7 +386,7 @@ impl MetalConnector {
372386
let mut connector_state = connector_drm_state.clone();
373387
if let Some(fb) = new_fb {
374388
let (crtc_x, crtc_y, crtc_w, crtc_h, src_width, src_height) =
375-
match &fb.direct_scanout_data {
389+
match &fb.core.direct_scanout_data {
376390
None => {
377391
let plane_w = plane.mode_w.get();
378392
let plane_h = plane.mode_h.get();
@@ -391,11 +405,11 @@ impl MetalConnector {
391405
}
392406
};
393407
changes.change_object(plane.id, |c| {
394-
c.change(drm_state.fb_id.id, fb.fb.id());
395-
drm_state.fb_id.value = fb.fb.id();
396-
connector_state.fb = fb.fb.id();
397-
connector_state.locked = fb.locked;
398-
if fb.direct_scanout_data.is_none() {
408+
c.change(drm_state.fb_id.id, fb.core.fb.id());
409+
drm_state.fb_id.value = fb.core.fb.id();
410+
connector_state.fb = fb.core.fb.id();
411+
connector_state.locked = fb.core.locked;
412+
if fb.core.direct_scanout_data.is_none() {
399413
connector_state.fb_idx += 1;
400414
}
401415
macro_rules! change {
@@ -456,7 +470,7 @@ impl MetalConnector {
456470
change!(src_y, 0);
457471
change!(src_w, (*width as u32) << 16);
458472
change!(src_h, (*height as u32) << 16);
459-
if !self.dev.is_nvidia
473+
if !self.dev.vendor.is_nvidia
460474
&& let Some(sf) = self.backend.signaled_sync_file.get()
461475
{
462476
c.change(plane.in_fence_fd, sf.0.raw() as u64);
@@ -489,7 +503,7 @@ impl MetalConnector {
489503
}
490504
}
491505
self.presentation_is_sync.set(true);
492-
if !self.dev.is_nvidia {
506+
if !self.dev.vendor.is_nvidia {
493507
if new_fb.is_some()
494508
&& let Some(sf) = self.backend.signaled_sync_file.get()
495509
{
@@ -636,7 +650,7 @@ impl MetalConnector {
636650
plane: &Rc<MetalPlane>,
637651
blend_cd: &Rc<ColorDescription>,
638652
cd: &Rc<ColorDescription>,
639-
) -> Option<DirectScanoutData> {
653+
) -> Option<(DirectScanoutData, DirectScanoutDataCore)> {
640654
let (ct, position) = pass.prepare_direct_scanout(
641655
plane.mode_w.get(),
642656
plane.mode_h.get(),
@@ -682,19 +696,46 @@ impl MetalConnector {
682696
// Shm buffers cannot be scanned out.
683697
return None;
684698
};
685-
let mut cache = self.scanout_buffers.borrow_mut();
686-
if let Some(buffer) = cache.get(&dmabuf.id) {
687-
return buffer.fb.as_ref().map(|fb| DirectScanoutData {
699+
let key = DirectScanoutKey {
700+
dma_buf_id: dmabuf.id,
701+
has_cursor_plane: self.cursor_enabled.get(),
702+
};
703+
if let Some(v) = self.scanout_impossible_cache.get(&key) {
704+
v.mark_used();
705+
return None;
706+
}
707+
let res = self.prepare_direct_scanout3(plane, dmabuf);
708+
if res.is_none() {
709+
self.scanout_impossible_cache.insert(key, ());
710+
}
711+
res.map(|fb| {
712+
let data = DirectScanoutData {
713+
fb_cd: ct.cd.clone(),
714+
fb_intent: ct.render_intent,
715+
key,
716+
};
717+
let core = DirectScanoutDataCore {
688718
tex: ct.tex.clone(),
689719
tex_resv: ct.buffer_resv.clone(),
690720
acquire_sync: ct.acquire_sync.clone(),
691721
release_sync,
692722
_fb_resv: fb_resv,
693723
lazy: ct.lazy.clone(),
694-
fb: fb.clone(),
695-
dma_buf_id: dmabuf.id,
724+
fb,
696725
position,
697-
});
726+
};
727+
(data, core)
728+
})
729+
}
730+
731+
fn prepare_direct_scanout3(
732+
&self,
733+
plane: &Rc<MetalPlane>,
734+
dmabuf: &Rc<DmaBuf>,
735+
) -> Option<Rc<DrmFramebuffer>> {
736+
let mut cache = self.scanout_buffers.borrow_mut();
737+
if let Some(buffer) = cache.get(&dmabuf.id) {
738+
return buffer.fb.clone();
698739
}
699740
let format = 'format: {
700741
if let Some(f) = plane.formats.get(&dmabuf.format.drm) {
@@ -711,18 +752,8 @@ impl MetalConnector {
711752
if !format.modifiers.contains(&dmabuf.modifier) {
712753
return None;
713754
}
714-
let data = match self.dev.master.add_fb(dmabuf, Some(format.format)) {
715-
Ok(fb) => Some(DirectScanoutData {
716-
tex: ct.tex.clone(),
717-
tex_resv: ct.buffer_resv.clone(),
718-
acquire_sync: ct.acquire_sync.clone(),
719-
release_sync,
720-
_fb_resv: fb_resv,
721-
lazy: ct.lazy.clone(),
722-
fb: Rc::new(fb),
723-
dma_buf_id: dmabuf.id,
724-
position,
725-
}),
755+
let fb = match self.dev.master.add_fb(dmabuf, Some(format.format)) {
756+
Ok(fb) => Some(Rc::new(fb)),
726757
Err(e) => {
727758
log::debug!(
728759
"Could not import dmabuf for direct scanout: {}",
@@ -735,10 +766,10 @@ impl MetalConnector {
735766
dmabuf.id,
736767
DirectScanoutCache {
737768
dmabuf: Rc::downgrade(dmabuf),
738-
fb: data.as_ref().map(|dsd| dsd.fb.clone()),
769+
fb: fb.clone(),
739770
},
740771
);
741-
data
772+
fb
742773
}
743774

744775
fn prepare_present_fb(
@@ -766,9 +797,30 @@ impl MetalConnector {
766797
}
767798
let copy;
768799
let fb;
800+
let fb_cd;
801+
let fb_intent;
769802
let tex;
770-
match &direct_scanout_data {
771-
None => {
803+
let direct_scanout_key;
804+
let (dsd, mut dsd_core) = direct_scanout_data.unzip();
805+
match (dsd, &mut dsd_core) {
806+
(Some(dsd), Some(core)) => {
807+
if let Some(lazy) = &core.lazy {
808+
lazy.record_use(TextureUse::Scanout);
809+
}
810+
let sync = match &core.acquire_sync {
811+
AcquireSync::None => None,
812+
AcquireSync::Implicit => None,
813+
AcquireSync::FdSync(sync) => Some(sync.clone()),
814+
AcquireSync::Unnecessary => None,
815+
};
816+
copy = RenderBufferCopy::for_both(sync);
817+
fb = core.fb.clone();
818+
fb_cd = dsd.fb_cd;
819+
fb_intent = dsd.fb_intent;
820+
direct_scanout_key = Some(dsd.key);
821+
tex = core.tex.clone();
822+
}
823+
_ => {
772824
let sf = buffer
773825
.render
774826
.fb
@@ -786,41 +838,30 @@ impl MetalConnector {
786838
.copy_to_dev(cd, Some(&latched.damage), sf)
787839
.map_err(MetalError::CopyToDev)?;
788840
fb = buffer.drm.clone();
841+
fb_cd = cd.clone();
842+
fb_intent = RenderIntent::Perceptual;
843+
direct_scanout_key = None;
789844
tex = buffer.render.tex.clone();
790845
}
791-
Some(dsd) => {
792-
if let Some(lazy) = &dsd.lazy {
793-
lazy.record_use(TextureUse::Scanout);
794-
}
795-
let sync = match &dsd.acquire_sync {
796-
AcquireSync::None => None,
797-
AcquireSync::Implicit => None,
798-
AcquireSync::FdSync(sync) => Some(sync.clone()),
799-
AcquireSync::Unnecessary => None,
800-
};
801-
copy = RenderBufferCopy::for_both(sync);
802-
fb = dsd.fb.clone();
803-
tex = dsd.tex.clone();
804-
}
805846
};
806847
Ok(PresentFb {
807-
fb,
808-
tex,
809-
direct_scanout_data,
848+
fb_intent,
810849
copy,
811-
locked: latched.locked,
850+
direct_scanout_key,
851+
core: PresentFbCore {
852+
fb,
853+
fb_cd,
854+
tex,
855+
direct_scanout_data: dsd_core,
856+
locked: latched.locked,
857+
},
812858
})
813859
}
814860

815-
fn perform_screencopies(
816-
&self,
817-
new_fb: &Option<PresentFb>,
818-
output: &OutputNode,
819-
cd: &Rc<ColorDescription>,
820-
) {
861+
fn perform_screencopies(&self, new_fb: &Option<PresentFb>, output: &OutputNode) {
821862
let active_fb;
822863
let fb = match &new_fb {
823-
Some(f) => f,
864+
Some(f) => &f.core,
824865
None => {
825866
active_fb = self.active_framebuffer.borrow();
826867
match &*active_fb {
@@ -834,7 +875,7 @@ impl MetalConnector {
834875
None => {
835876
output.perform_screencopies(
836877
&fb.tex,
837-
cd,
878+
&fb.fb_cd,
838879
None,
839880
None,
840881
&AcquireSync::Unnecessary,
@@ -848,7 +889,7 @@ impl MetalConnector {
848889
Some(dsd) => {
849890
output.perform_screencopies(
850891
&dsd.tex,
851-
cd,
892+
&fb.fb_cd,
852893
dsd.tex_resv.as_ref(),
853894
dsd.lazy.as_ref(),
854895
&dsd.acquire_sync,

0 commit comments

Comments
 (0)