video: probe format of primary plane in drm/egl context

We need to support hardware/drivers which do not support ARGB8888 in
their primary plane.

We also use p->primary_plane_format when creating the gbm surface, to
make sure it always matches (in actuality there should be little
difference).
This commit is contained in:
Anton Kindestam 2017-11-09 09:54:28 +01:00 committed by Jan Ekström
parent 04e5fbde43
commit cc16cd5aa4
1 changed files with 59 additions and 3 deletions

View File

@ -25,6 +25,7 @@
#include <unistd.h>
#include <gbm.h>
#include <drm_fourcc.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@ -71,6 +72,8 @@ struct priv {
struct gbm gbm;
struct framebuffer *fb;
uint32_t primary_plane_format;
bool active;
bool waiting_for_flip;
@ -122,7 +125,7 @@ static bool init_gbm(struct ra_ctx *ctx)
p->gbm.device,
p->kms->mode.hdisplay,
p->kms->mode.vdisplay,
GBM_FORMAT_XRGB8888,
p->primary_plane_format, // drm_fourcc.h defs should be gbm-compatible
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (!p->gbm.surface) {
MP_ERR(ctx->vo, "Failed to create GBM surface.\n");
@ -155,8 +158,13 @@ static void update_framebuffer_from_bo(struct ra_ctx *ctx, struct gbm_bo *bo)
uint32_t stride = gbm_bo_get_stride(bo);
uint32_t handle = gbm_bo_get_handle(bo).u32;
int ret = drmModeAddFB(fb->fd, fb->width, fb->height,
32, 32, stride, handle, &fb->id);
int ret = drmModeAddFB2(fb->fd, fb->width, fb->height,
p->primary_plane_format,
(uint32_t[4]){handle, 0, 0, 0},
(uint32_t[4]){stride, 0, 0, 0},
(uint32_t[4]){0, 0, 0, 0},
&fb->id, 0);
if (ret) {
MP_ERR(ctx->vo, "Failed to create framebuffer: %s\n", mp_strerror(errno));
}
@ -328,6 +336,49 @@ static void drm_egl_uninit(struct ra_ctx *ctx)
}
}
// If primary plane supports ARGB8888 we want to use that, but if it doesn't we
// fall back on XRGB8888. If the driver does not support atomic there is no
// particular reason to be using ARGB8888, so we fall back to XRGB8888 (another
// reason is that we do not have the convenient atomic_ctx and its convenient
// primary_plane field).
static bool probe_primary_plane_format(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
if (!p->kms->atomic_context) {
p->primary_plane_format = DRM_FORMAT_XRGB8888;
MP_VERBOSE(ctx->vo, "Not using DRM Atomic: Use DRM_FORMAT_XRGB8888 for primary plane.\n");
return true;
}
drmModePlane *drmplane =
drmModeGetPlane(p->kms->fd, p->kms->atomic_context->primary_plane->id);
bool have_argb8888 = false;
bool have_xrgb8888 = false;
bool result = false;
for (unsigned int i = 0; i < drmplane->count_formats; ++i) {
if (drmplane->formats[i] == DRM_FORMAT_ARGB8888) {
have_argb8888 = true;
} else if (drmplane->formats[i] == DRM_FORMAT_XRGB8888) {
have_xrgb8888 = true;
}
}
if (have_argb8888) {
p->primary_plane_format = DRM_FORMAT_ARGB8888;
MP_VERBOSE(ctx->vo, "DRM_FORMAT_ARGB8888 supported by primary plane.\n");
result = true;
} else if (have_xrgb8888) {
p->primary_plane_format = DRM_FORMAT_XRGB8888;
MP_VERBOSE(ctx->vo,
"DRM_FORMAT_ARGB8888 not supported by primary plane: "
"Falling back to DRM_FORMAT_XRGB8888.\n");
result = true;
}
drmModeFreePlane(drmplane);
return result;
}
static bool drm_egl_init(struct ra_ctx *ctx)
{
if (ctx->opts.probing) {
@ -355,6 +406,11 @@ static bool drm_egl_init(struct ra_ctx *ctx)
return false;
}
if (!probe_primary_plane_format(ctx)) {
MP_ERR(ctx->vo, "No suitable format found on DRM primary plane.\n");
return false;
}
if (!init_gbm(ctx)) {
MP_ERR(ctx->vo, "Failed to setup GBM.\n");
return false;