mpv/video/out/hwdec/dmabuf_interop_wl.c

84 lines
2.8 KiB
C
Raw Normal View History

/*
* 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/>.
*/
#include "video/out/wldmabuf/ra_wldmabuf.h"
#include "dmabuf_interop.h"
static bool mapper_init(struct ra_hwdec_mapper *mapper,
const struct ra_imgfmt_desc *desc)
{
return true;
}
static void mapper_uninit(const struct ra_hwdec_mapper *mapper)
{
}
static bool map(struct ra_hwdec_mapper *mapper,
struct dmabuf_interop *dmabuf_interop,
bool probing)
{
// 1. only validate format when composed layers is enabled (i.e. vaapi)
// 2. for drmprime, just return true for now, as this use case
// has not been tested.
if (!dmabuf_interop->composed_layers)
return true;
int layer_no = 0;
struct dmabuf_interop_priv *mapper_p = mapper->priv;
uint32_t drm_format = mapper_p->desc.layers[layer_no].format;
if (mapper_p->desc.nb_layers != 1) {
MP_VERBOSE(mapper, "Mapped surface has separate layers - expected composed layers.\n");
return false;
} else if (!ra_compatible_format(mapper->ra, drm_format,
mapper_p->desc.objects[0].format_modifier)) {
MP_VERBOSE(mapper, "Mapped surface with format %s; drm format '%s(%016lx)' "
"is not supported by compositor.\n",
mp_imgfmt_to_name(mapper->src->params.hw_subfmt),
mp_tag_str(drm_format),
mapper_p->desc.objects[0].format_modifier);
return false;
}
hwtransfer: use the right hardware config to find conversion targets The last piece in the puzzle for doing hardware conversions automatically is ensuring we only consider valid target formats for the conversion. Although it is unintuitive, some vaapi drivers can expose a different set of formats for uploads vs for conversions, and that is the case on the Intel hardware I have here. Before this change, we would use the upload target list, and our selection algorithm would pick a format that doesn't work for conversions, causing everything to fail. Whoops. Successfully obtaining the conversion target format list is a bit of a convoluted process, with only parts of it encapsulated by ffmpeg. Specifically, ffmpeg understands the concept of hardware configurations that can affect the constraints of a device, but does not define what configurations are - that is left up to the specific hwdevice type. In the case of vaapi, we need to create a config for the video processing endpoint, and use that when querying for constraints. I decided to encapsulate creation of the config as part of the hwdec init process, so that the constraint query can be down in the hwtransfer code in an opaque way. I don't know if any other hardware will need this capability, but if so, we'll be able to account for it. Then, when we look at probing, instead of checking for what formats are supported for transfers, we use the results of the constraint query with the conversion config. And as that config doesn't depend on the source format, we only need to do it once.
2023-08-03 02:45:35 +00:00
MP_VERBOSE(mapper, "Supported Wayland display format %s: '%s(%016lx)'\n",
mp_imgfmt_to_name(mapper->src->params.hw_subfmt),
mp_tag_str(drm_format), mapper_p->desc.objects[0].format_modifier);
return true;
}
static void unmap(struct ra_hwdec_mapper *mapper)
{
}
bool dmabuf_interop_wl_init(const struct ra_hwdec *hw,
struct dmabuf_interop *dmabuf_interop)
{
if (!ra_is_wldmabuf(hw->ra_ctx->ra))
return false;
if (strstr(hw->driver->name, "vaapi") != NULL)
dmabuf_interop->composed_layers = true;
dmabuf_interop->interop_init = mapper_init;
dmabuf_interop->interop_uninit = mapper_uninit;
dmabuf_interop->interop_map = map;
dmabuf_interop->interop_unmap = unmap;
return true;
}