2019-09-15 03:05:21 +00:00
|
|
|
/*
|
|
|
|
* This file is part of mpv.
|
|
|
|
*
|
|
|
|
* mpv is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* mpv is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-10-02 18:13:21 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2022-07-31 18:50:57 +00:00
|
|
|
#include "dmabuf_interop.h"
|
2019-09-15 03:05:21 +00:00
|
|
|
#include "video/out/placebo/ra_pl.h"
|
2021-05-19 02:05:46 +00:00
|
|
|
#include "video/out/placebo/utils.h"
|
2019-09-15 03:05:21 +00:00
|
|
|
|
2022-07-31 19:14:44 +00:00
|
|
|
static bool vaapi_pl_map(struct ra_hwdec_mapper *mapper,
|
|
|
|
struct dmabuf_interop *dmabuf_interop,
|
|
|
|
bool probing)
|
2019-09-15 03:05:21 +00:00
|
|
|
{
|
2022-08-10 04:00:21 +00:00
|
|
|
struct dmabuf_interop_priv *p = mapper->priv;
|
2022-01-11 12:37:31 +00:00
|
|
|
pl_gpu gpu = ra_pl_get(mapper->ra);
|
2019-09-15 03:05:21 +00:00
|
|
|
|
|
|
|
struct ra_imgfmt_desc desc = {0};
|
|
|
|
if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
|
|
|
|
return false;
|
|
|
|
|
2022-06-05 20:53:18 +00:00
|
|
|
// The calling code validates that the total number of exported planes
|
|
|
|
// equals the number we expected in p->num_planes.
|
|
|
|
int layer = 0;
|
|
|
|
int layer_plane = 0;
|
2019-09-15 03:05:21 +00:00
|
|
|
for (int n = 0; n < p->num_planes; n++) {
|
|
|
|
|
|
|
|
const struct ra_format *format = desc.planes[n];
|
2022-07-31 19:59:15 +00:00
|
|
|
int id = p->desc.layers[layer].planes[layer_plane].object_index;
|
2019-09-15 03:05:21 +00:00
|
|
|
int fd = p->desc.objects[id].fd;
|
|
|
|
uint32_t size = p->desc.objects[id].size;
|
2022-07-31 19:59:15 +00:00
|
|
|
uint32_t offset = p->desc.layers[layer].planes[layer_plane].offset;
|
|
|
|
uint32_t pitch = p->desc.layers[layer].planes[layer_plane].pitch;
|
2019-09-15 03:05:21 +00:00
|
|
|
|
2019-10-02 18:13:21 +00:00
|
|
|
// AMD drivers do not return the size in the surface description, so we
|
2021-10-04 04:18:55 +00:00
|
|
|
// need to query it manually.
|
2019-10-02 18:13:21 +00:00
|
|
|
if (size == 0) {
|
|
|
|
size = lseek(fd, 0, SEEK_END);
|
|
|
|
if (size == -1) {
|
|
|
|
MP_ERR(mapper, "Cannot obtain size of object with fd %d: %s\n",
|
|
|
|
fd, mp_strerror(errno));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
off_t err = lseek(fd, 0, SEEK_SET);
|
|
|
|
if (err == -1) {
|
|
|
|
MP_ERR(mapper, "Failed to reset offset for fd %d: %s\n",
|
|
|
|
fd, mp_strerror(errno));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-15 03:05:21 +00:00
|
|
|
struct pl_tex_params tex_params = {
|
|
|
|
.w = mp_image_plane_w(&p->layout, n),
|
|
|
|
.h = mp_image_plane_h(&p->layout, n),
|
|
|
|
.d = 0,
|
|
|
|
.format = format->priv,
|
|
|
|
.sampleable = true,
|
|
|
|
.import_handle = PL_HANDLE_DMA_BUF,
|
|
|
|
.shared_mem = (struct pl_shared_mem) {
|
|
|
|
.handle = {
|
|
|
|
.fd = fd,
|
|
|
|
},
|
|
|
|
.size = size,
|
|
|
|
.offset = offset,
|
2022-07-31 19:59:15 +00:00
|
|
|
.drm_format_mod = p->desc.objects[id].format_modifier,
|
2021-02-12 22:31:03 +00:00
|
|
|
.stride_w = pitch,
|
2019-09-15 03:05:21 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-02-03 15:20:18 +00:00
|
|
|
mppl_log_set_probing(gpu->log, probing);
|
2022-01-11 12:37:31 +00:00
|
|
|
pl_tex pltex = pl_tex_create(gpu, &tex_params);
|
2022-02-03 15:20:18 +00:00
|
|
|
mppl_log_set_probing(gpu->log, false);
|
|
|
|
if (!pltex)
|
2019-09-15 03:05:21 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
struct ra_tex *ratex = talloc_ptrtype(NULL, ratex);
|
|
|
|
int ret = mppl_wrap_tex(mapper->ra, pltex, ratex);
|
|
|
|
if (!ret) {
|
|
|
|
pl_tex_destroy(gpu, &pltex);
|
|
|
|
talloc_free(ratex);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
mapper->tex[n] = ratex;
|
|
|
|
|
|
|
|
MP_TRACE(mapper, "Object %d with fd %d imported as %p\n",
|
|
|
|
id, fd, ratex);
|
2022-06-05 20:53:18 +00:00
|
|
|
|
|
|
|
layer_plane++;
|
2022-07-31 19:59:15 +00:00
|
|
|
if (layer_plane == p->desc.layers[layer].nb_planes) {
|
2022-06-05 20:53:18 +00:00
|
|
|
layer_plane = 0;
|
|
|
|
layer++;
|
|
|
|
}
|
2019-09-15 03:05:21 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-02-26 14:13:10 +00:00
|
|
|
static void vaapi_pl_unmap(struct ra_hwdec_mapper *mapper)
|
2019-09-15 03:05:21 +00:00
|
|
|
{
|
2024-02-25 10:24:51 +00:00
|
|
|
for (int n = 0; n < MP_ARRAY_SIZE(mapper->tex); n++)
|
2019-09-15 03:05:21 +00:00
|
|
|
ra_tex_free(mapper->ra, &mapper->tex[n]);
|
|
|
|
}
|
|
|
|
|
2022-07-31 19:14:44 +00:00
|
|
|
bool dmabuf_interop_pl_init(const struct ra_hwdec *hw,
|
|
|
|
struct dmabuf_interop *dmabuf_interop)
|
2019-09-15 03:05:21 +00:00
|
|
|
{
|
2022-03-12 18:54:23 +00:00
|
|
|
pl_gpu gpu = ra_pl_get(hw->ra_ctx->ra);
|
2019-09-15 03:05:21 +00:00
|
|
|
if (!gpu) {
|
2022-02-26 14:13:10 +00:00
|
|
|
// This is not a libplacebo RA;
|
2019-09-15 03:05:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(gpu->import_caps.tex & PL_HANDLE_DMA_BUF)) {
|
2022-07-31 19:14:44 +00:00
|
|
|
MP_VERBOSE(hw, "libplacebo dmabuf interop requires support for "
|
2022-02-26 14:13:10 +00:00
|
|
|
"PL_HANDLE_DMA_BUF import.\n");
|
2019-09-15 03:05:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-07-31 19:14:44 +00:00
|
|
|
MP_VERBOSE(hw, "using libplacebo dmabuf interop\n");
|
2019-09-15 03:05:21 +00:00
|
|
|
|
2022-07-31 19:14:44 +00:00
|
|
|
dmabuf_interop->interop_map = vaapi_pl_map;
|
|
|
|
dmabuf_interop->interop_unmap = vaapi_pl_unmap;
|
2019-09-15 03:05:21 +00:00
|
|
|
|
|
|
|
return true;
|
2020-07-14 01:58:55 +00:00
|
|
|
}
|