-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow rendering on multiple outputs with <output> = * #26
Conversation
As part of this process, call eglMakeCurrent without a surface for initial EGL and mpv setup; and when performing EGL and OpenGL operations that are directly related to an EGLSurface, call eglMakeCurrent on that surface.
This commit also fixes an issue where a second xdg_output::done would mistakenly destroy outputs.
Holy crap!!! You're going to have to give me a bit to sort through what you did. |
Alright, I've looked it over... It doesn't effect current operation for single display.
was not the case for my system. Yes, it showed the video on all 3 monitors, but ran terribly. It seemed like the outputs were taking turns rendering then displaying the video.
One curiosity was that I didn't see any rise in hardware video decoding or overall usage This was the issue I was trying to convey with monitors of varying resolutions.
and can't be shared easily due to differences in width and height when rendered. Perhaps there is a way around this issue as well. Again, excellent work otherwise. |
I can reproduce this; the problem seems to be that diff --git a/src/main.c b/src/main.c
index 05c61c0..11648ab 100644
--- a/src/main.c
+++ b/src/main.c
@@ -128,6 +128,8 @@ static void render(struct display_output *output) {
}},
// Flip rendering (needed due to flipped GL coordinate system).
{MPV_RENDER_PARAM_FLIP_Y, &(int){1}},
+ {MPV_RENDER_PARAM_BLOCK_FOR_TARGET_TIME, &(int){0}},
+ {MPV_RENDER_PARAM_INVALID, NULL},
};
if (!eglMakeCurrent(egl_display, output->egl_surface, output->egl_surface, egl_context)) { |
You amaze me again! I was about to go on a full on rant on about.. CPU usage was a bit more brutal and unusual. At least RAM usage is A LOT better with just "*" option. GPU usage and power was just more brutal for the most part. Overall, a mixed bag as far as resource usage savings go. I have good news though, I believe this also can be fixed. The simplest solution for this, is to somehow limit/delay the output surface frame callback to the VIDEO_FPS. Sorry for the essay of information, I didn't want to leave anything out. |
The last option, |
Before this commit, every time redraw() was called, it would block and wait for a new frame. This works when only one output is being drawn; but when multiple outputs are drawn, this means only one output at a time is given the latest frame, instead of all of them. This change makes redraw() non-blocking,† and uses mpv_render_context's set_update_callback method to request redraws from for all outputs when a new frame is available. This requires a) tracking the lifetime of all frame callbacks, to ensure frames are not rendered too quickly (before the frame callback has returned) and b) extending the main loop so that it can be woken up via self-pipe trick after the mpv update callback is invoked. † eglSwapBuffers calls wl_display_roundtrip(), so technically redraw() ends up waiting for the compositor to respond. This can introduce some extra lag when drawing onto many outputs at once. It's possible to avoid this problem by managing the buffers onto which OpenGL draws ourselves and committing the output surfaces as a batch. However, doing so would be quite complicated.
I've updated the PR so that frame drawing is rate limited both by the wl_surface::frame callbacks and by frame update callbacks from |
After that last commit, I believe we are ready to rock. CPU and GPU usage/power is now as good as running multiple instances of mpvpaper(mpvaper³). GPU HW decode, VRAM, and RAM is without a doubt still better than mpvaper³ Just letting you know I plan on doing a bit of code cleanup and TLC after this pull. Thank you for such an awesome contribution! |
Example use: run the following on either a single or multi-monitor setup; the video should show on every display:
Notes:
halt_info.frame_ready = 1
in the last two seconds; thus as long as one monitor is visible, mpvpaper will continue running.intel_gpu_top
and a video drawn simultaneously on three small virtual outputs: runningmpvpaper '*' video.mkv
used only 20% of the hardware video decoding capacity, and total GPU power draw was 3 W ; while showing the same video with three independent copies of mpvpaper used 40% of the hardware video decoding capacity and increased power draw to 4.5W total.