310e506c06
Add support to overlay plane, in addition to primary and cursor planes. In this approach, the plane composition still requires an active primary plane and planes are composed associatively in the order: (primary <- overlay) <- cursor It enables to run the following IGT tests successfully: - kms_plane_cursor: - pipe-A-[overlay, primary, viewport]-size-[64, 128, 256] - kms_atomic: - plane-overlay-legacy and preserves the successful execution of kms_cursor_crc, kms_writeback and kms_flip Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/8261bf93d8a0e3ffaf81d8e7c9b3e9c229116be3.1619250933.git.melissa.srw@gmail.com
112 lines
2.8 KiB
C
112 lines
2.8 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
|
|
#include "vkms_drv.h"
|
|
#include <drm/drm_atomic_helper.h>
|
|
#include <drm/drm_probe_helper.h>
|
|
#include <drm/drm_simple_kms_helper.h>
|
|
|
|
static void vkms_connector_destroy(struct drm_connector *connector)
|
|
{
|
|
drm_connector_cleanup(connector);
|
|
}
|
|
|
|
static const struct drm_connector_funcs vkms_connector_funcs = {
|
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
|
.destroy = vkms_connector_destroy,
|
|
.reset = drm_atomic_helper_connector_reset,
|
|
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
|
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
|
};
|
|
|
|
static int vkms_conn_get_modes(struct drm_connector *connector)
|
|
{
|
|
int count;
|
|
|
|
count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX);
|
|
drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF);
|
|
|
|
return count;
|
|
}
|
|
|
|
static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = {
|
|
.get_modes = vkms_conn_get_modes,
|
|
};
|
|
|
|
int vkms_output_init(struct vkms_device *vkmsdev, int index)
|
|
{
|
|
struct vkms_output *output = &vkmsdev->output;
|
|
struct drm_device *dev = &vkmsdev->drm;
|
|
struct drm_connector *connector = &output->connector;
|
|
struct drm_encoder *encoder = &output->encoder;
|
|
struct drm_crtc *crtc = &output->crtc;
|
|
struct vkms_plane *primary, *cursor = NULL, *overlay = NULL;
|
|
int ret;
|
|
int writeback;
|
|
|
|
primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
|
|
if (IS_ERR(primary))
|
|
return PTR_ERR(primary);
|
|
|
|
if (vkmsdev->config->overlay) {
|
|
overlay = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_OVERLAY, index);
|
|
if (IS_ERR(overlay))
|
|
return PTR_ERR(overlay);
|
|
|
|
if (!overlay->base.possible_crtcs)
|
|
overlay->base.possible_crtcs = drm_crtc_mask(crtc);
|
|
}
|
|
|
|
if (vkmsdev->config->cursor) {
|
|
cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
|
|
if (IS_ERR(cursor))
|
|
return PTR_ERR(cursor);
|
|
}
|
|
|
|
ret = vkms_crtc_init(dev, crtc, &primary->base, &cursor->base);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = drm_connector_init(dev, connector, &vkms_connector_funcs,
|
|
DRM_MODE_CONNECTOR_VIRTUAL);
|
|
if (ret) {
|
|
DRM_ERROR("Failed to init connector\n");
|
|
goto err_connector;
|
|
}
|
|
|
|
drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
|
|
|
|
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
|
|
if (ret) {
|
|
DRM_ERROR("Failed to init encoder\n");
|
|
goto err_encoder;
|
|
}
|
|
encoder->possible_crtcs = 1;
|
|
|
|
ret = drm_connector_attach_encoder(connector, encoder);
|
|
if (ret) {
|
|
DRM_ERROR("Failed to attach connector to encoder\n");
|
|
goto err_attach;
|
|
}
|
|
|
|
if (vkmsdev->config->writeback) {
|
|
writeback = vkms_enable_writeback_connector(vkmsdev);
|
|
if (writeback)
|
|
DRM_ERROR("Failed to init writeback connector\n");
|
|
}
|
|
|
|
drm_mode_config_reset(dev);
|
|
|
|
return 0;
|
|
|
|
err_attach:
|
|
drm_encoder_cleanup(encoder);
|
|
|
|
err_encoder:
|
|
drm_connector_cleanup(connector);
|
|
|
|
err_connector:
|
|
drm_crtc_cleanup(crtc);
|
|
|
|
return ret;
|
|
}
|