diff options
Diffstat (limited to 'video/out')
36 files changed, 1635 insertions, 896 deletions
diff --git a/video/out/aspect.c b/video/out/aspect.c index 2d25bbdfd5..205ee3b89f 100644 --- a/video/out/aspect.c +++ b/video/out/aspect.c @@ -17,6 +17,7 @@ /* Stuff for correct aspect scaling. */ #include "aspect.h" +#include "math.h" #include "vo.h" #include "common/msg.h" #include "options/options.h" @@ -25,38 +26,36 @@ #include "vo.h" #include "sub/osd.h" -static void aspect_calc_panscan(struct mp_log *log, struct mp_vo_opts *opts, - int w, int h, int d_w, int d_h, +static void aspect_calc_panscan(struct mp_vo_opts *opts, + int w, int h, int d_w, int d_h, bool unscaled, int window_w, int window_h, double monitor_par, int *out_w, int *out_h) { - mp_dbg(log, "aspect(0) fitin: %dx%d monitor_par: %.2f\n", - window_w, window_h, monitor_par); int fwidth = window_w; int fheight = (float)window_w / d_w * d_h / monitor_par; - mp_dbg(log, "aspect(1) wh: %dx%d (org: %dx%d)\n", - fwidth, fheight, d_w, d_h); if (fheight > window_h || fheight < h) { int tmpw = (float)window_h / d_h * d_w * monitor_par; if (tmpw <= window_w) { fheight = window_h; fwidth = tmpw; - } else if (fheight > window_h) { - mp_warn(log, "No suitable new aspect found!\n"); } } - mp_dbg(log, "aspect(2) wh: %dx%d (org: %dx%d)\n", - fwidth, fheight, d_w, d_h); int vo_panscan_area = window_h - fheight; double f_w = fwidth / (double)fheight; double f_h = 1; - if (!vo_panscan_area) { + if (vo_panscan_area == 0) { vo_panscan_area = window_w - fwidth; f_w = 1; f_h = fheight / (double)fwidth; } + if (unscaled) { + fwidth = w * monitor_par; + fheight = h; + vo_panscan_area = 0; + } + *out_w = fwidth + vo_panscan_area * opts->panscan * f_w; *out_h = fheight + vo_panscan_area * opts->panscan * f_h; } @@ -73,18 +72,13 @@ static void clamp_size(int size, int *start, int *end) } static void src_dst_split_scaling(int src_size, int dst_size, - int scaled_src_size, bool unscaled, + int scaled_src_size, float zoom, float align, float pan, int *src_start, int *src_end, int *dst_start, int *dst_end, int *osd_margin_a, int *osd_margin_b) { - if (unscaled) { - scaled_src_size = src_size; - zoom = 0.0; - } - - scaled_src_size += zoom * scaled_src_size; + scaled_src_size *= powf(2, zoom); align = (align + 1) / 2; *src_start = 0; @@ -110,17 +104,6 @@ static void src_dst_split_scaling(int src_size, int dst_size, *dst_end = dst_size; } - if (unscaled) { - // Force unscaled by reducing the range for src or dst - int src_s = *src_end - *src_start; - int dst_s = *dst_end - *dst_start; - if (src_s > dst_s) { - *src_end = *src_start + dst_s; - } else if (src_s < dst_s) { - *dst_end = *dst_start + src_s; - } - } - // For sanity: avoid bothering VOs with corner cases clamp_size(src_size, src_start, src_end); clamp_size(dst_size, dst_start, dst_end); @@ -152,14 +135,14 @@ void mp_get_src_dst_rects(struct mp_log *log, struct mp_vo_opts *opts, }; if (opts->keepaspect) { int scaled_width, scaled_height; - aspect_calc_panscan(log, opts, src_w, src_h, src_dw, src_dh, + aspect_calc_panscan(opts, src_w, src_h, src_dw, src_dh, opts->unscaled, window_w, window_h, monitor_par, &scaled_width, &scaled_height); - src_dst_split_scaling(src_w, window_w, scaled_width, opts->unscaled, + src_dst_split_scaling(src_w, window_w, scaled_width, opts->zoom, opts->align_x, opts->pan_x, &src.x0, &src.x1, &dst.x0, &dst.x1, &osd.ml, &osd.mr); - src_dst_split_scaling(src_h, window_h, scaled_height, opts->unscaled, + src_dst_split_scaling(src_h, window_h, scaled_height, opts->zoom, opts->align_y, opts->pan_y, &src.y0, &src.y1, &dst.y0, &dst.y1, &osd.mt, &osd.mb); diff --git a/video/out/opengl/common.c b/video/out/opengl/common.c index f08fd4bfd9..46cbc2fc8c 100644 --- a/video/out/opengl/common.c +++ b/video/out/opengl/common.c @@ -369,8 +369,10 @@ void mpgl_load_functions2(GL *gl, void *(*get_fn)(void *ctx, const char *n), int major = 0, minor = 0; const char *version_string = gl->GetString(GL_VERSION); - if (!version_string) + if (!version_string) { + mp_fatal(log, "glGetString(GL_VERSION) returned NULL.\n"); goto error; + } mp_verbose(log, "GL_VERSION='%s'\n", version_string); if (strncmp(version_string, "OpenGL ES ", 10) == 0) { version_string += 10; diff --git a/video/out/opengl/common.h b/video/out/opengl/common.h index 9236ce1d6f..f790dcb166 100644 --- a/video/out/opengl/common.h +++ b/video/out/opengl/common.h @@ -89,7 +89,6 @@ struct GL { int mpgl_caps; // Bitfield of MPGL_CAP_* constants bool debug_context; // use of e.g. GLX_CONTEXT_DEBUG_BIT_ARB int fb_r, fb_g, fb_b; // frame buffer bit depth (0 if unknown) - bool fb_premultiplied; // assumption about FB alpha compositor usage void (GLAPIENTRY *Viewport)(GLint, GLint, GLsizei, GLsizei); void (GLAPIENTRY *Clear)(GLbitfield); diff --git a/video/out/opengl/context.c b/video/out/opengl/context.c index aada9df973..77e9709426 100644 --- a/video/out/opengl/context.c +++ b/video/out/opengl/context.c @@ -78,6 +78,17 @@ static const struct mpgl_driver *const backends[] = { #endif }; +// 0-terminated list of desktop GL versions a backend should try to +// initialize. The first entry is the most preferred version. +const int mpgl_preferred_gl_versions[] = { + 330, + 320, + 310, + 300, + 210, + 0 +}; + int mpgl_find_backend(const char *name) { if (name == NULL || strcmp(name, "auto") == 0) diff --git a/video/out/opengl/context.h b/video/out/opengl/context.h index cd12bb9f32..df842bc8a1 100644 --- a/video/out/opengl/context.h +++ b/video/out/opengl/context.h @@ -34,6 +34,8 @@ enum { VOFLAG_SW = 1 << 4, // Hint to accept a software GL renderer }; +extern const int mpgl_preferred_gl_versions[]; + struct MPGLContext; // A windowing backend (like X11, win32, ...), which provides OpenGL rendering. diff --git a/video/out/opengl/context_cocoa.c b/video/out/opengl/context_cocoa.c index e48472ff46..271bdb7444 100644 --- a/video/out/opengl/context_cocoa.c +++ b/video/out/opengl/context_cocoa.c @@ -124,7 +124,6 @@ static bool create_gl_context(struct MPGLContext *ctx, int vo_flags) mpgl_load_functions(ctx->gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log); ctx->gl->fb_r = ctx->gl->fb_g = ctx->gl->fb_b = cgl_color_size(ctx); - ctx->gl->fb_premultiplied = true; CGLReleasePixelFormat(p->pix); diff --git a/video/out/opengl/context_dxinterop.c b/video/out/opengl/context_dxinterop.c index d3287f1f28..4dfc3c2108 100644 --- a/video/out/opengl/context_dxinterop.c +++ b/video/out/opengl/context_dxinterop.c @@ -543,6 +543,20 @@ static int GLAPIENTRY dxinterop_swap_interval(int interval) return 1; } +static void * GLAPIENTRY dxinterop_get_native_display(const char *name) +{ + if (!current_ctx || !name) + return NULL; + struct priv *p = current_ctx->priv; + + if (p->device && strcmp("IDirect3DDevice9Ex", name) == 0) { + return p->device; + } else if (p->device_h && strcmp("dxinterop_device_HANDLE", name) == 0) { + return p->device_h; + } + return NULL; +} + static int dxinterop_init(struct MPGLContext *ctx, int flags) { struct priv *p = ctx->priv; @@ -566,6 +580,8 @@ static int dxinterop_init(struct MPGLContext *ctx, int flags) gl->SwapInterval = dxinterop_swap_interval; + gl->MPGetNativeDisplay = dxinterop_get_native_display; + if (d3d_create(ctx) < 0) goto fail; if (d3d_size_dependent_create(ctx) < 0) @@ -581,9 +597,6 @@ static int dxinterop_init(struct MPGLContext *ctx, int flags) DwmEnableMMCSS(TRUE); - ctx->native_display_type = "IDirect3DDevice9Ex"; - ctx->native_display = p->device; - return 0; fail: dxinterop_uninit(ctx); diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c index 63a14539fe..a100073780 100644 --- a/video/out/opengl/context_wayland.c +++ b/video/out/opengl/context_wayland.c @@ -183,7 +183,8 @@ static void waylandgl_uninit(MPGLContext *ctx) if (wl->egl_context.egl.ctx) { eglReleaseThread(); - wl_egl_window_destroy(wl->egl_context.egl_window); + if (wl->egl_context.egl_window) + wl_egl_window_destroy(wl->egl_context.egl_window); eglDestroySurface(wl->egl_context.egl.dpy, wl->egl_context.egl_surface); eglMakeCurrent(wl->egl_context.egl.dpy, NULL, NULL, EGL_NO_CONTEXT); eglDestroyContext(wl->egl_context.egl.dpy, wl->egl_context.egl.ctx); diff --git a/video/out/opengl/context_x11.c b/video/out/opengl/context_x11.c index 6a6441cd23..d9a584e87c 100644 --- a/video/out/opengl/context_x11.c +++ b/video/out/opengl/context_x11.c @@ -125,10 +125,8 @@ static bool create_context_x11_gl3(struct MPGLContext *ctx, int vo_flags, glx_ctx->fbc, 0, True, context_attribs); vo_x11_silence_xlib(-1); - if (!context) { - MP_VERBOSE(vo, "Could not create GL3 context. Retrying with legacy context.\n"); + if (!context) return false; - } // set context if (!glXMakeCurrent(vo->x11->display, vo->x11->window, context)) { @@ -253,9 +251,18 @@ static int glx_init(struct MPGLContext *ctx, int flags) bool success = false; if (!(flags & VOFLAG_GLES)) { - success = create_context_x11_gl3(ctx, flags, 300, false); - if (!success) - success = create_context_x11_old(ctx); + for (int n = 0; mpgl_preferred_gl_versions[n]; n++) { + int version = mpgl_preferred_gl_versions[n]; + MP_VERBOSE(vo, "Creating OpenGL %d.%d context...\n", + MPGL_VER_P(version)); + if (version >= 300) { + success = create_context_x11_gl3(ctx, flags, version, false); + } else { + success = create_context_x11_old(ctx); + } + if (success) + break; + } } if (!success) // try ES success = create_context_x11_gl3(ctx, flags, 200, true); @@ -267,7 +274,6 @@ static int glx_init(struct MPGLContext *ctx, int flags) glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_RED_SIZE, &ctx->gl->fb_r); glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_GREEN_SIZE, &ctx->gl->fb_g); glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_BLUE_SIZE, &ctx->gl->fb_b); - ctx->gl->fb_premultiplied = true; return 0; diff --git a/video/out/opengl/hwdec.c b/video/out/opengl/hwdec.c index 300197ac00..b58af9bae9 100644 --- a/video/out/opengl/hwdec.c +++ b/video/out/opengl/hwdec.c @@ -28,6 +28,7 @@ extern const struct gl_hwdec_driver gl_hwdec_vaegl; extern const struct gl_hwdec_driver gl_hwdec_vaglx; extern const struct gl_hwdec_driver gl_hwdec_videotoolbox; extern const struct gl_hwdec_driver gl_hwdec_vdpau; +extern const struct gl_hwdec_driver gl_hwdec_dxva2egl; extern const struct gl_hwdec_driver gl_hwdec_dxva2gldx; extern const struct gl_hwdec_driver gl_hwdec_dxva2; @@ -45,6 +46,9 @@ static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = { &gl_hwdec_videotoolbox, #endif #if HAVE_DXVA2_HWACCEL +#if HAVE_EGL_ANGLE + &gl_hwdec_dxva2egl, +#endif #if HAVE_GL_DXINTEROP &gl_hwdec_dxva2gldx, #endif diff --git a/video/out/opengl/hwdec.h b/video/out/opengl/hwdec.h index c04962dd76..5126d7f0fa 100644 --- a/video/out/opengl/hwdec.h +++ b/video/out/opengl/hwdec.h @@ -39,6 +39,7 @@ struct gl_hwdec_driver { // Prepare for rendering video. (E.g. create textures.) // Called on initialization, and every time the video size changes. // *params must be set to the format the hw textures return. + // This also can update hw->converted_imgfmt. int (*reinit)(struct gl_hwdec *hw, struct mp_image_params *params); // Return textures that contain a copy or reference of the given hw_image. int (*map_image)(struct gl_hwdec *hw, struct mp_image *hw_image, diff --git a/video/out/opengl/hwdec_dxva2egl.c b/video/out/opengl/hwdec_dxva2egl.c new file mode 100644 index 0000000000..eed942618c --- /dev/null +++ b/video/out/opengl/hwdec_dxva2egl.c @@ -0,0 +1,344 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <windows.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include "common/common.h" +#include "osdep/timer.h" +#include "osdep/windows_utils.h" +#include "hwdec.h" +#include "video/dxva2.h" +#include "video/d3d.h" +#include "video/hwdec.h" + +struct priv { + struct mp_d3d_ctx ctx; + + HMODULE d3d9_dll; + IDirect3D9Ex *d3d9ex; + IDirect3DDevice9Ex *device9ex; + IDirect3DQuery9 *query9; + IDirect3DTexture9 *texture9; + IDirect3DSurface9 *surface9; + + EGLDisplay egl_display; + EGLConfig egl_config; + EGLint alpha; + EGLSurface egl_surface; + + GLuint gl_texture; +}; + +static void destroy_textures(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + GL *gl = hw->gl; + + gl->DeleteTextures(1, &p->gl_texture); + p->gl_texture = 0; + + if (p->egl_display && p->egl_surface) { + eglReleaseTexImage(p->egl_display, p->egl_surface, EGL_BACK_BUFFER); + eglDestroySurface(p->egl_display, p->egl_surface); + p->egl_surface = NULL; + } + + if (p->surface9) { + IDirect3DSurface9_Release(p->surface9); + p->surface9 = NULL; + } + + if (p->texture9) { + IDirect3DTexture9_Release(p->texture9); + p->texture9 = NULL; + } +} + +static void destroy(struct gl_hwdec *hw) +{ + struct priv *p = hw->priv; + + destroy_textures(hw); + + if (p->query9) + IDirect3DQuery9_Release(p->query9); + + if (p->device9ex) + IDirect3DDevice9Ex_Release(p->device9ex); + + if (p->d3d9ex) + IDirect3D9Ex_Release(p->d3d9ex); + + if (p->d3d9_dll) + FreeLibrary(p->d3d9_dll); +} + +static int create(struct gl_hwdec *hw) +{ + if (hw->hwctx) + return -1; + + EGLDisplay egl_display = eglGetCurrentDisplay(); + if (!egl_display) + return -1; + + const char *exts = eglQueryString(egl_display, EGL_EXTENSIONS); + if (!exts || + !strstr(exts, "EGL_ANGLE_d3d_share_handle_client_buffer")) { + return -1; + } + + HRESULT hr; + struct priv *p = talloc_zero(hw, struct priv); + hw->priv = p; + + p->egl_display = egl_display; + + p->d3d9_dll = LoadLibraryW(L"d3d9.dll"); + if (!p->d3d9_dll) { + MP_FATAL(hw, "Failed to load \"d3d9.dll\": %s\n", + mp_LastError_to_str()); + goto fail; + } + + HRESULT (WINAPI *Direct3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **ppD3D); + Direct3DCreate9Ex = (void *)GetProcAddress(p->d3d9_dll, "Direct3DCreate9Ex"); + if (!Direct3DCreate9Ex) { + MP_FATAL(hw, "Direct3D 9Ex not supported\n"); + goto fail; + } + + hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &p->d3d9ex); + if (FAILED(hr)) { + MP_FATAL(hw, "Couldn't create Direct3D9Ex: %s\n", + mp_HRESULT_to_str(hr)); + goto fail; + } + + // We must create our own Direct3D9Ex device. ANGLE can give us the device + // it's using, but that's probably a ID3D11Device. + // (copied from chromium dxva_video_decode_accelerator_win.cc) + D3DPRESENT_PARAMETERS present_params = { + .BackBufferWidth = 1, + .BackBufferHeight = 1, + .BackBufferFormat = D3DFMT_UNKNOWN, + .BackBufferCount = 1, + .SwapEffect = D3DSWAPEFFECT_DISCARD, + .hDeviceWindow = NULL, + .Windowed = TRUE, + .Flags = D3DPRESENTFLAG_VIDEO, + .FullScreen_RefreshRateInHz = 0, + .PresentationInterval = 0, + }; + hr = IDirect3D9Ex_CreateDeviceEx(p->d3d9ex, + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + NULL, + D3DCREATE_FPU_PRESERVE | + D3DCREATE_HARDWARE_VERTEXPROCESSING | + D3DCREATE_DISABLE_PSGP_THREADING | + D3DCREATE_MULTITHREADED, + &present_params, + NULL, + &p->device9ex); + if (FAILED(hr)) { + MP_FATAL(hw, "Failed to create Direct3D9Ex device: %s\n", + mp_HRESULT_to_str(hr)); + goto fail; + } + + hr = IDirect3DDevice9_CreateQuery(p->device9ex, D3DQUERYTYPE_EVENT, + &p->query9); + if (FAILED(hr)) { + MP_FATAL(hw, "Failed to create Direct3D query interface: %s\n", + mp_HRESULT_to_str(hr)); + goto fail; + } + + // Test the query API + hr = IDirect3DQuery9_Issue(p->query9, D3DISSUE_END); + if (FAILED(hr)) { + MP_FATAL(hw, "Failed to issue Direct3D END test query: %s\n", + mp_HRESULT_to_str(hr)); + goto fail; + } + + EGLint attrs[] = { + EGL_BUFFER_SIZE, 32, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_ALPHA_SIZE, 0, + EGL_NONE + }; + EGLint count; + if (!eglChooseConfig(p->egl_display, attrs, &p->egl_config, 1, &count) || + !count) { + MP_ERR(hw, "Failed to get EGL surface configuration\n"); + goto fail; + } + + if (!eglGetConfigAttrib(p->egl_display, p->egl_config, + EGL_BIND_TO_TEXTURE_RGBA, &p->alpha)) { + MP_FATAL(hw, "Failed to query EGL surface alpha\n"); + goto fail; + } + + hw->converted_imgfmt = IMGFMT_RGB0; + + p->ctx.d3d9_device = (IDirect3DDevice9 *)p->device9ex; + p->ctx.hwctx.type = HWDEC_DXVA2; + p->ctx.hwctx.d3d_ctx = &p->ctx; + + hw->hwctx = &p->ctx.hwctx; + return 0; +fail: + destroy(hw); + return -1; +} + +static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) +{ + struct priv *p = hw->priv; + GL *gl = hw->gl; + HRESULT hr; + + destroy_textures(hw); + + assert(params->imgfmt == hw->driver->imgfmt); + + HANDLE share_handle = NULL; + hr = IDirect3DDevice9Ex_CreateTexture(p->device9ex, + params->w, params->h, + 1, D3DUSAGE_RENDERTARGET, + p->alpha ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8, + D3DPOOL_DEFAULT, + &p->texture9, + &share_handle); + if (FAILED(hr)) { + MP_ERR(hw, "Failed to create Direct3D9 texture: %s\n", + mp_HRESULT_to_str(hr)); + goto fail; + } + + hr = IDirect3DTexture9_GetSurfaceLevel(p->texture9, 0, &p->surface9); + if (FAILED(hr)) { + MP_ERR(hw, "Failed to get Direct3D9 surface from texture: %s\n", + mp_HRESULT_to_str(hr)); + goto fail; + } + + EGLint attrib_list[] = { + EGL_WIDTH, params->w, + EGL_HEIGHT, params->h, + EGL_TEXTURE_FORMAT, p->alpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB, + EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_NONE + }; + p->egl_surface = eglCreatePbufferFromClientBuffer( + p->egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, + share_handle, p->egl_config, attrib_list); + if (p->egl_surface == EGL_NO_SURFACE) { + MP_ERR(hw, "Failed to create EGL surface\n"); + goto fail; + } + + gl->GenTextures(1, &p->gl_texture); + gl->BindTexture(GL_TEXTURE_2D, p->gl_texture); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl->BindTexture(GL_TEXTURE_2D, 0); + + return 0; +fail: + destroy_textures(hw); + return -1; +} + +static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image, + GLuint *out_textures) +{ + struct priv *p = hw->priv; + GL *gl = hw->gl; + if (!p->surface9 || !p->egl_surface || !p->gl_texture) + return -1; + + HRESULT hr; + RECT rc = {0, 0, hw_image->w, hw_image->h}; + IDirect3DSurface9* hw_surface = d3d9_surface_in_mp_image(hw_image); + hr = IDirect3DDevice9Ex_StretchRect(p->device9ex, + hw_surface, &rc, + p->surface9, &rc, + D3DTEXF_NONE); + if (FAILED(hr)) { + MP_ERR(hw, "Direct3D RGB conversion failed: %s\n", + mp_HRESULT_to_str(hr)); + return -1; + } + + hr = IDirect3DQuery9_Issue(p->query9, D3DISSUE_END); + if (FAILED(hr)) { + MP_ERR(hw, "Failed to issue Direct3D END query\n"); + return -1; + } + + // There doesn't appear to be an efficient way to do a blocking flush + // of the above StretchRect. Timeout of 8ms is required to reliably + // render 4k on Intel Haswell, Ivybridge and Cherry Trail Atom. + const int max_retries = 8; + const int64_t wait_us = 1000; + int retries = 0; + while (true) { + hr = IDirect3DQuery9_GetData(p->query9, NULL, 0, D3DGETDATA_FLUSH); + if (FAILED(hr)) { + MP_ERR(hw, "Failed to query Direct3D flush state\n"); + return -1; + } else if (hr == S_FALSE) { + if (++retries > max_retries) { + MP_VERBOSE(hw, "Failed to flush frame after %lld ms\n", + (long long)(wait_us * max_retries) / 1000); + break; + } + mp_sleep_us(wait_us); + } else { + break; + } + } + + gl->BindTexture(GL_TEXTURE_2D, p->gl_texture); + eglBindTexImage(p->egl_display, p->egl_surface, EGL_BACK_BUFFER); + gl->BindTexture(GL_TEXTURE_2D, 0); + + out_textures[0] = p->gl_texture; + return 0; +} + +const struct gl_hwdec_driver gl_hwdec_dxva2egl = { + .name = "dxva2-egl", + .api = HWDEC_DXVA2, + .imgfmt = IMGFMT_DXVA2, + .create = create, + .reinit = reinit, |