summaryrefslogtreecommitdiffstats
path: root/video
Commit message (Collapse)AuthorAgeFilesLines
* wayland: improve behavior with touch eventsDudemanguy2021-08-082-19/+9
| | | | | | | | | | | | | | | | | | | | | | | There's currently some touch related code in mpv wayland, but clearly nobody actually uses because it's a broken mess. Initially an attempt to distinguish between two finger touches and one finger touch was made, but there's not a good way to make this work. For whatever reason, initiating either xdg_toplevel_resize or xdg_toplevel_move blocks any other touch events from occurring (at least in plasma). Trying to call these functions anywhere else is not really useful since the serial will be invalid outside of the touch down events (well it would work in the touch up event but that's just silly). Anyways, let's just make this work sanely. Eliminate the touch entries variable completely because it's pointless. Only one finger event is ever considered at a time. Touches besides the initial one are all ignored. If a user touches and drags within the touch edge radius, then a resize event occurs. If the user touches and drags elsewhere on the window, a move event occurs. A single tap displays the osc (which is clickable if you tap again). A double tap toggles fullscreen. Additionally, the default touch edge radius of 64 pixels is way too big (at least I think so). Cut this in half to 32 which feels a lot better (on a pinephone using plasma mobile anyway).
* wayland: correct window-scale behaviorDudemanguy2021-08-071-3/+10
| | | | | | | | | | | | | | The way the window-scale option is supposed to behave wasn't really ever documented until 25cfc81. It turns out that different OS/WMs may do slightly different things. For wayland, we need to fix two things. First, only return the wl->window_size in GET_UNFS (aka don't return the fullscreen size). For SET_UNFS, we need to change the behavior for the maximized window case. If the window is maximized, first attempt to unmaximize it and send the wayland event. If the compositor allows this to happen, then go ahead and set the new dimensions and resize it. In the case that the attempt to unmaximize is not successful, then don't attempt the resize and just save the window size dimensions for later to be used when the user unmaximizes the window.
* wayland: keep track of toplevel width/height againDudemanguy2021-08-062-1/+9
| | | | | | | | | | | | | | Regression from 24357cb. It's ugly but unfortunately keeping tracking of the last toplevel width and height really is the best way to solve this problem and removing it was a mistake. Compositors don't always send width/height coordinates of the actual window. The easiest way to trigger this is by changing window-scale/current-window-scale and then unfocusing the window. The compositor will send another toplevel configure event with coordinates of the window before the resize. Maybe compositors could be smarter but multiple ones do this (sway, gnome, plasma), so just keep the old workaround. The only difference this time is that the toplevel width/height is saved at the very beginning which also covers the case where it equals 0 (i.e. weston).
* wayland: cleanup handle_toplevel_configDudemanguy2021-08-032-13/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The source of many geometry woes. There's some loosely related toplevel things that should be cleaned up/fixed. First of all, VO_EVENT_LIVE_RESIZING is actually completely useless. It might have been useful sometime in the past, but there's no point. It doesn't "speed up" resizing in any way and appears to be originally for cocoa. Just remove it. Way back in the day, toplevel_width/height was added as a workaround for when we got uncoorperative (i.e. wrong) width/height coordinates from the compositor in this event. Basically it could happen due to numerous reasons but a lack of atomic commits was part of the reason and also mpv's geometry handling then was a lot rougher. We *shouldn't* need this workaround anymore. The width/height values are only used exactly when we need them. If mpv sets geometry on its own, it should still be the right dimensions. Related to the above, mpv never actually propertly handled the case where width or height was equal to 0. According to the xdg-shell spec, "If the width or height arguments are zero, it means the client should decided its own window dimension." An example of a compositor doing this is weston. It's, unsurprisingly, broken. Getting out of fullscreen or a maximized state does not restore the old window size like it should. The right way to handle this is to just return near the end of the function if we have a 0 for either argument and before any geometry is set (wl->geometry's width or height can never be zero). Luckily, state changes are already being detected so they just trigger the goto when needed. Finally, e2c24ad mistakenly removed the VO_EVENT_EXPOSE. There are edge cases where this is needed and it's safer to just force a redraw here when the window gets activated again. Just force wl->hidden to false first and then trigger the expose.
* wayland: unset hidden state in frame callbackDudemanguy2021-07-261-8/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | More wayland weirdness. So previously, flipping a hidden state from true to false was done in vo_wayland_wait_frame. In theory, this would be after you get the frame callback and all those events so there's no problem. However since the function also does a bunch of flushing/dispatching/etc. to the default display queue so a lot of unknown things can happen before we actually set the hidden variable back to false. For example if a single image was paused and left on another virtual desktop long enough (~5 minutes) while also not having focus, switching back to that desktop could render it a black frame. This edge case was supposed to be handled by the surface being activated again in the toplevel event but apparently that doesn't always work. The fix is to just delete all of that junk and set wl->hidden = false in the frame callback. What's actually happening is kind of a mystery honestly. Probably the compositor drops the buffers after a while as an optimization (sensible) and forces a repaint if you switch back to the virtual desktop. Somehow wl->hidden not being set to false would not properly trigger a repaint (likely because it also sends a toplevel event which does stuff) thus you just get a black window. If you just make sure to set hidden in the frame callback, it appears like all of these problems and edge cases are solved. Since this event must happen first, that makes sense. That simplifies a lot of stuff and fixes some subtle bugs at the same time so just go with this approach.
* egl_helpers: fix create_context fallback behaviorDudemanguy2021-07-253-16/+47
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* context_drm_egl: allow autoprobe selectionDudemanguy2021-07-231-5/+0
| | | | | | | | | | 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]: https://github.com/mpv-player/mpv/commit/f757163058c2e5c7136213b0f79923fcea34b71a
* wayland: refactor surface scalingDudemanguy2021-06-302-33/+56
| | | | | | | | | | | | | | | Another day, another wayland refactor. Way back when, dcc3c2e added support for the hidpi-window-scale option (something you probably should never set to no but whatever) to wayland. Well technically, it never had any runtime toggling support (don't remember if detecting when vo_opts changed was possible or not then; maybe not). Anyways in the process of fixing that, I went ahead and refactored how this is all handled. The key difference is that when hidpi-window-scale is disabled, wl->scaling is directly set to 1 instead of forcibly setting wl->current_output->scale to 1. Note that scaling operations don't always require a geometry reset/resize so set_surface_scaling needs to be separate from set_geometry. The logic here is kind of complicated but it (should) be correct.
* wayland: fix wl_surface_set_buffer_scale usageDudemanguy2021-06-273-3/+2
| | | | | | | | | | | 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.
* wayland: always be sure to initially try to renderDudemanguy2021-06-275-8/+7
| | | | | | | | | | | | | | | | | | | 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.
* wayland: remove unused includesDudemanguy2021-06-272-6/+0
| | | | Presentation time only lives in in wayland_common.
* wayland: handle app id option less stupidlyDudemanguy2021-06-261-4/+0
| | | | | | Not sure what I was on when I wrote this. wayland-app-id is supposed to default to "mpv". Just set that in the vo_sub_opts and don't do this weird m_config_cache_write_opt thing. Also make the doc entry nicer.
* wayland: reorganize wayland common codeDudemanguy2021-06-265-948/+962
| | | | | | | 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).
* vo_gpu: vulkan: displayvk: Fix handling of unconnected planesPhilip Langdale2021-06-121-1/+6
| | | | | | | | If a plane is not connected to any displays, we won't set an entry in the mapping of planes to displays. So ensure these unset entries are null and skip them. Fixes #8913
* vo_gpu: vulkan: implement a VkDisplayKHR backed contextPhilip Langdale2021-06-112-0/+392
| | | | | | | | | | | | | | | | | | | | | | | | This is the Vulkan equivalent of the drm context for OpenGL, with the big difference that it's implemented purely in terms of Vulkan calls and doesn't actually require drm or kms. The basic idea is to identify a display, mode, and plane on a device, and then create a display backed surface for the swapchain. In theory, past that point, everything is the same, and this is in fact the case on Intel hardware. I can get a video playing on a vt. On nvidia, naturally, things don't work that way. Instead, nvidia only implemented the extension for scenarios where a VR application is stealing a display from a running window system, and not for standalone scenarios. With additional code, I've got this scenario to work but that's a separate incremental change. Other people have tested on AMD, and report roughly the same behaviour as on Intel. Note, that in this change, the VT will not be correctly restored after qutting. The only way to restore the VT is to introduce some drm specific code which I will illustrate in a separate change.
* vo_gpu: vulkan: provide a helper to access device name optionPhilip Langdale2021-06-112-0/+17
| | | | | | | | | | | The VkDisplayKHR context type requires making calls against the physical device before the libplacebo context is initialised. That means we can't simply use the physical device object that libplacebo would create - instead we have to create a separate one, but make sure it's referring to the same physical device. To that end, we need the device name that the user may have requested so we can pass it on.
* vo_rpi: fix argument nameDudemanguy2021-06-081-2/+2
| | | | This is data not arg.
* wayland: refactor dispatching eventsDudemanguy2021-05-281-46/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was originally just a bugfix for a race condition, but the scope expanded a bit. Currently, the wayland code does a prepare_read -> dispatch_pending -> display_flush -> read_events -> dispatch_pending routine that's basically straight from the wayland client API documentation. This essentially just queues up all the wayland events mpv has and dispatches them to the compositor. We do this for blocking purposes on every frame we render. A very similar thing is done for wait_events from the VO. This code can pretty easily be unified and split off into a separate function, vo_wayland_dispatch_events. vo_wayland_wait_frame will call this function in a while loop (which will break either on timeout or if we receive frame callback from the compositor). wait_events needs to just check this in case we get some state change on the wakeup_pipe (i.e. waking up from the paused state). As for the actual bugfix part of this, it's a slight regression from c26d833. The toplevel config event always forced a redraw when a surface became activated again. This is for something like displaying cover art on a music file. If the window was originally out of view and then later brought back into focus, no picture would be rendered (i.e. the window is just black). That's because something like cover art is just 1 frame and the VO stops doing any other additional rendering. If you miss that 1 frame, nothing would show up ever again. The fix in this case is to always just force a redraw when the mpv window comes back into view. Well with the aforementioned commit, we stopped doing wl_display_roundtrip calls on every frame. That means we no longer do roundtrip blocking calls. We just be sure to queue up all of the events we have and then dispatch them. Because wayland is fundamentally an asynchronous protocol, there's no guarantee what order these events would be processed in. This meant that on occasion, a vo_wayland_wait_frame call (this could occur multiple times depending on the exact situation) would occur before the compositor would send back frame callback. That would result in the aforementioned bug of having just a black window. The fix, in this case, is to just do a vo_wayland_wait_frame call directly before we force the VO to do a redraw. Note that merely dispatching events isn't enough because we specifically need to wait for the compositor to give us frame callback before doing a new render. P.S. fix a typo too.
* win32: support the property 'focused'Avi Halachmi (:avih)2021-05-271-1/+12
| | | | | | | | | | | | | And also change the existing WM_KILLFOCUS handler to return 0 instead of 'break' (which later calls DefWindowProcW), as MSDN says we should do for WM_{KILL,SET}FOCUS. It seems that the 'focused' property is now supported by all main VOs: x11, macOS, wayland, Windows. TCT/sixel/caca probably don't support it, and unknown with SDL. Fixes #8868
* vo_gpu: replace --icc-contrast by --icc-force-contrastNiklas Haas2021-05-261-41/+40
| | | | | | | | | | | | | | Not only does this have semantics that make far more sense, it also has a default that makes far more sense. (Equivalent to the old `icc-contrast=inf`) This removes the weird 1000:1 contrast default assumption which especially broke perceptual profiles and also screws things up for OLED/CRT/etc. Should probably close some issues but I honestly can't be bothered to figure out which of the thousands colorimetry-related issues are affected.
* wayland: shuffle around the render loop againDudemanguy2021-05-245-35/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* wayland: send VO_EVENT_DPI on output event as wellDudemanguy2021-05-231-0/+1
| | | | The display scaling might change here, so we need to signal mpv's core.
* vo_gpu: fix extreme clipping with --gamut-clipping for HDR outputsNiklas Haas2021-05-221-1/+2
| | | | | | Checking against 1.0 is wrong for this code, because it's in an absolute luminance scale relative to reference white. We should be normalizing this by `dst.sig_peak`.
* wayland: simplify render loopDudemanguy2021-05-225-49/+36
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* vo_gpu: hwdec_vaapi: silence errors while probingNiklas Haas2021-05-194-4/+7
| | | | | Silences warnings related to DRM format modifiers that can show up while probing formats.
* vo_gpu: fix trivial memory leakYour Name2021-05-071-1/+3
| | | | Nobody noticed this? Seriously?
* Revert "vo_gpu: revert 8a09299 and conditionally clear framebuffer again"Your Name2021-05-071-5/+3
| | | | | | | | | | This reverts commit b8156a9a86ae4ff087b1b255c68a3ca38ec2d086. Apparently there are two problems here. One on Linux (fixed by the original change and this revert) and one on alternative-medicine-Job's OS. Since the latter has deprecated OpenGL and OpenGL is a second-class citizen, I think it's better to prefer the fix for a platform that is still alive.
* vf_sub: restore OSD if removedYour Name2021-05-071-0/+9
| | | | | | | When inserting vf_sub, the VO OSD is directed not to draw itself. But this flag was never unset, even when removing vf_sub. The fix is pretty shit, but appears to work.
* mac: add support for display-width/display-height propertyder richter2021-05-061-13/+20
| | | | | also merge back a helper function that was introduced in commit d3b7732 and for the purpose to be used with the new display res voctrl event.
* command: add display-width/display-height propertyDudemanguy2021-05-067-0/+34
| | | | | | | | | 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.
* filter_kernels: fix quadric windowNiklas Haas2021-05-041-1/+1
| | | | | | | | | 3909e4cdfcb9 seems to have replaced this 0.5 constant by 0.75, using its presence in glumpy as justification. 0.75 is clearly a bug in glumpy, as its own source code doesn't even match the comment immediately above it. Every other implementation of this window I could find uses 0.5, including e.g. ImageMagick.
* build: address AVCodec, AVInputFormat, AVOutputFormat const warningssfan52021-05-011-3/+3
| | | | FFmpeg recently changed these to be const on their side.
* wayland: ignore toplevel listener if geometry is 0Dudemanguy2021-04-261-0/+4
| | | | | | | | | | It turns out that if a user specifies fullscreen=yes and a width/height in an autoprofile, the compositor can execute its toplevel listener event. This can happen before we have any mpv window rendered at all so we end up performing a bunch of geometry operations and state checks when we shouldn't. It subtly messes up a lot of things like state detection. Just return from this function if the geometry has no width or height yet.
* mac: fix window geometry calculation on secondary screensder richter2021-04-241-19/+26
| | | | | | | | | | | | | | | this is a regression of af26402, where we changed the geometry calculation to use the visible frame and consider its origin. though the origin is not screen relative but relative to the main screen. the rest of the code expects a screen relative rectangle. because of that windows would be placed out of the screen bounds when not on the main screen. recalculate to origin to be screen relative and use those values for the rest of the calculations. to make the code a bit more comprehensible be a bit more explicit about what is done where with temporary variables and comments. also move the mp_rect calculation that moves the origin and flips the y position to a separate function, so we can reuse it later.
* win32: fit_window_on_screen: simplify, add commentsAvi Halachmi (:avih)2021-04-231-16/+17
| | | | | | | | | | The fit_on_screen logic was a bit twisted. Simplify it a bit and update few comments to explain better what it's used for. Note that the new logic is not identical to before, but its intent should now be clearer. This means there might be regressions or improvements at edge cases. If followup fixes are needed, then we should keep the intent clear. Most likely though that it's fine.
* win32: fit_window_on_screen: centralize logic (no-op)Avi Halachmi (:avih)2021-04-231-4/