diff options
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/opengl/hwdec.c | 144 | ||||
-rw-r--r-- | video/out/opengl/hwdec.h | 122 | ||||
-rw-r--r-- | video/out/opengl/hwdec_cuda.c | 168 | ||||
-rw-r--r-- | video/out/opengl/hwdec_d3d11egl.c | 185 | ||||
-rw-r--r-- | video/out/opengl/hwdec_d3d11eglrgb.c | 142 | ||||
-rw-r--r-- | video/out/opengl/hwdec_dxva2egl.c | 226 | ||||
-rw-r--r-- | video/out/opengl/hwdec_dxva2gldx.c | 187 | ||||
-rw-r--r-- | video/out/opengl/hwdec_ios.m | 209 | ||||
-rw-r--r-- | video/out/opengl/hwdec_osx.c | 154 | ||||
-rw-r--r-- | video/out/opengl/hwdec_rpi.c | 58 | ||||
-rw-r--r-- | video/out/opengl/hwdec_vaegl.c | 291 | ||||
-rw-r--r-- | video/out/opengl/hwdec_vaglx.c | 163 | ||||
-rw-r--r-- | video/out/opengl/hwdec_vdpau.c | 264 | ||||
-rw-r--r-- | video/out/opengl/ra_gl.c | 147 | ||||
-rw-r--r-- | video/out/opengl/ra_gl.h | 12 | ||||
-rw-r--r-- | video/out/opengl/video.c | 73 | ||||
-rw-r--r-- | video/out/opengl/video.h | 4 | ||||
-rw-r--r-- | video/out/vo_opengl.c | 8 | ||||
-rw-r--r-- | video/out/vo_opengl_cb.c | 6 |
19 files changed, 1425 insertions, 1138 deletions
diff --git a/video/out/opengl/hwdec.c b/video/out/opengl/hwdec.c index c9256c9c5b..5fbc1aa4a9 100644 --- a/video/out/opengl/hwdec.c +++ b/video/out/opengl/hwdec.c @@ -25,84 +25,85 @@ #include "options/m_config.h" #include "hwdec.h" -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_d3d11egl; -extern const struct gl_hwdec_driver gl_hwdec_d3d11eglrgb; -extern const struct gl_hwdec_driver gl_hwdec_dxva2gldx; -extern const struct gl_hwdec_driver gl_hwdec_dxva2; -extern const struct gl_hwdec_driver gl_hwdec_cuda; -extern const struct gl_hwdec_driver gl_hwdec_rpi_overlay; - -static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = { +extern const struct ra_hwdec_driver ra_hwdec_vaegl; +extern const struct ra_hwdec_driver ra_hwdec_vaglx; +extern const struct ra_hwdec_driver ra_hwdec_videotoolbox; +extern const struct ra_hwdec_driver ra_hwdec_vdpau; +extern const struct ra_hwdec_driver ra_hwdec_dxva2egl; +extern const struct ra_hwdec_driver ra_hwdec_d3d11egl; +extern const struct ra_hwdec_driver ra_hwdec_d3d11eglrgb; +extern const struct ra_hwdec_driver ra_hwdec_dxva2gldx; +extern const struct ra_hwdec_driver ra_hwdec_dxva2; +extern const struct ra_hwdec_driver ra_hwdec_cuda; +extern const struct ra_hwdec_driver ra_hwdec_rpi_overlay; + +static const struct ra_hwdec_driver *const mpgl_hwdec_drivers[] = { #if HAVE_VAAPI_EGL - &gl_hwdec_vaegl, + &ra_hwdec_vaegl, #endif #if HAVE_VAAPI_GLX - &gl_hwdec_vaglx, + &ra_hwdec_vaglx, #endif #if HAVE_VDPAU_GL_X11 - &gl_hwdec_vdpau, + &ra_hwdec_vdpau, #endif #if HAVE_VIDEOTOOLBOX_GL || HAVE_IOS_GL - &gl_hwdec_videotoolbox, + &ra_hwdec_videotoolbox, #endif #if HAVE_D3D_HWACCEL - &gl_hwdec_d3d11egl, - &gl_hwdec_d3d11eglrgb, + &ra_hwdec_d3d11egl, + &ra_hwdec_d3d11eglrgb, #if HAVE_D3D9_HWACCEL - &gl_hwdec_dxva2egl, + &ra_hwdec_dxva2egl, #endif #endif #if HAVE_GL_DXINTEROP_D3D9 - &gl_hwdec_dxva2gldx, + &ra_hwdec_dxva2gldx, #endif #if HAVE_CUDA_HWACCEL - &gl_hwdec_cuda, + &ra_hwdec_cuda, #endif #if HAVE_RPI - &gl_hwdec_rpi_overlay, + &ra_hwdec_rpi_overlay, #endif NULL }; -static struct gl_hwdec *load_hwdec_driver(struct mp_log *log, GL *gl, +static struct ra_hwdec *load_hwdec_driver(struct mp_log *log, struct ra *ra, struct mpv_global *global, struct mp_hwdec_devices *devs, - const struct gl_hwdec_driver *drv, + const struct ra_hwdec_driver *drv, bool is_auto) { - struct gl_hwdec *hwdec = talloc(NULL, struct gl_hwdec); - *hwdec = (struct gl_hwdec) { + struct ra_hwdec *hwdec = talloc(NULL, struct ra_hwdec); + *hwdec = (struct ra_hwdec) { .driver = drv, .log = mp_log_new(hwdec, log, drv->name), .global = global, - .gl = gl, + .ra = ra, .devs = devs, .probing = is_auto, + .priv = talloc_zero_size(hwdec, drv->priv_size), }; mp_verbose(log, "Loading hwdec driver '%s'\n", drv->name); - if (hwdec->driver->create(hwdec) < 0) { - talloc_free(hwdec); + if (hwdec->driver->init(hwdec) < 0) { + ra_hwdec_uninit(hwdec); mp_verbose(log, "Loading failed.\n"); return NULL; } return hwdec; } -struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl, +struct ra_hwdec *ra_hwdec_load_api(struct mp_log *log, struct ra *ra, struct mpv_global *g, struct mp_hwdec_devices *devs, enum hwdec_type api) { bool is_auto = HWDEC_IS_AUTO(api); for (int n = 0; mpgl_hwdec_drivers[n]; n++) { - const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n]; + const struct ra_hwdec_driver *drv = mpgl_hwdec_drivers[n]; if ((is_auto || api == drv->api) && !drv->testing_only) { - struct gl_hwdec *r = load_hwdec_driver(log, gl, g, devs, drv, is_auto); + struct ra_hwdec *r = load_hwdec_driver(log, ra, g, devs, drv, is_auto); if (r) return r; } @@ -111,7 +112,7 @@ struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl, } // Load by option name. -struct gl_hwdec *gl_hwdec_load(struct mp_log *log, GL *gl, +struct ra_hwdec *ra_hwdec_load(struct mp_log *log, struct ra *ra, struct mpv_global *g, struct mp_hwdec_devices *devs, const char *name) @@ -128,25 +129,25 @@ struct gl_hwdec *gl_hwdec_load(struct mp_log *log, GL *gl, } for (int n = 0; mpgl_hwdec_drivers[n]; n++) { - const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n]; + const struct ra_hwdec_driver *drv = mpgl_hwdec_drivers[n]; if (name && strcmp(drv->name, name) == 0) { - struct gl_hwdec *r = load_hwdec_driver(log, gl, g, devs, drv, false); + struct ra_hwdec *r = load_hwdec_driver(log, ra, g, devs, drv, false); if (r) return r; } } - return gl_hwdec_load_api(log, gl, g, devs, api_id); + return ra_hwdec_load_api(log, ra, g, devs, api_id); } -int gl_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt, +int ra_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param) { bool help = bstr_equals0(param, "help"); if (help) mp_info(log, "Available hwdecs:\n"); for (int n = 0; mpgl_hwdec_drivers[n]; n++) { - const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n]; + const struct ra_hwdec_driver *drv = mpgl_hwdec_drivers[n]; const char *api_name = m_opt_choice_str(mp_hwdec_names, drv->api); if (help) { mp_info(log, " %s [%s]\n", drv->name, api_name); @@ -172,18 +173,67 @@ int gl_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt, return M_OPT_INVALID; } -void gl_hwdec_uninit(struct gl_hwdec *hwdec) +void ra_hwdec_uninit(struct ra_hwdec *hwdec) { if (hwdec) - hwdec->driver->destroy(hwdec); + hwdec->driver->uninit(hwdec); talloc_free(hwdec); } -bool gl_hwdec_test_format(struct gl_hwdec *hwdec, int imgfmt) +bool ra_hwdec_test_format(struct ra_hwdec *hwdec, int imgfmt) +{ + for (int n = 0; hwdec->driver->imgfmts[n]; n++) { + if (hwdec->driver->imgfmts[n] == imgfmt) + return true; + } + return false; +} + +struct ra_hwdec_mapper *ra_hwdec_mapper_create(struct ra_hwdec *hwdec, + struct mp_image_params *params) +{ + assert(ra_hwdec_test_format(hwdec, params->imgfmt)); + + struct ra_hwdec_mapper *mapper = talloc_ptrtype(NULL, mapper); + *mapper = (struct ra_hwdec_mapper){ + .owner = hwdec, + .driver = hwdec->driver->mapper, + .log = hwdec->log, + .ra = hwdec->ra, + .priv = talloc_zero_size(mapper, hwdec->driver->mapper->priv_size), + .src_params = *params, + .dst_params = *params, + }; + if (mapper->driver->init(mapper) < 0) + ra_hwdec_mapper_free(&mapper); + return mapper; +} + +void ra_hwdec_mapper_free(struct ra_hwdec_mapper **mapper) +{ + struct ra_hwdec_mapper *p = *mapper; + if (p) { + ra_hwdec_mapper_unmap(p); + p->driver->uninit(p); + talloc_free(p); + } + *mapper = NULL; +} + +void ra_hwdec_mapper_unmap(struct ra_hwdec_mapper *mapper) { - if (!imgfmt) - return false; - if (hwdec->driver->test_format) - return hwdec->driver->test_format(hwdec, imgfmt); - return hwdec->driver->imgfmt == imgfmt; + if (mapper->driver->unmap) + mapper->driver->unmap(mapper); + mp_image_unrefp(&mapper->src); +} + +int ra_hwdec_mapper_map(struct ra_hwdec_mapper *mapper, struct mp_image *img) +{ + ra_hwdec_mapper_unmap(mapper); + mp_image_setrefp(&mapper->src, img); + if (mapper->driver->map(mapper) < 0) { + ra_hwdec_mapper_unmap(mapper); + return -1; + } + return 0; } diff --git a/video/out/opengl/hwdec.h b/video/out/opengl/hwdec.h index 6d4dc5d591..f978b70018 100644 --- a/video/out/opengl/hwdec.h +++ b/video/out/opengl/hwdec.h @@ -2,13 +2,14 @@ #define MPGL_HWDEC_H_ #include "common.h" +#include "ra.h" #include "video/hwdec.h" -struct gl_hwdec { - const struct gl_hwdec_driver *driver; +struct ra_hwdec { + const struct ra_hwdec_driver *driver; struct mp_log *log; struct mpv_global *global; - GL *gl; + struct ra *ra; struct mp_hwdec_devices *devs; // GLSL extensions required to sample textures from this. const char **glsl_extensions; @@ -20,79 +21,110 @@ struct gl_hwdec { float overlay_colorkey[4]; }; -struct gl_hwdec_plane { - GLuint gl_texture; - GLenum gl_target; - // Like struct gl_format.format (GL_RED etc.). Currently to detect - // GL_LUMINANCE_ALPHA and integer formats - can be left to 0 otherwise. - GLenum gl_format; - int tex_w, tex_h; // allocated texture size -}; +struct ra_hwdec_mapper { + const struct ra_hwdec_mapper_driver *driver; + struct mp_log *log; + struct ra *ra; + void *priv; + struct ra_hwdec *owner; + // Input frame parameters. (Set before init(), immutable.) + struct mp_image_params src_params; + // Output frame parameters (represents the format the textures return). Must + // be set by init(), immutable afterwards, + struct mp_image_params dst_params; + + // The currently mapped source image (or the image about to be mapped in + // ->map()). NULL if unmapped. The mapper can also clear this reference if + // the mapped textures contain a full copy. + struct mp_image *src; -struct gl_hwdec_frame { - struct gl_hwdec_plane planes[4]; + // The mapped textures and metadata about them. These fields change if a + // new frame is mapped (or unmapped), but otherwise remain constant. + // The common code won't mess with these, so you can e.g. set them in the + // .init() callback. + struct ra_tex *tex[4]; bool vdpau_fields; }; -struct gl_hwdec_driver { +// This can be used to map frames of a specific hw format as GL textures. +struct ra_hwdec_mapper_driver { + // Used to create ra_hwdec_mapper.priv. + size_t priv_size; + + // Init the mapper implementation. At this point, the field src_params, + // fns, devs, priv are initialized. + int (*init)(struct ra_hwdec_mapper *mapper); + // Destroy the mapper. unmap is called before this. + void (*uninit)(struct ra_hwdec_mapper *mapper); + + // Map mapper->src as texture, and set mapper->frame to textures using it. + // It is expected that that the textures remain valid until the next unmap + // or uninit call. + // The function is allowed to unref mapper->src if it's not needed (i.e. + // this function creates a copy). + // The underlying format can change, so you might need to do some form + // of change detection. You also must reject unsupported formats with an + // error. + // On error, returns negative value on error and remains unmapped. + int (*map)(struct ra_hwdec_mapper *mapper); + // Unmap the frame. Does nothing if already unmapped. Optional. + void (*unmap)(struct ra_hwdec_mapper *mapper); +}; + +struct ra_hwdec_driver { // Name of the interop backend. This is used for informational purposes only. const char *name; + // Used to create ra_hwdec.priv. + size_t priv_size; // Used to explicitly request a specific API. enum hwdec_type api; - // The hardware surface IMGFMT_ that must be passed to map_image later. - // If the test_format callback is set, this field is ignored! - int imgfmt; + // One of the hardware surface IMGFMT_ that must be passed to map_image later. + // Terminated with a 0 entry. (Extend the array size as needed.) + const int imgfmts[3]; // Dosn't load this unless requested by name. bool testing_only; + // Create the hwdec device. It must add it to hw->devs, if applicable. - int (*create)(struct gl_hwdec *hw); - // 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. - int (*reinit)(struct gl_hwdec *hw, struct mp_image_params *params); - // Return textures that contain a copy or reference of the given hw_image. - // The textures mirror the format returned by the reinit params argument. - // The textures must remain valid until unmap is called. - // hw_image remains referenced by the caller until unmap is called. - int (*map_frame)(struct gl_hwdec *hw, struct mp_image *hw_image, - struct gl_hwdec_frame *out_frame); - // Must be idempotent. - void (*unmap)(struct gl_hwdec *hw); - - void (*destroy)(struct gl_hwdec *hw); - - // Optional callback for checking input format support. - bool (*test_format)(struct gl_hwdec *hw, int imgfmt); - - // The following functions provide an alternative API. Each gl_hwdec_driver - // must have either map_frame or overlay_frame set (not both or none), and + int (*init)(struct ra_hwdec *hw); + void (*uninit)(struct ra_hwdec *hw); + + // This will be used to create a ra_hwdec_mapper from ra_hwdec. + const struct ra_hwdec_mapper_driver *mapper; + + // The following function provides an alternative API. Each ra_hwdec_driver + // must have either provide a mapper or overlay_frame (not both or none), and // if overlay_frame is set, it operates in overlay mode. In this mode, // OSD etc. is rendered via OpenGL, but the video is rendered as a separate // layer below it. // Non-overlay mode is strictly preferred, so try not to use overlay mode. - // Set the given frame as overlay, replacing the previous one. This can also // just change the position of the overlay. // hw_image==src==dst==NULL is passed to clear the overlay. - int (*overlay_frame)(struct gl_hwdec *hw, struct mp_image *hw_image, + int (*overlay_frame)(struct ra_hwdec *hw, struct mp_image *hw_image, struct mp_rect *src, struct mp_rect *dst, bool newframe); }; -struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl, +struct ra_hwdec *ra_hwdec_load_api(struct mp_log *log, struct ra *ra, struct mpv_global *g, struct mp_hwdec_devices *devs, enum hwdec_type api); -struct gl_hwdec *gl_hwdec_load(struct mp_log *log, GL *gl, +struct ra_hwdec *ra_hwdec_load(struct mp_log *log, struct ra *ra, struct mpv_global *g, struct mp_hwdec_devices *devs, const char *name); -int gl_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt, +int ra_hwdec_validate_opt(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param); -void gl_hwdec_uninit(struct gl_hwdec *hwdec); +void ra_hwdec_uninit(struct ra_hwdec *hwdec); + +bool ra_hwdec_test_format(struct ra_hwdec *hwdec, int imgfmt); -bool gl_hwdec_test_format(struct gl_hwdec *hwdec, int imgfmt); +struct ra_hwdec_mapper *ra_hwdec_mapper_create(struct ra_hwdec *hwdec, + struct mp_image_params *params); +void ra_hwdec_mapper_free(struct ra_hwdec_mapper **mapper); +void ra_hwdec_mapper_unmap(struct ra_hwdec_mapper *mapper); +int ra_hwdec_mapper_map(struct ra_hwdec_mapper *mapper, struct mp_image *img); #endif diff --git a/video/out/opengl/hwdec_cuda.c b/video/out/opengl/hwdec_cuda.c index fd432ee7f8..d40bafee24 100644 --- a/video/out/opengl/hwdec_cuda.c +++ b/video/out/opengl/hwdec_cuda.c @@ -35,21 +35,24 @@ #include "formats.h" #include "hwdec.h" #include "options/m_config.h" +#include "ra_gl.h" #include "video.h" -struct priv { +struct priv_owner { struct mp_hwdec_ctx hwctx; + CUcontext display_ctx; + CUcontext decode_ctx; +}; + +struct priv { struct mp_image layout; - GLuint gl_textures[4]; CUgraphicsResource cu_res[4]; CUarray cu_array[4]; - int plane_bytes[4]; CUcontext display_ctx; - CUcontext decode_ctx; }; -static int check_cu(struct gl_hwdec *hw, CUresult err, const char *func) +static int check_cu(struct ra_hwdec *hw, CUresult err, const char *func) { const char *err_name; const char *err_string; @@ -72,22 +75,24 @@ static int check_cu(struct gl_hwdec *hw, CUresult err, const char *func) #define CHECK_CU(x) check_cu(hw, (x), #x) -static int cuda_create(struct gl_hwdec *hw) +static int cuda_init(struct ra_hwdec *hw) { CUdevice display_dev; AVBufferRef *hw_device_ctx = NULL; CUcontext dummy; unsigned int device_count; int ret = 0; + struct priv_owner *p = hw->priv; - if (hw->gl->version < 210 && hw->gl->es < 300) { + if (!ra_is_gl(hw->ra)) + return -1; + + GL *gl = ra_gl_get(hw->ra); + if (gl->version < 210 && gl->es < 300) { MP_VERBOSE(hw, "need OpenGL >= 2.1 or OpenGL-ES >= 3.0\n"); return -1; } - struct priv *p = talloc_zero(hw, struct priv); - hw->priv = p; - bool loaded = cuda_load(); if (!loaded) { MP_VERBOSE(hw, "Failed to load CUDA symbols\n"); @@ -171,22 +176,43 @@ static int cuda_create(struct gl_hwdec *hw) return -1; } -static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) +static void cuda_uninit(struct ra_hwdec *hw) +{ + struct priv_owner *p = hw->priv; + + if (p->hwctx.ctx) + hwdec_devices_remove(hw->devs, &p->hwctx); + av_buffer_unref(&p->hwctx.av_device_ref); + + if (p->decode_ctx && p->decode_ctx != p->display_ctx) + CHECK_CU(cuCtxDestroy(p->decode_ctx)); + + if (p->display_ctx) + CHECK_CU(cuCtxDestroy(p->display_ctx)); +} + +#undef CHECK_CU +#define CHECK_CU(x) check_cu((mapper)->owner, (x), #x) + +static int mapper_init(struct ra_hwdec_mapper *mapper) { - struct priv *p = hw->priv; - GL *gl = hw->gl; + struct priv_owner *p_owner = mapper->owner->priv; + struct priv *p = mapper->priv; CUcontext dummy; int ret = 0, eret = 0; - assert(params->imgfmt == hw->driver->imgfmt); - params->imgfmt = params->hw_subfmt; - params->hw_subfmt = 0; + p->display_ctx = p_owner->display_ctx; - mp_image_set_params(&p->layout, params); + int imgfmt = mapper->src_params.hw_subfmt; + mapper->dst_params = mapper->src_params; + mapper->dst_params.imgfmt = imgfmt; + mapper->dst_params.hw_subfmt = 0; - struct gl_imgfmt_desc desc; - if (!gl_get_imgfmt_desc(gl, params->imgfmt, &desc)) { - MP_ERR(hw, "Unsupported format: %s\n", mp_imgfmt_to_name(params->imgfmt)); + mp_image_set_params(&p->layout, &mapper->dst_params); + + struct ra_imgfmt_desc desc; + if (!ra_get_imgfmt_desc(mapper->ra, imgfmt, &desc)) { + MP_ERR(mapper, "Unsupported format: %s\n", mp_imgfmt_to_name(imgfmt)); return -1; } @@ -194,26 +220,30 @@ static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) if (ret < 0) return ret; - gl->GenTextures(4, p->gl_textures); for (int n = 0; n < desc.num_planes; n++) { - const struct gl_format *fmt = desc.planes[n]; - - p->plane_bytes[n] = gl_bytes_per_pixel(fmt->format, fmt->type); - - gl->BindTexture(GL_TEXTURE_2D, p->gl_textures[n]); - GLenum filter = GL_LINEAR; - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); - 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->TexImage2D(GL_TEXTURE_2D, 0, fmt->internal_format, - mp_image_plane_w(&p->layout, n), - mp_image_plane_h(&p->layout, n), - 0, fmt->format, fmt->type, NULL); - gl->BindTexture(GL_TEXTURE_2D, 0); - - ret = CHECK_CU(cuGraphicsGLRegisterImage(&p->cu_res[n], p->gl_textures[n], - GL_TEXTURE_2D, + const struct ra_format *format = desc.planes[n]; + + struct ra_tex_params params = { + .dimensions = 2, + .w = mp_image_plane_w(&p->layout, n), + .h = mp_image_plane_h(&p->layout, n), + .d = 1, + .format = format, + .render_src = true, + .src_linear = format->linear_filter, + }; + + mapper->tex[n] = ra_tex_create(mapper->ra, ¶ms); + if (!mapper->tex[n]) { + ret = -1; + goto error; + } + + GLuint texture; + GLenum target; + ra_gl_get_raw_tex(mapper->ra, mapper->tex[n], &texture, &target); + + ret = CHECK_CU(cuGraphicsGLRegisterImage(&p->cu_res[n], texture, target, CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD)); if (ret < 0) goto error; @@ -240,10 +270,9 @@ static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) return ret; } -static void destroy(struct gl_hwdec *hw) +static void mapper_uninit(struct ra_hwdec_mapper *mapper) { - struct priv *p = hw->priv; - GL *gl = hw->gl; + struct priv *p = mapper->priv; CUcontext dummy; // Don't bail if any CUDA calls fail. This is all best effort. @@ -252,25 +281,18 @@ static void destroy(struct gl_hwdec *hw) if (p->cu_res[n] > 0) CHECK_CU(cuGraphicsUnregisterResource(p->cu_res[n])); p->cu_res[n] = 0; + ra_tex_free(mapper->ra, &mapper->tex[n]); } CHECK_CU(cuCtxPopCurrent(&dummy)); +} - if (p->decode_ctx != p->display_ctx) { - CHECK_CU(cuCtxDestroy(p->decode_ctx)); - } - - CHECK_CU(cuCtxDestroy(p->display_ctx)); - - gl->DeleteTextures(4, p->gl_textures); - - hwdec_devices_remove(hw->devs, &p->hwctx); - av_buffer_unref(&p->hwctx.av_device_ref); +static void mapper_unmap(struct ra_hwdec_mapper *mapper) +{ } -static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image, - struct gl_hwdec_frame *out_frame) +static int mapper_map(struct ra_hwdec_mapper *mapper) { - struct priv *p = hw->priv; + struct priv *p = mapper->priv; CUcontext dummy; int ret = 0, eret = 0; @@ -278,31 +300,21 @@ static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image, if (ret < 0) return ret; - *out_frame = (struct gl_hwdec_frame) { 0, }; - for (int n = 0; n < p->layout.num_planes; n++) { - // widthInBytes must account for the chroma plane - // elements being two samples wide. CUDA_MEMCPY2D cpy = { .srcMemoryType = CU_MEMORYTYPE_DEVICE, .dstMemoryType = CU_MEMORYTYPE_ARRAY, - .srcDevice = (CUdeviceptr)hw_image->planes[n], - .srcPitch = hw_image->stride[n], + .srcDevice = (CUdeviceptr)mapper->src->planes[n], + .srcPitch = mapper->src->stride[n], .srcY = 0, .dstArray = p->cu_array[n], - .WidthInBytes = mp_image_plane_w(&p->layout, n) * p->plane_bytes[n], + .WidthInBytes = mp_image_plane_w(&p->layout, n) * + mapper->tex[n]->params.format->pixel_size, .Height = mp_image_plane_h(&p->layout, n), }; ret = CHECK_CU(cuMemcpy2D(&cpy)); if (ret < 0) goto error; - - out_frame->planes[n] = (struct gl_hwdec_plane){ - .gl_texture = p->gl_textures[n], - .gl_target = GL_TEXTURE_2D, - .tex_w = mp_image_plane_w(&p->layout, n), - .tex_h = mp_image_plane_h(&p->layout, n), - }; } @@ -314,12 +326,18 @@ static int map_frame(struct gl_hwdec *hw, struct mp_image *hw_image, return ret; } -const struct gl_hwdec_driver gl_hwdec_cuda = { +const struct ra_hwdec_driver ra_hwdec_cuda = { .name = "cuda", .api = HWDEC_CUDA, - .imgfmt = IMGFMT_CUDA, - .create = cuda_create, - .reinit = reinit, - .map_frame = map_frame, - .destroy = destroy, + .imgfmts = {IMGFMT_CUDA, 0}, + .priv_size = sizeof(struct priv_owner), + .init = cuda_init, + .uninit = cuda_uninit, + .mapper = &(const struct ra_hwdec_mapper_driver){ + .priv_size = sizeof(struct priv), + .init = mapper_init, + .uninit = mapper_uninit, + .map = mapper_map, + .unmap = mapper_unmap, + }, }; diff --git a/video/out/opengl/hwdec_d3d11egl.c b/video/out/opengl/hwdec_d3d11egl.c index 686bb99d1a..3988f8310e 100644 --- a/video/out/opengl/hwdec_d3d11egl.c +++ b/video/out/opengl/hwdec_d3d11egl.c @@ -28,6 +28,7 @@ #include "osdep/timer.h" #include "osdep/windows_utils.h" #include "hwdec.h" +#include "ra_gl.h" #include "video/hwdec.h" #include "video/decode/d3d.h" @@ -35,15 +36,12 @@ #define EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB #endif -struct priv { +struct priv_owner { struct mp_hwdec_ctx hwctx; ID3D11Device *d3d11_device; EGLDisplay egl_display; - EGLStreamKHR egl_stream; - GLuint gl_textures[3]; - // EGL_KHR_stream EGLStreamKHR (EGLAPIENTRY *CreateStreamKHR)(EGLDisplay dpy, const EGLint *attrib_list); @@ -68,36 +66,29 @@ struct priv { const EGLAttrib *attrib_list); }; -static void destroy_objects(struct gl_hwdec *hw) -{ - struct priv *p = hw->priv; - GL *gl = hw->gl; - - if (p->egl_stream) - p->DestroyStreamKHR(p->egl_display, p->egl_stream); - p->egl_stream = 0; - - for (int n = 0; n < 3; n++) { - gl->DeleteTextures(1, &p->gl_textures[n]); - p->gl_textures[n] = 0; - } -} +struct priv { + EGLStreamKHR egl_stream; + GLuint gl_textures[2]; +}; -static void destroy(struct gl_hwdec *hw) +static void uninit(struct ra_hwdec *hw) { - struct priv *p = hw->priv; + struct priv_owner *p = hw->priv; - destroy_objects(hw); - - hwdec_devices_remove(hw->devs, &p->hwctx); + if (p->hwctx.ctx) + hwdec_devices_remove(hw->devs, &p->hwctx); if (p->d3d11_device) ID3D11Device_Release(p->d3d11_device); - p->d3d11_device = NULL; } -static int create(struct gl_hwdec *hw) +static int init(struct ra_hwdec *hw) { + struct priv_owner *p = hw->priv; + HRESULT hr; + + if (!ra_is_gl(hw->ra)) + return -1; if (!angle_load()) return -1; @@ -108,19 +99,17 @@ static int create(struct gl_hwdec *hw) if (!eglGetCurrentContext()) return -1; + GL *gl = ra_gl_get(hw->ra); + const char *exts = eglQueryString(egl_display, EGL_EXTENSIONS); if (!exts || !strstr(exts, "EGL_ANGLE_d3d_share_handle_client_buffer") || !strstr(exts, "EGL_ANGLE_stream_producer_d3d_texture_nv12") || - !(strstr(hw->gl->extensions, "GL_OES_EGL_image_external_essl3") || - hw->gl->es == 200) || + !(strstr(gl->extensions, "GL_OES_EGL_image_external_essl3") || + gl->es == 200) || !strstr(exts, "EGL_EXT_device_query") || - !(hw->gl->mpgl_caps & MPGL_CAP_TEX_RG)) + !(gl->mpgl_caps & MPGL_CAP_TEX_RG)) return -1; - HRESULT hr; - struct priv *p = talloc_zero(hw, struct priv); - hw->priv = p; - p->egl_display = egl_display; p->CreateStreamKHR = (void *)eglGetProcAddress("eglCreateStreamKHR"); @@ -149,7 +138,7 @@ static int create(struct gl_hwdec *hw) static const char *es2_exts[] = {"GL_NV_EGL_stream_consumer_external", 0}; static const char *es3_exts[] = {"GL_NV_EGL_stream_consumer_external", "GL_OES_EGL_image_external_essl3", 0}; - hw->glsl_extensions = hw->gl->es == 200 ? es2_exts : es3_exts; + hw->glsl_extensions = gl->es == 200 ? es2_exts : es3_exts; PFNEGLQUERYDISPLAYATTRIBEXTPROC p_eglQueryDisplayAttribEXT = (void *)eglGetProcAddress("eglQueryDisplayAttribEXT"); @@ -201,30 +190,44 @@ static int create(struct gl_hwdec *hw) return 0; fail: - destroy(hw); return -1; } -static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) +static void mapper_uninit(struct ra_hwdec_mapper *mapper) { - struct priv *p = hw->priv; - GL *gl = hw->gl; + struct priv_owner *o = mapper->owner->priv; + struct priv *p = mapper->priv; + GL *gl = ra_gl_get(mapper->ra); - destroy_objects(hw); + if (p->egl_stream) + o->DestroyStreamKHR(o->egl_display, p->egl_stream); + p->egl_stream = 0; + + gl->DeleteTextures(2, p->gl_textures); +} + +static int mapper_init(struct ra_hwdec_mapper *mapper) +{ + struct priv_owner *o = mapper->owner->priv; + struct priv *p = mapper->priv; + GL *gl = ra_gl_get(mapper->ra); - if (params->hw_subfmt != IMGFMT_NV12) { - MP_FATAL(hw, "Format not supported.\n"); + if (mapper->src_params.hw_subfmt != IMGFMT_NV12) { + MP_FATAL(mapper, "Format not supported.\n"); return -1; } - // Hope that the given texture unit range is not "in use" by anything. + mapper->dst_params = mapper->src_params; + mapper->dst_params.imgfmt = mapper->src_params.hw_subfmt; + mapper->dst_params.hw_subfmt = 0; + // The texture units need to be bound during init only, and are free for // use again after the initialization here is done. int texunits = 0; // [texunits, texunits + num_planes) int num_planes = 2; int gl_target = GL_TEXTURE_EXTERNA |