diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2016-06-25 02:25:44 +0200 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2016-06-25 02:25:44 +0200 |
commit | ad56f2c46ac6deec86870ec10f2a11a644df07d4 (patch) | |
tree | 89f2d90c5586560911e67c872b530c77f151168d /video/out | |
parent | 0536841647ef7931bffb4386d8ffbb5b2b568e8a (diff) | |
parent | 393bb2a565dc1e27812e1dd20747814892f80da2 (diff) | |
download | mpv-ad56f2c46ac6deec86870ec10f2a11a644df07d4.tar.bz2 mpv-ad56f2c46ac6deec86870ec10f2a11a644df07d4.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'video/out')
69 files changed, 4448 insertions, 2496 deletions
diff --git a/video/out/bitmap_packer.c b/video/out/bitmap_packer.c index 4896076422..3f75a72bcb 100644 --- a/video/out/bitmap_packer.c +++ b/video/out/bitmap_packer.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <assert.h> #include <stdio.h> +#include <limits.h> #include <libavutil/common.h> @@ -46,10 +47,7 @@ void packer_reset(struct bitmap_packer *packer) void packer_get_bb(struct bitmap_packer *packer, struct pos out_bb[2]) { out_bb[0] = (struct pos) {0}; - out_bb[1] = (struct pos) { - FFMIN(packer->used_width + packer->padding, packer->w), - FFMIN(packer->used_height + packer->padding, packer->h), - }; + out_bb[1] = (struct pos) {packer->used_width, packer->used_height}; } #define HEIGHT_SORT_BITS 4 @@ -138,8 +136,12 @@ int packer_pack(struct bitmap_packer *packer) struct pos *in = packer->in; int xmax = 0, ymax = 0; for (int i = 0; i < packer->count; i++) { - if (in[i].x <= packer->padding || in[i].y <= packer->padding) + if (in[i].x <= 0 || in[i].y <= 0) { in[i] = (struct pos){0, 0}; + } else { + in[i].x += packer->padding * 2; + in[i].y += packer->padding * 2; + } if (in[i].x < 0 || in [i].x > 65535 || in[i].y < 0 || in[i].y > 65535) { fprintf(stderr, "Invalid OSD / subtitle bitmap size\n"); abort(); @@ -147,8 +149,6 @@ int packer_pack(struct bitmap_packer *packer) xmax = FFMAX(xmax, in[i].x); ymax = FFMAX(ymax, in[i].y); } - xmax = FFMAX(0, xmax - packer->padding); - ymax = FFMAX(0, ymax - packer->padding); if (xmax > packer->w) packer->w = 1 << (av_log2(xmax - 1) + 1); if (ymax > packer->h) @@ -156,21 +156,27 @@ int packer_pack(struct bitmap_packer *packer) while (1) { int used_width = 0; int y = pack_rectangles(in, packer->result, packer->count, - packer->w + packer->padding, - packer->h + packer->padding, + packer->w, packer->h, packer->scratch, &used_width); if (y >= 0) { - // No padding at edges packer->used_width = FFMIN(used_width, packer->w); packer->used_height = FFMIN(y, packer->h); assert(packer->w == 0 || IS_POWER_OF_2(packer->w)); assert(packer->h == 0 || IS_POWER_OF_2(packer->h)); + if (packer->padding) { + for (int i = 0; i < packer->count; i++) { + packer->result[i].x += packer->padding; + packer->result[i].y += packer->padding; + } + } return packer->w != w_orig || packer->h != h_orig; } - if (packer->w <= packer->h && packer->w != packer->w_max) - packer->w = FFMIN(packer->w * 2, packer->w_max); - else if (packer->h != packer->h_max) - packer->h = FFMIN(packer->h * 2, packer->h_max); + int w_max = packer->w_max > 0 ? packer->w_max : INT_MAX; + int h_max = packer->h_max > 0 ? packer->h_max : INT_MAX; + if (packer->w <= packer->h && packer->w != w_max) + packer->w = FFMIN(packer->w * 2, w_max); + else if (packer->h != h_max) + packer->h = FFMIN(packer->h * 2, h_max); else { packer->w = w_orig; packer->h = h_orig; @@ -201,9 +207,8 @@ int packer_pack_from_subbitmaps(struct bitmap_packer *packer, if (b->format == SUBBITMAP_EMPTY) return 0; packer_set_size(packer, b->num_parts); - int a = packer->padding; for (int i = 0; i < b->num_parts; i++) - packer->in[i] = (struct pos){b->parts[i].w + a, b->parts[i].h + a}; + packer->in[i] = (struct pos){b->parts[i].w, b->parts[i].h}; return packer_pack(packer); } diff --git a/video/out/bitmap_packer.h b/video/out/bitmap_packer.h index b86c3ec4f9..8fd2fce599 100644 --- a/video/out/bitmap_packer.h +++ b/video/out/bitmap_packer.h @@ -23,7 +23,6 @@ struct bitmap_packer { int asize; }; -struct ass_image; struct sub_bitmaps; // Clear all internal state. Leave the following fields: w_max, h_max diff --git a/video/out/cocoa/events_view.m b/video/out/cocoa/events_view.m index 6fec712a33..4a0c4bfe04 100644 --- a/video/out/cocoa/events_view.m +++ b/video/out/cocoa/events_view.m @@ -358,8 +358,13 @@ { NSPasteboard *pboard = [sender draggingPasteboard]; if ([[pboard types] containsObject:NSURLPboardType]) { - NSURL *file_url = [NSURL URLFromPasteboard:pboard]; - [self.adapter handleFilesArray:@[[file_url absoluteString]]]; + NSArray *pbitems = [pboard readObjectsForClasses:@[[NSURL class]] + options:@{}]; + NSMutableArray* ar = [[[NSMutableArray alloc] init] autorelease]; + for (NSURL* url in pbitems) { + [ar addObject:[url path]]; + } + [self.adapter handleFilesArray:ar]; return YES; } else if ([[pboard types] containsObject:NSFilenamesPboardType]) { NSArray *pbitems = [pboard propertyListForType:NSFilenamesPboardType]; diff --git a/video/out/cocoa/window.m b/video/out/cocoa/window.m index 646281df79..d89e296b40 100644 --- a/video/out/cocoa/window.m +++ b/video/out/cocoa/window.m @@ -56,6 +56,11 @@ [self.adapter setNeedsResize]; } +- (void)windowDidChangeScreen:(NSNotification *)notification +{ + [self.adapter windowDidChangeScreen:notification]; +} + - (void)windowDidChangeScreenProfile:(NSNotification *)notification { [self.adapter didChangeWindowedScreenProfile:[self screen]]; diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m index 30b832da75..21e1246b1c 100644 --- a/video/out/cocoa_common.m +++ b/video/out/cocoa_common.m @@ -49,6 +49,9 @@ #include "common/msg.h" +static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, + const CVTimeStamp* outputTime, CVOptionFlags flagsIn, + CVOptionFlags* flagsOut, void* displayLinkContext); static int vo_cocoa_fullscreen(struct vo *vo); static void cocoa_rm_fs_screen_profile_observer(struct vo_cocoa_state *s); static void cocoa_add_screen_reconfiguration_observer(struct vo *vo); @@ -370,6 +373,7 @@ static void vo_cocoa_update_screens_pointers(struct vo *vo) static void vo_cocoa_update_screen_fps(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; + NSScreen *screen = vo->opts->fullscreen ? s->fs_screen : s->current_screen; NSDictionary* sinfo = [screen deviceDescription]; NSNumber* sid = [sinfo objectForKey:@"NSScreenNumber"]; @@ -377,16 +381,24 @@ static void vo_cocoa_update_screen_fps(struct vo *vo) CVDisplayLinkRef link; CVDisplayLinkCreateWithCGDisplay(did, &link); - s->screen_fps = CVDisplayLinkGetActualOutputVideoRefreshPeriod(link); + CVDisplayLinkSetOutputCallback(link, &displayLinkCallback, NULL); + CVDisplayLinkStart(link); + CVDisplayLinkSetCurrentCGDisplay(link, did); + + double display_period = CVDisplayLinkGetActualOutputVideoRefreshPeriod(link); - if (s->screen_fps == 0) { + if (display_period > 0) { + s->screen_fps = 1/display_period; + } else { // Fallback to using Nominal refresh rate from DisplayLink, // CVDisplayLinkGet *Actual* OutputVideoRefreshPeriod seems to // return 0 on some Apple devices. Use the nominal refresh period // instead. const CVTime t = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); - if (!(t.flags & kCVTimeIsIndefinite)) + if (!(t.flags & kCVTimeIsIndefinite)) { s->screen_fps = (t.timeScale / (double) t.timeValue); + MP_VERBOSE(vo, "Falling back to %f for display sync.\n", s->screen_fps); + } } CVDisplayLinkRelease(link); @@ -394,6 +406,13 @@ static void vo_cocoa_update_screen_fps(struct vo *vo) flag_events(vo, VO_EVENT_WIN_STATE); } +static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, + const CVTimeStamp* outputTime, CVOptionFlags flagsIn, + CVOptionFlags* flagsOut, void* displayLinkContext) +{ + return kCVReturnSuccess; +} + static void vo_cocoa_update_screen_info(struct vo *vo, struct mp_rect *out_rc) { struct vo_cocoa_state *s = vo->cocoa; @@ -931,6 +950,11 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg) [[EventsResponder sharedInstance] handleFilesArray:files]; } +- (void)windowDidChangeScreen:(NSNotification *)notification +{ + vo_cocoa_update_screen_info(self.vout, NULL); +} + - (void)didChangeWindowedScreenProfile:(NSScreen *)screen { flag_events(self.vout, VO_EVENT_ICC_PROFILE_CHANGED); diff --git a/video/out/drm_common.c b/video/out/drm_common.c index c105a1463f..a39db93617 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -222,7 +222,7 @@ void kms_destroy(struct kms *kms) static void vt_switcher_sighandler(int sig) { unsigned char event = sig == RELEASE_SIGNAL ? EVT_RELEASE : EVT_ACQUIRE; - write(vt_switcher_pipe[1], &event, sizeof(event)); + (void)write(vt_switcher_pipe[1], &event, sizeof(event)); } static bool has_signal_installed(int signo) @@ -312,7 +312,7 @@ void vt_switcher_release(struct vt_switcher *s, void vt_switcher_interrupt_poll(struct vt_switcher *s) { unsigned char event = EVT_INTERRUPT; - write(vt_switcher_pipe[1], &event, sizeof(event)); + (void)write(vt_switcher_pipe[1], &event, sizeof(event)); } void vt_switcher_destroy(struct vt_switcher *s) diff --git a/video/out/opengl/angle_common.c b/video/out/opengl/angle_common.c new file mode 100644 index 0000000000..21cc924714 --- /dev/null +++ b/video/out/opengl/angle_common.c @@ -0,0 +1,13 @@ +#include "angle_common.h" + +// Test if Direct3D11 can be used by us. Basically, this prevents trying to use +// D3D11 on Win7, and then failing somewhere in the process. +bool d3d11_check_decoding(ID3D11Device *dev) +{ + HRESULT hr; + // We assume that NV12 is always supported, if hw decoding is supported at + // all. + UINT supported = 0; + hr = ID3D11Device_CheckFormatSupport(dev, DXGI_FORMAT_NV12, &supported); + return !FAILED(hr) && (supported & D3D11_BIND_DECODER); +} diff --git a/video/out/opengl/angle_common.h b/video/out/opengl/angle_common.h new file mode 100644 index 0000000000..14ecd6ab3c --- /dev/null +++ b/video/out/opengl/angle_common.h @@ -0,0 +1,13 @@ +#ifndef MP_ANGLE_COMMON_H +#define MP_ANGLE_COMMON_H + +#include <initguid.h> +#include <assert.h> +#include <windows.h> +#include <d3d11.h> + +#include <stdbool.h> + +bool d3d11_check_decoding(ID3D11Device *dev); + +#endif
\ No newline at end of file diff --git a/video/out/opengl/angle_dynamic.c b/video/out/opengl/angle_dynamic.c new file mode 100644 index 0000000000..f4540c473a --- /dev/null +++ b/video/out/opengl/angle_dynamic.c @@ -0,0 +1,33 @@ +#include <pthread.h> +#include <windows.h> + +#define ANGLE_NO_ALIASES +#include "angle_dynamic.h" + +#include "common/common.h" + +#define ANGLE_DECL(NAME, VAR) \ + VAR; +ANGLE_FNS(ANGLE_DECL) + +static bool angle_loaded; +static pthread_once_t angle_load_once = PTHREAD_ONCE_INIT; + +static void angle_do_load(void) +{ + // Note: we let this handle "leak", as the functions remain valid forever. + HANDLE angle_dll = LoadLibraryW(L"LIBEGL.DLL"); + if (!angle_dll) + return; +#define ANGLE_LOAD_ENTRY(NAME, VAR) \ + MP_CONCAT(PFN_, NAME) = (void *)GetProcAddress(angle_dll, #NAME); \ + if (!MP_CONCAT(PFN_, NAME)) return; + ANGLE_FNS(ANGLE_LOAD_ENTRY) + angle_loaded = true; +} + +bool angle_load(void) +{ + pthread_once(&angle_load_once, angle_do_load); + return angle_loaded; +} diff --git a/video/out/opengl/angle_dynamic.h b/video/out/opengl/angle_dynamic.h new file mode 100644 index 0000000000..87ad85c268 --- /dev/null +++ b/video/out/opengl/angle_dynamic.h @@ -0,0 +1,82 @@ +// Based on Khronos headers, thus MIT licensed. + +#ifndef MP_ANGLE_DYNAMIC_H +#define MP_ANGLE_DYNAMIC_H + +#include <stdbool.h> + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#define ANGLE_FNS(FN) \ + FN(eglBindAPI, EGLBoolean (*EGLAPIENTRY PFN_eglBindAPI)(EGLenum)) \ + FN(eglBindTexImage, EGLBoolean (*EGLAPIENTRY PFN_eglBindTexImage) \ + (EGLDisplay, EGLSurface, EGLint)) \ + FN(eglChooseConfig, EGLBoolean (*EGLAPIENTRY PFN_eglChooseConfig) \ + (EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)) \ + FN(eglCreateContext, EGLContext (*EGLAPIENTRY PFN_eglCreateContext) \ + (EGLDisplay, EGLConfig, EGLContext, const EGLint *)) \ + FN(eglCreatePbufferFromClientBuffer, EGLSurface (*EGLAPIENTRY \ + PFN_eglCreatePbufferFromClientBuffer)(EGLDisplay, EGLenum, \ + EGLClientBuffer, EGLConfig, const EGLint *)) \ + FN(eglCreateWindowSurface, EGLSurface (*EGLAPIENTRY \ + PFN_eglCreateWindowSurface)(EGLDisplay, EGLConfig, \ + EGLNativeWindowType, const EGLint *)) \ + FN(eglDestroyContext, EGLBoolean (*EGLAPIENTRY PFN_eglDestroyContext) \ + (EGLDisplay, EGLContext)) \ + FN(eglDestroySurface, EGLBoolean (*EGLAPIENTRY PFN_eglDestroySurface) \ + (EGLDisplay, EGLSurface)) \ + FN(eglGetConfigAttrib, EGLBoolean (*EGLAPIENTRY PFN_eglGetConfigAttrib) \ + (EGLDisplay, EGLConfig, EGLint, EGLint *)) \ + FN(eglGetCurrentContext, EGLContext (*EGLAPIENTRY \ + PFN_eglGetCurrentContext)(void)) \ + FN(eglGetCurrentDisplay, EGLDisplay (*EGLAPIENTRY \ + PFN_eglGetCurrentDisplay)(void)) \ + FN(eglGetDisplay, EGLDisplay (*EGLAPIENTRY PFN_eglGetDisplay) \ + (EGLNativeDisplayType)) \ + FN(eglGetError, EGLint (*EGLAPIENTRY PFN_eglGetError)(void)) \ + FN(eglGetProcAddress, void *(*EGLAPIENTRY \ + PFN_eglGetProcAddress)(const char *)) \ + FN(eglInitialize, EGLBoolean (*EGLAPIENTRY PFN_eglInitialize) \ + (EGLDisplay, EGLint *, EGLint *)) \ + FN(eglMakeCurrent, EGLBoolean (*EGLAPIENTRY PFN_eglMakeCurrent) \ + (EGLDisplay, EGLSurface, EGLSurface, EGLContext)) \ + FN(eglQueryString, const char *(*EGLAPIENTRY PFN_eglQueryString) \ + (EGLDisplay, EGLint)) \ + FN(eglSwapBuffers, EGLBoolean (*EGLAPIENTRY PFN_eglSwapBuffers) \ + (EGLDisplay, EGLSurface)) \ + FN(eglReleaseTexImage, EGLBoolean (*EGLAPIENTRY PFN_eglReleaseTexImage) \ + (EGLDisplay, EGLSurface, EGLint)) \ + FN(eglTerminate, EGLBoolean (*EGLAPIENTRY PFN_eglTerminate)(EGLDisplay)) + +#define ANGLE_EXT_DECL(NAME, VAR) \ + extern VAR; +ANGLE_FNS(ANGLE_EXT_DECL) + +bool angle_load(void); + +// Source compatibility to statically linked ANGLE. +#ifndef ANGLE_NO_ALIASES +#define eglBindAPI PFN_eglBindAPI +#define eglBindTexImage PFN_eglBindTexImage +#define eglChooseConfig PFN_eglChooseConfig +#define eglCreateContext PFN_eglCreateContext +#define eglCreatePbufferFromClientBuffer PFN_eglCreatePbufferFromClientBuffer +#define eglCreateWindowSurface PFN_eglCreateWindowSurface +#define eglDestroyContext PFN_eglDestroyContext +#define eglDestroySurface PFN_eglDestroySurface +#define eglGetConfigAttrib PFN_eglGetConfigAttrib +#define eglGetCurrentContext PFN_eglGetCurrentContext +#define eglGetCurrentDisplay PFN_eglGetCurrentDisplay +#define eglGetDisplay PFN_eglGetDisplay +#define eglGetError PFN_eglGetError +#define eglGetProcAddress PFN_eglGetProcAddress +#define eglInitialize PFN_eglInitialize +#define eglMakeCurrent PFN_eglMakeCurrent +#define eglQueryString PFN_eglQueryString +#define eglReleaseTexImage PFN_eglReleaseTexImage +#define eglSwapBuffers PFN_eglSwapBuffers +#define eglTerminate PFN_eglTerminate +#endif + +#endif diff --git a/video/out/opengl/common.c b/video/out/opengl/common.c index 46cbc2fc8c..dd44165b81 100644 --- a/video/out/opengl/common.c +++ b/video/out/opengl/common.c @@ -72,6 +72,8 @@ struct gl_functions { int provides; // bitfield of MPGL_CAP_* constants int ver_core; // introduced as required function int ver_es_core; // introduced as required GL ES function + int ver_exclude; // not applicable to versions >= ver_exclude + int ver_es_exclude; // same for GLES const struct gl_function *functions; }; @@ -144,15 +146,23 @@ static const struct gl_functions gl_functions[] = { .ver_core = 210, |