Commit Graph

979 Commits

Author SHA1 Message Date
sfan5 c3d78b0017 video: opengl: use gl_check_extension() instead of strstr()
Using a simple substring match for extension checks is considered bad practice
because it's incorrect when one extension is a prefix of another's name.
This will almost surely not make a difference in practice but do it for correctness anyway.
2021-11-17 22:38:34 +01:00
sfan5 f5cc28a627 context_drm_egl: use mpegl_get_display() helper over own code
Although there are no known problems with this, using the helper should
be more portable. It will also prefer EGL 1.5's eglGetPlatformDisplay
over eglGetPlatformDisplayEXT if available.
2021-11-17 22:38:34 +01:00
Dudemanguy c478a1efba egl_helpers: remove EGL_OPENGL_ES3_BIT
d2e8bc4499 was the the commit that
originally introduced the usage of this bit. As the message states, the
purpose was to force creating GLES 3 contexts on drivers that do not
return a higher version context than what was requested. With the recent
opengl refactors, mpv's gl selection has already moved away from such
complicated queries. Perhaps when that commit was added things were
different, but nowadays it seems like Mesa simply returns the highest
driver version available that is compatibile with the request (i.e.
requesting GLES 2 returns a GLES 3 context on my machine). In that case,
let's just simply drop EGL_OPENGL_ES3_BIT altogether as it does break
GLES 2 only machines. Fixes #9431.
2021-11-11 16:51:51 +00:00
sfan5 3a10210c56 context_drm_egl: use eglCreatePlatformWindowSurfaceEXT if available
This is identical to eglCreateWindowSurface but should be
preferred as part of EGL's platform extension.
2021-11-11 17:41:42 +01:00
Philip Langdale 2b9d8ae8b1 context_drm_egl: add support for BGR surface formats
The new GBM supporting nvidia drivers declare support for 10bit
surfaces using BGR ordering, rather than RGB, so add support for them.

We've also seen examples of hardware supporting BGR8888 but not
RGB8888 so let's support those too.

Of course, the nvidia EGL driver doesn't publish support for any 10bit
formats so you can't actually do 10bit display. Perhaps they'll
eventually fix that.
2021-11-10 09:57:58 -08:00
Philip Langdale 10d677575a context_drm_egl: use gbm_surface_create_with_modifiers
The GBM supporting nvidia driver doesn't support creating surfaces
without modifiers and using modifiers is more and more recommended as
the right way to do this.

Enumerating modifiers is painfully verbose, but necessary if we are to
allow the driver to pick the best possible one.
2021-11-10 09:57:58 -08:00
Jan Ekström f560437594 drm_common: enable specific device selection by means of path 2021-10-25 20:37:03 +02:00
Dudemanguy 7ad5ad4098 egl_helpers: ensure debug context attrs/bit exist
Regression from e13fe1299d. Apparently,
Broadcom's EGL does not support the EGL_CONTEXT_FLAGS_KHR attribute nor
EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR. Just define these as EGL_NONE and 0
respectively if we do not have them.
2021-10-21 03:16:33 +00:00
Emil Velikov e13fe1299d egl_helpers: add support for debug contexts
With the recent refactor and quick look against the GLX code path, it's
fairly obvious, and trivial, how to add support for debug contexts.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov 6354540cf8 vo_gpu: context_glx: cleanup create_context_x11_gl3 code path
Drop the gl3 suffix from the function name - it's no longer needed, with
the _old function gone.

Push the mpgl_min_required_gl_versions[] looping within the function,
reducing the identical glXGetProcAddress/glXQueryExtensionsString calls
while making the code neater.

v2:
 - tabs -> spaces indentation
 - mpgl_preferred_gl_versions -> mpgl_min_required_gl_versions
 - 320 -> 300 (in glx code path)

v3:
 - legacy code path is gone \o/

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov e869d519ba vo_gpu: context_glx: remove legacy create_context_x11_old()
The old/legacy code-path isn't really needed for mpv use-cases.

In particular:

All Mesa drivers (even GL 2.1 ones like lima/vc4) work fine with the
"non-legacy" path.

From proprietary/binary drivers - the vendor either does not support
desktop GL or the drivers/HW is not actively supported.

Looking at the Nvidia HW - anything GeForce 7 and older is GL 2.1 and
lacks decent video acceleration. The latest official drivers are from
2017.

All newer Nvidia HW is GL 3.3+ thus must have GLX_ARB_create_context as
in the non-legacy path, while also good acceleration albeit via VDPAU
in some cases.

With the old path gone, provide meaningful error message in the very
unlikely case that GLX_ARB_create_context is missing.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov 20e9c66fa9 egl_helpers: fixup the EGL_KHR_create_context-less codepath
With earlier commit f8e62d3d82 ("egl_helpers: fix create_context
fallback behavior") we added a fallback for creating OpenGL context
while EGL_KHR_create_context is missing.

While it looked correct at first, it is missing the eglMakeCurrent()
call after creating the EGL context. Thus calling glGetString() fails.

Instead of doing that we can just remove some code - simply pass the
CLIENT_VERSION 2, as attributes which is honoured by EGL regardless of
the client API. This allows us to remove the special case and drop some
code.

v2:
 - mpgl_preferred_gl_versions -> mpgl_min_required_gl_versions

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov 538fb6541e video: opengl: rework and remove ra_gl_ctx_test_version()
The ra_gl_ctx_test_version() helper is quite clunky, in that it pushes a
simple check too deep into the call chain. As such it makes it hard to
reason, let alone have the GLX and EGL code paths symmetrical.

Introduce a simple helper ra_gl_ctx_get_glesmode() which returns the
current glesmode, so the platforms can clearly reason about should and
should not be executed.

v2:
 - mpgl_preferred_gl_versions -> mpgl_min_required_gl_versions
 - 320 -> 300 (in glx code path)

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov e3883512b1 vo_gpu: opengl: remove --opengl-restrict
As the documentation of the toggle says - the implementation can (and
will actually if they follow the GLX/EGL spec) return context version
greater than the one requested.

This happens with all Mesa drivers that I've tested as well as the
Nvidia binary drivers.

This toggle seems like a workaround for buggy drivers, yet it's lacking
context about the vendor and version.

Remove it for now - I'll be happy to reinstate it (partially or in full)
as we get concrete details.

This allows us to simplify ra_gl_ctx_test_version() making the whole
context creation business easier to follow by mere mortals.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov e992ebe128 egl_helpers: remove explicit GLES 3 request
Alike the GL commit earlier - the EGL spec essentially mandates that
implementation will return GLES 3.0+ (if supported by the driver), even
though only GLES 2 is requested.

The only thing we should watch out is - we should add both ES2_BIT and
ES3_BIT as EGL_RENDERABLE_TYPE.

This has been verified against the Mesa drivers (i965, iris, swrast) and
Nvidia binary drivers.

v2:
 - int es_version -> bool es
 - unloop create_context() execution

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov 0b918edfb5 vo_gpu: opengl: reduce versions in mpgl_preferred_gl_versions
Currently mpv requires a bare minimum of GL 2.1, although it tries to
use 3.2+ core contexts when possible.

The GLX and EGL spec effectively guarantee that the implementation will
give you the highest compatible version possible. In other words:

Requesting 3.2 core profile will always give you core profile and the
version will be in the 3.2 .. 4.6 range - as supported by the drivers.

Similarly for 2.1 - implementation will give you either:
 - 2.1 .. 3.1, or
 - 3.2 .. 4.6 compat profile

This has been verified against the Mesa drivers (i965, iris, swrast) and
Nvidia binary drivers.

As such, drop the list to 320, 210 and terminating 0.

v2:
 - mpgl_preferred_gl_versions -> mpgl_min_required_gl_versions
 - update ^^ comment

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-16 20:33:53 +00:00
Emil Velikov 899dae41f3 context_drm_egl: re-enable drmSet/DropMaster calls
The ioctls were disabled a while back since they error out and allegedly
cause problem with X running in another VT.

Omitting the ioctls is not cool, even as a workaround.

If they fail, the user is supposed to fallback appropriately - use a suid
wrapper, logind-like daemon or otherwise.

As of kernel 5.10, they should just work in nearly all cases, so let's
just reinstate the calls.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
2021-10-15 19:00:34 +02:00
Dudemanguy f8e62d3d82 egl_helpers: fix create_context fallback behavior
The EGL stuff is really complicated because of historical reasons
(tl;dr: blame EGL). There was one edge case with EGL context creation
that lead to incorrect behavior. EGL_KHR_create_context was created with
EGL 1.4 (which mpv does support) but it is still possible for an EGL 1.4
device to not implement this extension. That means that none of the EGL
attrs that pass a specific opengl version work. So for this obscure
case, there is a fallback context creation at the very end which simply
creates an EGLContext without passing any special attrs.

This has another problem however. mpv has a hard requirement on at least
desktop opengl 2.1 or opengl ES 2.0 to function (we're not asking for
much here). Since the fallback EGL context creation has no version
checking, it is entirely possible to create an EGL context with a
desktop opengl version under 2.1. As you get further along in the code,
the user will encounter the hard opengl version check and then error
out. However, we're supposed to also actually check if GLES works
(that's what the opengl-es=auto option is for) so this is a bug.

The fix is to do a bit of code duplication and make a mpgl_check_version
specifically for if we hit the edge case of needing to create an EGL
context without the EGL_KHR_create_context extension. Grab the version
with the function pointer, check if it's under 210, if so destroy the
EGL context and set it to NULL. After that, if the user has set
opengl-es to auto, mpv will try GLES next. If it is set to no, then mpv
will simply fail as desired. Fixes #5915.

Sidenote: the ra_gl_ctx_test_version originally testing 140 doesn't make
any sense. Passing the version number in that function only does
something if the user has set opengl-restrict. What we need to do is to
pass the version of the created context to that function. If the version
is higher than the opengl-restrict option, then make this a failure.
2021-07-25 15:32:53 +00:00
Dudemanguy 747b152001 context_drm_egl: allow autoprobe selection
This was explictly coded to avoid the autoprobe way back when in
2015[1] with no real explanation. In theory, there shouldn't be any
issues allowing this. If a user runs mpv in tty, this is probably what
they actually want in most cases. Perhaps something strange happens on
nvidia, but it should just fail anyway during the autoprobe.

[1]: f757163058
2021-07-23 17:54:58 +00:00
Dudemanguy a02901cae7 wayland: fix wl_surface_set_buffer_scale usage
The wl_surface lives for the entire lifetime of the vo. It's only
neccesary to set the scale initially and when the output scaling changes
(the surface moves to a different output with a different scale or the
output itself changes it scale). All of the calls that were being made
in the egl/vulkan resize functions are not needed. vo_wlshm wasn't
correctly rescaling itself before this commit since it had no logic to
handle scale changes. This should all be shared, common code in the
surface/output listeners.
2021-06-27 10:58:59 -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 573f696077 wayland: remove unused includes
Presentation time only lives in in wayland_common.
2021-06-27 10:20:05 -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
Dudemanguy a88fdfde0c command: add display-width/display-height property
For some reason, this never existed before. Add VOCTRL_GET_DISPLAY_RES
and use it to obtain the current display's resolution from each
vo/windowing backend if applicable. Users can then access the current
display resolution as display-width and display-height as per the client
api. Note that macOS/cocoa was not attempted in this commit since the
author has no clue how to write swift.
2021-05-06 17:36:55 +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 f5a094db04 vo_gpu: EGL: hack for alpha on different platforms
7fb972f fixed transparency on x11/EGL/Mesa but happened to also break it
for wayland and nvidia. Ideally on wayland, you should just be able to
pick the right EGLConfig that has alpha but this doesn't seem to work
because reasons. So just go back to setting the EGL_ALPHA_SIZE bit if
the user asks for alpha. Apparently this worked before for nvidia as
well. The hack is to just run an eglQueryString in the x11egl context.
If it picks up Mesa as the EGL_VENDOR, then force ctx->opts.want_alpha
to 0 and let pick_xrgba_config take care of the rest.
2020-10-15 13:44:07 +00: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
wm4 7fb972fd39 vo_gpu: EGL: fix transparency on X11/EGL/Mesa
Transparent windows on X11/EGL/native Mesa GL didn't work for various
reasons. From what I remember, the current code did work with nvidia at
least. Mesa has made attempts to fix this, but they never really made it
in.

But it turns out you can make EGL/Mesa list the EGLConfigs that use X11
RGBA visuals, and context_x11egl.c contains code that explicitly selects
them if alpha is requested (see pick_xrgba_config()).

The reason EGL/Mesa did not list them (and thus breaking transparency)
is because we requested a EGL_ALPHA_SIZE != 0 if alpha is requested. But
the transparent EGLConfigs use EGL_ALPHA_SIZE == 0. That's because EGL
doesn't actually support the concept of transparent windows; the alpha
size parameter is something else (memory rendering without FBOs or
something, I don't care enough to look up the real reasons).

This still won't work on Wayland. Every EGL backend needs platform
specific code. (Good job, EGL, such an awesome platform independent
standard.)

Fixes: #6590
2020-08-27 11:55:20 +02:00
wm4 b5b83a1ed5 vo_gpu: EGL: slightly better debug logging of EGL configs 2020-08-27 11:55:20 +02: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
Dudemanguy 486516f723 wayland: don't rely on presentation discarded
When using presentation time, we have to be sure to update the ust when
no presentation events are received to make sure playback is still
smooth and in sync. Part of the recent presentation time refactor was to
use the presentation discarded event to signal that the window is
hidden. Evidently, this doesn't work the same everywhere for whatever
reason (drivers?? hardware??) and at least one user experienced issues
with playback getting out of sync since (presumably) the discarded event
didn't occur when hiding the window. Instead, let's just go back to the
old way of checking if the last_ust is equal to the ust value of the
last member in the wayland sync queue. Fixes #8010.
2020-08-16 16:29:00 -05:00
Dudemanguy e9cde72536 wayland: refactor presentation time
The motivation for this change was a segfault caused by e107342 which
has complicated reasons for occuring (i.e. I'm not 100% sure but I think
it is a really weird race). The major part of this commit is moving the
initialization of presentation listener to the frame_callback function.
Calling it in swap_buffers worked fine but in practice it meant a lot of
meaningless function calls if a window was hidden (the presentation
would just be immediately discarded). By calling it in frame_callback,
we ensure the listener is only created when it is possible to receive a
presentation event.

Of course calling the presentation listener in feedback_presented or
feedback_discarded was considered, but ultimately these events are too
slow. Receiving the ust/msc/sbc triplet here and then passing it to mpv
results in higher vsync judder since there is (likely) not enough time
before the next pageflip. By design, the frame callback is meant to give
us as much time as possible before the next repaint so calling it here
is probably optimal.

Additionally, we can make better use of the feedback_discarded event.
The wp_presentation_feedback should not be destroyed here. It will be
taken care of either when we get feedback again or when the player
quits. Instead what we can do is set a bool that tells wayland_sync_swap
to update itself based on mp_time delta. In practice, the result is not
any different than before, but it should be more understandable what is
going on now.

Of course, the segfault mentioned at the beginning is fixed with this as
well.
2020-08-16 18:34:09 +00:00
wm4 c1fc5354c3 wayland: fix build
Broken by previous commit. I've split a commit incorrectly.

Fixes: #7802
2020-06-04 20:15:43 +02:00
Jan Palus ac1634360b drm: add typedef for PFNEGLGETPLATFORMDISPLAYEXTPROC (#7314)
extension is not mandatory and is not provided on ie Raspberry Pi
2020-05-14 15:07:58 +02:00
wm4 4019c11314 video: fix rgb30 component order
Was broken with a zimg wrapper refucktor before the previous commit. In
addition, it seems this didn't match the vo_drm format, or the format
naming convention. So the order actually changes, and the format is
redefined. (The img_format.h comment was probably wrong.)

Change vo_gpu to the new format as well, so we can still test it.
2020-05-09 18:02:57 +02:00
Jan Palus 3023837fb9 egl_helpers: add typedef for EGLAttrib (#7314)
part of EGL 1.5 which is not present ie on Raspberry Pi
2020-04-23 14:04:26 +02:00
Dudemanguy 055a490cef wayland: use mp_time deltas for presentation time
One not-so-nice hack in the wayland code is the assumption of when a
window is hidden (out of view from the compositor) and an arbitrary
delay for enabling/disabling the usage of presentation time. Since you
do not receive any presentation feedback when a window is hidden on
wayland (a feature or misfeature depending on who you ask), the ust is
updated based on the refresh_nsec statistic gathered from the previous
feedback event.

The flaw with this is that refresh_nsec basically just reports back the
display's refresh rate (1 / refresh_rate * 10^9). It doesn't tell you
how long the vsync interval really was. So as a video is left playing
out of view, the wl->last_queue_display_time becomes increasingly
inaccurate. This led to a vsync spike when bringing the mpv window back
into sight after it was hidden for a period of time. The hack for
working around this is to just wait a while before enabling presentation
time again. The discrepancy between the "bogus"
wl->last_queue_display_time and the actual value you get from the
feedback only happens initially after a switch. If you just discard
those values, you avoid the dramatic vsync spike.

It turns out that there's a smarter way to do this. Just use mp_time_us
deltas. The whole reason for these hacks is because
wl->last_queue_display_time wasn't close enough to how long it would
take for a frame to actually display if it wasn't hidden. Instead, mpv's
internal timer can be used, and the difference between wayland_sync_swap
calls is a close enough proxy for the vsync interval (certainly better
than using the monitor's refresh rate). This avoids the entire conundrum
of massive vsync spikes when bringing the player back into view, and it
means we can get rid of extra crap like wl->hidden.
2020-04-20 21:02:02 +00:00
Niklas Haas 7e52e72746 vo_gpu: opengl: make sure to always clean up debug callbacks
In theory this mostly happens automatically, especially after the 5
vsync limit disables this already. But if we uninit before 5 vsyncs are
rendered, this can get left in a dangling 'enabled' state, which leaks a
debug report callback.

Always explicitly disable it just to be on the safe side.
2020-04-15 07:21:36 +02:00
wm4 26f4f18c06 options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with

   {"name", ...

followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.

I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.

Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.

Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.

In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-18 19:52:01 +01:00
wm4 d3ad4e2308 options: remove intpair option type
This was mostly unused, and has certain problems. Just get rid of it.

It was still used in CDDA (--cdda-span) and a debug option for OpenGL
(--opengl-check-pattern). Replace both of these with 2 options, where
each sets the start/end values of the former span. Both were
undocumented somehow (normally we require all options to be documented),
so I'm not caring about compatibility, and not bothering to add it to
the API changelog.
2020-03-13 16:50:27 +01:00
Sven Kroeger fc8c1fcfb2 drm_prime: double free bug
This commit fixes a bug where handle for a framebuffer gets double
freed.
It seems to happen that the same prime fd gets two framebuffers.
As the prime fd is the same the resulting prime handle is also the
same.
This means one handle but 2 framebuffers and can lead to the following
chain:

1. The first framebuffer gets deleted the handle gets also freed via
the ioctl.

2. In startup phase not all 4 dumb buffers for overlay drawing
are set up. It can happen that the last dumb buffer gets the
handle we freed above.

3. The second framebuffer gets freed and the handle will be
freed again resulting that the 4's dumb buffer handle is not
backed by a buffer.

4. Drm prime continues to assign handles to its prime fds an
will lead to have this handle which was just freed to
reassign again but to an prime buffer.

5.Now the overlay should be drawn into dumb buffer 4 which
still has the same handle but is backed by the wrong buffer.
This leads to two different behaviors:

- MPV crashes as the drm prime buffers size als calculated
by the decoder output format. The overlay output format
differs and it takes more space. SO the size check
in kernel fails.

- MPV is continuing play. This happens when the decoders
allocates a bigger buffer than needed for the overlay.
For example overlay is Full HD and decoder output is 4k.
This leads to the behavior das the overlay wil be drawn
into the wrong buffer as its a drm prime buffer and results
in a flicker every fourth step.
2020-03-05 18:12:57 +01:00
linkmauve 322eb72679 OpenGL: Also detect softpipe as a software driver
Because it is.
2020-02-25 21:32:04 +02:00
dudemanguy b926f18938 wayland: remove wayland-frame-wait-offset option
This originally existed as a hack for weston. In certain scenarios, a
frame taking too long to render would cause vo_wayland_wait_frame to
timeout which would result in a ton of dropped frames. The naive
solution was to just to add a slight delay to the time value. If a
frame took too long, it would likely to fall under the timeout value and
all was well. This was exposed to the user since the default delay
(1000) was completely arbitrary.

However with presentation time, this doesn't appear to be neccesary.
Fresh frames that take longer than the display's refresh rate (16.666 ms
in most cases) behave well in Weston. In the other two main compositors
without presentation time (GNOME and Plasma), they also do not
experience any ill effects. It's better not to overcomplicate things, so
this "feature" can be removed now.
2020-01-31 00:40:44 +00:00
der richter 3275cd04b7 cocoa-cb: add support for forcing the dedicated GPU for rendering
this deprecates the old cocoa backend only option and moves it to the
general macos ones. add support for the new option in the cocoa-cb
layer creation and use the new option in the olde cocoa backend.

Fixes #7272
2020-01-26 12:12:22 +01:00