So it turns out that mpv already has an mp_tag_str which makes a
readable string out of fourccs (drm formats are these).
drm_format_string, on the other hand, has a ton of baggage with having
to check different libdrm versions for certain headers, adding
compile-time defines (because there are no version defines in the libdrm
headers), etc. It's a lot simpler to just use what mpv already has and
it returns what you actually care about: i.e. is this format supported
or not. Fixes https://github.com/mpv-player/mpv-build/issues/184
This driver makes use of dmabuffer and viewporter interfaces
to enable efficient display of vaapi surfaces, avoiding
any unnecessary colour space conversion, and avoiding scaling
or colour conversion using GPU shader resources.
5774ce759a added the new output name event
and used them for the --fs-screen-name option. It turns out that the
display-names property could also make use of these names, so go ahead
and use output->name in this case if we have them. If not, fallback to
output->model like before.
These values and options were simply never looked at in the drm egl
context. This pretty much is just a copy and paste of what is in vo_drm.
Fixes#10157.
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*.
921d0548033384f69ecf
It is possible for vo_gpu_next to attempt a resize before the windowing
backend is fully initialized. In practice, this can happen on wayland
which means libplacebo attempts a 0x0 resize. Depending on the API, a
0x0 resize may be allowed (vulkan or d3d11), but libplacebo just returns
a 0 in this case which mpv doesn't do anything with anyway. In the case
of opengl, this usage is explictly forbidden and will result in a
warning which may confuse users. Solve this by just not trying a resize
if dwidth and dheight in the vo are not available. Fixes#10083.
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).
In wayland 1.20.0, a couple of new events, name and description, were
added to the interface. Description is not particularly useful, but name
returns back nice names for the output like "DP-1" and so on. It makes
sense to use these for fs-screen-name and prefer them over the model
name (old way of doing it) if they are available. The only problem is
that 1.20.0 is pretty new so old distros aren't going to have it anytime
soon. Deal with this by adding some defines.
Because wayland is a special snowflake, mpv wound up incorporating a lot
of logic into its render loop where visibilty checks are performed
before rendering anything (in the name of efficiency of course). Only
wayland actually uses this, but there's no reason why other backends
(x11 in this commit) can't be smarter. It's far easier on xorg since we
can just query _NET_WM_STATE_HIDDEN directly and not have to do silly
callback dances.
The function, vo_x11_check_net_wm_state_change, already tracks net wm
changes, including _NET_WM_STATE_HIDDEN. There is an already existing
window_hidden variable but that is actually just for checking if the
window was mapped and has nothing to do with this particular atom. mpv
also currently assumes that a _NET_WM_STATE_HIDDEN is exactly the same
as being minimized but according to the spec, that's not neccesarily
true (in practice, it's likely that these are the same though). Anyways,
just keep track of this state in a new variable (hidden) and use that
for determing if mpv should render or not.
There is one catch though: this cannot work if a display sync mode is
used. This is why the previous commit is needed. The display sync modes
in mpv require a blocking vsync implementation since its render loop is
directly driven by vsync. In xorg, if nothing is actually rendered, then
there's nothing for eglSwapBuffers (or FIFO for vulkan) to block on so
it returns immediately. This, of course, results in completely broken
video. We just need to check to make sure that we aren't in a display
sync mode before trying to be smart about rendering. Display sync is
power inefficient anyways, so no one is really being hurt here. As an
aside, this happens to work in wayland because there's basically a
custom (and ugly) vsync blocking function + timeout but that's off
topic.
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).
This lets us remap various messages which might now be happening at
each frame onto the trace level, thus unaffecting the initial debug
log level.
Additionally - thanks to this ability - the previously globally denied
message queue abandonment messages can now be handled and mapped to
trace log level, as on that log level they may be of use.
Recommended by rossy and based on his libplacebo commit
6d72f6445566eddb0493447d0bda72d98a99d40c .
Instead of always having the reference outside of calling resize,
request a backbuffer at start and relieve the backbuffer at
submission for presentation.
Query the description of the swap chain, which should in all theory
contain the format of the backbuffer. Then utilize a newly added
ra_d3d11 function to map the format to an ra_format. After that,
utilize the depth of the first plane of the format, as previously.
This makes use of the new frame acquire/release callbacks to hold on to
hwdec images only as long as necessary. This should greatly improve the
smoothness/efficiency of hwdec interop, by not holding on to them for
longer than needed.
This also avoids the need to pool hwdec mappers altogether.
Should fix#10067 as well, since frames are now only mapped when we
actually use them.
9a7b2015e1 added the --screen-name option
for x11, but it was unfortunately broken. The commit does correctly
handle vo_x11_update_screeninfo and select the correct screen. However,
vo_x11_sizehint was missed. Specifically, the force_pos bool was always
false because it only took into account --screen being set and not
--screen-name. To fix this, just add an extra condition to the force_pos
bool so it becomes true if there's a string in --screen_name. Fixes
issue #9877.
Previously on wayland, it would result in an egl config with only 2 alpha
bits, which technically matches what was requested, but is not very useful.
Fixes#9862
Variable Refresh Rate (VRR), aka Freesync or Adaptive Sync can be used
with DRM by setting the VRR_ENABLED property on a crtc if the
connector reports that it is VRR_CAPABLE. This is a useful feature
for us as it is common to play 24/25/50 fps content on displays that
are nominally locked to 60Hz. VRR can allow this content to play at
native framerates.
This is a simple change as we just need to check the capability
and set the enabled property if requested by the user. I've defaulted
it to disabled for now, but it might make sense to default to auto
in the long term.
Pulling in <libplacebo/utils/libav.h> in particular triggers the
notorious _av_vkfmt_from_pixfmt linking issue when FFmpeg is built
without Vulkan support.
When I introduced the concept of lazy loading of hwdecs by img format,
I did not propagate the probing flag correctly, leading to the new
normal loading path not runnng with probing set, meaning that any
errors would show up, creating unnecessary noise.
This change fixes this regression.
As found out by @philipl, failing to pass this from the VkInstance to
the VkDevice is bad style. We might want to override the get_proc_addr
pointer in the future.
Our logging here today is very poor. We don't make it clear what
formats we are probing, or even that a certain format failed in most
cases. In the case where we do log the error, we don't make it clear
which format it was that failed.
The end result is that we have no idea what the possible and final
format spaces are, which makes it very hard to debug whether things are
working correctly, or to work on supporting additional formats.
This code fails if we have DR buffers, but none of them correspond to
the current frame. Normally only happens if e.g. changing the decoder at
runtime, since DR buffers are not properly reinit in that case.
(Arguably a separate bug)
The current map_frame() code fails to clean up after itself on the
failure paths. But if map_frame returns false, no cleanup code is ever
attempted. Add the relevant calls to clean up state manually,
throughout.
So, turns out the approach in 7f67a553f doesn't work for all codecs. In
particular, sometimes lavc will internally allocate a new AVBuffer that
just points at the old AVBuffer but has a different opaque field for
some reason. In these cases, the DR metadata doesn't survive the
round-trip through libavcodec.
I explored several alternative ways of solving this problem, including
adding new mp_image fields, but in the end none of them survived the
round-trip through AVFrame and back. The `priv` and `opaque` fields
in respectively `mp_image` and `AVFrame` are also too heavily overloaded
to be of much help.
In the end, bite the bullet and use the same approach as done in
`vo_gpu`, which is to just keep track of a list of all allocations. This
is a really ugly way of doing things IMO, but ultimately, completely
safe.
Some decoders, notably hevcdec, will unconditionally memset() the entire
AVBufferRef based on the AVBufferRef size. This is bad news for us,
since it also overwrites our `struct dr_buf`.
Rewrite this code to make it more robust - keep track of the DR buf
metadata in a separate allocation instead. Has the unfortunate downside
of technically being undefined behavior if `opaque` is not at least 64
bits in size, though, but avoids this issue.
Maybe there's a better way for us to unconditionally keep track of DR
allocation metadata. I could try adding it into the `mp_image` itself.
Maybe on a rainy day. For now, this works.
Fixes#9949
Might fix#9526
There are two major ways of going about this:
1. Expose the native ra_gl/ra_pl/ra_d3d11 objects to the pre-existing
hwdec mappers, and then add code in vo_gpu_next to rewrap those
ra_tex objects into pl_tex.
2. Wrap the underlying pl_opengl/pl_d3d11 into a ra_pl object and expose
it to the hwdec mappers, then directly use the resulting pl_tex.
I ultimately opted for approach 1 because it enables compatibility with
more hardware decoders, specifically including ones that use native
OpenGL calls currently. The second approach only really works with
cuda_vk and vaapi_pl.
This avoids decoding/caching more frames in advance than necessary. In
particular, this is very important for hwdec, which generally can't have
too many decoded frames in a pool at the same time.
So I can reuse it in vo_gpu_next without having to reinvent the wheel.
In theory, a lot of the stuff could be made more private inside the
hwdec code itself, but for the time being I don't care about refactoring
this code, merely sharing it.
We don't need to hold on to buffers longer than necessary. Doesn't
matter for vo_gpu but greatly matters for vo_gpu_next, since it persists
hwdec mapped textures for longer periods.
Unfortunately, only provides benefits for hwdecs which do explicit
copies in their decode path, which currently just means cuda and
d3d11va.
There's really nothing vulkan-specific about this hwdec wrapper, and it
actually works perfectly fine with an OpenGL-based ra_pl. This is not
hugely important at the time, but I still think it makes sense in case
we ever decide to make vo_gpu_next wrap OpenGL contexts to ra_pl instead
of exposing the underlying ra_gl.
Easiest way is by just using a designated struct initializer. If we
don't, `p->images` ends up inheriting random data, which leaks into e.g.
eglDestroyImageKHR.
It's a small miracle this never blew up before. Or maybe it did. Who
knows.
libplacebo v198 fixed this properly by adding the ability to flip planes
directly, which is done automatically by the swapchain helpers.
As such, we no longer need to concern ourselves with hacky logic to flip
planes using the crop. This also removes the need for the OSD coordinate
hack on OpenGL.
Render subs at the output resolution, rather than the video resolution.
Uses the new APIs found in libplacebo 197+, to allow controlling the OSD
resolution even for image-attached overlays.
Also fixes an issue where the overlay state did not get correctly
updated while paused. To avoid regenerating the OSD / flushing the cache
constantly, we keep track of OSD changes and only regenerate the OSD
when the OSD state is expected to change in some way (e.g. resolution
change). This requires introducing a new VOCTRL to inform the VO when
the UPDATE_OSD-tagged options have changed.
Fixes#9744, #9524, #9399 and #9398.
Historically, we have treated hwdec interop loading as a completely
separate step from loading the hwdecs themselves. Some hwdecs need an
interop, and some don't, and users generally configure the exact
hwdec they want, so interops that aren't relevant for that hwdec
shouldn't be loaded to save time and avoid warning/error spam.
The basic approach here is to recognise that interops are tied to
hwdecs by imgfmt. The hwdec outputs some format, and an interop is
needed to get that format to the vo without read back.
So, when we try to load an hwdec, instead of just blindly loading all
interops as we do today, let's pass the imgfmt in and only load
interops that work for that format. If more than one interop is
available for the format, the existing logic (whatever it is) will
continue to be used to pick one.
We also have one callsite in filters where we seem to pre-emptively
load all the interops. It's probably possible to trace down a specific
format but for now I'm just letting it keep loading all of them; it's
no worse than before.
You may notice there is no documentation update - and that's because
the current docs say that when the interop mode is `auto`, the interop
is loaded on demand. So reality now reflects the docs. How nice.
This is an annoying special case only really needed because of the
`vflip` filter. mpv handles this by directly adjusting the plane
transform. The libplacebo API, unfortunately, does not allow passing the
required information for this to work smoothly.
Long-term I plan on adding support for plane flipping in libplacebo
directly, but for the meantime, we will have to work-around it by moving
the flipping to the whole-image `crop` instead. Not an ideal solution
but better than crashing.
Fixes#9855
We're getting bug reports that the recent change to add extra usage
flags to swapchain buffers (for gpu-next) breaks mpv on some Windows 7
systems, and it seems like this is only happening with flip-model
swapchains.
Creating swapchains with DXGI_USAGE_UNORDERED_ACCESS should be valid. At
least, it's not specifically disallowed, unlike some other flags[1]. So,
just disable it for flip-model swapchains in Windows 7, rather than
disabling it everywhere.
[1]: https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-usage
Drag and drop in wayland is weird and it seems everyone does this
slightly differently (fun). In the past, there was a crash that
occured (fixed by 700f4ef5fa) which
involved using the wl_data_offer_finish in an incorrect way that
triggered a protocol error (always fatal). The fix involved moving the
function call to data_device_handle_drop which seemingly works, but it
has an unfortunate side effect. It appears like GTK applications (or at
least firefox) close the pipe after this function is called which makes
it impossible for mpv to read data from the fd (well you could force it
open again in theory but let's not do that). Who knows if that was the
case when that commit was made (probably not because I'd think I would
have noticed; could just be a dummy though), but obviously having broken
dnd for a major application isn't so fun (this works with QT and
chromium anyway).
Ideally one would just simply check the pipe in data_device_handle_drop,
but this doesn't work because it doesn't seem the compositor actually
sends mpv the data by then. There's not actually a defined event when
you're supposed to be able to read data from this pipe, so we wait for
the usual event checking loop later for this. In that case,
wl_data_offer_finish needs to go back into check_dnd_fd, but we have to
be careful when calling it otherwise we'd just commit protocol errors
like before. We check to make sure we even have a valid wl->dnd_offer
before trying to indicate that it is finished and additionally make sure
there is a valid dnd_action (after checking the fd, it's always set back
to -1).
This doesn't fix everything though. Specifically, sway with
focus_follows_mouse (the default) and GTK as the data source still
doesn't work. The reason is that when you do a drag and drop in sway
with that option on, a new wl_data_device.data_offer event is sent out
instantly after the drop event. This happens before any data is sent
across the fd and before mpv even has a chance to check it. What GTK
does, when getting this new data_offer event, is close the pipe
(POLLHUP). This means mpv can't read it when we reach the event loop and
thus no data is ever read and broken drag and drop. From the client
side, this isn't really fixable since the wayland protocol doesn't have
a clear indication of when clients are supposed to read from the fd and
both the compositor and data source are doing things totally out of our
control. So we'll consider this weird case, "not our bug" at least. The
rest should work.