summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorMartin Herkt <lachs0r@srsfckn.biz>2016-08-15 15:19:29 +0200
committerMartin Herkt <lachs0r@srsfckn.biz>2016-08-15 15:19:29 +0200
commitfd1bc95b4865ff789780c2213eefbdf77f0d4d1f (patch)
tree639e098e46cf1b77ecea7df95d7b968c25e1d0c9 /video
parent1e00bcc14c9b0d9beb8e152f958fc0db4bc6d31b (diff)
parentd7a7e9a8c861c4a9881fcef5cf69c746742b8b88 (diff)
downloadmpv-fd1bc95b4865ff789780c2213eefbdf77f0d4d1f.tar.bz2
mpv-fd1bc95b4865ff789780c2213eefbdf77f0d4d1f.tar.xz
Merge branch 'master' into release/current
Diffstat (limited to 'video')
-rw-r--r--video/decode/vd_lavc.c2
-rw-r--r--video/decode/videotoolbox.c122
-rw-r--r--video/filter/refqueue.c9
-rw-r--r--video/filter/refqueue.h1
-rw-r--r--video/filter/vf_d3d11vpp.c29
-rw-r--r--video/filter/vf_vavpp.c2
-rw-r--r--video/hwdec.h1
-rw-r--r--video/mp_image.c2
-rw-r--r--video/mp_image.h3
-rw-r--r--video/out/cocoa_common.m6
-rw-r--r--video/out/opengl/context.h5
-rw-r--r--video/out/opengl/context_angle.c62
-rw-r--r--video/out/opengl/context_wayland.c17
-rw-r--r--video/out/opengl/context_x11.c14
-rw-r--r--video/out/opengl/context_x11egl.c12
-rw-r--r--video/out/opengl/hwdec_d3d11egl.c1
-rw-r--r--video/out/opengl/hwdec_d3d11eglrgb.c1
-rw-r--r--video/out/opengl/hwdec_dxva2egl.c1
-rw-r--r--video/out/opengl/hwdec_dxva2gldx.c1
-rw-r--r--video/out/opengl/hwdec_osx.c13
-rw-r--r--video/out/opengl/hwdec_vaegl.c8
-rw-r--r--video/out/opengl/hwdec_vaglx.c1
-rw-r--r--video/out/opengl/hwdec_vdpau.c2
-rw-r--r--video/out/opengl/lcms.c4
-rw-r--r--video/out/opengl/video.c24
-rw-r--r--video/out/vo.c76
-rw-r--r--video/out/vo.h10
-rw-r--r--video/out/vo_direct3d.c1
-rw-r--r--video/out/vo_drm.c5
-rw-r--r--video/out/vo_opengl.c21
-rw-r--r--video/out/vo_opengl_cb.c6
-rw-r--r--video/out/vo_sdl.c4
-rw-r--r--video/out/vo_vaapi.c2
-rw-r--r--video/out/vo_vdpau.c2
-rw-r--r--video/out/vo_wayland.c9
-rw-r--r--video/out/vo_x11.c2
-rw-r--r--video/out/vo_xv.c2
-rw-r--r--video/out/w32_common.c26
-rw-r--r--video/out/wayland_common.c356
-rw-r--r--video/out/wayland_common.h12
-rw-r--r--video/out/x11_common.c79
-rw-r--r--video/out/x11_common.h7
-rw-r--r--video/vaapi.c2
43 files changed, 523 insertions, 442 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 5962f883cd..eb63e58e92 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -126,6 +126,7 @@ const struct m_sub_options vd_lavc_conf = {
extern const struct vd_lavc_hwdec mp_vd_lavc_vdpau;
extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox;
+extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox_copy;
extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi;
extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy;
extern const struct vd_lavc_hwdec mp_vd_lavc_dxva2;
@@ -158,6 +159,7 @@ static const struct vd_lavc_hwdec *const hwdec_list[] = {
#endif
#if HAVE_VIDEOTOOLBOX_HWACCEL
&mp_vd_lavc_videotoolbox,
+ &mp_vd_lavc_videotoolbox_copy,
#endif
#if HAVE_VAAPI_HWACCEL
&mp_vd_lavc_vaapi,
diff --git a/video/decode/videotoolbox.c b/video/decode/videotoolbox.c
index c69d5e89e6..c6f1a472bf 100644
--- a/video/decode/videotoolbox.c
+++ b/video/decode/videotoolbox.c
@@ -24,14 +24,16 @@
#include "common/msg.h"
#include "video/mp_image.h"
#include "video/decode/lavc.h"
+#include "video/mp_image_pool.h"
#include "config.h"
+struct priv {
+ struct mp_image_pool *sw_pool;
+};
-static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
+static int probe_copy(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
const char *codec)
{
- if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_VIDEOTOOLBOX))
- return HWDEC_ERR_NO_CTX;
switch (mp_codec_to_av_codec_id(codec)) {
case AV_CODEC_ID_H264:
case AV_CODEC_ID_H263:
@@ -45,8 +47,19 @@ static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
return 0;
}
+static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
+ const char *codec)
+{
+ if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_VIDEOTOOLBOX))
+ return HWDEC_ERR_NO_CTX;
+ return probe_copy(ctx, hwdec, codec);
+}
+
static int init(struct lavc_ctx *ctx)
{
+ struct priv *p = talloc_ptrtype(NULL, p);
+ p->sw_pool = talloc_steal(p, mp_image_pool_new(17));
+ ctx->hwdec_priv = p;
return 0;
}
@@ -82,15 +95,10 @@ static void print_videotoolbox_error(struct mp_log *log, int lev, char *message,
mp_msg(log, lev, "%s: %d\n", message, error_code);
}
-static int init_decoder(struct lavc_ctx *ctx, int w, int h)
+static int init_decoder_common(struct lavc_ctx *ctx, int w, int h, AVVideotoolboxContext *vtctx)
{
av_videotoolbox_default_free(ctx->avctx);
- AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context();
-
- struct mp_vt_ctx *vt = hwdec_devices_load(ctx->hwdec_devs, HWDEC_VIDEOTOOLBOX);
- vtctx->cv_pix_fmt_type = vt->get_vt_fmt(vt);
-
int err = av_videotoolbox_default_init2(ctx->avctx, vtctx);
if (err < 0) {
print_videotoolbox_error(ctx->log, MSGL_ERR, "failed to init videotoolbox decoder", err);
@@ -100,17 +108,99 @@ static int init_decoder(struct lavc_ctx *ctx, int w, int h)
return 0;
}
+static int init_decoder(struct lavc_ctx *ctx, int w, int h)
+{
+ AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context();
+ struct mp_vt_ctx *vt = hwdec_devices_load(ctx->hwdec_devs, HWDEC_VIDEOTOOLBOX);
+ vtctx->cv_pix_fmt_type = vt->get_vt_fmt(vt);
+
+ return init_decoder_common(ctx, w, h, vtctx);
+}
+
+static int init_decoder_copy(struct lavc_ctx *ctx, int w, int h)
+{
+ return init_decoder_common(ctx, w, h, NULL);
+}
+
static void uninit(struct lavc_ctx *ctx)
{
if (ctx->avctx)
av_videotoolbox_default_free(ctx->avctx);
+
+ struct priv *p = ctx->hwdec_priv;
+ if (!p)
+ return;
+
+ talloc_free(p->sw_pool);
+ p->sw_pool = NULL;
+
+ talloc_free(p);
+ ctx->hwdec_priv = NULL;
+}
+
+static int mp_imgfmt_from_cvpixelformat(uint32_t cvpixfmt)
+{
+ switch (cvpixfmt) {
+ case kCVPixelFormatType_420YpCbCr8Planar: return IMGFMT_420P;
+ case kCVPixelFormatType_422YpCbCr8: return IMGFMT_UYVY;
+ case kCVPixelFormatType_32BGRA: return IMGFMT_RGB0;
+ case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: return IMGFMT_NV12;
+ }
+ return 0;
+}
+
+static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *hw_image)
+{
+ if (hw_image->imgfmt != IMGFMT_VIDEOTOOLBOX)
+ return hw_image;
+
+ struct priv *p = ctx->hwdec_priv;
+ struct mp_image *image = NULL;
+ CVPixelBufferRef pbuf = (CVPixelBufferRef)hw_image->planes[3];
+ CVPixelBufferLockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
+ size_t width = CVPixelBufferGetWidth(pbuf);
+ size_t height = CVPixelBufferGetHeight(pbuf);
+ uint32_t cvpixfmt = CVPixelBufferGetPixelFormatType(pbuf);
+ int pixfmt = mp_imgfmt_from_cvpixelformat(cvpixfmt);
+ if (!pixfmt)
+ goto unlock;
+
+ struct mp_image img = {0};
+ mp_image_setfmt(&img, pixfmt);
+ mp_image_set_size(&img, width, height);
+
+ if (CVPixelBufferIsPlanar(pbuf)) {
+ int planes = CVPixelBufferGetPlaneCount(pbuf);
+ for (int i = 0; i < planes; i++) {
+ img.planes[i] = CVPixelBufferGetBaseAddressOfPlane(pbuf, i);
+ img.stride[i] = CVPixelBufferGetBytesPerRowOfPlane(pbuf, i);
+ }
+ } else {
+ img.planes[0] = CVPixelBufferGetBaseAddress(pbuf);
+ img.stride[0] = CVPixelBufferGetBytesPerRow(pbuf);
+ }
+
+ mp_image_copy_attributes(&img, hw_image);
+
+ image = mp_image_pool_new_copy(p->sw_pool, &img);
+
+unlock:
+ CVPixelBufferUnlockBaseAddress(pbuf, kCVPixelBufferLock_ReadOnly);
+
+ if (image) {
+ talloc_free(hw_image);
+ return image;
+ } else {
+ return hw_image;
+ }
}
static struct mp_image *process_image(struct lavc_ctx *ctx, struct mp_image *img)
{
if (img->imgfmt == IMGFMT_VIDEOTOOLBOX) {
CVPixelBufferRef pbuf = (CVPixelBufferRef)img->planes[3];
- img->params.hw_subfmt = CVPixelBufferGetPixelFormatType(pbuf);
+ uint32_t cvpixfmt = CVPixelBufferGetPixelFormatType(pbuf);
+ img->params.hw_subfmt = mp_imgfmt_from_cvpixelformat(cvpixfmt);
}
return img;
}
@@ -124,3 +214,15 @@ const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox = {
.init_decoder = init_decoder,
.process_image = process_image,
};
+
+const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox_copy = {
+ .type = HWDEC_VIDEOTOOLBOX_COPY,
+ .copying = true,
+ .image_format = IMGFMT_VIDEOTOOLBOX,
+ .probe = probe_copy,
+ .init = init,
+ .uninit = uninit,
+ .init_decoder = init_decoder_copy,
+ .process_image = copy_image,
+ .delay_queue = HWDEC_DELAY_QUEUE_COUNT,
+};
diff --git a/video/filter/refqueue.c b/video/filter/refqueue.c
index 04de3124a4..6b2e5a2110 100644
--- a/video/filter/refqueue.c
+++ b/video/filter/refqueue.c
@@ -75,15 +75,6 @@ bool mp_refqueue_should_deint(struct mp_refqueue *q)
!(q->flags & MP_MODE_INTERLACED_ONLY);
}
-// Whether the current output frame is marked as interlaced.
-bool mp_refqueue_is_interlaced(struct mp_refqueue *q)
-{
- if (!mp_refqueue_has_output(q))
- return false;
-
- return q->queue[q->pos]->fields & MP_IMGFIELD_INTERLACED;
-}
-
// Whether the current output frame (field) is the top field, bottom field
// otherwise. (Assumes the caller forces deinterlacing.)
bool mp_refqueue_is_top_field(struct mp_refqueue *q)
diff --git a/video/filter/refqueue.h b/video/filter/refqueue.h
index ef23bee906..bb23506ac2 100644
--- a/video/filter/refqueue.h
+++ b/video/filter/refqueue.h
@@ -27,7 +27,6 @@ enum {
void mp_refqueue_set_mode(struct mp_refqueue *q, int flags);
bool mp_refqueue_should_deint(struct mp_refqueue *q);
-bool mp_refqueue_is_interlaced(struct mp_refqueue *q);
bool mp_refqueue_is_top_field(struct mp_refqueue *q);
bool mp_refqueue_top_field_first(struct mp_refqueue *q);
bool mp_refqueue_is_second_field(struct mp_refqueue *q);
diff --git a/video/filter/vf_d3d11vpp.c b/video/filter/vf_d3d11vpp.c
index 6faf712a67..7a52565782 100644
--- a/video/filter/vf_d3d11vpp.c
+++ b/video/filter/vf_d3d11vpp.c
@@ -29,7 +29,12 @@
#include "video/mp_image_pool.h"
// missing in MinGW
+#define D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BLEND 0x1
#define D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB 0x2
+#define D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_ADAPTIVE 0x4
+#define D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_MOTION_COMPENSATION 0x8
+#define D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_INVERSE_TELECINE 0x10
+#define D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_FRAME_RATE_CONVERSION 0x20
struct vf_priv_s {
ID3D11Device *vo_dev;
@@ -57,6 +62,7 @@ struct vf_priv_s {
int deint_enabled;
int interlaced_only;
+ int mode;
};
static void release_tex(void *arg)
@@ -159,8 +165,8 @@ static int recreate_video_proc(struct vf_instance *vf)
if (FAILED(hr))
goto fail;
- MP_VERBOSE(vf, "Found %d rate conversion caps.\n",
- (int)caps.RateConversionCapsCount);
+ MP_VERBOSE(vf, "Found %d rate conversion caps. Looking for caps=0x%x.\n",
+ (int)caps.RateConversionCapsCount, p->mode);
int rindex = -1;
for (int n = 0; n < caps.RateConversionCapsCount; n++) {
@@ -170,8 +176,7 @@ static int recreate_video_proc(struct vf_instance *vf)
if (FAILED(hr))
goto fail;
MP_VERBOSE(vf, " - %d: 0x%08x\n", n, (unsigned)rcaps.ProcessorCaps);
- if (rcaps.ProcessorCaps & D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB)
- {
+ if (rcaps.ProcessorCaps & p->mode) {
MP_VERBOSE(vf, " (matching)\n");
if (rindex < 0)
rindex = n;
@@ -179,10 +184,12 @@ static int recreate_video_proc(struct vf_instance *vf)
}
if (rindex < 0) {
- MP_WARN(vf, "No video deinterlacing processor found.\n");
+ MP_WARN(vf, "No fitting video processor found, picking #0.\n");
rindex = 0;
}
+ // TOOD: so, how do we select which rate conversion mode the processor uses?
+
hr = ID3D11VideoDevice_CreateVideoProcessor(p->video_dev, p->vp_enum, rindex,
&p->video_proc);
if (FAILED(hr)) {
@@ -262,7 +269,7 @@ static int render(struct vf_instance *vf)
mp_image_copy_attributes(out, in);
D3D11_VIDEO_FRAME_FORMAT d3d_frame_format;
- if (!mp_refqueue_is_interlaced(p->queue)) {
+ if (!mp_refqueue_should_deint(p->queue)) {
d3d_frame_format = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
} else if (mp_refqueue_top_field_first(p->queue)) {
d3d_frame_format = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST;
@@ -282,7 +289,7 @@ static int render(struct vf_instance *vf)
goto cleanup;
}
- if (!mp_refqueue_is_interlaced(p->queue)) {
+ if (!mp_refqueue_should_deint(p->queue)) {
d3d_frame_format = D3D11_VIDEO_FRAME_FORMAT_PROGRESSIVE;
} else if (mp_refqueue_is_top_field(p->queue)) {
d3d_frame_format = D3D11_VIDEO_FRAME_FORMAT_INTERLACED_TOP_FIELD_FIRST;
@@ -518,6 +525,13 @@ fail:
static const m_option_t vf_opts_fields[] = {
OPT_FLAG("deint", deint_enabled, 0),
OPT_FLAG("interlaced-only", interlaced_only, 0),
+ OPT_CHOICE("mode", mode, 0,
+ ({"blend", D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BLEND},
+ {"bob", D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB},
+ {"adaptive", D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_ADAPTIVE},
+ {"mocomp", D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_MOTION_COMPENSATION},
+ {"ivctc", D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_INVERSE_TELECINE},
+ {"none", 0})),
{0}
};
@@ -530,6 +544,7 @@ const vf_info_t vf_info_d3d11vpp = {
.priv_defaults = &(const struct vf_priv_s) {
.deint_enabled = 1,
.interlaced_only = 1,
+ .mode = D3D11_VIDEO_PROCESSOR_PROCESSOR_CAPS_DEINTERLACE_BOB,
},
.options = vf_opts_fields,
};
diff --git a/video/filter/vf_vavpp.c b/video/filter/vf_vavpp.c
index b24f886241..ad669ac159 100644
--- a/video/filter/vf_vavpp.c
+++ b/video/filter/vf_vavpp.c
@@ -169,7 +169,7 @@ static struct mp_image *render(struct vf_instance *vf)
mp_image_copy_attributes(img, in);
unsigned int flags = va_get_colorspace_flag(p->params.color.space);
- if (!mp_refqueue_is_interlaced(p->queue)) {
+ if (!mp_refqueue_should_deint(p->queue)) {
flags |= VA_FRAME_PICTURE;
} else if (mp_refqueue_is_top_field(p->queue)) {
flags |= VA_TOP_FIELD;
diff --git a/video/hwdec.h b/video/hwdec.h
index 5d563c983b..4d99076f16 100644
--- a/video/hwdec.h
+++ b/video/hwdec.h
@@ -12,6 +12,7 @@ enum hwdec_type {
HWDEC_AUTO_COPY,
HWDEC_VDPAU,
HWDEC_VIDEOTOOLBOX,
+ HWDEC_VIDEOTOOLBOX_COPY,
HWDEC_VAAPI,
HWDEC_VAAPI_COPY,
HWDEC_DXVA2,
diff --git a/video/mp_image.c b/video/mp_image.c
index a4ce6d1cc5..531565f837 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -512,7 +512,7 @@ char *mp_image_params_to_str_buf(char *b, size_t bs,
mp_snprintf_cat(b, bs, " [%d:%d]", p->p_w, p->p_h);
mp_snprintf_cat(b, bs, " %s", mp_imgfmt_to_name(p->imgfmt));
if (p->hw_subfmt)
- mp_snprintf_cat(b, bs, "[%llu]", (unsigned long long)(p->hw_subfmt));
+ mp_snprintf_cat(b, bs, "[%s]", mp_imgfmt_to_name(p->hw_subfmt));
mp_snprintf_cat(b, bs, " %s/%s",
m_opt_choice_str(mp_csp_names, p->color.space),
m_opt_choice_str(mp_csp_levels_names, p->color.levels));
diff --git a/video/mp_image.h b/video/mp_image.h
index dfbe4ee0ba..13e364ae24 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -39,8 +39,7 @@
// usually copy the whole struct, so that fields added later will be preserved.
struct mp_image_params {
enum mp_imgfmt imgfmt; // pixel format
- uint64_t hw_subfmt; // underlying format for some hwaccel pixfmts
- // (will use the HW API's format identifiers)
+ enum mp_imgfmt hw_subfmt; // underlying format for some hwaccel pixfmts
int w, h; // image dimensions
int p_w, p_h; // define pixel aspect ratio (undefined: 0/0)
struct mp_colorspace color;
diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m
index 21e1246b1c..557e28e4f1 100644
--- a/video/out/cocoa_common.m
+++ b/video/out/cocoa_common.m
@@ -90,8 +90,6 @@ struct vo_cocoa_state {
uint32_t old_dwidth;
uint32_t old_dheight;
- NSData *icc_wnd_profile;
- NSData *icc_fs_profile;
id fs_icc_changed_ns_observer;
pthread_mutex_t lock;
@@ -421,7 +419,6 @@ static void vo_cocoa_update_screen_info(struct vo *vo, struct mp_rect *out_rc)
return;
vo_cocoa_update_screens_pointers(vo);
- vo_cocoa_update_screen_fps(vo);
if (out_rc) {
NSRect r = [s->current_screen frame];
@@ -584,6 +581,7 @@ static void cocoa_screen_reconfiguration_observer(
struct vo *vo = ctx;
MP_WARN(vo, "detected display mode change, updating screen info\n");
vo_cocoa_update_screen_info(vo, NULL);
+ vo_cocoa_update_screen_fps(vo);
}
}
@@ -614,6 +612,7 @@ int vo_cocoa_config_window(struct vo *vo)
run_on_main_thread(vo, ^{
struct mp_rect screenrc;
vo_cocoa_update_screen_info(vo, &screenrc);
+ vo_cocoa_update_screen_fps(vo);
struct vo_win_geometry geo;
vo_calc_window_geometry(vo, &screenrc, &geo);
@@ -953,6 +952,7 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
- (void)windowDidChangeScreen:(NSNotification *)notification
{
vo_cocoa_update_screen_info(self.vout, NULL);
+ vo_cocoa_update_screen_fps(self.vout);
}
- (void)didChangeWindowedScreenProfile:(NSScreen *)screen
diff --git a/video/out/opengl/context.h b/video/out/opengl/context.h
index df842bc8a1..a546e00be0 100644
--- a/video/out/opengl/context.h
+++ b/video/out/opengl/context.h
@@ -63,6 +63,11 @@ struct mpgl_driver {
// This behaves exactly like vo_driver.control().
int (*control)(struct MPGLContext *ctx, int *events, int request, void *arg);
+ // These behave exactly like vo_driver.wakeup/wait_events. They are
+ // optional.
+ void (*wakeup)(struct MPGLContext *ctx);
+ void (*wait_events)(struct MPGLContext *ctx, int64_t until_time_us);
+
// Destroy the GL context and possibly the underlying VO backend.
void (*uninit)(struct MPGLContext *ctx);
};
diff --git a/video/out/opengl/context_angle.c b/video/out/opengl/context_angle.c
index 28515f431f..ebc803fdb1 100644
--- a/video/out/opengl/context_angle.c
+++ b/video/out/opengl/context_angle.c
@@ -15,6 +15,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <initguid.h>
#include <windows.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -33,11 +34,15 @@
#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
#endif
+// Windows 8 enum value, not present in mingw-w64 headers
+#define DXGI_ADAPTER_FLAG_SOFTWARE (2)
+
struct priv {
EGLDisplay egl_display;
EGLContext egl_context;
EGLSurface egl_surface;
bool use_es2;
+ bool sw_adapter_msg_shown;
PFNEGLPOSTSUBBUFFERNVPROC eglPostSubBufferNV;
};
@@ -104,6 +109,15 @@ static bool create_context_egl(MPGLContext *ctx, EGLConfig config, int version)
return true;
}
+static void show_sw_adapter_msg(struct MPGLContext *ctx)
+{
+ struct priv *p = ctx->priv;
+ if (p->sw_adapter_msg_shown)
+ return;
+ MP_WARN(ctx->vo, "Using a software adapter\n");
+ p->sw_adapter_msg_shown = true;
+}
+
static void d3d_init(struct MPGLContext *ctx)
{
HRESULT hr;
@@ -111,6 +125,7 @@ static void d3d_init(struct MPGLContext *ctx)
struct vo *vo = ctx->vo;
IDXGIDevice *dxgi_dev = NULL;
IDXGIAdapter *dxgi_adapter = NULL;
+ IDXGIAdapter1 *dxgi_adapter1 = NULL;
IDXGIFactory *dxgi_factory = NULL;
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT =
@@ -147,6 +162,25 @@ static void d3d_init(struct MPGLContext *ctx)
goto done;
}
+ // Windows 8 can choose a software adapter even if mpv didn't ask for
+ // one. If this is the case, show a warning message.
+ hr = IDXGIAdapter_QueryInterface(dxgi_adapter, &IID_IDXGIAdapter1,
+ (void**)&dxgi_adapter1);
+ if (SUCCEEDED(hr)) {
+ DXGI_ADAPTER_DESC1 desc;
+ hr = IDXGIAdapter1_GetDesc1(dxgi_adapter1, &desc);
+ if (SUCCEEDED(hr)) {
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
+ show_sw_adapter_msg(ctx);
+
+ // If the primary display adapter is a software adapter, the
+ // DXGI_ADAPTER_FLAG_SOFTWARE won't be set, but the device IDs
+ // should still match the Microsoft Basic Render Driver
+ if (desc.VendorId == 0x1414 && desc.DeviceId == 0x8c)
+ show_sw_adapter_msg(ctx);
+ }
+ }
+
hr = IDXGIAdapter_GetParent(dxgi_adapter, &IID_IDXGIFactory,
(void**)&dxgi_factory);
if (FAILED(hr)) {
@@ -168,6 +202,8 @@ done:
IDXGIDevice_Release(dxgi_dev);
if (dxgi_adapter)
IDXGIAdapter_Release(dxgi_adapter);
+ if (dxgi_adapter1)
+ IDXGIAdapter1_Release(dxgi_adapter1);
if (dxgi_factory)
IDXGIFactory_Release(dxgi_factory);
}
@@ -204,31 +240,39 @@ static int angle_init(struct MPGLContext *ctx, int flags)
}
EGLint d3d_types[] = {EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE};
+ EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE};
+ EGLint d3d_dev_types[] = {EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE};
for (int i = 0; i < MP_ARRAY_SIZE(d3d_types); i++) {
EGLint display_attributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
d3d_types[i],
EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE,
+ d3d_dev_types[i],
EGL_NONE,
};
p->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc,
display_attributes);
- if (p->egl_display != EGL_NO_DISPLAY)
- break;
+ if (p->egl_display == EGL_NO_DISPLAY)
+ continue;
+
+ if (!eglInitialize(p->egl_display, NULL, NULL)) {
+ p->egl_display = EGL_NO_DISPLAY;
+ continue;
+ }
+
+ if (d3d_dev_types[i] == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE)
+ show_sw_adapter_msg(ctx);
+ break;
}
if (p->egl_display == EGL_NO_DISPLAY) {
MP_FATAL(vo, "Couldn't get display\n");
goto fail;
}
- if (!eglInitialize(p->egl_display, NULL, NULL)) {
- MP_FATAL(vo, "Couldn't initialize EGL\n");
- goto fail;
- }
-
const char *exts = eglQueryString(p->egl_display, EGL_EXTENSIONS);
if (exts)
MP_DBG(ctx->vo, "EGL extensions: %s\n", exts);
diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c
index e74132bcf2..efb6128b92 100644
--- a/video/out/opengl/context_wayland.c
+++ b/video/out/opengl/context_wayland.c
@@ -59,9 +59,7 @@ static void egl_resize(struct vo_wayland_state *wl)
/* set size for mplayer */
wl->vo->dwidth = scale*wl->window.width;
wl->vo->dheight = scale*wl->window.height;
-
wl->vo->want_redraw = true;
- wl->window.events = 0;
}
static int egl_create_context(struct vo_wayland_state *wl,
@@ -207,8 +205,7 @@ static void waylandgl_swap_buffers(MPGLContext *ctx)
if (!wl->frame.callback)
vo_wayland_request_frame(ctx->vo, NULL, NULL);
- if (!vo_wayland_wait_frame(ctx->vo))
- MP_DBG(wl, "discarding frame callback\n");
+ vo_wayland_wait_events(ctx->vo, 0);
eglSwapBuffers(wl->egl_context.egl.dpy, wl->egl_context.egl_surface);
}
@@ -225,6 +222,16 @@ static int waylandgl_control(MPGLContext *ctx, int *events, int request,
return r;
}
+static void wayland_wakeup(struct MPGLContext *ctx)
+{
+ vo_wayland_wakeup(ctx->vo);
+}
+
+static void wayland_wait_events(struct MPGLContext *ctx, int64_t until_time_us)
+{
+ vo_wayland_wait_events(ctx->vo, until_time_us);
+}
+
static int waylandgl_init(struct MPGLContext *ctx, int flags)
{
if (!vo_wayland_init(ctx->vo))
@@ -239,5 +246,7 @@ const struct mpgl_driver mpgl_driver_wayland = {
.reconfig = waylandgl_reconfig,
.swap_buffers = waylandgl_swap_buffers,
.control = waylan