summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/client-api-changes.rst13
-rw-r--r--DOCS/interface-changes.rst2
-rw-r--r--DOCS/man/options.rst3
-rw-r--r--DOCS/man/vo.rst9
-rw-r--r--libmpv/client.h13
-rw-r--r--libmpv/mpv.def6
-rw-r--r--libmpv/opengl_cb.h11
-rw-r--r--libmpv/render.h309
-rw-r--r--libmpv/render_gl.h155
-rw-r--r--player/client.c164
-rw-r--r--player/client.h19
-rw-r--r--player/core.h2
-rw-r--r--player/main.c3
-rw-r--r--player/playloop.c1
-rw-r--r--player/video.c1
-rw-r--r--video/out/gpu/libmpv_gpu.c182
-rw-r--r--video/out/gpu/libmpv_gpu.h38
-rw-r--r--video/out/libmpv.h72
-rw-r--r--video/out/opengl/libmpv_gl.c113
-rw-r--r--video/out/vo.c9
-rw-r--r--video/out/vo.h1
-rw-r--r--video/out/vo_libmpv.c (renamed from video/out/vo_opengl_cb.c)425
-rw-r--r--wscript_build.py4
23 files changed, 1267 insertions, 288 deletions
diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst
index df2b42aa70..845953580a 100644
--- a/DOCS/client-api-changes.rst
+++ b/DOCS/client-api-changes.rst
@@ -33,6 +33,19 @@ API changes
::
--- mpv 0.29.0 ---
+ 1.28 - deprecate the render opengl_cb API, and replace it with render.h
+ and render_gl.h. The goal is allowing support for APIs other than
+ OpenGL. The old API is emulated with the new API.
+ Likewise, the "opengl-cb" VO is renamed to "libmpv".
+ mpv_get_sub_api() is deprecated along the opengl_cb API.
+ The new API is relatively similar, but not the same. The rough
+ equivalents are:
+ mpv_opengl_cb_init_gl => mpv_render_context_create
+ mpv_opengl_cb_set_update_callback => mpv_render_context_set_update_callback
+ mpv_opengl_cb_draw => mpv_render_context_render
+ mpv_opengl_cb_report_flip => mpv_render_context_report_swap
+ mpv_opengl_cb_uninit_gl => mpv_render_context_free
+ The VO opengl-cb is also renamed to "libmpv".
1.27 - make opengl-cb the default VO. This causes a subtle behavior change
if the API user called mpv_opengl_cb_init_gl(), but does not set
the "vo" option. Before, it would still have used another VO (like
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index e18fec4c1d..5830b413e0 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -72,6 +72,8 @@ Interface changes
will probably stall.
- deprecate the OpenGL cocoa backend, option choice --gpu-context=cocoa
when used with --gpu-api=opengl (use --vo=opengl-cb)
+ - rename --vo=opengl-cb to --vo=libmpv (goes in hand with the opengl-cb
+ API deprecation, see client-api-changes.rst)
- make --deinterlace=yes always deinterlace, instead of trying to check
certain unreliable video metadata. Also flip the defaults of all builtin
HW deinterlace filters to always deinterlace.
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 8246dd0f49..2716302e72 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -5221,6 +5221,9 @@ The following video options are currently all specific to ``--vo=gpu`` and
NOTE: On Windows, the default profile must be an ICC profile. WCS profiles
are not supported.
+ Applications using libmpv with the render API need to provide the ICC
+ profile via ``MPV_RENDER_PARAM_ICC_PROFILE``.
+
``--icc-cache-dir=<dirname>``
Store and load the 3D LUTs created from the ICC profile in this directory.
This can be used to speed up loading, since LittleCMS 2 can take a while to
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst
index 8e8b9803be..672f3c68f6 100644
--- a/DOCS/man/vo.rst
+++ b/DOCS/man/vo.rst
@@ -428,13 +428,14 @@ Available video output drivers are:
``--vo-image-outdir=<dirname>``
Specify the directory to save the image files to (default: ``./``).
-``opengl-cb``
- For use with libmpv direct OpenGL embedding. As a special case, on OS X it
+``libmpv``
+ For use with libmpv direct embedding. As a special case, on OS X it
is used like a normal VO within mpv (cocoa-cb). Otherwise useless in any
other contexts.
- (See ``<mpv/opengl_cb.h>``.)
+ (See ``<mpv/render.h>``.)
- This also supports many of the options the ``gpu`` VO has.
+ This also supports many of the options the ``gpu`` VO has, depending on the
+ backend.
``rpi`` (Raspberry Pi)
Native video output on the Raspberry Pi using the MMAL API.
diff --git a/libmpv/client.h b/libmpv/client.h
index 424bf0613d..07237c9d4d 100644
--- a/libmpv/client.h
+++ b/libmpv/client.h
@@ -210,7 +210,7 @@ extern "C" {
* relational operators (<, >, <=, >=).
*/
#define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
-#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 27)
+#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 28)
/**
* The API user is allowed to "#define MPV_ENABLE_DEPRECATED 0" before
@@ -1691,6 +1691,11 @@ int mpv_get_wakeup_pipe(mpv_handle *ctx);
*/
void mpv_wait_async_requests(mpv_handle *ctx);
+#if MPV_ENABLE_DEPRECATED
+
+/**
+ * @deprecated use render.h
+ */
typedef enum mpv_sub_api {
/**
* For using mpv's OpenGL renderer on an external OpenGL context.
@@ -1698,6 +1703,8 @@ typedef enum mpv_sub_api {
* This context can be used with mpv_opengl_cb_* functions.
* Will return NULL if unavailable (if OpenGL support was not compiled in).
* See opengl_cb.h for details.
+ *
+ * @deprecated use render.h
*/
MPV_SUB_API_OPENGL_CB = 1
} mpv_sub_api;
@@ -1705,9 +1712,13 @@ typedef enum mpv_sub_api {
/**
* This is used for additional APIs that are not strictly part of the core API.
* See the individual mpv_sub_api member values.
+ *
+ * @deprecated use render.h
*/
void *mpv_get_sub_api(mpv_handle *ctx, mpv_sub_api sub_api);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/libmpv/mpv.def b/libmpv/mpv.def
index 0384c7db9d..5299f69c9a 100644
--- a/libmpv/mpv.def
+++ b/libmpv/mpv.def
@@ -28,6 +28,12 @@ mpv_opengl_cb_report_flip
mpv_opengl_cb_render
mpv_opengl_cb_set_update_callback
mpv_opengl_cb_uninit_gl
+mpv_render_context_create
+mpv_render_context_free
+mpv_render_context_render
+mpv_render_context_report_swap
+mpv_render_context_set_parameter
+mpv_render_context_set_update_callback
mpv_request_event
mpv_request_log_messages
mpv_resume
diff --git a/libmpv/opengl_cb.h b/libmpv/opengl_cb.h
index 384372b617..ce88a8570a 100644
--- a/libmpv/opengl_cb.h
+++ b/libmpv/opengl_cb.h
@@ -18,6 +18,10 @@
#include "client.h"
+#if !MPV_ENABLE_DEPRECATED
+#error "This header and all API provided by it is deprecated. Use render.h instead."
+#else
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -27,6 +31,9 @@ extern "C" {
* Overview
* --------
*
+ * Warning: this API is deprecated. A very similar API is provided by render.h
+ * and render_gl.h. The deprecated API is emulated with the new API.
+ *
* This API can be used to make mpv render into a foreign OpenGL context. It
* can be used to handle video display.
*
@@ -328,7 +335,6 @@ int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts,
*/
int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h);
-#if MPV_ENABLE_DEPRECATED
/**
* Deprecated. Use mpv_opengl_cb_draw(). This function is equivalent to:
*
@@ -341,7 +347,6 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h);
* was never marked as stable).
*/
int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4]);
-#endif
/**
* Tell the renderer that a frame was flipped at the given time. This is
@@ -375,4 +380,6 @@ int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx);
}
#endif
+#endif /* else #if MPV_ENABLE_DEPRECATED */
+
#endif
diff --git a/libmpv/render.h b/libmpv/render.h
new file mode 100644
index 0000000000..64a317d73c
--- /dev/null
+++ b/libmpv/render.h
@@ -0,0 +1,309 @@
+/* Copyright (C) 2018 the mpv developers
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MPV_CLIENT_API_RENDER_H_
+#define MPV_CLIENT_API_RENDER_H_
+
+#include "client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Overview
+ * --------
+ *
+ * This API can be used to make mpv render using supported graphic APIs (such
+ * as OpenGL). It can be used to handle video display.
+ *
+ * The renderer needs to be created with mpv_render_context_create() before
+ * you start playback (or otherwise cause a VO to be created). Then (with most
+ * backends) mpv_render_context_render() can be used to explicitly render the
+ * current video frame. Use mpv_render_context_set_update_callback() to get
+ * notified when there is a new frame to draw.
+ *
+ * Preferably rendering should be done in a separate thread. If you call
+ * normal libmpv API functions on the renderer thread, deadlocks can result
+ * (these are made non-fatal with timeouts, but user experience will obviously
+ * suffer).
+ *
+ * You can output and embed video without this API by setting the mpv "wid"
+ * option to a native window handle (see "Embedding the video window" section
+ * in the client.h header). In general, using the render API is recommended,
+ * because window embedding can cause various issues, especially with GUI
+ * toolkits and certain platforms.
+ *
+ * Supported backends
+ * ------------------
+ *
+ * OpenGL: via MPV_RENDER_API_TYPE_OPENGL, see render_gl.h header.
+ *
+ * Threading
+ * ---------
+ *
+ * The mpv_render_* functions can be called from any thread, under the
+ * following conditions:
+ * - only one of the mpv_render_* functions can be called at the same time
+ * (unless they belong to different mpv cores created by mpv_create())
+ * - never can be called from within the callbacks set with
+ * mpv_set_wakeup_callback() or mpv_render_context_set_update_callback()
+ * - if the OpenGL backend is used, for all functions the OpenGL context
+ * must be "current" in the calling thread, and it must be the same OpenGL
+ * context as the mpv_render_context was created with. Otherwise, undefined
+ * behavior will occur.
+ *
+ * Context and handle lifecycle
+ * ----------------------------
+ *
+ * Video initialization will fail if the render context was not initialized yet
+ * (with mpv_render_context_create()), or it will revert to a VO that creates
+ * its own window.
+ *
+ * Calling mpv_render_context_free() while a VO is using the render context is
+ * active will disable video.
+ *
+ * You must free the context with mpv_render_context_free() before the mpv core
+ * is destroyed. If this doesn't happen, undefined behavior will result.
+ */
+
+/**
+ * Opaque context, returned by mpv_render_context_create().
+ */
+typedef struct mpv_render_context mpv_render_context;
+
+/**
+ * Parameters for mpv_render_param (which is used in a few places such as
+ * mpv_render_context_create().
+ *
+ * Also see mpv_render_param for conventions and how to use it.
+ */
+typedef enum mpv_render_param_type {
+ /**
+ * Not a valid value, but also used to terminate a params array. Its value
+ * is always guaranteed to be 0 (even if the ABI changes in the future).
+ */
+ MPV_RENDER_PARAM_INVALID = 0,
+ /**
+ * The render API to use. Valid for mpv_render_context_create().
+ *
+ * Type: char*
+ *
+ * Defined APIs:
+ *
+ * MPV_RENDER_API_TYPE_OPENGL:
+ * OpenGL desktop 2.1 or later (preferably core profile compatible to
+ * OpenGL 3.2), or OpenGLES 2.0 or later.
+ * Providing MPV_RENDER_PARAM_OPENGL_INIT_PARAMS is required.
+ * It is expected that an OpenGL context is valid and "current" when
+ * calling mpv_render_* functions (unless specified otherwise). It
+ * must be the same context for the same mpv_render_context.
+ */
+ MPV_RENDER_PARAM_API_TYPE = 1,
+ /**
+ * Required parameters for initializing the OpenGL renderer. Valid for
+ * mpv_render_context_create().
+ * Type: mpv_opengl_init_params*
+ */
+ MPV_RENDER_PARAM_OPENGL_INIT_PARAMS = 2,
+ /**
+ * Describes a GL render target. Valid for mpv_render_context_render().
+ * Type: mpv_opengl_fbo*
+ */
+ MPV_RENDER_PARAM_OPENGL_FBO = 3,
+ /**
+ * Control flipped rendering. Valid for mpv_render_context_render().
+ * Type: int*
+ * If the value is set to 0, render normally. Otherwise, render it flipped,
+ * which is needed e.g. when rendering to an OpenGL default framebuffer
+ * (which has a flipped coordinate system).
+ */
+ MPV_RENDER_PARAM_FLIP_Y = 4,
+ /**
+ * Control surface depth. Valid for mpv_render_context_render().
+ * Type: int*
+ * This implies the depth of the surface passed to the render function in
+ * bits per channel. If omitted or set to 0, the renderer will assume 8.
+ * Typically used to control dithering.
+ */
+ MPV_RENDER_PARAM_DEPTH = 5,
+ /**
+ * ICC profile blob. Valid for mpv_render_context_set_parameter().
+ * Type: mpv_byte_array*
+ * Set an ICC profile for use with the "icc-profile-auto" option. (If the
+ * option is not enabled, the ICC data will not be used.)
+ */
+ MPV_RENDER_PARAM_ICC_PROFILE = 6,
+ /**
+ * Ambient light in lux. Valid for mpv_render_context_set_parameter().
+ * Type: int*
+ * This can be used for automatic gamma correction.
+ */
+ MPV_RENDER_PARAM_AMBIENT_LIGHT = 7,
+} mpv_render_param_type;
+
+/**
+ * Predefined values for MPV_RENDER_PARAM_API_TYPE.
+ */
+#define MPV_RENDER_API_TYPE_OPENGL "opengl"
+
+/**
+ * Used to pass arbitrary parameters to some mpv_render_* functions. The
+ * meaning of the data parameter is determined by the type, and each
+ * MPV_RENDER_PARAM_* documents what type the value must point to.
+ *
+ * Each value documents the required data type as the pointer you cast to
+ * void* and set on mpv_render_param.data. For example, if MPV_RENDER_PARAM_FOO
+ * documents the type as Something* , then the code should look like this:
+ *
+ * Something foo = {...};
+ * mpv_render_param param;
+ * param.type = MPV_RENDER_PARAM_FOO;
+ * param.data = & foo;
+ *
+ * Normally, the data field points to exactly 1 object. If the type is char*,
+ * it points to a 0-terminated string.
+ *
+ * In all cases (unless documented otherwise) the pointers need to remain
+ * valid during the call only. Unless otherwise documented, the API functions
+ * will not write to the params array or any data pointed to it.
+ *
+ * As a convention, parameter arrays are always terminated by type==0. There
+ * is no specific order of the parameters required. The order of fields is
+ * guaranteed (even after ABI changes).
+ */
+typedef struct mpv_render_param {
+ enum mpv_render_param_type type;
+ void *data;
+} mpv_render_param;
+
+/**
+ * Initialize the renderer state. Depending on the backend used, this will
+ * access the underlying GPU API and initialize its own objects.
+ *
+ * You must free the context with mpv_render_context_free(). Not doing so before
+ * the mpv core is destroyed may result in memory leaks or crashes.
+ *
+ * Currently, only at most 1 context can exists per mpv core (it represents the
+ * main video output).
+ *
+ * @param res set to the context (on success) or NULL (on failure). The value
+ * is never read and always overwritten.
+ * @param mpv handle used to get the core (the mpv_render_context won't depend
+ * on this specific handle, only the core referenced by it)
+ * @param params an array of parameters, terminated by type==0. It's left
+ * unspecified what happens with unknown parameters. At least
+ * MPV_RENDER_PARAM_API_TYPE is required, and most backends will
+ * require another backend-specific parameter.
+ * @return error code, including but not limited to:
+ * MPV_ERROR_UNSUPPORTED: the OpenGL version is not supported
+ * (or required extensions are missing)
+ * MPV_ERROR_NOT_IMPLEMENTED: an unknown API type was provided, or
+ * support for the requested API was not
+ * built in the used libmpv binary.
+ * MPV_ERROR_INVALID_PARAMETER: at least one of the provided parameters was
+ * not valid.
+ */
+int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv,
+ mpv_render_param *params);
+
+/**
+ * Attempt to change a single parameter. Not all backends and parameter types
+ * support all kinds of changes.
+ *
+ * @param ctx a valid render context
+ * @param param the parameter type and data that should be set
+ * @return error code. If a parameter could actually be changed, this returns
+ * success, otherwise an error code depending on the parameter type
+ * and situation.
+ */
+int mpv_render_context_set_parameter(mpv_render_context *ctx,
+ mpv_render_param param);
+
+typedef void (*mpv_render_update_fn)(void *cb_ctx);
+
+/**
+ * Set the callback that notifies you when a new video frame is available, or
+ * if the video display configuration somehow changed and requires a redraw.
+ * Similar to mpv_set_wakeup_callback(), you must not call any mpv API from
+ * the callback, and all the other listed restrictions apply (such as not
+ * exiting the callback by throwing exceptions).
+ *
+ * This can be called from any thread, except from an update callback. In case
+ * of the OpenGL backend, no OpenGL state or API is accessed.
+ *
+ * @param callback callback(callback_ctx) is called if the frame should be
+ * redrawn
+ * @param callback_ctx opaque argument to the callback
+ */
+void mpv_render_context_set_update_callback(mpv_render_context *ctx,
+ mpv_render_update_fn callback,
+ void *callback_ctx);
+
+/**
+ * Render video.
+ *
+ * Typically renders the video to a target surface provided via mpv_render_param
+ * (the details depend on the backend in use). Options like "panscan" are
+ * applied to determine which part of the video should be visible and how the
+ * video should be scaled. You can change these options at runtime by using the
+ * mpv property API.
+ *
+ * The renderer will reconfigure itself every time the target surface
+ * configuration (such as size) is changed.
+ *
+ * This function implicitly pulls a video frame from the internal queue and
+ * renders it. If no new frame is available, the previous frame is redrawn.
+ * The update callback set with mpv_render_context_set_update_callback()
+ * notifies you when a new frame was added. The details potentially depend on
+ * the backends and the provided parameters.
+ *
+ * @param ctx a valid render context
+ * @param params an array of parameters, terminated by type==0. Which parameters
+ * are required depends on the backend. It's left unspecified what
+ * happens with unknown parameters.
+ * @return error code
+ */
+int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params);
+
+/**
+ * Tell the renderer that a frame was flipped at the given time. This is
+ * optional, but can help the player to achieve better timing.
+ *
+ * Note that calling this at least once informs libmpv that you will use this
+ * function. If you use it inconsistently, expect bad video playback.
+ *
+ * If this is called while no video is initialized, it is ignored.
+ *
+ * @param ctx a valid render context
+ */
+void mpv_render_context_report_swap(mpv_render_context *ctx);
+
+/**
+ * Destroy the mpv renderer state.
+ *
+ * If video is still active (e.g. a file playing), video will be disabled
+ * forcefully.
+ *
+ * @param ctx a valid render context. After this function returns, this is not
+ * a valid pointer anymore. NULL is also allowed and does nothing.
+ */
+void mpv_render_context_free(mpv_render_context *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmpv/render_gl.h b/libmpv/render_gl.h
new file mode 100644
index 0000000000..01c09e80df
--- /dev/null
+++ b/libmpv/render_gl.h
@@ -0,0 +1,155 @@
+/* Copyright (C) 2018 the mpv developers
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MPV_CLIENT_API_RENDER_GL_H_
+#define MPV_CLIENT_API_RENDER_GL_H_
+
+#include "render.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * OpenGL backend
+ * --------------
+ *
+ * This header contains definitions for using OpenGL with the render.h API.
+ *
+ * OpenGL interop
+ * --------------
+ *
+ * The OpenGL backend has some special rules, because OpenGL itself uses
+ * implicit per-thread contexts, which causes additional API problems.
+ *
+ * This assumes the OpenGL context lives on a certain thread controlled by the
+ * API user. All mpv_render_* APIs have to be assumed to implicitly use the
+ * OpenGL context if you pass a mpv_render_context using the OpenGL backend,
+ * unless specified otherwise.
+ *
+ * The OpenGL context is indirectly accessed through the OpenGL function
+ * pointers returned by the get_proc_address callback in mpv_opengl_init_params.
+ * Generally, mpv will not load the system OpenGL library when using this API.
+ *
+ * OpenGL state
+ * ------------
+ *
+ * OpenGL has a large amount of implicit state. All the mpv functions mentioned
+ * above expect that the OpenGL state is reasonably set to OpenGL standard
+ * defaults. Likewise, mpv will attempt to leave the OpenGL context with
+ * standard defaults. The following state is excluded from this:
+ *
+ * - the glViewport state
+ * - the glScissor state (but GL_SCISSOR_TEST is in its default value)
+ * - glBlendFuncSeparate() state (but GL_BLEND is in its default value)
+ * - glClearColor() state
+ * - mpv may overwrite the callback set with glDebugMessageCallback()
+ * - mpv always disables GL_DITHER at init
+ *
+ * Messing with the state could be avoided by creating shared OpenGL contexts,
+ * but this is avoided for the sake of compatibility and interoperability.
+ *
+ * On OpenGL 2.1, mpv will strictly call functions like glGenTextures() to
+ * create OpenGL objects. You will have to do the same. This ensures that
+ * objects created by mpv and the API users don't clash. Also, legacy state
+ * must be either in its defaults, or not interfere with core state.
+ *
+ * API use
+ * -------
+ *
+ * The mpv_render_* API is used. That API supports multiple backends, and this
+ * section documents specifics for the OpenGL backend.
+ *
+ * Use mpv_render_context_create() with MPV_RENDER_PARAM_API_TYPE set to
+ * MPV_RENDER_API_TYPE_OPENGL, and MPV_RENDER_PARAM_OPENGL_INIT_PARAMS provided.
+ *
+ * Call mpv_render_context_render() with MPV_RENDER_PARAM_OPENGL_FBO to render
+ * the video frame to an FBO.
+ *
+ * Hardware decoding
+ * -----------------
+ *
+ * Hardware decoding via this API is fully supported, but requires some
+ * additional setup. (At least if direct hardware decoding modes are wanted,
+ * instead of copying back surface data from GPU to CPU RAM.)
+ *
+ * There may be certain requirements on the OpenGL implementation:
+ *
+ * - Windows: ANGLE is required (although in theory GL/DX interop could be used)
+ * - Intel/Linux: EGL is required, and also a glMPGetNativeDisplay() callback
+ * must be provided (see sections below)
+ * - nVidia/Linux: Both GLX and EGL should work (GLX is required if vdpau is
+ * used, e.g. due to old drivers.)
+ * - OSX: CGL is required (CGLGetCurrentContext() returning non-NULL)
+ * - iOS: EAGL is required (EAGLContext.currentContext returning non-nil)
+ *
+ * Once these things are setup, hardware decoding can be enabled/disabled at
+ * any time by setting the "hwdec" property.
+ */
+
+/**
+ * For initializing the mpv OpenGL state via MPV_RENDER_PARAM_OPENGL_INIT_PARAMS.
+ */
+typedef struct mpv_opengl_init_params {
+ /**
+ * This retrieves OpenGL function pointers, and will use them in subsequent
+ * operation.
+ * Usually, GL context APIs do this for you (e.g. with glXGetProcAddressARB
+ * or wglGetProcAddress), but some APIs do not always return pointers for
+ * all standard functions (even if present); in this case you have to
+ * compensate by looking up these functions yourself and returning them
+ * from this callback.
+ */
+ void *(*get_proc_address)(void *ctx, const char *name);
+ /**
+ * Value passed as ctx parameter to get_proc_address().
+ */
+ void *get_proc_address_ctx;
+ /**
+ * This should not be used. The main purpose is signaling support for
+ * "GL_MP_MPGetNativeDisplay", which is needed for compatibility with the
+ * opengl_cb API only. Thus it's deprecated and will be removed or ignored
+ * when the opengl_cb API is removed.
+ */
+ const char *extra_exts;
+} mpv_opengl_init_params;
+
+/**
+ * For MPV_RENDER_PARAM_OPENGL_FBO.
+ */
+typedef struct mpv_opengl_fbo {
+ /**
+ * Framebuffer object name. This must be either a valid FBO generated by
+ * glGenFramebuffers() that is complete and color-renderable, or 0. If the
+ * value is 0, this refers to the OpenGL default framebuffer.
+ */
+ int fbo;
+ /**
+ * Valid dimensions. This must refer to the size of the framebuffer. This
+ * must always be set.
+ */
+ int w, h;
+ /**
+ * Underlying texture internal format (e.g. GL_RGBA8), or 0 if unknown. If
+ * this is the default framebuffer, this can be an equivalent.
+ */
+ int internal_format;
+} mpv_opengl_fbo;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/player/client.c b/player/client.c
index 1df7e659d8..45af55bee9 100644
--- a/player/client.c
+++ b/player/client.c
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include <errno.h>
#include <locale.h>
+#include <math.h>
#include <assert.h>
#include "common/common.h"
@@ -46,8 +47,6 @@
#include "core.h"
#include "client.h"
-#include "config.h"
-
/*
* Locking hierarchy:
*
@@ -74,6 +73,9 @@ struct mp_client_api {
struct mp_custom_protocol *custom_protocols;
int num_custom_protocols;
+
+ struct mpv_render_context *render_context;
+ struct mpv_opengl_cb_context *gl_cb_ctx;
};
struct observe_property {
@@ -156,6 +158,16 @@ void mp_clients_destroy(struct MPContext *mpctx)
if (!mpctx->clients)
return;
assert(mpctx->clients->num_clients == 0);
+
+ TA_FREEP(&mpctx->clients->gl_cb_ctx);
+
+ // The API user is supposed to call mpv_render_context_free(). It's simply
+ // not allowed not to do this.
+ if (mpctx->clients->render_context) {
+ MP_FATAL(mpctx, "Broken API use: mpv_render_context_free() not called.\n");
+ abort();
+ }
+
pthread_mutex_destroy(&mpctx->clients->lock);
talloc_free(mpctx->clients);
mpctx->clients = NULL;
@@ -279,6 +291,11 @@ struct mp_log *mp_client_get_log(struct mpv_handle *ctx)
return ctx->log;
}
+struct mpv_global *mp_client_get_global(struct mpv_handle *ctx)
+{
+ return ctx->mpctx->global;
+}
+
struct MPContext *mp_client_get_core(struct mpv_handle *ctx)
{
return ctx->mpctx;
@@ -1672,7 +1689,9 @@ int64_t mpv_get_time_us(mpv_handle *ctx)
return mp_time_us();
}
-// Used by vo_opengl_cb to synchronously uninitialize video.
+#include "video/out/libmpv.h"
+
+// Used by vo_libmpv to synchronously uninitialize video.
void kill_video(struct mp_client_api *client_api)
{
struct MPContext *mpctx = client_api->mpctx;
@@ -1686,58 +1705,163 @@ void kill_video(struct mp_client_api *client_api)
mp_dispatch_unlock(mpctx->dispatch);
}
+// Used by vo_libmpv to set the current render context.
+bool mp_set_main_render_context(struct mp_client_api *client_api,
+ struct mpv_render_context *ctx, bool active)
+{
+ assert(ctx);
+
+ pthread_mutex_lock(&client_api->lock);
+ bool is_set = !!client_api->render_context;
+ bool is_same = client_api->render_context == ctx;
+ // Can set if it doesn't remove another existing ctx.
+ bool res = is_same || !is_set;
+ if (res)
+ client_api->render_context = active ? ctx : NULL;
+ pthread_mutex_unlock(&client_api->lock);
+ return res;
+}
+
+// Used by vo_libmpv. Relies on guarantees by mp_render_context_acquire().
+struct mpv_render_context *
+mp_client_api_acquire_render_context(struct mp_client_api *ca)
+{
+ struct mpv_render_context *res = NULL;
+ pthread_mutex_lock(&ca->lock);
+ if (ca->render_context && mp_render_context_acquire(ca->render_context))
+ res = ca->render_context;
+ pthread_mutex_unlock(&ca->lock);
+ return res;
+}
+
+// Emulation of old opengl_cb API.
+
#include "libmpv/opengl_cb.h"
+#include "libmpv/render_gl.h"
+
+struct mpv_opengl_cb_context {
+ struct mp_client_api *client_api;
+ mpv_opengl_cb_update_fn callback;
+ void *callback_ctx;
+};
-#if HAVE_GL
static mpv_opengl_cb_context *opengl_cb_get_context(mpv_handle *ctx)
{
- mpv_opengl_cb_context *cb = ctx->mpctx->gl_cb_ctx;
+ pthread_mutex_lock(&ctx->clients->lock);
+ mpv_opengl_cb_context *cb = ctx->clients->gl_cb_ctx;
if (!cb) {
- cb = mp_opengl_create(ctx->mpctx->global, ctx->clients);
- ctx->mpctx->gl_cb_ctx = cb;
+ cb = talloc_zero(NULL, struct mpv_opengl_cb_context);
+ cb->client_api = ctx->clients;
+ cb->client_api->gl_cb_ctx = cb;
}
+ pthread_mutex_unlock(&ctx->clients->lock);
return cb;
}
-#else
-static mpv_opengl_cb_context *opengl_c