0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 20:03:10 +02:00
Commit Graph

32 Commits

Author SHA1 Message Date
Dudemanguy
ab3002851e vo_wlshm: bail out of resize if width/height is 0
It can happen during initialization and of course nothing good will
happen if we let this go through (i.e. segfault). Return and wait for
geometry to finish setting up in the wayland stuff before doing the
initial resize.
2023-07-08 20:47:35 -05:00
Ray Smith
8a43fc0e9a wayland: use bool type for alpha framebuffer tracking
ra_ctx_opts.want_alpha and vo_wayland_set_opaque_region's alpha
argument are only used as bool but both are ints. Particularly for the
function argument, passing a 0 or 1 is confusing - at first glance it
looks like you're specifying an alpha value of 0 or 1.

Since they're only used as bools, make them bools.
2023-02-28 14:53:32 +00:00
Dudemanguy
879824a47f wayland: add wp-fractional-scale-v1 support
This protocol is pretty important since it finally lets us solve the
longstanding issue of fractional scaling in wayland (no more mpv doing
rendering over the target resolution and then being scaled down). This
protocol also can completely replace the buffer_scale usage that we are
currently using for integer scaling so hopefully this can be removed
sometime in the future. Note that vo_dmabuf_wayland is omitted from the
fractional scale handling because we want the compositor to handle all
the scaling for that VO.

Fixes #9443.
2023-01-24 00:04:39 +00:00
Dudemanguy
006ec9ce43 wayland: rewrite geometry and scaling handling
This is in preparation for fractional scaling support. Basically, redo
all the coordinates in wayland so that wl->geometry is equal exactly to
what is being put out to the screen (no extra wl->scaling multiplication
required). The wl->vdparams variable is also eliminated for simplicity.
This changes mpv's behavior on wayland with hidpi scaling but that will
be addressed in more detail with the next commit.
2023-01-24 00:04:39 +00:00
Dudemanguy
4beb1bcae7 vo_wlshm: properly support video panscan
Turns out it was already doing this under the hood the entire time. The
only catch is that the vo just needed a resize.
2023-01-09 19:30:26 -06:00
Dudemanguy
e43393c4da vo_wlshm: cleanup on failure
If failure occurs during preinit, vo_wlshm should goto an error and
cleaup itself like the other VOs.
2023-01-08 12:39:50 -06:00
Dudemanguy
295ceab382 wayland: error out if essential protocol support is missing
Related issue: #10868. While most protocols are in theory optional, a
small amount of them are absolutely essential and nothing will work
without them. We should make sure to error out in those cases and not
try to actually do anything. For wayland support in general,
wl_compositor support is obviously required. If there is no wl_surface,
you can't do anything. Additionally, vo_wlshm quite obviously requires
wl_shm so mark that one as well. vo_dmabuf_wayland needs linux_dmabuf,
viewporter, wl_shm, and wl_subcompositor. In practice, these are all
very standard protocols and shouldn't be missing but the linked issue
above is at least one example where a compositor was stuck on an ancient
version of a wayland interface.
2022-11-15 14:42:02 +00:00
Dudemanguy
d2a0791fe8 wayland: correctly handle non-CLOCK_MONOTONIC clocks
The wayland presentation time code currently always assumes that only
CLOCK_MONOTONIC can be used. There is a naive attempt to ignore clocks
other than CLOCK_MONOTONIC, but the logic is actually totally wrong and
the timestamps would be used anyway. Fix this by checking a use_present
bool (similar to use_present in xorg) which is set to true if we receive
a valid clock in the clockid event. Additionally, allow
CLOCK_MONOTONIC_RAW as a valid clockid. In practice, it should be the
same as CLOCK_MONOTONIC for us (ntp/adjustime difference wouldn't
matter). Since this is a linux-specific clock, add a define for it if it
is not found.
2022-10-06 18:08:51 +00:00
Dudemanguy
7ce26dd324 vo: move wayland presentation to separate files
Wayland had some specific code that it used for implementing the
presentation time protocol. It turns out that xorg's present extension
is extremely similar, so it would be silly to duplicate this whole mess
again. Factor this out to separate, independent code and introduce the
mp_present struct which is used for handling the ust/msc values and some
other associated values. Also, add in some helper functions so all the
dirty details live specifically in present_sync. The only
wayland-specific part is actually obtaining ust/msc values. Since only
wayland or xorg are expected to use this, add a conditional to the build
that only adds this file when either one of those are present.

You may observe that sbc is completely omitted. This field existed in
wayland, but was completely unused (presentation time doesn't return
this). Xorg's present extension also doesn't use this so just get rid of
it all together. The actual calculation is slightly altered so it is
correct for our purposes. We want to get the presentation event of the
last frame that was just occured (this function executes right after the
buffer swap). The adjustment is to just remove the vsync_duration
subtraction. Also, The overly-complicated queue approach is removed.
This has no actual use in practice (on wayland or xorg). Presentation
statistics are only ever used after the immediate preceding swap to
update vsync timings or thrown away.
2022-06-19 18:13:55 +00:00
Aaron Boxer
3536b53ed1 vo: move allocate_memfd method to wayland_common 2022-05-30 19:51:46 +00:00
Dudemanguy
8a8580e05c wayland: use wl_surface_damage_buffer
Since 2018, wl_surface_damage_buffer has been explicitly preferred and
recommended over wl_surface_damage*. mpv was still using the old
function in a couple of spots. The only difference is that we need to
pass buffer coordinates instead of surface coordinates. In vo_wlshm,
this is done by using vo->dwidth/vo->dheight since that is always used
whenever wl_buffers are created. In the case of the cursor surfaace, we
actually already passed buffer coordinates to it (img->width/height)
which was probablly technically wrong with wl_surface_damage, but it
doesn't really matter in practice. This requires bumping wl_compositor
to version 4 which is no problem since this dates back to 2015*.

921d054803
3384f69ecf
2022-04-27 20:31:07 +00:00
Dudemanguy
cd1b04411f vo_wlshm: use draw_frame instead of draw_image
draw_image is an old API that was deprecated long ago. However when
wlshm was originally added, it used draw_image. There's no particular
reason for this and it can trivially be switched to draw_frame instead.
This has some real advantages (notably --vo=wlshm --idle --force-window
actually works).
2022-04-21 14:47:43 +00:00
Dudemanguy
2c2a856f25 wayland: unify visibility checking code
A bit of a personal pet peeve. vulkan, opengl, and wlshm all had
different methods for doing wayland's "check for visibility before
drawing" thing. The specific backend doesn't matter in this case and the
logic should all be shared. Additionally, the external swapchain that
the opengl code on wayland uses is done away with and it instead copies
vulkan by using a param. This keeps things looking more uniform across
backends and also makes it easier to extend to other platforms (see the
next couple of commits).
2022-04-11 18:14:22 +00:00
Dudemanguy
e9e1c41060 vo_wlshm: remove empty options struct
This doesn't do anything and isn't needed as there are no wlshm-specific
options.
2021-08-09 16:39:08 -05:00
Dudemanguy
76bddaccd6 wayland: always be sure to initially try to render
A subtle regression from c26d833. On sway if mpv was set to be a
floating window in the config, set_buffer_scale would actually get
applied twice according to the wayland log. That meant a 1920x1080
window would appear as a 960x540 window if the scale of the wl_output
was set to 2. This only affected egl on sway (didn't occur on weston and
was too lazy to try anything else; probably they were fine). Since
wl->render is initially false, that meant that the very first run
through the render loop returns false. This probably caused something
weird to happen with the set_buffer_scale calls (the egl window gets
created and everything but mpv doesn't write to it just yet) which makes
the set_buffer_scale call happen an extra time. Since it was always
intended for mpv to initally render, this is worth fixing. Just chnage
wl->render to wl->hidden (again) and flip the bools around. That way,
the initial false value results in render == true and mpv tries to draw
on the first pass. This fixes the weird scaling behavior because
reasons.
2021-06-27 10:58:42 -05:00
Dudemanguy
488581912d wayland: reorganize wayland common code
Mostly a cosmetic change that (hopefully) makes things look better. Some
functions and structs that were previously being exported in the wayland
header were made static to the wayland_common.c file (these shouldn't be
accessed by anyone else).
2021-06-26 17:24:44 -05:00
Dudemanguy
c26d83348b wayland: shuffle around the render loop again
Take two. f4e89dd went wrong by moving vo_wayland_wait_frame before
start_frame was called. Whether or not this matters depends on the
compositor, but some weird things can happen. Basically, it's a
scheduling issue. vo_wayland_wait_frame queues all events and sends them
to the server to process (with no blocking if presentation time is
available). If mpv changes state while rendering (and this function is
called before every frame is drawn), then that event also gets
dispatched and sent to the compositor. This, in some cases, can cause
some funny behavior because the next frame gets attached to the surface
while the old buffer is getting released. It's safer to call this
function after the swap already happens and well before mpv calls its
next draw. There's no weird scheduling of events, and the compositor log
is more normal.

The second part of this is to fix some stuttering issues. This is mostly
just conjecture, but probably what was happening was this thing called
"composition". The easiest way to see this is to play a video on the
default audio sync mode (probably easiest to see on a typical 23.976
video). Have that in a window and float it over firefox (floating
windows are bloat on a tiling wm anyway). Then in firefox, do some short
bursts of smooth scrolling (likely uses egl). Some stutter in video
rendering could be observed, particularly in panning shots.

Compositors are supposed to prevent tearing so what likely was happening
was that the compositor was simply holding the buffer a wee bit longer
to make sure it happened in sync with the smooth scrolling. Because the
mpv code waits precisely on presentation time, the loop would timeout on
occasion instead of receiving the frame callback. This would then lead
to a skipped frame when rendering and thus causing stuttering.

The fix is simple: just only count consecutive timeouts as not receiving
frame callback. If a compositor holds the mpv buffer slightly longer to
avoid tearing, then we will definitely receive frame callback on the
next round of the render loop. This logic also appears to be sound for
plasma (funfact: Plasma always returns frame callback even when the
window is hidden. Not sure what's up with that, but luckily it doesn't
matter to us.), so get rid of the goofy 1/vblank_time thing and just
keep it a simple > 1 check.
2021-05-24 19:20:31 +00:00
Dudemanguy
f4e89dde36 wayland: simplify render loop
This is actually a very nice simplification that should have been
thought of years ago (sue me). In a nutshell, the story with the
wayland code is that the frame callback and swap buffer behavior doesn't
fit very well with mpv's rendering loop. It's been refactored/changed
quite a few times over the years and works well enough but things could
be better. The current iteration works with an external swapchain to
check if we have frame callback before deciding whether or not to
render. This logic was implemented in both egl and vulkan.

This does have its warts however. There's some hidden state detection
logic which works but is kind of ugly. Since wayland doesn't allow
clients to know if they are actually visible (questionable but
whatever), you can just reasonably assume that if a bunch of callbacks
are missed in a row, you're probably not visible. That's fine, but it is
indeed less than ideal since the threshold is basically entirely
arbitrary and mpv does do a few wasteful renders before it decides that
the window is actually hidden.

The biggest urk in the vo_wayland_wait_frame is the use of
wl_display_roundtrip. Wayland developers would probably be offended by
the way mpv abuses that function, but essentially it was a way to have
semi-blocking behavior needed for display-resample to work. Since the
swap interval must be 0 on wayland (otherwise it will block the entire
player's rendering loop), we need some other way to wait on vsync. The
idea here was to dispatch and poll a bunch of wayland events, wait (with
a timeout) until we get frame callback, and then wait for the compositor
to process it. That pretty much perfectly waits on vsync and lets us
keep all the good timings and all that jazz that we want for mpv. The
problem is that wl_display_roundtrip is conceptually a bad function. It
can internally call wl_display_dispatch which in certain instances,
empty event queue, will block forever. Now strictly speaking, this
probably will never, ever happen (once I was able to to trigger it by
hardcoding an error into a compositor), but ideally
vo_wayland_wait_frame should never infinitely block and stall the
player. Unfortunately, removing that function always lead to problems
with timings and unsteady vsync intervals so it survived many refactors.

Until now, of course. In wayland, the ideal is to never do wasteful
rendering (i.e. don't render if the window isn't visible). Instead of
wrestling around with hidden states and possible missed vblanks, let's
rearrange the wayland rendering logic so we only ever draw a frame when
the frame callback is returned to use (within a reasonable timeout to
avoid blocking forever).

This slight rearrangement of the wait allows for several simplifications
to be made. Namely, wl_display_roundtrip stops being needed. Instead, we
can rely entirely on totally nonblocking calls (dispatch_pending, flush,
and so on). We still need to poll the fd here to actually get the frame
callback event from the compositor, but there's no longer any reason to
do extra waiting. As soon as we get the callback, we immediately draw.
This works quite well and has stable vsync (display-resample and audio).
Additionally, all of the logic about hidden states is no longer needed.
If vo_wayland_wait_frame times out, it's okay to assume immediately that
the window is not visible and skip rendering.

Unfortunately, there's one limitation on this new approach. It will only
work correctly if the compositor implements presentation time. That
means a reduced version of the old way still has to be carried around in
vo_wayland_wait_frame. So if the compositor has no presentation time,
then we are forced to use wl_display_roundtrip and juggle some funny
assumptions about whether or not the window is hidden or not. Plasma is
the only real notable compositor without presentation time at this stage
so perhaps this "legacy" mechanism could be removed in the future.
2021-05-22 00:59:56 +00:00
Emmanuel Gil Peyrot
f8a9654873 vo_wlshm: support big endian systems
The video was otherwise blue, and that’s not how it should be. :)
2021-02-04 21:13:09 +02:00
Dudemanguy
4029a695b5 vo_wlshm: support presentation time
We get presentation feedback for free thanks to the last commit.
Implementing it in wlshm is pretty straightfoward from there.
2020-12-14 22:44:43 +00:00
Dudemanguy
b59eaf57fe wayland: unify frame/presentation callback code
Originally when presentation time was implemented, the frame callback
and presentation feedback functions were called in each rendering api's
separate backend (egl and vulkan). This meant that their respective
structs were basically copy and pasted across both files. Plus later
vo_wlshm started using frame callbacks too. Things got refactored a few
times and it turns out there's actually no need to have these things
separate anymore. The frame callback can just be initialized in
vo_wayland_init and then everything else will follow from there. Just
move all of this code to wayland_common and get rid of the duplication.

Sidenote: This means that vo_wlshm can actually receive presentation
feedback now. It's really simple to do so might as well. See the next
commit.
2020-12-14 22:44:43 +00:00
Dudemanguy
dae6b1be96 Revert "wayland: conditionally commit surface on resize"
30dcfbc is a workaround for incorrect border sizes that could occur on
sway/wlroots in certain edge cases. This seemed harmless enough, but it
turns out that on mutter the extra wl_surface_commit somehow causes the
window always go to the top left of the screen after you leave
fullscreen. No idea why this occurs, but the original commit is a
workaround a sway bug and causing regressions for other users isn't
right despite the author being biased towards sway/wlroots.

This reverts commit 30dcfbc9cb.
2020-11-08 09:51:52 -06:00
Dudemanguy
b60545bdc6 wayland: update opaque region on runtime
Made possible with 00b9c81. 34b8adc let the wayland surface set an
opaque region depending on if alpha was set by the user or not. However,
there was no attempted detection for runtime changes and it is possible
(at least in wayland vulkan) to toggle the alpha on and off. So this
meant, we could be incorrectly signalling an opaque region if the user
happened to change the alpha. Additionally, add a helper function for
this and use it everywhere we want to set the opaque region.
2020-10-15 13:43:45 +00:00
Dudemanguy
deaea70630 wayland: be less strict about when to render
efb0c5c changed the rendering logic of mpv on wayland and made it skip
rendering when it did not receive frame callback in time. The idea was
to skip rendering when the surface was hidden and be less wasteful. This
unfortunately had issues in certain instances where a frame callback
could be missed (but the window was still in view) due to imprecise
rendering (like the default audio video-sync mode). This would lead to
the video appearing to stutter since mpv would skip rendering in those
cases.

To account for this case, simply re-add an old heuristic for detecting
if a window is hidden or not since the goal is to simply not render when
a window is hidden. If the wait on the frame callback times out enough
times in a row, then we consider the window hidden and thus begin to
skip rendering then. The actual threshold to consider a surface as
hidden is completely arbitrary (greater than your monitor's refresh
rate), but it's safe enough since realistically you're not going to miss
60+ frame callbacks in a row unless the surface actually is hidden.
Fixes #8169.
2020-10-15 13:36:49 +00:00
Dudemanguy
34b8adc456 wayland: set an opaque region
Apparently a part of the wayland spec. A compositor may use a surface
that has set part of itself as opaque for various optimizations. For
mpv, we simply set the entire surface as opaque as long as the user has
not set alpha=yes (note: alpha is technically broken in the wayland EGL
backend at the time of this commit but oh well). wlshm is always opaque.
Fixes #8125.
2020-10-01 11:12:22 -05:00
Dudemanguy
efb0c5c446 wayland: only render if we have frame callback
Back in the olden days, mpv's wayland backend was driven by the frame
callback. This had several issues and was removed in favor of the
current approach which allowed some advanced features (like
display-resample and presentation time) to actually work properly.
However as a consequence, it meant that mpv always rendered, even if the
surface was hidden. Wayland people consider this "wasteful" (and well
they aren't wrong). This commit aims to avoid wasteful rendering by
doing some additional checks in the swapchain. There's three main parts
to this.

1. Wayland EGL now uses an external swapchain (like the drm context).
Before we start a new frame, we check to see if we are waiting on a
callback from the compositor. If there is no wait, then go ahead and
proceed to render the frame, swap buffers, and then initiate
vo_wayland_wait_frame to poll (with a timeout) for the next potential
callback. If we are still waiting on callback from the compositor when
starting a new frame, then we simple skip rendering it entirely until
the surface comes back into view.

2. Wayland on vulkan has essentially the same approach although the
details are a little different. The ra_vk_ctx does not have support for
an external swapchain and although such a mechanism could theoretically
be added, it doesn't make much sense with libplacebo. Instead,
start_frame was added as a param and used to check for callback.

3. For wlshm, it's simply a matter of adding frame callback to it,
leveraging vo_wayland_wait_frame, and using the frame callback value to
whether or not to draw the image.
2020-09-21 20:42:17 +00:00
Dudemanguy
30dcfbc9cb wayland: conditionally commit surface on resize
It was possible for sway to get incorrectly sized borders if you resized
the mpv window in a creative manner (e.g. open a video in a non-floating
mode, set window scale to 2, then float it and witness wrong border
sizes). This is possibly a sway bug (Plasma doesn't have these border
issues at least), but there's a reasonable workaround for this.

The reason for the incorrect border size is because it is possible for
mpv to ignore the width/height from the toplevel listener and set its
own size. This new size can differ from what sway/wlroots believes the
size is which is what causes the sever side decorations to be drawn on
incorrect dimensions.

A simple trick is to just explicitly commit the surface after a resize
is performed. This is only done if mpv is not fullscreened or maximized
since we always obey the compositor widths/heights in those cases.
Sending the commit signals the compositor of the new change in the
surface and thus sway/wlroots updates its internal coordinates
appropriately and borders are no longer broken.
2020-08-20 16:57:37 +00:00
Michael Forney
3cb9e93cdf vo_wlshm, vo_drm: set image size with mp_image_set_size
The image w and h members must match params.w and params.h, so
should not be changed directly. The helper function mp_image_set_size
is designed for this purpose, so just use that instead.

This prevents an assertion error with the rewritten draw_bmp.

Fixes #7721.
2020-05-17 12:53:26 +02:00
wm4
5a45a4ca39 vo_drm, wo_wlshm: mention that it's software scaling
(But does anyone even read --vo=help output?)
2020-02-11 21:45:16 +01:00
wm4
835586513d sws_utils: shuffle around some shit
Purpose uncertain. I guess it's slightly better, maybe.

The move of the sws/zimg options from VO opts (vo_opt_list) to the
top-level option list is tricky. VO opts have some helper code in vo.c,
that sends VOCTRL_SET_PANSCAN to the VO on every VO opts change. That's
because updating certain VO options used to be this way (and not just
the panscan option). This isn't needed anymore for sws/zimg options, so
explicitly move them away.
2019-10-31 15:26:03 +01:00
Emmanuel Gil Peyrot
a6000d3114 vo_wlshm: use memfd_create() instead of shm_open()
This syscall avoids the need to guess an unused filename in /dev/shm and
allows seals to be placed on it.  We immediately return if no fd got
returned, as there isn’t anything we can do otherwise.

Seals especially allow the compositor to drop the SIGBUS protections,
since the kernel promises the fd won’t ever shrink.

This removes support for any platform but Linux from this vo.
2019-10-17 19:38:04 +02:00
Michael Forney
2fcd5271eb Reintroduce vo_wayland as vo_wlshm
vo_wayland was removed during the wayland rewrite done in 0.28. However,
it is still useful for systems that do not have OpenGL.

The new wayland_common code makes vo_wayland much simpler, and
eliminates many of the issues the previous vo_wayland had.
2019-10-17 12:26:22 +02:00