File Index
Files and directories
Sign in
FILE

vkms_plane.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/vkms/vkms_plane.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2
  3#include "vkms_config.h"
  4#include <linux/iosys-map.h>
  5
  6#include <drm/drm_atomic.h>
  7#include <drm/drm_atomic_helper.h>
  8#include <drm/drm_blend.h>
  9#include <drm/drm_fourcc.h>
 10#include <drm/drm_gem_atomic_helper.h>
 11#include <drm/drm_gem_framebuffer_helper.h>
 12#include <drm/drm_print.h>
 13
 14#include "vkms_drv.h"
 15#include "vkms_formats.h"
 16
 17static const u32 vkms_formats[] = {
 18	DRM_FORMAT_ARGB8888,
 19	DRM_FORMAT_ABGR8888,
 20	DRM_FORMAT_BGRA8888,
 21	DRM_FORMAT_RGBA8888,
 22	DRM_FORMAT_XRGB8888,
 23	DRM_FORMAT_XBGR8888,
 24	DRM_FORMAT_RGB888,
 25	DRM_FORMAT_BGR888,
 26	DRM_FORMAT_XRGB16161616,
 27	DRM_FORMAT_XBGR16161616,
 28	DRM_FORMAT_ARGB16161616,
 29	DRM_FORMAT_ABGR16161616,
 30	DRM_FORMAT_RGB565,
 31	DRM_FORMAT_BGR565,
 32	DRM_FORMAT_NV12,
 33	DRM_FORMAT_NV16,
 34	DRM_FORMAT_NV24,
 35	DRM_FORMAT_NV21,
 36	DRM_FORMAT_NV61,
 37	DRM_FORMAT_NV42,
 38	DRM_FORMAT_YUV420,
 39	DRM_FORMAT_YUV422,
 40	DRM_FORMAT_YUV444,
 41	DRM_FORMAT_YVU420,
 42	DRM_FORMAT_YVU422,
 43	DRM_FORMAT_YVU444,
 44	DRM_FORMAT_P010,
 45	DRM_FORMAT_P012,
 46	DRM_FORMAT_P016,
 47	DRM_FORMAT_R1,
 48	DRM_FORMAT_R2,
 49	DRM_FORMAT_R4,
 50	DRM_FORMAT_R8,
 51};
 52
 53static struct drm_plane_state *
 54vkms_plane_duplicate_state(struct drm_plane *plane)
 55{
 56	struct vkms_plane_state *vkms_state;
 57	struct vkms_frame_info *frame_info;
 58
 59	vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
 60	if (!vkms_state)
 61		return NULL;
 62
 63	frame_info = kzalloc(sizeof(*frame_info), GFP_KERNEL);
 64	if (!frame_info) {
 65		DRM_DEBUG_KMS("Couldn't allocate frame_info\n");
 66		kfree(vkms_state);
 67		return NULL;
 68	}
 69
 70	vkms_state->frame_info = frame_info;
 71
 72	__drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);
 73
 74	return &vkms_state->base.base;
 75}
 76
 77static void vkms_plane_destroy_state(struct drm_plane *plane,
 78				     struct drm_plane_state *old_state)
 79{
 80	struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);
 81	struct drm_crtc *crtc = vkms_state->base.base.crtc;
 82
 83	if (crtc && vkms_state->frame_info->fb) {
 84		/* dropping the reference we acquired in
 85		 * vkms_primary_plane_update()
 86		 */
 87		if (drm_framebuffer_read_refcount(vkms_state->frame_info->fb))
 88			drm_framebuffer_put(vkms_state->frame_info->fb);
 89	}
 90
 91	kfree(vkms_state->frame_info);
 92	vkms_state->frame_info = NULL;
 93
 94	__drm_gem_destroy_shadow_plane_state(&vkms_state->base);
 95	kfree(vkms_state);
 96}
 97
 98static void vkms_plane_reset(struct drm_plane *plane)
 99{
100	struct vkms_plane_state *vkms_state;
101
102	if (plane->state) {
103		vkms_plane_destroy_state(plane, plane->state);
104		plane->state = NULL; /* must be set to NULL here */
105	}
106
107	vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);
108	if (!vkms_state) {
109		DRM_ERROR("Cannot allocate vkms_plane_state\n");
110		return;
111	}
112
113	__drm_gem_reset_shadow_plane(plane, &vkms_state->base);
114}
115
116static const struct drm_plane_funcs vkms_plane_funcs = {
117	.update_plane		= drm_atomic_helper_update_plane,
118	.disable_plane		= drm_atomic_helper_disable_plane,
119	.reset			= vkms_plane_reset,
120	.atomic_duplicate_state = vkms_plane_duplicate_state,
121	.atomic_destroy_state	= vkms_plane_destroy_state,
122};
123
124static void vkms_plane_atomic_update(struct drm_plane *plane,
125				     struct drm_atomic_state *state)
126{
127	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
128									   plane);
129	struct vkms_plane_state *vkms_plane_state;
130	struct drm_shadow_plane_state *shadow_plane_state;
131	struct drm_framebuffer *fb = new_state->fb;
132	struct vkms_frame_info *frame_info;
133	u32 fmt;
134
135	if (!new_state->crtc || !fb)
136		return;
137
138	fmt = fb->format->format;
139	vkms_plane_state = to_vkms_plane_state(new_state);
140	shadow_plane_state = &vkms_plane_state->base;
141
142	frame_info = vkms_plane_state->frame_info;
143	memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect));
144	memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect));
145	frame_info->fb = fb;
146	memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map));
147	drm_framebuffer_get(frame_info->fb);
148	frame_info->rotation = new_state->rotation;
149
150	vkms_plane_state->pixel_read_line = get_pixel_read_line_function(fmt);
151	get_conversion_matrix_to_argb_u16(fmt, new_state->color_encoding, new_state->color_range,
152					  &vkms_plane_state->conversion_matrix);
153}
154
155static int vkms_plane_atomic_check(struct drm_plane *plane,
156				   struct drm_atomic_state *state)
157{
158	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
159										 plane);
160	struct drm_crtc_state *crtc_state;
161	int ret;
162
163	if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))
164		return 0;
165
166	crtc_state = drm_atomic_get_crtc_state(state,
167					       new_plane_state->crtc);
168	if (IS_ERR(crtc_state))
169		return PTR_ERR(crtc_state);
170
171	ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
172						  DRM_PLANE_NO_SCALING,
173						  DRM_PLANE_NO_SCALING,
174						  true, true);
175	if (ret != 0)
176		return ret;
177
178	return 0;
179}
180
181static int vkms_prepare_fb(struct drm_plane *plane,
182			   struct drm_plane_state *state)
183{
184	struct drm_shadow_plane_state *shadow_plane_state;
185	struct drm_framebuffer *fb = state->fb;
186	int ret;
187
188	if (!fb)
189		return 0;
190
191	shadow_plane_state = to_drm_shadow_plane_state(state);
192
193	ret = drm_gem_plane_helper_prepare_fb(plane, state);
194	if (ret)
195		return ret;
196
197	return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
198}
199
200static void vkms_cleanup_fb(struct drm_plane *plane,
201			    struct drm_plane_state *state)
202{
203	struct drm_shadow_plane_state *shadow_plane_state;
204	struct drm_framebuffer *fb = state->fb;
205
206	if (!fb)
207		return;
208
209	shadow_plane_state = to_drm_shadow_plane_state(state);
210
211	drm_gem_fb_vunmap(fb, shadow_plane_state->map);
212}
213
214static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {
215	.atomic_update		= vkms_plane_atomic_update,
216	.atomic_check		= vkms_plane_atomic_check,
217	.prepare_fb		= vkms_prepare_fb,
218	.cleanup_fb		= vkms_cleanup_fb,
219};
220
221struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
222				   struct vkms_config_plane *plane_cfg)
223{
224	struct drm_device *dev = &vkmsdev->drm;
225	struct vkms_plane *plane;
226
227	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 0,
228					   &vkms_plane_funcs,
229					   vkms_formats, ARRAY_SIZE(vkms_formats),
230					   NULL, vkms_config_plane_get_type(plane_cfg),
231					   NULL);
232	if (IS_ERR(plane))
233		return plane;
234
235	drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs);
236
237	drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,
238					   DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);
239
240	drm_plane_create_color_properties(&plane->base,
241					  BIT(DRM_COLOR_YCBCR_BT601) |
242					  BIT(DRM_COLOR_YCBCR_BT709) |
243					  BIT(DRM_COLOR_YCBCR_BT2020),
244					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
245					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
246					  DRM_COLOR_YCBCR_BT601,
247					  DRM_COLOR_YCBCR_FULL_RANGE);
248
249	if (vkms_config_plane_get_default_pipeline(plane_cfg))
250		vkms_initialize_colorops(&plane->base);
251
252	return plane;
253}
~/ Read-only file preview.